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.dax;
016:
017: import org.griphyn.vdl.dax.*;
018: import org.griphyn.vdl.classes.LFN;
019: import java.util.Vector;
020: import java.io.Writer;
021: import java.io.IOException;
022:
023: /**
024: * This class captures the logical filename and its linkage. Also,
025: * some static methods allow to use the linkage constants outside
026: * the class.<p>
027: *
028: * <code>Filename</code> extends the <code>Leaf</code> class by adding a
029: * filename, linkage type, temporary pattern, and management attributes.
030: *
031: * @author Jens-S. Vöckler
032: * @author Yong Zhao
033: * @version $Revision: 366 $
034: *
035: * @see Leaf
036: * @see PseudoText
037: */
038: public class Filename extends Leaf implements Cloneable {
039: /**
040: * The filename is the logical name of the file. With the help of
041: * the replica location service (RLS), the physical filename is
042: * determined by the concrete planner.
043: */
044: private String m_filename = null;
045:
046: /**
047: * The linkage type of the logical file aids the linkage process.
048: */
049: private int m_link = LFN.NONE;
050:
051: /**
052: * Marks a filename for registration in a replica catalog. If
053: * marked with false, the replica registration will not take place.
054: * This is useful for transient or non-important results.
055: *
056: * @see #m_dontTransfer
057: * @see #m_temporary
058: */
059: private boolean m_dontRegister = false;
060:
061: /**
062: * Marks a filename for transfer to the result collector. If
063: * marked with false, the file is usually a temporary file, and will
064: * not be transferred to the output collector. Inter-pool transfers
065: * may still happen in multi-pool mode. In optional mode, failure to
066: * transfer due to missing source file will not be fatal.
067: *
068: * @see #m_dontRegister
069: * @see #m_temporary
070: */
071: private int m_dontTransfer = LFN.XFER_MANDATORY;
072:
073: /**
074: * If a filename is marked transient, the higher level planners might
075: * have some notion where to place it, or how to name it. Lower level
076: * planners are not necessarily required to follow this hint.
077: *
078: * @see #m_dontRegister
079: * @see #m_dontTransfer
080: */
081: private String m_temporary = null;
082:
083: /**
084: * If a filename is marked as optional, it's non-existence must not
085: * stop a workflow. Regular files, however, are not optional.
086: */
087: private boolean m_optional = false;
088:
089: /*
090: * Records the VDL variable that was responsible for generating this
091: * logical filename.
092: */
093: private String m_variable = null;
094:
095: /**
096: * The type of the filename, whether it refers to a data, pattern or executable.
097: */
098: private int m_type = LFN.TYPE_DATA;
099:
100: /**
101: * Creates and returns a copy of this object.
102: * @return a new instance.
103: */
104: public Object clone() {
105: return new Filename(this .m_filename, this .m_link,
106: this .m_temporary, this .m_dontRegister,
107: this .m_dontTransfer, this .m_variable, this .m_optional);
108: }
109:
110: /**
111: * Default ctor: create a hollow instance which needs to be filled
112: * with content.
113: */
114: public Filename() {
115: super ();
116: }
117:
118: /**
119: * Default ctor: create an instance with a logical filename. The linkage
120: * defaults to {@link org.griphyn.vdl.classes.LFN#NONE}.
121: *
122: * @param filename is the logical filename to store.
123: */
124: public Filename(String filename) {
125: super ();
126: this .m_filename = filename;
127: this .m_dontRegister = false;
128: this .m_dontTransfer = LFN.XFER_MANDATORY;
129: }
130:
131: /**
132: * ctor: create a file with a name and linkage.
133: *
134: * @param filename is the logical filename to store.
135: * @param link is the linkage of the file to remember.
136: * @throws IllegalArgumentException if the linkage does not match the
137: * legal range.
138: */
139: public Filename(String filename, int link)
140: throws IllegalArgumentException {
141: super ();
142: this .m_filename = filename;
143: this .m_dontRegister = false;
144: this .m_dontTransfer = LFN.XFER_MANDATORY;
145: if (LFN.isInRange(link))
146: this .m_link = link;
147: else
148: throw new IllegalArgumentException();
149: }
150:
151: /**
152: * ctor: create a transient file with a name, linkage and hint.
153: *
154: * @param filename is the logical filename to store.
155: * @param link is the linkage of the file to remember.
156: * @param hint is the transient filename. If null, the file is regular,
157: * if set, the file is assumed to be neither registered not transferred.
158: * @exception IllegalArgumentException if the linkage does not match the
159: * legal range.
160: */
161: public Filename(String filename, int link, String hint)
162: throws IllegalArgumentException {
163: super ();
164: this .m_filename = filename;
165: this .m_temporary = hint;
166: if ((this .m_temporary = hint) == null) {
167: this .m_dontRegister = false;
168: this .m_dontTransfer = LFN.XFER_MANDATORY;
169: } else {
170: this .m_dontRegister = true;
171: this .m_dontTransfer = LFN.XFER_NOT;
172: }
173:
174: if (LFN.isInRange(link))
175: this .m_link = link;
176: else
177: throw new IllegalArgumentException();
178: }
179:
180: /**
181: * ctor: Creates a filename given all specs.
182: *
183: * @param filename is the logical filename to store.
184: * @param link is the linkage of the file to remember.
185: * @param hint is an expression for a temporary filename choice.
186: * @param dontRegister whether to to register with a replica catalog.
187: * @param dontTransfer whether to transfer the file to the collector.
188: * @param variable is the variable that is responsible for this LFN.
189: * @throws IllegalArgumentException if the linkage does not match the
190: * legal range, or the transfer mode does not match its legal range.
191: * @since 1.6
192: */
193: public Filename(String filename, int link, String hint,
194: boolean dontRegister, int dontTransfer, String variable)
195: throws IllegalArgumentException {
196: super ();
197: this .m_filename = filename;
198: this .m_temporary = hint;
199: this .m_dontRegister = dontRegister;
200: this .m_variable = variable;
201:
202: if (LFN.transferInRange(dontTransfer))
203: this .m_dontTransfer = dontTransfer;
204: else
205: throw new IllegalArgumentException("Illegal transfer mode");
206:
207: if (LFN.isInRange(link))
208: this .m_link = link;
209: else
210: throw new IllegalArgumentException("Illegal linkage type");
211: }
212:
213: /**
214: * ctor: Creates a filename given all specs.
215: *
216: * @param filename is the logical filename to store.
217: * @param link is the linkage of the file to remember.
218: * @param hint is an expression for a temporary filename choice.
219: * @param dontRegister whether to to register with a replica catalog.
220: * @param dontTransfer whether to transfer the file to the collector.
221: * @param variable is the variable that is responsible for this LFN.
222: * @param optional records the optionality of a given file.
223: * @throws IllegalArgumentException if the linkage does not match the
224: * legal range, or the transfer mode does not match its legal range.
225: * @since 1.8
226: */
227: public Filename(String filename, int link, String hint,
228: boolean dontRegister, int dontTransfer, String variable,
229: boolean optional) throws IllegalArgumentException {
230: super ();
231: this .m_filename = filename;
232: this .m_temporary = hint;
233: this .m_dontRegister = dontRegister;
234: this .m_variable = variable;
235: this .m_optional = optional;
236:
237: if (LFN.transferInRange(dontTransfer))
238: this .m_dontTransfer = dontTransfer;
239: else
240: throw new IllegalArgumentException("Illegal transfer mode");
241:
242: if (LFN.isInRange(link))
243: this .m_link = link;
244: else
245: throw new IllegalArgumentException("Illegal linkage type");
246: }
247:
248: /**
249: * convenience ctor: create a DAX filename from a VDLx filename.
250: * @param lfn is a VDLx logical filename.
251: */
252: public Filename(LFN lfn) throws IllegalArgumentException {
253: super ();
254: this .m_filename = lfn.getFilename();
255: this .m_link = lfn.getLink();
256: this .m_temporary = lfn.getTemporary();
257: this .m_dontRegister = !lfn.getRegister();
258: this .m_dontTransfer = lfn.getTransfer();
259: this .m_optional = lfn.getOptional();
260: this .m_type = lfn.getType();
261: }
262:
263: // /**
264: // * @deprecated Use the finer control of {@link #getDontRegister}
265: // * and {@link #getDontTransfer}.
266: // *
267: // * @return true, if the current filename instance points to
268: // * a transient (dontRegister, dontTransfer) file. False for all other
269: // * cases.
270: // */
271: // public boolean getIsTransient()
272: // {
273: // return ( this.m_dontRegister && this.m_dontTransfer );
274: // }
275:
276: /**
277: * Accessor: Obtains the linkage type from the object.
278: *
279: * @return the linkage type of the current object. Note that
280: * <code>Filename</code> constructor defaults to no linkage.
281: * @see #setLink(int)
282: */
283: public int getLink() {
284: return this .m_link;
285: }
286:
287: /**
288: * Accessor: Obtains the logical filename for this instance.
289: *
290: * @return the logical filename.
291: * @see #setFilename( java.lang.String )
292: */
293: public String getFilename() {
294: return this .m_filename;
295: }
296:
297: /**
298: * Accessor: Obtains the predicate on registring with a replica
299: * catalog.
300: *
301: * @return false if the file will be registered with a replica catalog.
302: *
303: * @deprecated
304: *
305: * @see #getRegister( )
306: * @since 1.6
307: */
308: public boolean getDontRegister() {
309: return this .m_dontRegister;
310: }
311:
312: /**
313: * Accessor: Obtains the predicate on registring with a replica
314: * catalog.
315: *
316: * @return true if the file will be registered with a replica catalog.
317: *
318: * @see #setRegister( boolean )
319: *
320: * @since 2.1
321: */
322: public boolean getRegister() {
323: return !this .m_dontRegister;
324: }
325:
326: /**
327: * Accessor: Returns the predicate on the type of the LFN
328: *
329: * @return the type of LFN
330: *
331: *
332: * @see #setType( int )
333: * @since 2.1
334: */
335: public int getType() {
336: return this .m_type;
337: }
338:
339: /**
340: * Accessor: Obtains the transfer mode.
341: *
342: * @return false if the file will be tranferred to an output collector.
343: *
344: * @deprecated
345: * @see #getTransfer()
346: *
347: * @since 1.6
348: */
349: public int getDontTransfer() {
350: return this .m_dontTransfer;
351: }
352:
353: /**
354: * Accessor: Obtains the transfering mode.
355: *
356: * @return true if the file will be tranferred to an output collector.
357: *
358: * @see #setTransfer( int )
359: * @since 2.1
360: */
361: public int getTransfer() {
362: return this .m_dontTransfer;
363: }
364:
365: /**
366: * Acessor: Obtains the optionality of the file.
367: *
368: * @return false, if the file is required, or true, if it is optional.
369: * @see #setOptional( boolean )
370: * @since 1.8
371: */
372: public boolean getOptional() {
373: return this .m_optional;
374: }
375:
376: /**
377: * Accessor: Obtains the file name suggestion for a transient file.
378: * If a filename is marked transient, the higher level planners might
379: * have some notion where to place it, or how to name it. Lower level
380: * planners are not necessarily required to follow this hint.
381: *
382: * @return the transient name suggestion of the file. The current
383: * settings will always be returned, regardless of the transiency
384: * state of the file.
385: * @see #setTemporary(String)
386: */
387: public String getTemporary() {
388: return this .m_temporary;
389: }
390:
391: /**
392: * Accessor: Obtains the responsible variable.
393: *
394: * @return the variable responsible for setting this LFN.
395: * @see #setVariable( String )
396: * @since 1.7
397: */
398: public String getVariable() {
399: return this .m_variable;
400: }
401:
402: // /**
403: // * @deprecated Use the finer control of {@link #setDontRegister} and
404: // * {@link #setDontTranfer} for transiency control.
405: // *
406: // * @param transient is the transience state of this filename instance.
407: // * dontRegister and dontTransfer will both be set to the value of
408: // * transient.
409: // *
410: // * @see #getIsTransient()
411: // */
412: // public void setIsTransient( boolean isTransient )
413: // { this.m_dontRegister = this.m_dontTransfer = isTransient; }
414:
415: /**
416: * Accessor: Sets the linkage type.
417: *
418: * @param link is the new linkage type to use. Please note that it
419: * must match the range of legal values.
420: * @throws IllegalArgumentException if the range is beyong legal values.
421: * @see #getLink()
422: */
423: public void setLink(int link) throws IllegalArgumentException {
424: if (LFN.isInRange(link))
425: this .m_link = link;
426: else
427: throw new IllegalArgumentException();
428: }
429:
430: /**
431: * Accessor: Sets the filename
432: *
433: * @param name is the new logical filename.
434: * @see #getFilename()
435: */
436: public void setFilename(String name) {
437: this .m_filename = name;
438: }
439:
440: /**
441: * Accessor: Sets the predicate on registring with a replica catalog.
442: *
443: * @param dontRegister is false, if the file should be registered with a
444: * replica catalog.
445: *
446: * @deprecated
447: *
448: * @see #setRegister()
449: *
450: * @since 1.6
451: */
452: public void setDontRegister(boolean dontRegister) {
453: this .m_dontRegister = dontRegister;
454: }
455:
456: /**
457: * Accessor: Sets the predicate on registring with a replica catalog.
458: *
459: * @param register is true, if the file should be registered with a
460: * replica catalog.
461: *
462: *
463: * @see #getRegister( )
464: * @since 2.1
465: */
466: public void setRegister(boolean register) {
467: this .m_dontRegister = !register;
468: }
469:
470: /**
471: * Accessor: Sets the transfer mode.
472: *
473: * @param dontTransfer is false, if the file should be transferred to
474: * the output collector.
475: * @exception IllegalArgumentException if the transfer mode is outside
476: * its legal range.
477: *
478: * @deprecated
479: *
480: * @see #setTransfer( )
481: * @see org.griphyn.vdl.classes.LFN#XFER_MANDATORY
482: * @see org.griphyn.vdl.classes.LFN#XFER_OPTIONAL
483: * @see org.griphyn.vdl.classes.LFN#XFER_NOT
484: * @since 1.6
485: */
486: public void setDontTransfer(int dontTransfer)
487: throws IllegalArgumentException {
488: if (LFN.transferInRange(dontTransfer))
489: this .m_dontTransfer = dontTransfer;
490: else
491: throw new IllegalArgumentException();
492: }
493:
494: /**
495: * Accessor: Sets the transfer mode.
496: *
497: * @param transfer the transfer flag
498: *
499: * @exception IllegalArgumentException if the transfer mode is outside
500: * its legal range.
501: * @see #getTransfer( )
502: * @see org.griphyn.vdl.classes.LFN#XFER_MANDATORY
503: * @see org.griphyn.vdl.classes.LFN#XFER_OPTIONAL
504: * @see org.griphyn.vdl.classes.LFN#XFER_NOT
505: *
506: * @since 2.1
507: */
508: public void setTransfer(int transfer)
509: throws IllegalArgumentException {
510: if (LFN.transferInRange(transfer))
511: this .m_dontTransfer = transfer;
512: else
513: throw new IllegalArgumentException();
514: }
515:
516: /**
517: * Acessor: Sets the optionality of the file.
518: *
519: * @param optional false, if the file is required, or true, if it is
520: * optional.
521: * @see #getOptional()
522: * @since 1.8
523: */
524: public void setOptional(boolean optional) {
525: this .m_optional = optional;
526: }
527:
528: /**
529: * Accessor: Sets the predicate on the type of the LFN
530: *
531: * @param type the type of LFN
532: *
533: *
534: * @see #getType( )
535: *
536: * @since 2.1
537: */
538: public void setType(int type) {
539: if (LFN.typeInRange(type)) {
540: this .m_type = type;
541: } else {
542: throw new IllegalArgumentException("Invalid LFN type "
543: + type);
544: }
545: }
546:
547: /**
548: * Accessor: Sets a file name suggestion for a transient file. If a
549: * filename is marked transient, the higher level planners might have
550: * some notion where to place it, or how to name it. Lower level
551: * planners are not necessarily required to follow this hint.
552: *
553: * @param name is a transient name suggestion for this filename instance.
554: * No automatic marking of transiency will be done!
555: * @see #getTemporary()
556: */
557: public void setTemporary(String name) {
558: this .m_temporary = name;
559: }
560:
561: /**
562: * Accessor: Sets the responsible variable.
563: *
564: * @param variable the variable responsible for setting this LFN.
565: * @see #getVariable()
566: * @since 1.7
567: */
568: public void setVariable(String variable) {
569: this .m_variable = variable;
570: }
571:
572: /**
573: * Convenience function to call the static test, if a filename can
574: * use the abbreviated notation.
575: *
576: * @return true, if abbreviatable notation is possible.
577: * @see org.griphyn.vdl.classes.LFN#abbreviatable( String, boolean, int, boolean )
578: */
579: private boolean abbreviatable() {
580: return LFN.abbreviatable(this .m_temporary, this .m_dontRegister,
581: this .m_dontTransfer, this .m_optional);
582: }
583:
584: /**
585: * Convert the logical filename and linkage into something human
586: * readable. The output is also slightly nudged towards machine
587: * parsability. This method overwrites the inherited methods since it
588: * appears to be faster to do it this way.<p>
589: *
590: * @return a textual description of the element and its attributes.
591: */
592: public String toString() {
593: // slight over-allocation is without harm
594: StringBuffer result = new StringBuffer(
595: this .m_filename.length() + 32);
596:
597: result.append("@{");
598: result.append(LFN.toString(this .m_link));
599: result.append(":\"");
600: result.append(escape(this .m_filename));
601: if (this .m_temporary != null) {
602: result.append("\":\"");
603: result.append(escape(this .m_temporary));
604: }
605: result.append('"');
606:
607: if (!abbreviatable()) {
608: result.append('|');
609: if (this .m_optional)
610: result.append('o');
611: if (!this .m_dontRegister)
612: result.append('r');
613: if (this .m_dontTransfer != LFN.XFER_NOT)
614: result
615: .append(this .m_dontTransfer == LFN.XFER_OPTIONAL ? 'T'
616: : 't');
617: }
618: result.append('}');
619: return result.toString();
620: }
621:
622: /**
623: * Converts the active state into something meant for human consumption.
624: * The method will be called when recursively traversing the instance
625: * tree.
626: *
627: * @param stream is a stream opened and ready for writing. This can also
628: * be a string stream for efficient output.
629: */
630: public void toString(Writer stream) throws IOException {
631: stream.write("@{");
632: stream.write(LFN.toString(this .m_link));
633: stream.write(":\"");
634: stream.write(escape(this .m_filename)); // risk NullPointerException
635: if (this .m_temporary != null) {
636: stream.write("\":\"");
637: stream.write(escape(this .m_temporary));
638: }
639: stream.write('"');
640:
641: if (!abbreviatable()) {
642: stream.write('|');
643: if (this .m_optional)
644: stream.write('o');
645: if (!this .m_dontRegister)
646: stream.write('r');
647: if (this .m_dontTransfer != LFN.XFER_NOT)
648: stream
649: .write(this .m_dontTransfer == LFN.XFER_OPTIONAL ? 'T'
650: : 't');
651:
652: }
653:
654: stream.write("}");
655: }
656:
657: /**
658: * Dumps the state of the filename as PlainFilenameType or
659: * StdioFilenameType without the transiency information.
660: *
661: * @param indent is a <code>String</code> of spaces used for pretty
662: * printing. The initial amount of spaces should be an empty string.
663: * @param namespace is the XML schema namespace prefix. If neither
664: * empty nor null, each element will be prefixed with this prefix,
665: * and the root element will map the XML namespace.
666: * @param flag 0x01: also dump the linkage information, 0x02: also
667: * dump optionality
668: *
669: * @return a String which contains the state of the current class
670: * and its siblings using XML. Note that these strings might become large. */
671: public String shortXML(String indent, String namespace, int flag) {
672: // slight over-allocation is without harm
673: StringBuffer result = new StringBuffer(
674: this .m_filename.length() + 32);
675:
676: if (indent != null)
677: result.append(indent);
678: result.append('<');
679: if (namespace != null && namespace.length() > 0)
680: result.append(namespace).append(':');
681: result.append("filename file=\"").append(
682: quote(this .m_filename, true));
683: if (this .m_variable != null && this .m_variable.length() > 0)
684: result.append("\" varname=\"").append(
685: quote(this .m_variable, true));
686: if ((flag & 0x01) == 0x01)
687: result.append("\" link=\"").append(
688: LFN.toString(this .m_link));
689: if ((flag & 0x02) == 0x02 && this .m_optional)
690: result.append("\" optional=\"true\"");
691: result.append("\"/>");
692:
693: return result.toString();
694: }
695:
696: /**
697: * Dumps the state of the current element as XML output. This method
698: * converts the data into pretty-printed XML output meant for machine
699: * consumption. This method overwrites the inherited methods since it
700: * appears to be faster to do it this way.<p>
701: *
702: * @param indent is a <code>String</code> of spaces used for pretty
703: * printing. The initial amount of spaces should be an empty string.
704: * @param namespace is the XML schema namespace prefix. If neither
705: * empty nor null, each element will be prefixed with this prefix,
706: * and the root element will map the XML namespace.
707: *
708: * @return a String which contains the state of the current class
709: * and its siblings using XML. Note that these strings might become large.
710: */
711: public String toXML(String indent, String namespace) {
712: // slight over-allocation is without harm
713: StringBuffer result = new StringBuffer(
714: this .m_filename.length() + 128);
715:
716: if (indent != null)
717: result.append(indent);
718: result.append('<');
719: if (namespace != null && namespace.length() > 0)
720: result.append(namespace).append(':');
721: result.append("filename file=\"").append(
722: quote(this .m_filename, true));
723: result.append("\" link=\"").append(LFN.toString(this .m_link));
724: result.append("\" register=\"").append(
725: Boolean.toString(this .getRegister()));
726: result.append("\" transfer=\"").append(
727: LFN.transferString(this .getTransfer()));
728: result.append("\" optional=\"").append(
729: Boolean.toString(this .m_optional));
730: result.append("\" type=\"").append(
731: LFN.typeString(this .getType()));
732:
733: if (this .m_temporary != null) {
734: result.append("\" temporaryHint=\"");
735: result.append(quote(this .m_temporary, true));
736: }
737: result.append("\"/>");
738:
739: return result.toString();
740: }
741:
742: /**
743: * Dumps the state of the filename as PlainFilenameType or
744: * StdioFilenameType without the transiency information.
745: *
746: * @param stream is a stream opened and ready for writing. This can also
747: * be a string stream for efficient output.
748: * @param indent is a <code>String</code> of spaces used for pretty
749: * printing. The initial amount of spaces should be an empty string.
750: * The parameter is used internally for the recursive traversal.
751: * @param namespace is the XML schema namespace prefix. If neither
752: * empty nor null, each element will be prefixed with this prefix,
753: * and the root element will map the XML namespace.
754: * @param flag if 0x01, dump linkage, if 0x02 is set, dump optionality.
755: * @exception IOException if something fishy happens to the stream.
756: */
757: public void shortXML(Writer stream, String indent,
758: String namespace, int flag) throws IOException {
759: // if ( indent != null && indent.length() > 0 ) stream.write( indent );
760: stream.write('<');
761: if (namespace != null && namespace.length() > 0) {
762: stream.write(namespace);
763: stream.write(':');
764: }
765: stream.write("filename");
766: writeAttribute(stream, " file=\"", this .m_filename);
767: if (this .m_variable != null && this .m_variable.length() > 0)
768: writeAttribute(stream, " varname=\"", this .m_variable);
769: if ((flag & 0x01) == 0x01)
770: writeAttribute(stream, " link=\"", LFN
771: .toString(this .m_link));
772: if ((flag & 0x02) == 0x02 && this .m_optional)
773: stream.write(" optional=\"true\"");
774: stream.write("/>");
775: }
776:
777: /**
778: * Dump the state of the current element as XML output. This function
779: * traverses all sibling classes as necessary, and converts the data
780: * into pretty-printed XML output. The stream interface should be able
781: * to handle large output efficiently.
782: *
783: * @param stream is a stream opened and ready for writing. This can also
784: * be a string stream for efficient output.
785: * @param indent is a <code>String</code> of spaces used for pretty
786: * printing. The initial amount of spaces should be an empty string.
787: * The parameter is used internally for the recursive traversal.
788: * @param namespace is the XML schema namespace prefix. If neither
789: * empty nor null, each element will be prefixed with this prefix,
790: * and the root element will map the XML namespace.
791: * @exception IOException if something fishy happens to the stream.
792: */
793: public void toXML(Writer stream, String indent, String namespace)
794: throws IOException {
795: // if ( indent != null && indent.length() > 0 ) stream.write( indent );
796: stream.write('<');
797: if (namespace != null && namespace.length() > 0) {
798: stream.write(namespace);
799: stream.write(':');
800: }
801: stream.write("filename");
802: writeAttribute(stream, " varname=\"", this .m_variable);
803: writeAttribute(stream, " file=\"", this .m_filename);
804: writeAttribute(stream, " link=\"", LFN.toString(this .m_link));
805: writeAttribute(stream, " register=\"", Boolean.toString(this
806: .getRegister()));
807: writeAttribute(stream, " dontTransfer=\"", LFN
808: .transferString(this .getTransfer()));
809: writeAttribute(stream, " optional=\"", Boolean
810: .toString(this .m_optional));
811: writeAttribute(stream, " type=\"", LFN.typeString(this
812: .getType()));
813:
814: if (this .m_temporary != null)
815: writeAttribute(stream, " temporaryHint=\"",
816: this .m_temporary);
817:
818: stream.write("/>");
819: }
820:
821: }
|