david_williams | cfdb2cd | 2004-11-11 08:37:49 +0000 | [diff] [blame] | 1 | /******************************************************************************* |
amywu | ecebb04 | 2007-04-10 20:07:35 +0000 | [diff] [blame] | 2 | * Copyright (c) 2001, 2005 IBM Corporation and others. |
david_williams | cfdb2cd | 2004-11-11 08:37:49 +0000 | [diff] [blame] | 3 | * All rights reserved. This program and the accompanying materials |
| 4 | * are made available under the terms of the Eclipse Public License v1.0 |
| 5 | * which accompanies this distribution, and is available at |
| 6 | * http://www.eclipse.org/legal/epl-v10.html |
amywu | ecebb04 | 2007-04-10 20:07:35 +0000 | [diff] [blame] | 7 | * |
david_williams | cfdb2cd | 2004-11-11 08:37:49 +0000 | [diff] [blame] | 8 | * Contributors: |
| 9 | * IBM Corporation - initial API and implementation |
| 10 | * Jens Lukowski/Innoopract - initial renaming/restructuring |
| 11 | * |
| 12 | *******************************************************************************/ |
nitind | d6e591d | 2005-03-14 22:21:57 +0000 | [diff] [blame] | 13 | package org.eclipse.wst.dtd.core.internal; |
david_williams | cfdb2cd | 2004-11-11 08:37:49 +0000 | [diff] [blame] | 14 | |
| 15 | import java.util.ArrayList; |
| 16 | import java.util.Collections; |
| 17 | import java.util.List; |
| 18 | |
| 19 | import org.eclipse.swt.graphics.Image; |
nitind | d6e591d | 2005-03-14 22:21:57 +0000 | [diff] [blame] | 20 | import org.eclipse.wst.dtd.core.internal.document.DTDModelImpl; |
| 21 | import org.eclipse.wst.dtd.core.internal.parser.DTDRegionTypes; |
david_williams | cfdb2cd | 2004-11-11 08:37:49 +0000 | [diff] [blame] | 22 | import org.eclipse.wst.dtd.core.internal.text.RegionIterator; |
david_williams | c911388 | 2005-04-09 03:19:38 +0000 | [diff] [blame] | 23 | import org.eclipse.wst.sse.core.internal.model.FactoryRegistry; |
david_williams | 4ad020f | 2005-04-18 08:00:30 +0000 | [diff] [blame] | 24 | import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion; |
| 25 | import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion; |
| 26 | import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion; |
david_williams | cfdb2cd | 2004-11-11 08:37:49 +0000 | [diff] [blame] | 27 | import org.eclipse.wst.sse.core.internal.text.TextRegionListImpl; |
david_williams | c16014c | 2004-11-11 17:11:35 +0000 | [diff] [blame] | 28 | import org.eclipse.wst.xml.core.internal.document.NodeContainer; |
nitind | d6e591d | 2005-03-14 22:21:57 +0000 | [diff] [blame] | 29 | import org.w3c.dom.Node; |
david_williams | cfdb2cd | 2004-11-11 08:37:49 +0000 | [diff] [blame] | 30 | |
| 31 | |
| 32 | public abstract class DTDNode extends NodeContainer implements IndexedRegion { |
| 33 | |
| 34 | // these are characteroffsets |
| 35 | protected DTDFile dtdFile; |
| 36 | |
| 37 | // flat node that contains this node |
| 38 | protected IStructuredDocumentRegion flatNode; |
| 39 | |
| 40 | protected TextRegionListImpl regions = new TextRegionListImpl(); |
| 41 | |
| 42 | protected TextRegionListImpl whitespace = new TextRegionListImpl(); |
| 43 | |
| 44 | public DTDNode(DTDFile dtdFile, IStructuredDocumentRegion flatNode) { |
| 45 | this.dtdFile = dtdFile; |
| 46 | this.flatNode = flatNode; |
| 47 | } |
| 48 | |
| 49 | public void addRegion(ITextRegion region) { |
| 50 | /* |
| 51 | * if (startRegion == null) { startRegion = region; } endRegion = |
| 52 | * region; |
| 53 | */ |
| 54 | regions.add(region); |
| 55 | } |
| 56 | |
| 57 | public void addWhitespaceRegion(ITextRegion region) { |
| 58 | whitespace.add(region); |
| 59 | } |
| 60 | |
david_williams | cfdb2cd | 2004-11-11 08:37:49 +0000 | [diff] [blame] | 61 | public void beginRecording(Object requestor, String label) { |
| 62 | getDTDFile().getDTDModel().beginRecording(requestor, label); |
| 63 | } |
| 64 | |
nitind | d6e591d | 2005-03-14 22:21:57 +0000 | [diff] [blame] | 65 | public Node cloneNode(boolean deepest) { |
david_williams | cfdb2cd | 2004-11-11 08:37:49 +0000 | [diff] [blame] | 66 | return null; |
| 67 | } |
| 68 | |
| 69 | public boolean contains(int testPosition) { |
| 70 | return containsRange(testPosition, testPosition); |
| 71 | } |
| 72 | |
| 73 | public boolean containsRange(int start, int end) { |
| 74 | return getStartOffset() <= start && end <= getEndOffset(); |
| 75 | } |
| 76 | |
| 77 | public void delete(DTDNode child) { |
david_williams | 3804601 | 2005-04-08 19:04:29 +0000 | [diff] [blame] | 78 | beginRecording(this, DTDCoreMessages._UI_LABEL_DTD_NODE_DELETE); //$NON-NLS-1$ |
david_williams | cfdb2cd | 2004-11-11 08:37:49 +0000 | [diff] [blame] | 79 | delete(this, child); |
| 80 | endRecording(this); |
| 81 | } |
| 82 | |
| 83 | public void delete(Object requestor, DTDNode child) { |
| 84 | replaceText(requestor, child.getStartOffset(), child.getFullNodeLength(), ""); //$NON-NLS-1$ |
| 85 | } |
| 86 | |
| 87 | public void endRecording(Object requestor) { |
| 88 | getDTDFile().getDTDModel().endRecording(requestor); |
| 89 | } |
| 90 | |
| 91 | public Object[] getChildren() { |
| 92 | return getChildrenList().toArray(); |
| 93 | } |
| 94 | |
| 95 | public List getChildrenList() { |
nitind | d6e591d | 2005-03-14 22:21:57 +0000 | [diff] [blame] | 96 | Node child = getFirstChild(); |
david_williams | cfdb2cd | 2004-11-11 08:37:49 +0000 | [diff] [blame] | 97 | if (child != null) { |
| 98 | List children = new ArrayList(); |
| 99 | for (; child != null; child = child.getNextSibling()) { |
| 100 | children.add(child); |
| 101 | } |
| 102 | return children; |
nitind | d6e591d | 2005-03-14 22:21:57 +0000 | [diff] [blame] | 103 | } |
| 104 | else { |
david_williams | cfdb2cd | 2004-11-11 08:37:49 +0000 | [diff] [blame] | 105 | return Collections.EMPTY_LIST; |
| 106 | } |
| 107 | } |
| 108 | |
| 109 | public DTDNode getDeepestNode(int offset) { |
| 110 | if (contains(offset)) { |
| 111 | // now see if a child contains this offset |
| 112 | Object[] children = getChildren(); |
| 113 | for (int i = 0; i < children.length; i++) { |
| 114 | DTDNode child = (DTDNode) children[i]; |
| 115 | DTDNode deepest = child.getDeepestNode(offset); |
| 116 | if (deepest != null) { |
| 117 | return deepest; |
| 118 | } |
| 119 | } // end of for () |
| 120 | return this; |
| 121 | } |
| 122 | return null; |
| 123 | } |
| 124 | |
| 125 | public DTDNode getDeepestNode(int start, int end) { |
| 126 | if (containsRange(start, end)) { |
| 127 | // now see if a child contains this offset |
| 128 | Object[] children = getChildren(); |
| 129 | for (int i = 0; i < children.length; i++) { |
| 130 | DTDNode child = (DTDNode) children[i]; |
| 131 | DTDNode deepest = child.getDeepestNode(start, end); |
| 132 | if (deepest != null) { |
| 133 | return deepest; |
| 134 | } |
| 135 | } // end of for () |
| 136 | return this; |
| 137 | } |
| 138 | return null; |
| 139 | } |
| 140 | |
| 141 | public DTDFile getDTDFile() { |
| 142 | return dtdFile; |
| 143 | } |
| 144 | |
| 145 | public int getEndOffset() { |
david_williams | 29d6968 | 2004-11-20 17:49:29 +0000 | [diff] [blame] | 146 | return getStructuredDTDDocumentRegion().getEndOffset(getEndRegion()); |
david_williams | cfdb2cd | 2004-11-11 08:37:49 +0000 | [diff] [blame] | 147 | } |
| 148 | |
| 149 | public ITextRegion getEndRegion() { |
david_williams | 29d6968 | 2004-11-20 17:49:29 +0000 | [diff] [blame] | 150 | return regions.get(regions.size() - 1);// endRegion; |
david_williams | cfdb2cd | 2004-11-11 08:37:49 +0000 | [diff] [blame] | 151 | } |
| 152 | |
| 153 | /** |
| 154 | */ |
david_williams | 68bf9b3 | 2005-03-26 04:29:10 +0000 | [diff] [blame] | 155 | public FactoryRegistry getFactoryRegistry() { |
david_williams | cfdb2cd | 2004-11-11 08:37:49 +0000 | [diff] [blame] | 156 | DTDModelImpl model = dtdFile.getDTDModel(); |
| 157 | if (model != null) { |
david_williams | 68bf9b3 | 2005-03-26 04:29:10 +0000 | [diff] [blame] | 158 | FactoryRegistry reg = model.getFactoryRegistry(); |
david_williams | cfdb2cd | 2004-11-11 08:37:49 +0000 | [diff] [blame] | 159 | if (reg != null) |
| 160 | return reg; |
| 161 | } |
| 162 | return null; |
| 163 | } |
| 164 | |
| 165 | public int getFullNodeLength() { |
| 166 | return getWhitespaceEndOffset() - getStartOffset(); |
| 167 | } |
| 168 | |
| 169 | public String getFullNodeText() { |
| 170 | String text = getNodeText(); |
| 171 | if (whitespace.size() > 0) { |
| 172 | RegionIterator iter = new RegionIterator(whitespace); |
| 173 | while (iter.hasNext()) { |
| 174 | ITextRegion region = iter.next(); |
david_williams | 29d6968 | 2004-11-20 17:49:29 +0000 | [diff] [blame] | 175 | text += getStructuredDTDDocumentRegion().getText(region); |
david_williams | cfdb2cd | 2004-11-11 08:37:49 +0000 | [diff] [blame] | 176 | } |
| 177 | } |
| 178 | return text; |
| 179 | } |
| 180 | |
| 181 | abstract public Image getImage(); |
| 182 | |
| 183 | public String getName() { |
| 184 | ITextRegion region = getNameRegion(); |
| 185 | if (region != null) { |
david_williams | 29d6968 | 2004-11-20 17:49:29 +0000 | [diff] [blame] | 186 | return getStructuredDTDDocumentRegion().getText(region); |
david_williams | cfdb2cd | 2004-11-11 08:37:49 +0000 | [diff] [blame] | 187 | } |
| 188 | return ""; //$NON-NLS-1$ |
| 189 | } |
| 190 | |
| 191 | public ITextRegion getNameRegion() { |
| 192 | RegionIterator iter = iterator(); |
| 193 | while (iter.hasNext()) { |
| 194 | ITextRegion region = iter.next(); |
| 195 | if (region.getType() == DTDRegionTypes.NAME) { |
| 196 | return region; |
| 197 | } |
| 198 | } |
| 199 | return null; |
| 200 | } |
| 201 | |
| 202 | // return the first token containing the specified token type |
| 203 | public ITextRegion getNextRegion(RegionIterator iter, String type) { |
| 204 | while (iter.hasNext()) { |
| 205 | ITextRegion region = iter.next(); |
| 206 | if (region.getType().equals(type)) { |
| 207 | return region; |
| 208 | } |
| 209 | } |
| 210 | return null; |
| 211 | } |
| 212 | |
| 213 | public int getNodeLength() { |
| 214 | return getEndOffset() - getStartOffset(); |
| 215 | } |
| 216 | |
| 217 | public String getNodeName() { |
| 218 | return getName(); |
| 219 | } |
| 220 | |
| 221 | public String getNodeText() { |
| 222 | StringBuffer sb = new StringBuffer(); |
| 223 | |
| 224 | RegionIterator iter = iterator(); |
| 225 | while (iter.hasNext()) { |
| 226 | ITextRegion region = iter.next(); |
david_williams | 29d6968 | 2004-11-20 17:49:29 +0000 | [diff] [blame] | 227 | sb.append(getStructuredDTDDocumentRegion().getText(region)); |
david_williams | cfdb2cd | 2004-11-11 08:37:49 +0000 | [diff] [blame] | 228 | } |
| 229 | return sb.toString(); |
| 230 | } |
| 231 | |
| 232 | public short getNodeType() { |
| 233 | return -1; |
| 234 | } |
| 235 | |
| 236 | public int getStartOffset() { |
david_williams | 29d6968 | 2004-11-20 17:49:29 +0000 | [diff] [blame] | 237 | return getStructuredDTDDocumentRegion().getStartOffset(getStartRegion()); |
david_williams | cfdb2cd | 2004-11-11 08:37:49 +0000 | [diff] [blame] | 238 | } |
| 239 | |
david_williams | 29d6968 | 2004-11-20 17:49:29 +0000 | [diff] [blame] | 240 | // private Region startRegion,endRegion; |
david_williams | cfdb2cd | 2004-11-11 08:37:49 +0000 | [diff] [blame] | 241 | public ITextRegion getStartRegion() { |
| 242 | return regions.get(0); |
david_williams | 29d6968 | 2004-11-20 17:49:29 +0000 | [diff] [blame] | 243 | // return startRegion; |
david_williams | cfdb2cd | 2004-11-11 08:37:49 +0000 | [diff] [blame] | 244 | } |
| 245 | |
| 246 | /** |
| 247 | * Get the value of flatNode. |
| 248 | * |
| 249 | * @return value of flatNode. |
david_williams | 29d6968 | 2004-11-20 17:49:29 +0000 | [diff] [blame] | 250 | * |
| 251 | * ISSUE:named changed not to be confused with default access protected |
| 252 | * super class method, but should re-think if this is correct technique. |
| 253 | * Perhaps getFirstRegion? |
david_williams | cfdb2cd | 2004-11-11 08:37:49 +0000 | [diff] [blame] | 254 | */ |
david_williams | 29d6968 | 2004-11-20 17:49:29 +0000 | [diff] [blame] | 255 | public IStructuredDocumentRegion getStructuredDTDDocumentRegion() { |
david_williams | cfdb2cd | 2004-11-11 08:37:49 +0000 | [diff] [blame] | 256 | return flatNode; |
| 257 | } |
| 258 | |
| 259 | // return end offset including whitespace |
| 260 | // or just the end offset if there is no whitespace |
| 261 | public int getWhitespaceEndOffset() { |
| 262 | if (whitespace.size() > 0) { |
| 263 | ITextRegion region = whitespace.get(whitespace.size() - 1); |
david_williams | 29d6968 | 2004-11-20 17:49:29 +0000 | [diff] [blame] | 264 | return getStructuredDTDDocumentRegion().getEndOffset(region); |
david_williams | cfdb2cd | 2004-11-11 08:37:49 +0000 | [diff] [blame] | 265 | } |
| 266 | |
| 267 | return getEndOffset(); |
| 268 | } |
| 269 | |
| 270 | public boolean hasTrailingWhitespace() { |
| 271 | return whitespace.size() > 0; |
| 272 | } |
| 273 | |
| 274 | public RegionIterator iterator() { |
david_williams | 29d6968 | 2004-11-20 17:49:29 +0000 | [diff] [blame] | 275 | // System.out.println("create region iter " + this.getClass() + " with |
david_williams | cfdb2cd | 2004-11-11 08:37:49 +0000 | [diff] [blame] | 276 | // start , end = " + getStartOffset() + ", " +getEndOffset()); |
| 277 | return new RegionIterator(regions); |
| 278 | } |
| 279 | |
| 280 | public void replaceText(Object requestor, int start, int length, String newText) { |
| 281 | getDTDFile().getStructuredDocument().replaceText(requestor, start, length, newText); |
| 282 | } |
| 283 | |
| 284 | public void resolveRegions() { |
| 285 | } |
| 286 | |
| 287 | public void setName(Object requestor, String name) { |
| 288 | if (!getName().equals(name)) { |
| 289 | ITextRegion nameRegion = getNameRegion(); |
| 290 | if (nameRegion != null) { |
david_williams | 29d6968 | 2004-11-20 17:49:29 +0000 | [diff] [blame] | 291 | // nameToken.updateText(name); |
david_williams | cfdb2cd | 2004-11-11 08:37:49 +0000 | [diff] [blame] | 292 | getDTDFile().getDTDModel().getReferenceUpdater().nameAboutToChange(requestor, this, name); |
david_williams | 29d6968 | 2004-11-20 17:49:29 +0000 | [diff] [blame] | 293 | replaceText(requestor, getStructuredDTDDocumentRegion().getStartOffset(nameRegion), nameRegion.getLength(), name); |
david_williams | cfdb2cd | 2004-11-11 08:37:49 +0000 | [diff] [blame] | 294 | } |
| 295 | } |
| 296 | } |
| 297 | |
| 298 | public void setName(String name) { |
david_williams | 3804601 | 2005-04-08 19:04:29 +0000 | [diff] [blame] | 299 | beginRecording(this, DTDCoreMessages._UI_LABEL_DTD_NODE_NAME_CHG); //$NON-NLS-1$ |
david_williams | cfdb2cd | 2004-11-11 08:37:49 +0000 | [diff] [blame] | 300 | setName(this, name); |
| 301 | endRecording(this); |
| 302 | } |
| 303 | |
| 304 | /** |
| 305 | * Set the value of flatNode. |
| 306 | * |
| 307 | * @param v |
david_williams | 29d6968 | 2004-11-20 17:49:29 +0000 | [diff] [blame] | 308 | * Value to assign to flatNode. ISSUE:named changed not to be |
| 309 | * confused with default access protected super class method, |
| 310 | * but should re-think if this is correct technique |
david_williams | cfdb2cd | 2004-11-11 08:37:49 +0000 | [diff] [blame] | 311 | */ |
david_williams | 29d6968 | 2004-11-20 17:49:29 +0000 | [diff] [blame] | 312 | void setStructuredDTDDocumentRegion(IStructuredDocumentRegion v) { |
david_williams | cfdb2cd | 2004-11-11 08:37:49 +0000 | [diff] [blame] | 313 | this.flatNode = v; |
| 314 | } |
| 315 | |
| 316 | // skips past next name token in the iterator |
| 317 | protected void skipPastName(RegionIterator iter) { |
| 318 | while (iter.hasNext()) { |
| 319 | ITextRegion currentRegion = iter.next(); |
| 320 | if (currentRegion.getType() == DTDRegionTypes.NAME) { |
| 321 | break; |
| 322 | } |
| 323 | } |
| 324 | } |
| 325 | |
| 326 | public boolean supports(java.lang.String feature, java.lang.String version) { |
| 327 | return false; |
| 328 | } |
| 329 | |
| 330 | } |