001package org.jsoup.nodes; 002 003import java.util.List; 004 005/** 006 A node that does not hold any children. E.g.: {@link TextNode}, {@link DataNode}, {@link Comment}. 007 */ 008public abstract class LeafNode extends Node { 009 Object value; // either a string value, or an attribute map (in the rare case multiple attributes are set) 010 011 protected final boolean hasAttributes() { 012 return value instanceof Attributes; 013 } 014 015 @Override 016 public final Attributes attributes() { 017 ensureAttributes(); 018 return (Attributes) value; 019 } 020 021 private void ensureAttributes() { 022 if (!hasAttributes()) { 023 Object coreValue = value; 024 Attributes attributes = new Attributes(); 025 value = attributes; 026 if (coreValue != null) 027 attributes.put(nodeName(), (String) coreValue); 028 } 029 } 030 031 String coreValue() { 032 return attr(nodeName()); 033 } 034 035 void coreValue(String value) { 036 attr(nodeName(), value); 037 } 038 039 @Override 040 public String attr(String key) { 041 if (!hasAttributes()) { 042 return nodeName().equals(key) ? (String) value : EmptyString; 043 } 044 return super.attr(key); 045 } 046 047 @Override 048 public Node attr(String key, String value) { 049 if (!hasAttributes() && key.equals(nodeName())) { 050 this.value = value; 051 } else { 052 ensureAttributes(); 053 super.attr(key, value); 054 } 055 return this; 056 } 057 058 @Override 059 public boolean hasAttr(String key) { 060 ensureAttributes(); 061 return super.hasAttr(key); 062 } 063 064 @Override 065 public Node removeAttr(String key) { 066 ensureAttributes(); 067 return super.removeAttr(key); 068 } 069 070 @Override 071 public String absUrl(String key) { 072 ensureAttributes(); 073 return super.absUrl(key); 074 } 075 076 @Override 077 public String baseUri() { 078 return hasParent() ? parent().baseUri() : ""; 079 } 080 081 @Override 082 protected void doSetBaseUri(String baseUri) { 083 // noop 084 } 085 086 @Override 087 public int childNodeSize() { 088 return 0; 089 } 090 091 @Override 092 public Node empty() { 093 return this; 094 } 095 096 @Override 097 protected List<Node> ensureChildNodes() { 098 return EmptyNodes; 099 } 100 101 @Override 102 protected LeafNode doClone(Node parent) { 103 LeafNode clone = (LeafNode) super.doClone(parent); 104 105 // Object value could be plain string or attributes - need to clone 106 if (hasAttributes()) 107 clone.value = ((Attributes) value).clone(); 108 109 return clone; 110 } 111}