KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > idaremedia > antx > FlexString


1 /**
2  * $Id: FlexString.java 180 2007-03-15 12:56:38Z ssmc $
3  * Copyright 2002-2004 iDare Media, Inc. All rights reserved.
4  *
5  * Originally written by iDare Media, Inc. for release into the public domain. This
6  * library, source form and binary form, is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public License as published by the
8  * Free Software Foundation; either version 2.1 of the License, or (at your option) any
9  * later version.<p>
10  *
11  * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
12  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13  * See the GNU LGPL (GNU Lesser General Public License) for more details.<p>
14  *
15  * You should have received a copy of the GNU Lesser General Public License along with this
16  * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite
17  * 330, Boston, MA 02111-1307 USA. The LGPL can be found online at
18  * http://www.fsf.org/copyleft/lesser.html<p>
19  *
20  * This product has been influenced by several projects within the open-source community.
21  * The JWare developers wish to acknowledge the open-source community's support. For more
22  * information regarding the open-source products used within JWare, please visit the
23  * JWare website.
24  *----------------------------------------------------------------------------------------*
25  * WEBSITE- http://www.jware.info EMAIL- inquiries@jware.info
26  *----------------------------------------------------------------------------------------*
27  **/

28
29 package com.idaremedia.antx;
30
31 import java.util.Locale JavaDoc;
32
33 import org.apache.tools.ant.Project;
34
35 import com.idaremedia.antx.helpers.Tk;
36 import com.idaremedia.antx.parameters.Handling;
37
38 /**
39  * Wrapper for a string value that is determined from a literal, a property's value,
40  * an AntX variable's value, or a reference's string form. A FlexString also encapsulates
41  * many of the common manipulation instructions associated with string comparision so
42  * every component doesn't have to. A FlexString uses a {@linkplain Stringifier} to
43  * convert references to their string forms.
44  * <p>
45  * Usually FlexStrings reflect implementation-details of other classes; however, as
46  * of AntX 0.3, FlexStrings can be exposed as (rather verbose) elements within other
47  * types and tasks.
48  * <p>
49  * A <span class="src">FlexString</span> will try to resolve any property references in
50  * its raw value before using it. This means you can use property variables to hold
51  * the property/reference/variable names themselves like:
52  * <span class="src">property="build.@{build.type}"</span> where
53  * "<span class="src">build.type</span>" is determined by the flex string at
54  * evaluation time.
55  * <p>
56  * Implementation Note: if both the <i>is-property</i> and <i>is-exported</i> options
57  * are activated, the {@linkplain #getValue getValue} method will first read the
58  * property's value and then use that output as the exported property's name. This is
59  * usually what the desired effect is if both these options are checked; otherwise, make
60  * sure only one of these options is checked. Note that a Flexstring cannot be both an
61  * variable property and a reference; these are exclusive definitions.
62  *
63  * @since JWare/AntX 0.1
64  * @author ssmc, &copy;2002-2004 <a HREF="http://www.jware.info">iDare&nbsp;Media,&nbsp;Inc.</a>
65  * @version 0.5
66  * @.safety single
67  * @.group impl,helper
68  * @see Stringifier
69  **/

70
71 public class FlexString extends AssertableProjectComponent implements Cloneable JavaDoc
72 {
73     /**
74      * Creates a new null flex string.
75      **/

76     public FlexString()
77     {
78         m_normalizeLower= true;
79     }
80
81     /**
82      * Creates a new defined flex string.
83      * @param value string's raw value
84      **/

85     public FlexString(String JavaDoc value)
86     {
87         this();
88         set(value);
89     }
90
91     /**
92      * Creates a new property flex string.
93      * @param value string's raw value
94      * @param isP <i>true</i> if value is property name
95      **/

96     public FlexString(String JavaDoc value, boolean isP)
97     {
98         this();
99         set(value);
100         setIsProperty(isP);
101     }
102
103
104     /**
105      * Creates a new flex string that uppercases string to
106      * normalize for case-insensitivity. By default strings
107      * are lower-cased to normalize.
108      * @param uppercaseToNormalize <i>true</i> to use UPPER case
109      **/

110     public FlexString(boolean uppercaseToNormalize)
111     {
112         m_normalizeLower= !uppercaseToNormalize;
113     }
114
115
116     /**
117      * Returns a clone of this flex string.
118      * @since JWare/AntX 0.3
119      **/

120     public Object JavaDoc clone()
121     {
122         try {
123             return super.clone();
124         } catch(CloneNotSupportedException JavaDoc clnx) {
125             throw new Error JavaDoc(uistrs().get(AntX.CLONE_BROKEN_MSGID));
126         }
127     }
128
129
130     /**
131      * Returns <i>true</i> if this flexstring has not been defined.
132      **/

133     public final boolean isUndefined()
134     {
135         return m_actualString==null;
136     }
137
138
139     /**
140      * Sets this flexstring's raw underlying value. All
141      * process instructions are applied to this string.
142      **/

143     public void set(String JavaDoc value)
144     {
145         m_actualString= value;
146     }
147
148
149     /**
150      * Script-facing synonym for {@linkplain #set set()}.
151      * @since JWare/AntX 0.3
152      **/

153     public final void setString(String JavaDoc value)
154     {
155         set(value);
156     }
157
158
159     /**
160      * Returns this flexstring's raw underlying value. Returns
161      * <i>null</i> if never set.
162      **/

163     public String JavaDoc get()
164     {
165         return m_actualString;
166     }
167
168
169     /**
170      * Marks this flexstring's value as a property name. The
171      * property is read by {@linkplain #getValue getValue}.
172      **/

173     public void setIsProperty(boolean b)
174     {
175         m_isProperty= b;
176     }
177
178
179     /**
180      * Returns <i>true</i> if this flexstring's value is
181      * actually a property name. Is <i>false</i> by default.
182      **/

183     public boolean isProperty()
184     {
185         return m_isProperty;
186     }
187
188
189     /**
190      * Marks this flexstring's value as an exported property's name.
191      * The exported property's value is read by {@linkplain #getValue
192      * getValue}.
193      **/

194     public void setIsExported(boolean b)
195     {
196         m_isExported= b;
197     }
198
199
200     /**
201      * Returns <i>true</i> if this flexstring's value is actually
202      * an exported property's name. Is <i>false</i> by default.
203      **/

204     public boolean isExported()
205     {
206         return m_isExported;
207     }
208
209
210     /**
211      * Marks this flexstring's value as a referenced object's name.
212      * The referenced value is read (and stringified) by {@linkplain
213      * #getValue getValue}.
214      **/

215     public void setIsReference(boolean b)
216     {
217         m_isReference= b;
218     }
219
220
221     /**
222      * Returns <i>true</i> if this flexstring's value is actually
223      * an reference object's name. Is <i>false</i> by default.
224      **/

225     public boolean isReference()
226     {
227         return m_isReference;
228     }
229
230
231     /**
232      * Forces this string to consider its underlying value as
233      * a literal. Resets all the source options.
234      * @since JWare/AntX 0.2
235      **/

236     public void setIsLiteral()
237     {
238         m_isProperty = false;
239         m_isReference = false;
240         m_isExported = false;
241     }
242
243
244     /**
245      * Returns <i>true</i> if this flexstring's value is literal;
246      * no other "is-a" options apply.
247      * @since JWare/AntX 0.2
248      **/

249     public boolean isLiteral()
250     {
251         return !m_isProperty && !m_isExported && !m_isReference;
252     }
253
254
255     /**
256      * Tells this string to only use <em>guaranteed</em> string
257      * values. So references are considered <i>null</i> unless
258      * the refer to string-like things (like a String, Enum,
259      * Environment.Variable, etc.) Flex strings are lenient by
260      * default (uses the 'toString()' method to stringify everything).
261      * @since JWare/AntX 0.2
262      **/

263     public void setLenient(boolean lenient)
264     {
265         m_isLenient = lenient;
266     }
267
268
269     /**
270      * Returns <i>true</i> if this flexstring will tolerate any
271      * type of reference; defaulting to the standard 'toString()'
272      * method to stringify it. Defaults <i>true</i>.
273      * @since JWare/AntX 0.2
274      * @see Stringifier
275      **/

276     public boolean isLenient()
277     {
278         return m_isLenient;
279     }
280
281
282     /**
283      * Tells this flexstring to trim whitespace from the
284      * underlying value.
285      **/

286     public void setTrim(boolean b)
287     {
288         m_isTrimmed= b;
289     }
290
291
292     /**
293      * Returns <i>true</i> if this flexstring's value will be
294      * trimmed of whitespace. Is <i>false</i> by default.
295      **/

296     public boolean isTrimmed()
297     {
298         return m_isTrimmed;
299     }
300
301
302     /**
303      * Tells this flexstring to normalize case of underlying
304      * value for case-insensitive comparisions.
305      **/

306     public void setIgnoreCase(boolean ignored)
307     {
308         m_ignoreCase= ignored;
309     }
310
311
312     /**
313      * Returns <i>true</i> if this flexstring will try to
314      * normalize the case of its underlying string. Usually either
315      * lowercases or UPPERCASES the string to normalize.
316      * By default leaves string's case unchanged.
317      **/

318     public boolean isIgnoreCase()
319     {
320         return m_ignoreCase;
321     }
322
323
324     /**
325      * Sets whether a value containing only whitespace is
326      * considered same as an undefined value.
327      * @since JWare/AntX 0.2
328      **/

329     public void setIgnoreWhitespace(boolean ignored)
330     {
331         m_ignoreWS= ignored;
332     }
333
334
335     /**
336      * Script-facing synonym for {@linkplain #setIgnoreWhitespace
337      * setIgnoreWhitespace()}. If the choice is one of "ignore",
338      * "reject", or "balk", then whitespace is considered as
339      * undefined.
340      **/

341     public void setWhitespace(Handling response)
342     {
343         response = Handling.simplifyIgnoreOrNot
344             (response,Handling.ACCEPT);
345
346         setIgnoreWhitespace(Handling.IGNORE.equals(response));
347     }
348
349
350     /**
351      * Returns <i>true</i> if values of all whitespace
352      * should be ignored (as if undefined). Defaults <i>false</i>.
353      * @since JWare/AntX 0.2
354      **/

355     public boolean isIgnoreWhitespace()
356     {
357         return m_ignoreWS;
358     }
359
360
361     /**
362      * Sets a starts-with filter for this flexstring's value. If
363      * the value begins with this string it considered not-set.
364      * @param filter the filtering prefix (<i>null</i> to clear)
365      * @since JWare/AntX 0.3
366      **/

367     public void setIgnorePrefix(String JavaDoc filter)
368     {
369         m_swFilter = filter;
370     }
371
372
373     /**
374      * Returns this flex string's starts-with filter or <i>null</i>
375      * if never set.
376      * @since JWare/AntX 0.3
377      **/

378     public String JavaDoc getPrefixFilter()
379     {
380         return m_swFilter;
381     }
382
383
384     /**
385      * Marks this flexstring's value as a path (to be normalized).
386      * This setting affects the {@linkplain #targetString targetString}
387      * form of this flexstring.
388      * @param isPath <i>true</i> to normalize value like path
389      * @since JWare/AntX 0.4
390      **/

391     public void setIsPath(boolean isPath)
392     {
393         if (isPath) {
394             m_isMask |= ISPATH;
395         } else {
396             m_isMask &= ~ISPATH;
397         }
398     }
399
400
401     /**
402      * Returns <i>true</i> if this value represent a file system path.
403      * @since JWare/AntX 0.4
404      **/

405     public final boolean isPath()
406     {
407         return (m_isMask&ISPATH)==ISPATH;
408     }
409
410
411     /**
412      * Returns this flexstring's processed value. All instructions
413      * are applied to returned value. Returns <i>null</i> if
414      * value never set or the referenced property doesn't exist.
415      * Returns the empty string if trimming is turned on and the
416      * underlying value was all whitespace. If this flexstring is a
417      * property name and <span class="src">P</span> is undefined,
418      * always returns <i>null</i>. This method is implemented as a
419      * template method that first calls: {@linkplain #sourceString
420      * sourceString(&#8230;)}, {@linkplain #targetString targetString(&#8230;)},
421      * and {@linkplain #modifiedString modifiedString(&#8230;)} in order.
422      * @param P [optional] the project from which properties read
423      * @throws IllegalStateException if definition is contradictory
424      **/

425     public String JavaDoc getValue(final Project P)
426     {
427         verify_(!(isExported() && isReference()), "getvalu- exported|reference");
428
429         String JavaDoc value = sourceString(P);
430
431         if (value!=null) {
432             value = targetString(P,value);
433             if (value!=null) {
434                 value = modifiedString(P,value);
435             }
436         }
437
438         return value;
439     }
440
441
442     /**
443      * Same as {@linkplain #getValue(Project) getValue(Project)} but
444      * using this component's assigned project.
445      **/

446     public String JavaDoc getValue()
447     {
448         return getValue(getProject());
449     }
450
451
452     /**
453      * Figure out what to do with generic reference types. Never
454      * returns <i>null</i>. Subclasses can customize here to use
455      * other mechanism to map from object to string. By default
456      * just uses a {@linkplain Stringifier}.
457      * @param o object to stringify (non-null)
458      * @param P [optional] project context
459      * @since JWare/AntX 0.4 (made protected from private)
460      **/

461     protected String JavaDoc stringFrom(Object JavaDoc o, Project P)
462     {
463         return Stringifier.get(isLenient()).stringFrom(o,P);
464     }
465
466
467     /**
468      * Returns the value string that a {@linkplain #getValue getValue}
469      * will use to determine the target value. By default returns
470      * the {@linkplain #get raw string} or the current value
471      * of the raw string if that string was itself a variable.
472      * @param P [optional] project context
473      * @see #get
474      * @since JWare/AntX 0.4
475      **/

476     public String JavaDoc sourceString(Project P)
477     {
478         String JavaDoc value= get();
479
480         if (value==null) {
481             return null;
482         }
483         return Tk.resolveString(P,value,true);//Like if/unless
484
}
485
486
487
488     /**
489      * Returns the value string on which this item's modifiers
490      * should be applied.
491      * @param P [optional] project context
492      * @param source item's {@linkplain #sourceString source} string
493      * @since JWare/AntX 0.4
494      **/

495     public String JavaDoc targetString(Project P, String JavaDoc source)
496     {
497         String JavaDoc value = source;
498
499         if (isProperty()) {
500             value = (P!=null) ? P.getProperty(value) : null;
501             if (value==null) {
502                 return null;
503             }
504         }
505
506         if (isExported()) {
507             value = ExportedProperties.readstring(value);
508             if (value==null) {
509                 return null;
510             }
511         } else if (isReference()) {
512             Object JavaDoc object = P.getReference(value);
513             if (object==null) {
514                 return null;
515             }
516             value = stringFrom(object,P);
517             if (value==null) {
518                 return null;
519             }
520         }
521
522         if (value!=null && isPath()) {
523             value = AntXFixture.fileUtils().normalize(value).getPath();
524         }
525
526         return value;
527     }
528
529
530     /**
531      * Applies all of this string's modifiers to the given string.
532      * Usually called by {@linkplain #getValue getValue} after referenced
533      * fixture item has been retrieved.
534      * @param P [optional] project context
535      * @param value item's {@linkplain #targetString target} string
536      * @since JWare/AntX 0.4
537      **/

538     protected String JavaDoc modifiedString(Project P, String JavaDoc value)
539     {
540         if (isIgnoreWhitespace()) {
541             if (Tk.isWhitespace(value)) {
542                 return null;
543             }
544         }
545
546         if (isTrimmed()) {
547             value= value.trim();
548             if (value.length()==0) {
549                 return value;
550             }
551         }
552
553         if (isIgnoreCase()) {
554             value= m_normalizeLower ?
555                 value.toLowerCase(Locale.US) : value.toUpperCase(Locale.US);
556         }
557
558         if (getPrefixFilter()!=null) {
559             if (value.startsWith(getPrefixFilter())) {
560                 return null;
561             }
562         }
563
564         return value;
565     }
566
567
568     /**
569      * Returns a diagnostics string of this flex value.
570      * @see #toAttributeName
571      **/

572     public String JavaDoc toString()
573     {
574         StringBuffer JavaDoc sb= AntXFixture.newSmallStringBuffer();
575         if (isLiteral()) {
576             sb.append("Literal/");
577         } else if (isReference()) {
578             sb.append("Reference/");
579         } else {
580             if (isProperty()) {
581                 sb.append("Property/");
582             }
583             if (isExported()) {
584                 sb.append("Variable/");
585             }
586         }
587         sb.append("[");
588         sb.append(get());
589         sb.append("]");
590         return sb.toString();
591     }
592
593
594
595     /**
596      * Returns the standard name for the value parameter
597      * of this flex value. Returns one of "value", "property",
598      * "reference", or "variable".
599      * @since JWare/AntX 0.5
600      **/

601     public String JavaDoc toAttributeName()
602     {
603         if (isReference()) {
604             return "reference";
605         }
606         if (isProperty()) {
607             if (isExported()) {
608                 return "variable";
609             }
610             return "property";
611         }
612         return "value";
613    }
614
615
616     private final boolean m_normalizeLower;
617     private String JavaDoc m_actualString;
618     private boolean m_isProperty, m_isExported, m_isReference;
619     private boolean m_ignoreCase, m_ignoreWS, m_isTrimmed;
620     private boolean m_isLenient = true;
621     private String JavaDoc m_swFilter;
622
623     private static final int ISPATH=0x01;
624     private int m_isMask;
625 }
626
627 /* end-of-FlexString.java */
628
Popular Tags