KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > tools > ant > types > DataType


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */

18
19 package org.apache.tools.ant.types;
20
21 import java.util.Stack JavaDoc;
22
23 import org.apache.tools.ant.Project;
24 import org.apache.tools.ant.BuildException;
25 import org.apache.tools.ant.ComponentHelper;
26 import org.apache.tools.ant.ProjectComponent;
27 import org.apache.tools.ant.util.IdentityStack;
28
29 /**
30  * Base class for those classes that can appear inside the build file
31  * as stand alone data types.
32  *
33  * <p>This class handles the common description attribute and provides
34  * a default implementation for reference handling and checking for
35  * circular references that is appropriate for types that can not be
36  * nested inside elements of the same type (i.e. &lt;patternset&gt;
37  * but not &lt;path&gt;).</p>
38  *
39  */

40 public abstract class DataType extends ProjectComponent implements Cloneable JavaDoc {
41     // CheckStyle:VisibilityModifier OFF
42

43     /**
44      * Value to the refid attribute.
45      *
46      * @deprecated since 1.7.
47      * The user should not be directly referencing
48      * variable. Please use {@link #getRefid} instead.
49      */

50     protected Reference ref;
51
52     /**
53      * Are we sure we don't hold circular references?
54      *
55      * <p>Subclasses are responsible for setting this value to false
56      * if we'd need to investigate this condition (usually because a
57      * child element has been added that is a subclass of
58      * DataType).</p>
59      *
60      * @deprecated since 1.7.
61      * The user should not be directly referencing
62      * variable. Please use {@link #setChecked} or
63      * {@link #isChecked} instead.
64      */

65     protected boolean checked = true;
66     // CheckStyle:VisibilityModifier ON
67

68     /**
69      * Has the refid attribute of this element been set?
70      * @return true if the refid attribute has been set
71      */

72     public boolean isReference() {
73         return ref != null;
74     }
75
76     /**
77      * Set the value of the refid attribute.
78      *
79      * <p>Subclasses may need to check whether any other attributes
80      * have been set as well or child elements have been created and
81      * thus override this method. if they do the must call
82      * <code>super.setRefid</code>.</p>
83      * @param ref the reference to use
84      */

85     public void setRefid(final Reference ref) {
86         this.ref = ref;
87         checked = false;
88     }
89
90     /**
91      * Gets as descriptive as possible a name used for this datatype instance.
92      * @return <code>String</code> name.
93      */

94     protected String JavaDoc getDataTypeName() {
95         return ComponentHelper.getElementName(getProject(), this, true);
96     }
97
98     /**
99      * Convenience method.
100      * @since Ant 1.7
101      */

102     protected void dieOnCircularReference() {
103         dieOnCircularReference(getProject());
104     }
105
106     /**
107      * Convenience method.
108      * @param p the Ant Project instance against which to resolve references.
109      * @since Ant 1.7
110      */

111     protected void dieOnCircularReference(Project p) {
112         if (checked || !isReference()) {
113             return;
114         }
115         dieOnCircularReference(new IdentityStack(this), p);
116     }
117
118     /**
119      * Check to see whether any DataType we hold references to is
120      * included in the Stack (which holds all DataType instances that
121      * directly or indirectly reference this instance, including this
122      * instance itself).
123      *
124      * <p>If one is included, throw a BuildException created by {@link
125      * #circularReference circularReference}.</p>
126      *
127      * <p>This implementation is appropriate only for a DataType that
128      * cannot hold other DataTypes as children.</p>
129      *
130      * <p>The general contract of this method is that it shouldn't do
131      * anything if {@link #checked <code>checked</code>} is true and
132      * set it to true on exit.</p>
133      * @param stack the stack of references to check.
134      * @param project the project to use to dereference the references.
135      * @throws BuildException on error.
136      */

137     protected void dieOnCircularReference(final Stack JavaDoc stack,
138                                           final Project project)
139         throws BuildException {
140
141         if (checked || !isReference()) {
142             return;
143         }
144         Object JavaDoc o = ref.getReferencedObject(project);
145
146         if (o instanceof DataType) {
147             IdentityStack id = IdentityStack.getInstance(stack);
148
149             if (id.contains(o)) {
150                 throw circularReference();
151             } else {
152                 id.push(o);
153                 ((DataType) o).dieOnCircularReference(id, project);
154                 id.pop();
155             }
156         }
157         checked = true;
158     }
159
160     /**
161      * Allow DataTypes outside org.apache.tools.ant.types to indirectly call
162      * dieOnCircularReference on nested DataTypes.
163      * @param dt the DataType to check.
164      * @param stk the stack of references to check.
165      * @param p the project to use to dereference the references.
166      * @throws BuildException on error.
167      * @since Ant 1.7
168      */

169     public static void invokeCircularReferenceCheck(DataType dt, Stack JavaDoc stk,
170                                                     Project p) {
171         dt.dieOnCircularReference(stk, p);
172     }
173
174     /**
175      * Performs the check for circular references and returns the
176      * referenced object.
177      * @return the dereferenced object.
178      * @throws BuildException if the reference is invalid (circular ref, wrong class, etc).
179      * @since Ant 1.7
180      */

181     protected Object JavaDoc getCheckedRef() {
182         return getCheckedRef(getProject());
183     }
184
185     /**
186      * Performs the check for circular references and returns the
187      * referenced object.
188      * @param p the Ant Project instance against which to resolve references.
189      * @return the dereferenced object.
190      * @throws BuildException if the reference is invalid (circular ref, wrong class, etc).
191      * @since Ant 1.7
192      */

193     protected Object JavaDoc getCheckedRef(Project p) {
194         return getCheckedRef(getClass(), getDataTypeName(), p);
195     }
196
197     /**
198      * Performs the check for circular references and returns the
199      * referenced object.
200      * @param requiredClass the class that this reference should be a subclass of.
201      * @param dataTypeName the name of the datatype that the reference should be
202      * (error message use only).
203      * @return the dereferenced object.
204      * @throws BuildException if the reference is invalid (circular ref, wrong class, etc).
205      */

206     protected Object JavaDoc getCheckedRef(final Class JavaDoc requiredClass,
207                                    final String JavaDoc dataTypeName) {
208         return getCheckedRef(requiredClass, dataTypeName, getProject());
209     }
210
211     /**
212      * Performs the check for circular references and returns the
213      * referenced object. This version allows the fallback Project instance to be specified.
214      * @param requiredClass the class that this reference should be a subclass of.
215      * @param dataTypeName the name of the datatype that the reference should be
216      * (error message use only).
217      * @param project the fallback Project instance for dereferencing.
218      * @return the dereferenced object.
219      * @throws BuildException if the reference is invalid (circular ref, wrong class, etc),
220      * or if <code>project</code> is <code>null</code>.
221      * @since Ant 1.7
222      */

223     protected Object JavaDoc getCheckedRef(final Class JavaDoc requiredClass,
224                                    final String JavaDoc dataTypeName, final Project project) {
225         if (project == null) {
226             throw new BuildException("No Project specified");
227         }
228         dieOnCircularReference(project);
229         Object JavaDoc o = ref.getReferencedObject(project);
230         if (!(requiredClass.isAssignableFrom(o.getClass()))) {
231             log("Class " + o.getClass() + " is not a subclass of " + requiredClass,
232                     Project.MSG_VERBOSE);
233             String JavaDoc msg = ref.getRefId() + " doesn\'t denote a " + dataTypeName;
234             throw new BuildException(msg);
235         }
236         return o;
237     }
238
239     /**
240      * Creates an exception that indicates that refid has to be the
241      * only attribute if it is set.
242      * @return the exception to throw
243      */

244     protected BuildException tooManyAttributes() {
245         return new BuildException("You must not specify more than one "
246             + "attribute when using refid");
247     }
248
249     /**
250      * Creates an exception that indicates that this XML element must
251      * not have child elements if the refid attribute is set.
252      * @return the exception to throw
253      */

254     protected BuildException noChildrenAllowed() {
255         return new BuildException("You must not specify nested elements "
256             + "when using refid");
257     }
258
259     /**
260      * Creates an exception that indicates the user has generated a
261      * loop of data types referencing each other.
262      * @return the exception to throw
263      */

264     protected BuildException circularReference() {
265         return new BuildException("This data type contains a circular "
266             + "reference.");
267     }
268
269     /**
270      * The flag that is used to indicate that circular references have been checked.
271      * @return true if circular references have been checked
272      */

273     protected boolean isChecked() {
274         return checked;
275     }
276
277     /**
278      * Set the flag that is used to indicate that circular references have been checked.
279      * @param checked if true, if circular references have been checked
280      */

281     protected void setChecked(final boolean checked) {
282         this.checked = checked;
283     }
284
285     /**
286      * get the reference set on this object
287      * @return the reference or null
288      */

289     public Reference getRefid() {
290         return ref;
291     }
292
293     /**
294      * check that it is ok to set attributes, i.e that no reference is defined
295      * @since Ant 1.6
296      * @throws BuildException if not allowed
297      */

298     protected void checkAttributesAllowed() {
299         if (isReference()) {
300             throw tooManyAttributes();
301         }
302     }
303
304     /**
305      * check that it is ok to add children, i.e that no reference is defined
306      * @since Ant 1.6
307      * @throws BuildException if not allowed
308      */

309     protected void checkChildrenAllowed() {
310         if (isReference()) {
311             throw noChildrenAllowed();
312         }
313     }
314
315     /**
316      * Basic DataType toString().
317      * @return this DataType formatted as a String.
318      */

319     public String JavaDoc toString() {
320         String JavaDoc d = getDescription();
321         return d == null ? getDataTypeName() : getDataTypeName() + " " + d;
322     }
323
324     /**
325      * @since Ant 1.7
326      * @return a shallow copy of this DataType.
327      * @throws CloneNotSupportedException if there is a problem.
328      */

329     public Object JavaDoc clone() throws CloneNotSupportedException JavaDoc {
330         DataType dt = (DataType) super.clone();
331         dt.setDescription(getDescription());
332         if (getRefid() != null) {
333             dt.setRefid(getRefid());
334         }
335         dt.setChecked(isChecked());
336         return dt;
337     }
338 }
339
340
Popular Tags