1 /**
2 * Copyright (c) 2008-2011, 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
17 package org.yaml.snakeyaml.nodes;
18
19 import org.yaml.snakeyaml.error.Mark;
20
21 /**
22 * Base class for all nodes.
23 * <p>
24 * The nodes form the node-graph described in the <a
25 * href="http://yaml.org/spec/1.1/">YAML Specification</a>.
26 * </p>
27 * <p>
28 * While loading, the node graph is usually created by the
29 * {@link org.yaml.snakeyaml.composer.Composer}, and later transformed into
30 * application specific Java classes by the classes from the
31 * {@link org.yaml.snakeyaml.constructor} package.
32 * </p>
33 */
34 public abstract class Node {
35 private Tag tag;
36 private Mark startMark;
37 protected Mark endMark;
38 private Class<? extends Object> type;
39 private boolean twoStepsConstruction;
40 /**
41 * true when the tag is assigned by the resolver
42 */
43 protected boolean resolved;
44 protected Boolean useClassConstructor;
45
46 public Node(Tag tag, Mark startMark, Mark endMark) {
47 setTag(tag);
48 this.startMark = startMark;
49 this.endMark = endMark;
50 this.type = Object.class;
51 this.twoStepsConstruction = false;
52 this.resolved = true;
53 this.useClassConstructor = null;
54 }
55
56 /**
57 * Tag of this node.
58 * <p>
59 * Every node has a tag assigned. The tag is either local or global.
60 *
61 * @return Tag of this node.
62 */
63 public Tag getTag() {
64 return this.tag;
65 }
66
67 public Mark getEndMark() {
68 return endMark;
69 }
70
71 /**
72 * For error reporting.
73 *
74 * @see class variable 'id' in PyYAML
75 * @return scalar, sequence, mapping
76 */
77 public abstract NodeId getNodeId();
78
79 public Mark getStartMark() {
80 return startMark;
81 }
82
83 public void setTag(Tag tag) {
84 if (tag == null) {
85 throw new NullPointerException("tag in a Node is required.");
86 }
87 this.tag = tag;
88 }
89
90 /**
91 * Two Nodes are never equal.
92 */
93 @Override
94 public final boolean equals(Object obj) {
95 return super.equals(obj);
96 }
97
98 public Class<? extends Object> getType() {
99 return type;
100 }
101
102 public void setType(Class<? extends Object> type) {
103 if (!type.isAssignableFrom(this.type)) {
104 this.type = type;
105 }
106 }
107
108 public void setTwoStepsConstruction(boolean twoStepsConstruction) {
109 this.twoStepsConstruction = twoStepsConstruction;
110 }
111
112 /**
113 * Indicates if this node must be constructed in two steps.
114 * <p>
115 * Two-step construction is required whenever a node is a child (direct or
116 * indirect) of it self. That is, if a recursive structure is build using
117 * anchors and aliases.
118 * </p>
119 * <p>
120 * Set by {@link org.yaml.snakeyaml.composer.Composer}, used during the
121 * construction process.
122 * </p>
123 * <p>
124 * Only relevant during loading.
125 * </p>
126 *
127 * @return <code>true</code> if the node is self referenced.
128 */
129 public boolean isTwoStepsConstruction() {
130 return twoStepsConstruction;
131 }
132
133 @Override
134 public final int hashCode() {
135 return super.hashCode();
136 }
137
138 public boolean useClassConstructor() {
139 if (useClassConstructor == null) {
140 if (isResolved() && !Object.class.equals(type) && !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
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 */
163 public boolean isResolved() {
164 return resolved;
165 }
166 }