1 /**
2 * Copyright (c) 2008-2012, 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
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 */
62 public Tag getTag() {
63 return this.tag;
64 }
65
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 */
76 public abstract NodeId getNodeId();
77
78 public Mark getStartMark() {
79 return startMark;
80 }
81
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
93 public final boolean equals(Object obj) {
94 return super.equals(obj);
95 }
96
97 public Class<? extends Object> getType() {
98 return type;
99 }
100
101 public void setType(Class<? extends Object> type) {
102 if (!type.isAssignableFrom(this.type)) {
103 this.type = type;
104 }
105 }
106
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 */
128 public boolean isTwoStepsConstruction() {
129 return twoStepsConstruction;
130 }
131
132 @Override
133 public final int hashCode() {
134 return super.hashCode();
135 }
136
137 public boolean useClassConstructor() {
138 if (useClassConstructor == null) {
139 if (isResolved() && !Object.class.equals(type) && !tag.equals(Tag.NULL)) {
140 return true;
141 } else if (tag.isCompatible(getType())) {
142 // the tag is compatible with the runtime class
143 // the tag will be ignored
144 return true;
145 } else {
146 return false;
147 }
148 }
149 return useClassConstructor.booleanValue();
150 }
151
152 public void setUseClassConstructor(Boolean useClassConstructor) {
153 this.useClassConstructor = useClassConstructor;
154 }
155
156 /**
157 * Indicates if the tag was added by
158 * {@link org.yaml.snakeyaml.resolver.Resolver}.
159 *
160 * @return <code>true</code> if the tag of this node was resolved</code>
161 */
162 public boolean isResolved() {
163 return resolved;
164 }
165 }