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