View Javadoc

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 }