View Javadoc

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 }