1 21 package au.id.jericho.lib.html; 22 23 import java.util.*; 24 25 220 public final class Element extends Segment implements HTMLElementName { 221 private final StartTag startTag; 222 private final EndTag endTag; 223 private Segment content=null; 224 Element parentElement=Element.NOT_CACHED; 225 private int depth=-1; 226 227 static final Element NOT_CACHED=new Element(); 228 229 Element(final Source source, final StartTag startTag, final EndTag endTag) { 230 super(source, startTag.begin, endTag==null ? startTag.end : endTag.end); 231 this.startTag=startTag; 232 this.endTag=(endTag==null || endTag.length()==0) ? null : endTag; 233 } 234 235 private Element() { 236 startTag=null; 237 endTag=null; 238 } 239 240 253 public Element getParentElement() { 254 if (parentElement==Element.NOT_CACHED) { 255 source.getChildElements(); 256 if (parentElement==Element.NOT_CACHED) parentElement=null; 257 } 258 return parentElement; 259 } 260 261 271 public final List getChildElements() { 272 return childElements!=null ? childElements : getChildElements(-1); 273 } 274 275 final List getChildElements(int depth) { 276 if (depth!=-1) this.depth=depth; 277 if (childElements==null) { 278 if (!Config.IncludeServerTagsInElementHierarchy && end==startTag.end) { 279 childElements=Collections.EMPTY_LIST; 280 } else { 281 final int childDepth=(depth==-1 ? -1 : depth+1); 282 childElements=new ArrayList(); 283 int pos=Config.IncludeServerTagsInElementHierarchy ? begin+1 : startTag.end; 284 final int maxChildBegin=(Config.IncludeServerTagsInElementHierarchy || endTag==null) ? end : endTag.begin; 285 while (true) { 286 final StartTag childStartTag=source.findNextStartTag(pos); 287 if (childStartTag==null || childStartTag.begin>=maxChildBegin) break; 288 if (Config.IncludeServerTagsInElementHierarchy) { 289 if (childStartTag.begin<startTag.end && !childStartTag.getTagType().isServerTag() && !startTag.getTagType().isServerTag()) { 290 pos=childStartTag.end; 294 continue; 295 } 296 } else if (childStartTag.getTagType().isServerTag()) { 297 pos=childStartTag.end; 298 continue; 299 } 300 final Element childElement=childStartTag.getElement(); 301 childElement.parentElement=this; 302 if (childElement.end>end && source.isLoggingEnabled()) source.log("Child element "+childElement.getDebugInfo()+" extends beyond end of parent "+getDebugInfo()); 303 childElements.add(childElement); 304 childElement.getChildElements(childDepth); 305 pos=childElement.end; 306 } 307 } 308 } 309 return childElements; 310 } 311 312 327 public int getDepth() { 328 if (depth==-1) { 329 getParentElement(); 330 if (depth==-1) depth=0; 331 } 332 return depth; 333 } 334 335 346 public Segment getContent() { 347 if (content==null) content=new Segment(source,startTag.end,getContentEnd()); 348 return content; 349 } 350 351 355 public StartTag getStartTag() { 356 return startTag; 357 } 358 359 366 public EndTag getEndTag() { 367 return endTag; 368 } 369 370 379 public String getName() { 380 return startTag.getName(); 381 } 382 383 400 public boolean isEmpty() { 401 return startTag.end==getContentEnd(); 402 } 403 404 424 public boolean isEmptyElementTag() { 425 return isEmpty() && startTag.isEmptyElementTag(); 426 } 427 428 436 public Attributes getAttributes() { 437 return getStartTag().getAttributes(); 438 } 439 440 452 public String getAttributeValue(final String attributeName) { 453 return getStartTag().getAttributeValue(attributeName); 454 } 455 456 460 public FormControl getFormControl() { 461 return FormControl.construct(this); 462 } 463 464 public String getDebugInfo() { 465 if (this==NOT_CACHED) return "NOT_CACHED"; 466 final StringBuffer sb=new StringBuffer (); 467 sb.append("Element ").append(super.getDebugInfo()).append(": "); 468 startTag.appendStartTagDebugInfo(sb); 469 sb.append(endTag==null ? "(no end tag)" : "(with end tag)"); 470 return sb.toString(); 471 } 472 473 483 public String getContentText() { 484 return isEmpty() ? null : toString(); 485 } 486 487 497 public static boolean isBlock(final String elementName) { 498 return HTMLElements.getBlockLevelElementNames().contains(elementName.toLowerCase()); 499 } 500 501 511 public static boolean isInline(final String elementName) { 512 return HTMLElements.getInlineLevelElementNames().contains(elementName.toLowerCase()); 513 } 514 515 int getContentEnd() { 516 return endTag!=null ? endTag.begin : end; 517 } 518 } 519 520 | Popular Tags |