1 19 20 21 package org.netbeans.modules.editor.structure.api; 22 23 import java.util.Collections ; 24 import java.util.Enumeration ; 25 import java.util.HashMap ; 26 import java.util.HashSet ; 27 import java.util.Iterator ; 28 import java.util.List ; 29 import java.util.Map ; 30 import javax.swing.text.AttributeSet ; 31 import javax.swing.text.BadLocationException ; 32 import javax.swing.text.Document ; 33 import javax.swing.text.Position ; 34 35 36 59 public final class DocumentElement { 60 61 private String name; 62 private String type; 63 private Position startPos, endPos; 64 private int startSectionLength, endSectionLength; 65 private DocumentModel model; 66 private Attributes attributes; 67 private int elementEmpty; 68 private boolean isRootElement; 69 70 private static final int ELEMENT_EMPTY_UNSET = 0; 71 private static final int ELEMENT_EMPTY_TRUE = 1; 72 private static final int ELEMENT_EMPTY_FALSE = 2; 73 74 private HashSet <DocumentElementListener> deListeners = new HashSet <DocumentElementListener>(); 76 77 DocumentElement(String name, String type, Map attrsMap, 78 int startOffset, int endOffset, DocumentModel model) throws BadLocationException { 79 this.name = name; 80 this.model = model; 81 this.startSectionLength = startSectionLength; 82 this.endSectionLength = endSectionLength; 83 this.type = type; 84 this.attributes = new Attributes(this, attrsMap); 85 this.elementEmpty = ELEMENT_EMPTY_UNSET; 86 this.isRootElement = false; 87 88 setStartPosition(startOffset); 90 setEndPosition(endOffset); 91 } 92 93 98 public AttributeSet getAttributes() { 99 return this.attributes; 100 } 101 102 107 public Document getDocument() { 108 return model.getDocument(); 109 } 110 111 117 public DocumentElement getElement(int index) { 118 return (DocumentElement)getChildren().get(index); 119 } 120 121 127 public int getElementCount() { 128 return getChildren().size(); 129 } 130 131 138 public int getStartOffset() { 139 return startPos.getOffset(); 140 } 141 142 149 public int getEndOffset() { 150 return endPos.getOffset(); 151 } 152 153 167 public int getElementIndex(int offset) { 168 Iterator children = getChildren().iterator(); 173 int min_delta = Integer.MAX_VALUE; 174 DocumentElement nearest = null; 175 while(children.hasNext()) { 176 DocumentElement de = (DocumentElement)children.next(); 177 178 if(de.getStartOffset() <= offset && de.getEndOffset() > offset) { 180 nearest = de; 181 break; 182 } else { 183 int start_delta = Math.abs(de.getStartOffset() - offset); 185 int end_delta = Math.abs(de.getEndOffset() - offset); 186 int delta = Math.min(start_delta, end_delta); 187 188 if(min_delta > delta) { 189 nearest = de; 190 min_delta = delta; 191 } 192 } 193 } 194 195 if(nearest == null) return -1; 196 else return getChildren().indexOf(nearest); 197 198 } 199 200 204 public String getName() { 205 return name; 206 } 207 208 212 public DocumentElement getParentElement() { 213 return model.getParent(this); 214 } 215 216 217 public boolean isLeaf() { 218 return getChildren().isEmpty(); 219 } 220 221 222 223 void setAttributes(Map attrs) { 225 this.attributes = new Attributes(this, attrs); 226 } 227 228 229 230 void setElementIsEmptyState(boolean state) { 231 elementEmpty = state ? ELEMENT_EMPTY_TRUE : ELEMENT_EMPTY_FALSE; 232 } 233 234 237 238 boolean isEmpty() { 239 if(elementEmpty == ELEMENT_EMPTY_UNSET) elementEmpty = model.isEmpty(this) ? ELEMENT_EMPTY_TRUE : ELEMENT_EMPTY_FALSE; 240 return elementEmpty == ELEMENT_EMPTY_TRUE; 241 } 242 243 246 public DocumentModel getDocumentModel() { 247 return model; 248 } 249 250 257 public String getType() { 258 return type; 259 } 260 261 262 public List <DocumentElement> getChildren() { 263 return model.getChildren(this); 264 } 265 266 267 public void addDocumentElementListener(DocumentElementListener del) { 268 deListeners.add(del); 269 } 270 271 272 public void removeDocumentElementListener(DocumentElementListener del) { 273 deListeners.remove(del); 274 } 275 276 277 278 synchronized void setRootElement(boolean value) { 280 this.isRootElement = value; 281 } 282 283 boolean isRootElement() { 284 return this.isRootElement; 285 } 286 287 void setStartPosition(int offset) throws BadLocationException { 288 startPos = model.getDocument().createPosition(offset); 289 } 290 291 void setEndPosition(int offset) throws BadLocationException { 292 endPos = model.getDocument().createPosition(offset); 293 } 294 295 String getContent() throws BadLocationException { 296 return model.getDocument().getText(getStartOffset(), getEndOffset() - getStartOffset()); 297 } 298 299 private void fireDocumentElementEvent(DocumentElementEvent dee) { 300 for (DocumentElementListener cl: deListeners) { 301 switch(dee.getType()) { 302 case DocumentElementEvent.CHILD_ADDED: cl.elementAdded(dee);break; 303 case DocumentElementEvent.CHILD_REMOVED: cl.elementRemoved(dee);break; 304 case DocumentElementEvent.CONTENT_CHANGED: cl.contentChanged(dee);break; 305 case DocumentElementEvent.ATTRIBUTES_CHANGED: cl.attributesChanged(dee);break; 306 } 307 } 308 } 309 310 void childAdded(DocumentElement de) { 312 fireDocumentElementEvent(new DocumentElementEvent(DocumentElementEvent.CHILD_ADDED, this, de)); 314 } 315 316 void childRemoved(DocumentElement de) { 318 fireDocumentElementEvent(new DocumentElementEvent(DocumentElementEvent.CHILD_REMOVED, this, de)); 320 } 321 322 void contentChanged() { 324 fireDocumentElementEvent(new DocumentElementEvent(DocumentElementEvent.CONTENT_CHANGED, this, null)); 326 } 327 328 void attributesChanged() { 330 fireDocumentElementEvent(new DocumentElementEvent(DocumentElementEvent.ATTRIBUTES_CHANGED, this, null)); 331 } 332 333 334 public boolean equals(Object o) { 335 if(!(o instanceof DocumentElement)) return false; 336 337 DocumentElement de = (DocumentElement)o; 338 339 return (de.getName().equals(getName()) && 340 de.getType().equals(getType()) && 341 de.getStartOffset() == getStartOffset() && 342 de.getEndOffset() == getEndOffset() ); } 345 346 public String toString() { 347 String elementContent = ""; 348 try { 349 elementContent = getContent().trim().length() > PRINT_MAX_CHARS ? 350 getContent().trim().substring(0, PRINT_MAX_CHARS) + "..." : 351 getContent().trim(); 352 }catch(BadLocationException e) { 353 elementContent = "error:" + e.getMessage(); 354 } 355 return "DE (" + hashCode() + ")[\"" + getName() + 356 "\" (" + getType() + 357 ") <" + getStartOffset() + 358 "-" + getEndOffset() + 359 "> '" + encodeNewLines(elementContent) + 360 "']"; 361 } 362 363 private String encodeNewLines(String s) { 364 StringBuffer encoded = new StringBuffer (); 365 for(int i = 0; i < s.length(); i++) { 366 if(s.charAt(i) == '\n') encoded.append("\\n"); else encoded.append(s.charAt(i)); 367 } 368 return encoded.toString(); 369 } 370 371 372 373 static final class Attributes implements AttributeSet { 374 private Map attrs; 375 private DocumentElement de; 376 377 Attributes(DocumentElement element, Map m) { 378 de = element; 379 attrs = m; 380 } 381 382 public int getAttributeCount() { 383 return attrs.size(); 384 } 385 386 public boolean isDefined(Object attrName) { 387 return attrs.containsKey(attrName); 388 } 389 390 public boolean isEqual(AttributeSet attr) { 391 if(getAttributeCount() != attr.getAttributeCount()) return false; 392 return containsAttributes(attr); 393 } 394 395 public AttributeSet copyAttributes() { 396 HashMap clone = new HashMap (getAttributeCount()); 397 clone.putAll(attrs); 398 return new Attributes(de, clone); 399 } 400 401 public Object getAttribute(Object key) { 402 return attrs.get(key); 403 } 404 405 public Enumeration <?> getAttributeNames() { 406 return Collections.enumeration(attrs.keySet()); 407 } 408 409 public boolean containsAttribute(Object name, Object value) { 410 return value.equals(getAttribute(name)); 411 } 412 413 public boolean containsAttributes(AttributeSet attributes) { 414 Enumeration e = attributes.getAttributeNames(); 415 while(e.hasMoreElements()) { 416 Object key = e.nextElement(); 417 Object value = attributes.getAttribute(key); 418 if(!containsAttribute(key, value)) return false; 419 } 420 return true; 421 } 422 423 public String toString() { 424 Enumeration e = getAttributeNames(); 425 StringBuffer sb = new StringBuffer (); 426 while(e.hasMoreElements()) { 427 Object key = e.nextElement(); 428 Object value = getAttribute(key); 429 sb.append(key); 430 sb.append('='); 431 sb.append(value); 432 sb.append(' '); 433 } 434 return sb.toString(); 435 } 436 437 public AttributeSet getResolveParent() { 438 return de.getParentElement() != null ? de.getParentElement().getAttributes() : null; 439 } 440 441 public int compareTo(AttributeSet as) { 442 return toString().compareTo(as.toString()); 443 } 444 445 } 446 447 private final int PRINT_MAX_CHARS = 10; 448 } 449 | Popular Tags |