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