001: /*
002: * This file or a portion of this file is licensed under the terms of
003: * the Globus Toolkit Public License, found in file ../GTPL, or at
004: * http://www.globus.org/toolkit/download/license.html. This notice must
005: * appear in redistributions of this file, with or without modification.
006: *
007: * Redistributions of this Software, with or without modification, must
008: * reproduce the GTPL in: (1) the Software, or (2) the Documentation or
009: * some other similar material which is provided with the Software (if
010: * any).
011: *
012: * Copyright 1999-2004 University of Chicago and The University of
013: * Southern California. All rights reserved.
014: */
015: package org.griphyn.vdl.classes;
016:
017: import org.griphyn.vdl.classes.*;
018: import java.util.*;
019: import java.io.IOException;
020: import java.io.Writer;
021: import java.io.Serializable;
022:
023: /**
024: * This class defines the formal arguments to a <code>Transformation</code>.
025: *
026: * @author Jens-S. Vöckler
027: * @author Yong Zhao
028: * @version $Revision: 50 $
029: *
030: * @see Transformation
031: */
032: public class Declare extends VDL implements Serializable {
033: /**
034: * Each formal argument has a name to which it is bound.
035: */
036: private String m_name;
037:
038: /**
039: * Each formal argument has a specific type. There are currently
040: * only the type of {@link Scalar} and {@link List}.
041: */
042: private int m_containerType = Value.SCALAR;
043:
044: /**
045: * For linking the DAG we need to know if the argument is passed into
046: * the transformation, produced by the transformation, or has some
047: * other behavior.
048: */
049: private int m_link = LFN.NONE;
050:
051: /**
052: * The default value of a formal argument is optional. The notion of a
053: * default value is taken from C++.
054: */
055: private Value m_value;
056:
057: /**
058: * Default ctor: needed for JDO
059: */
060: public Declare() {
061: super ();
062: }
063:
064: /**
065: * ctor: Construct a new formal argument with a binding and default
066: * container type.
067: *
068: * @param name is the binding.
069: * @param ct is the container type, the type of the argument.
070: * @throws IllegalArgumentException if the container type is outside
071: * the legal range [{@link Value#SCALAR}, {@link Value#LIST}].
072: */
073: public Declare(String name, int ct) throws IllegalArgumentException {
074: super ();
075: this .m_name = name;
076: if (Value.isInRange(ct))
077: this .m_containerType = ct;
078: else
079: throw new IllegalArgumentException(
080: "container type outside legal range");
081: }
082:
083: /**
084: * ctor: Construct a new formal argument with a binding and default
085: * container type, as well as a linkage for the argument.
086: *
087: * @param name is the binding.
088: * @param ct is the container type, the type of the argument.
089: * @param link is the linkage type for the argument.
090: * @throws IllegalArgumentException if the container type is outside
091: * the legal range [{@link Value#SCALAR}, {@link Value#LIST}], or
092: * the linkage is outside [{@link LFN#NONE}, {@link LFN#INOUT}].
093: */
094: public Declare(String name, int ct, int link)
095: throws IllegalArgumentException {
096: super ();
097: this .m_name = name;
098: if (Value.isInRange(ct))
099: this .m_containerType = ct;
100: else
101: throw new IllegalArgumentException(
102: "container type outside legal range");
103:
104: if (LFN.isInRange(link))
105: this .m_link = link;
106: else
107: throw new IllegalArgumentException(
108: "linkage type outside legal range");
109: }
110:
111: /**
112: * ctor: Construct a new formal argument with a binding and default
113: * value. The container type will be determined from the default value.
114: *
115: * @param name is the binding.
116: * @param value is either a {@link Scalar} or {@link List} value.
117: */
118: public Declare(String name, Value value) {
119: super ();
120: this .m_name = name;
121: this .m_value = value;
122: this .m_containerType = value.getContainerType();
123: }
124:
125: /**
126: * ctor: Construct a new formal argument with a binding and default
127: * value. The container type will be determined from the default value.
128: * The linkage is set separately.
129: *
130: * @param name is the binding.
131: * @param value is either a {@link Scalar} or {@link List} value.
132: * @param link is the linkage of the value for DAG creation.
133: * @throws IllegalArgumentException if the linkage is outside
134: * [{@link LFN#NONE}, {@link LFN#INOUT}].
135: */
136: public Declare(String name, Value value, int link)
137: throws IllegalArgumentException {
138: super ();
139: this .m_name = name;
140: this .m_value = value;
141: this .m_containerType = value.getContainerType();
142: if (LFN.isInRange(link))
143: this .m_link = link;
144: else
145: throw new IllegalArgumentException(
146: "linkage type outside legal range");
147: }
148:
149: /**
150: * Accessor: Obtains the optional default value for the parameter.
151: *
152: * @return the default as {@link Scalar} or {@link List}, or null,
153: * if not default value was registered.
154: * @see #setValue(Value)
155: */
156: public Value getValue() {
157: return this .m_value;
158: }
159:
160: /**
161: * Accessor: Obtains the bound name of the formal argument.
162: *
163: * @return the name by which an actual arguments in a {@link Derivation}
164: * can refer to this formal argument.
165: * @see #setName( java.lang.String )
166: */
167: public String getName() {
168: return this .m_name;
169: }
170:
171: /**
172: * Accessor: Obtains the linkage type of the formal argument.
173: *
174: * @return the linkage as an integer.
175: * @see #setLink(int)
176: * @see LFN#NONE
177: * @see LFN#INPUT
178: * @see LFN#OUTPUT
179: * @see LFN#INOUT
180: */
181: public int getLink() {
182: return this .m_link;
183: }
184:
185: /**
186: * Accessor: Obtains the container type. Note that the registered
187: * container type will be taken in case there is no default value.
188: * Otherwise the container type of the default value will be taken.
189: *
190: * @return the container type of the formal argument.
191: * @see #setContainerType(int)
192: * @see Value#SCALAR
193: * @see Value#LIST
194: */
195: public int getContainerType() {
196: return (m_value != null) ? m_value.getContainerType()
197: : m_containerType;
198: }
199:
200: /**
201: * Accessor: Establishes a new name with this formal argument to bind
202: * to by an actual argument. FIXME: Note that no checks will be done
203: * concerning the uniqueness of the new name.
204: *
205: * @param name is the new binding.
206: * @see #getName()
207: */
208: public void setName(String name) {
209: this .m_name = name;
210: }
211:
212: /**
213: * Accessor: Sets a new linkage type for the formal argument.
214: *
215: * @param link is the new linkage type from {@link LFN}.
216: * @throws IllegalArgumentException, if the argument is outside
217: * the valid range.
218: * @see #getLink()
219: */
220: public void setLink(int link) throws IllegalArgumentException {
221: if (!LFN.isInRange(link))
222: throw new IllegalArgumentException();
223: this .m_link = link;
224: }
225:
226: /**
227: * Accessor: Sets a new container type for the formal argument. If
228: * a default value is known, the new container type must match the
229: * default value's container type.
230: *
231: * @param containerType is the new integer describing a container type.
232: * @throws IllegalArgumentException if the container type is neither
233: * {@link Value#SCALAR} nor {@link Value#LIST}.
234: * @see #getContainerType()
235: */
236: public void setContainerType(int containerType)
237: throws IllegalArgumentException {
238: if (m_value == null) {
239: // no default value known, need to set container type
240: if (Value.isInRange(containerType))
241: this .m_containerType = containerType;
242: else
243: throw new IllegalArgumentException(
244: "container type outside legal range");
245: } else {
246: // there is a default value, new type must match default
247: if (m_value.getContainerType() != containerType)
248: throw new IllegalArgumentException(
249: "new container type does not match container type of default value");
250: }
251: }
252:
253: /**
254: * Accessor: Sets or overwrites the optional default value of a formal
255: * argument. FIXME: A value of null should be usable to kill a default
256: * value. The new default must match the container type.
257: *
258: * @param value is the new default value.
259: * @throws IllegalArgumentException if the container type of the new
260: * value and of the registered container type for the parameter don't
261: * match.
262: * @see #getValue()
263: */
264: public void setValue(Value value) throws IllegalArgumentException {
265: if (value.getContainerType() == this .m_containerType)
266: this .m_value = value;
267: else
268: // container types do not match
269: throw new IllegalArgumentException(
270: "container type of new value does not match declared container type");
271: }
272:
273: /**
274: * Dumps the content of the use element into a string for human consumption.
275: *
276: * @return a textual description of the element and its attributes.
277: * Be advised that these strings might become large.
278: */
279: public String toString() {
280: String value = this .m_value == null ? "" : this .m_value
281: .toString();
282: StringBuffer result = new StringBuffer(12
283: + this .m_name.length() + value.length());
284:
285: result.append(LFN.toString(this .m_link));
286: result.append(' ');
287: result.append(this .m_name);
288: if (this .m_containerType == Value.LIST)
289: result.append("[]");
290:
291: if (this .m_value != null) {
292: result.append('=');
293: result.append(value);
294: }
295: return result.toString();
296: }
297:
298: /**
299: * Dumps the content of the declaration into a string for human
300: * consumption.
301: *
302: * @param stream is a stream opened and ready for writing. This can also
303: * be a string stream for efficient output.
304: * @exception IOException if something fishy happens to the stream.
305: */
306: public void toString(Writer stream) throws IOException {
307: stream.write(LFN.toString(this .m_link));
308: stream.write(' ');
309: stream.write(escape(this .m_name));
310: if (this .m_containerType == Value.LIST)
311: stream.write("[]");
312:
313: if (this .m_value != null) {
314: stream.write('=');
315: this .m_value.toString(stream);
316: }
317: }
318:
319: /**
320: * Dump the state of the current element as XML output. This function
321: * traverses all sibling classes as necessary, and converts the data
322: * into pretty-printed XML output. The stream interface should be able
323: * to handle large output efficiently, if you use a buffered writer.
324: *
325: * @param stream is a stream opened and ready for writing. This can also
326: * be a string stream for efficient output.
327: * @param indent is a <code>String</code> of spaces used for pretty
328: * printing. The initial amount of spaces should be an empty string.
329: * The parameter is used internally for the recursive traversal.
330: * If a <code>null</code> value is specified, no indentation nor
331: * linefeeds will be generated.
332: * @param namespace is the XML schema namespace prefix. If neither
333: * empty nor null, each element will be prefixed with this prefix,
334: * and the root element will map the XML namespace.
335: * @exception IOException if something fishy happens to the stream.
336: */
337: public void toXML(Writer stream, String indent, String namespace)
338: throws IOException {
339: String newline = System.getProperty("line.separator", "\r\n");
340: String tag = (namespace != null && namespace.length() > 0) ? namespace
341: + ":declare"
342: : "declare";
343:
344: if (indent != null && indent.length() > 0)
345: stream.write(indent);
346: stream.write('<');
347: stream.write(tag);
348:
349: writeAttribute(stream, " name=\"", this .m_name); // null-safe
350: if (LFN.isInRange(this .m_link))
351: writeAttribute(stream, " link=\"", LFN
352: .toString(this .m_link));
353:
354: if (this .m_containerType == Value.LIST) {
355: stream.write(" container=\"list\"");
356: } else if (this .m_containerType == Value.SCALAR) {
357: stream.write(" container=\"scalar\"");
358: }
359:
360: if (this .m_value == null) {
361: // no default value
362: stream.write("/>");
363: } else {
364: // there is a default value
365: String newindent = indent == null ? null : indent + " ";
366: stream.write('>');
367: if (indent != null)
368: stream.write(newline);
369:
370: // dump content
371: this .m_value.toXML(stream, newindent, namespace);
372:
373: // write close tag
374: if (indent != null && indent.length() > 0)
375: stream.write(indent);
376: stream.write("</");
377: stream.write(tag);
378: stream.write('>');
379: }
380: if (indent != null)
381: stream.write(newline);
382: }
383: }
|