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