1 /** 2 * Copyright (c) 2008, SnakeYAML 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 * in compliance with the License. You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software distributed under the License 10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 * or implied. See the License for the specific language governing permissions and limitations under 12 * the License. 13 */ 14 package org.yaml.snakeyaml.nodes; 15 16 import java.util.List; 17 import org.yaml.snakeyaml.comments.CommentLine; 18 import org.yaml.snakeyaml.error.Mark; 19 20 /** 21 * Base class for all nodes. 22 * <p> 23 * The nodes form the node-graph described in the <a href="http://yaml.org/spec/1.1/">YAML 24 * Specification</a>. 25 * </p> 26 * <p> 27 * While loading, the node graph is usually created by the 28 * {@link org.yaml.snakeyaml.composer.Composer}, and later transformed into application specific 29 * Java classes by the classes from the {@link org.yaml.snakeyaml.constructor} package. 30 * </p> 31 */ 32 public abstract class Node { 33 34 private Tag tag; 35 private final Mark startMark; 36 protected Mark endMark; 37 private Class<? extends Object> type; 38 private boolean twoStepsConstruction; 39 private String anchor; 40 private List<CommentLine> inLineComments; 41 private List<CommentLine> blockComments; 42 // End Comments are only on the last node in a document 43 private List<CommentLine> endComments; 44 45 /** 46 * true when the tag is assigned by the resolver 47 */ 48 protected boolean resolved; 49 protected Boolean useClassConstructor; 50 Node(Tag tag, Mark startMark, Mark endMark)51 public Node(Tag tag, Mark startMark, Mark endMark) { 52 setTag(tag); 53 this.startMark = startMark; 54 this.endMark = endMark; 55 this.type = Object.class; 56 this.twoStepsConstruction = false; 57 this.resolved = true; 58 this.useClassConstructor = null; 59 this.inLineComments = null; 60 this.blockComments = null; 61 this.endComments = null; 62 } 63 64 /** 65 * Tag of this node. 66 * <p> 67 * Every node has a tag assigned. The tag is either local or global. 68 * 69 * @return Tag of this node. 70 */ getTag()71 public Tag getTag() { 72 return this.tag; 73 } 74 getEndMark()75 public Mark getEndMark() { 76 return endMark; 77 } 78 79 /** 80 * For error reporting. 81 * 82 * @see "class variable 'id' in PyYAML" 83 * @return scalar, sequence, mapping 84 */ getNodeId()85 public abstract NodeId getNodeId(); 86 getStartMark()87 public Mark getStartMark() { 88 return startMark; 89 } 90 setTag(Tag tag)91 public void setTag(Tag tag) { 92 if (tag == null) { 93 throw new NullPointerException("tag in a Node is required."); 94 } 95 this.tag = tag; 96 } 97 98 /** 99 * Node is only equal to itself 100 */ 101 @Override equals(Object obj)102 public final boolean equals(Object obj) { 103 return super.equals(obj); 104 } 105 getType()106 public Class<? extends Object> getType() { 107 return type; 108 } 109 setType(Class<? extends Object> type)110 public void setType(Class<? extends Object> type) { 111 if (!type.isAssignableFrom(this.type)) { 112 this.type = type; 113 } 114 } 115 setTwoStepsConstruction(boolean twoStepsConstruction)116 public void setTwoStepsConstruction(boolean twoStepsConstruction) { 117 this.twoStepsConstruction = twoStepsConstruction; 118 } 119 120 /** 121 * Indicates if this node must be constructed in two steps. 122 * <p> 123 * Two-step construction is required whenever a node is a child (direct or indirect) of it self. 124 * That is, if a recursive structure is build using anchors and aliases. 125 * </p> 126 * <p> 127 * Set by {@link org.yaml.snakeyaml.composer.Composer}, used during the construction process. 128 * </p> 129 * <p> 130 * Only relevant during loading. 131 * </p> 132 * 133 * @return <code>true</code> if the node is self referenced. 134 */ isTwoStepsConstruction()135 public boolean isTwoStepsConstruction() { 136 return twoStepsConstruction; 137 } 138 139 @Override hashCode()140 public final int hashCode() { 141 return super.hashCode(); 142 } 143 useClassConstructor()144 public boolean useClassConstructor() { 145 if (useClassConstructor == null) { 146 // the tag is compatible with the runtime class 147 // the tag will be ignored 148 if (!tag.isSecondary() && resolved && !Object.class.equals(type) && !tag.equals(Tag.NULL)) { 149 return true; 150 } else { 151 return tag.isCompatible(getType()); 152 } 153 } 154 return useClassConstructor.booleanValue(); 155 } 156 setUseClassConstructor(Boolean useClassConstructor)157 public void setUseClassConstructor(Boolean useClassConstructor) { 158 this.useClassConstructor = useClassConstructor; 159 } 160 161 /** 162 * Indicates if the tag was added by {@link org.yaml.snakeyaml.resolver.Resolver}. 163 * 164 * @return true if the tag of this node was resolved 165 * 166 * @deprecated Since v1.22. Absent in immediately prior versions, but present previously. Restored 167 * deprecated for backwards compatibility. 168 */ 169 @Deprecated isResolved()170 public boolean isResolved() { 171 return resolved; 172 } 173 getAnchor()174 public String getAnchor() { 175 return anchor; 176 } 177 setAnchor(String anchor)178 public void setAnchor(String anchor) { 179 this.anchor = anchor; 180 } 181 182 /** 183 * The ordered list of in-line comments. The first of which appears at the end of the line 184 * respresent by this node. The rest are in the following lines, indented per the Spec to indicate 185 * they are continuation of the inline comment. 186 * 187 * @return the comment line list. 188 */ getInLineComments()189 public List<CommentLine> getInLineComments() { 190 return inLineComments; 191 } 192 setInLineComments(List<CommentLine> inLineComments)193 public void setInLineComments(List<CommentLine> inLineComments) { 194 this.inLineComments = inLineComments; 195 } 196 197 /** 198 * The ordered list of blank lines and block comments (full line) that appear before this node. 199 * 200 * @return the comment line list. 201 */ getBlockComments()202 public List<CommentLine> getBlockComments() { 203 return blockComments; 204 } 205 setBlockComments(List<CommentLine> blockComments)206 public void setBlockComments(List<CommentLine> blockComments) { 207 this.blockComments = blockComments; 208 } 209 210 /** 211 * The ordered list of blank lines and block comments (full line) that appear AFTER this node. 212 * <p> 213 * NOTE: these comment should occur only in the last node in a document, when walking the node 214 * tree "in order" 215 * 216 * @return the comment line list. 217 */ getEndComments()218 public List<CommentLine> getEndComments() { 219 return endComments; 220 } 221 setEndComments(List<CommentLine> endComments)222 public void setEndComments(List<CommentLine> endComments) { 223 this.endComments = endComments; 224 } 225 } 226