1 /** 2 * Copyright (c) 2008, http://www.snakeyaml.org 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package org.yaml.snakeyaml.nodes; 17 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 24 * href="http://yaml.org/spec/1.1/">YAML 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 29 * application specific Java classes by the classes from the 30 * {@link org.yaml.snakeyaml.constructor} package. 31 * </p> 32 */ 33 public abstract class Node { 34 private Tag tag; 35 private Mark startMark; 36 protected Mark endMark; 37 private Class<? extends Object> type; 38 private boolean twoStepsConstruction; 39 /** 40 * true when the tag is assigned by the resolver 41 */ 42 protected boolean resolved; 43 protected Boolean useClassConstructor; 44 Node(Tag tag, Mark startMark, Mark endMark)45 public Node(Tag tag, Mark startMark, Mark endMark) { 46 setTag(tag); 47 this.startMark = startMark; 48 this.endMark = endMark; 49 this.type = Object.class; 50 this.twoStepsConstruction = false; 51 this.resolved = true; 52 this.useClassConstructor = null; 53 } 54 55 /** 56 * Tag of this node. 57 * <p> 58 * Every node has a tag assigned. The tag is either local or global. 59 * 60 * @return Tag of this node. 61 */ getTag()62 public Tag getTag() { 63 return this.tag; 64 } 65 getEndMark()66 public Mark getEndMark() { 67 return endMark; 68 } 69 70 /** 71 * For error reporting. 72 * 73 * @see "class variable 'id' in PyYAML" 74 * @return scalar, sequence, mapping 75 */ getNodeId()76 public abstract NodeId getNodeId(); 77 getStartMark()78 public Mark getStartMark() { 79 return startMark; 80 } 81 setTag(Tag tag)82 public void setTag(Tag tag) { 83 if (tag == null) { 84 throw new NullPointerException("tag in a Node is required."); 85 } 86 this.tag = tag; 87 } 88 89 /** 90 * Two Nodes are never equal. 91 */ 92 @Override equals(Object obj)93 public final boolean equals(Object obj) { 94 return super.equals(obj); 95 } 96 getType()97 public Class<? extends Object> getType() { 98 return type; 99 } 100 setType(Class<? extends Object> type)101 public void setType(Class<? extends Object> type) { 102 if (!type.isAssignableFrom(this.type)) { 103 this.type = type; 104 } 105 } 106 setTwoStepsConstruction(boolean twoStepsConstruction)107 public void setTwoStepsConstruction(boolean twoStepsConstruction) { 108 this.twoStepsConstruction = twoStepsConstruction; 109 } 110 111 /** 112 * Indicates if this node must be constructed in two steps. 113 * <p> 114 * Two-step construction is required whenever a node is a child (direct or 115 * indirect) of it self. That is, if a recursive structure is build using 116 * anchors and aliases. 117 * </p> 118 * <p> 119 * Set by {@link org.yaml.snakeyaml.composer.Composer}, used during the 120 * construction process. 121 * </p> 122 * <p> 123 * Only relevant during loading. 124 * </p> 125 * 126 * @return <code>true</code> if the node is self referenced. 127 */ isTwoStepsConstruction()128 public boolean isTwoStepsConstruction() { 129 return twoStepsConstruction; 130 } 131 132 @Override hashCode()133 public final int hashCode() { 134 return super.hashCode(); 135 } 136 useClassConstructor()137 public boolean useClassConstructor() { 138 if (useClassConstructor == null) { 139 if (!tag.isSecondary() && isResolved() && !Object.class.equals(type) 140 && !tag.equals(Tag.NULL)) { 141 return true; 142 } else if (tag.isCompatible(getType())) { 143 // the tag is compatible with the runtime class 144 // the tag will be ignored 145 return true; 146 } else { 147 return false; 148 } 149 } 150 return useClassConstructor.booleanValue(); 151 } 152 setUseClassConstructor(Boolean useClassConstructor)153 public void setUseClassConstructor(Boolean useClassConstructor) { 154 this.useClassConstructor = useClassConstructor; 155 } 156 157 /** 158 * Indicates if the tag was added by 159 * {@link org.yaml.snakeyaml.resolver.Resolver}. 160 * 161 * @return <code>true</code> if the tag of this node was resolved</code> 162 */ isResolved()163 public boolean isResolved() { 164 return resolved; 165 } 166 } 167