View Javadoc

1   ////////////////////////////////////////////////////////////////////////////////
2   // MillScript: an Open Spice interpreter and batch website creation tool
3   // Copyright (C) 2004-2005 Kevin Rogers - Written to address a bug in
4   // MillScript but some inspiration taken from JSpice,
5   // org.openspice.jspice.lib.CastLib,
6   // Copyright (C) 2003 Stephen F. K. Leach
7   //
8   // This file is part of MillScript.
9   //
10  // MillScript is free software; you can redistribute it and/or modify it under
11  // the terms of the GNU General Public License as published by the Free
12  // Software Foundation; either version 2 of the License, or (at your option)
13  // any later version.
14  //
15  // MillScript is distributed in the hope that it will be useful, but WITHOUT
16  // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17  // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
18  // more details.
19  //
20  // You should have received a copy of the GNU General Public License along with
21  // MillScript; if not, write to the Free Software Foundation, Inc., 59 Temple
22  // Place, Suite 330, Boston, MA  02111-1307  USA
23  ////////////////////////////////////////////////////////////////////////////////
24  package org.millscript.millscript.tools;
25  
26  import org.millscript.commons.alert.Alert;
27  import org.millscript.commons.util.IList;
28  import org.millscript.commons.util.IMap;
29  import org.millscript.commons.util.list.IJavaUtilList;
30  import org.millscript.commons.util.map.IJavaUtilMap;
31  import org.millscript.commons.vfs.VEntry;
32  import org.millscript.commons.vfs.VFile;
33  import org.millscript.commons.vfs.VFolder;
34  import org.millscript.millscript.alert.Alerts;
35  import org.millscript.millscript.datatypes.Binding;
36  import org.millscript.millscript.datatypes.DatabaseSource;
37  import org.millscript.millscript.datatypes.Deferred;
38  import org.millscript.millscript.datatypes.Fragment;
39  import org.millscript.millscript.datatypes.Image;
40  import org.millscript.millscript.datatypes.SpiceClass;
41  import org.millscript.millscript.datatypes.SpiceObject;
42  import org.millscript.millscript.datatypes.XmlComment;
43  import org.millscript.millscript.datatypes.XmlElement;
44  import org.millscript.millscript.functions.Function;
45  import org.millscript.millscript.functions.Page;
46  import org.millscript.millscript.functions.SpiceClassConstructorFunction;
47  
48  import java.util.Calendar;
49  import java.util.List;
50  import java.util.Map;
51  import java.util.regex.Pattern;
52  
53  /**
54   * Utility class to handle casting to a specific type from a plain object. All
55   * these casts support deferred objects.
56   *
57   * @see org.millscript.millscript.datatypes.Deferred
58   */
59  public final class CastLibrary {
60  
61      /**
62       * Utility method for generating an Alert with a given message and the
63       * specified object as a culprit.
64       *
65       * @param msg   the alert message
66       * @param obj   the culprit object
67       * @return  a new Alert for the specified message and object
68       */
69      private static Alert oops( final String msg, final Object obj ) {
70          return Alerts.eval( msg, null ).culprit( "object", obj ).mishap();
71      }
72  
73      /**
74       * Utility method for generating an Alert with a given message, explanation
75       * and the specified object as a culprit.
76       *
77       * @param msg   the alert message
78       * @param explanation   the alert message explanation
79       * @param obj   the culprit object
80       * @return  a new Alert for the specified message and object
81       */
82      private static Alert oops( final String msg, final String explanation, final Object obj ) {
83          return Alerts.eval( msg, explanation ).culprit( "object", obj ).mishap();
84      }
85  
86      /**
87       * Casts the supplied Object to a binding for a regular expression match.
88       *
89       * @param   x   an object to cast to a Binding
90       * @return  an Binding cast from the specified object
91       */
92      public static Binding toBinding( final Object x ) {
93          try {
94              if ( x != null ) {
95                  return (Binding)x;
96              }
97              throw oops( "Binding needed", x );
98          } catch ( ClassCastException ex ) {
99              try {
100                 return toBinding( ((Deferred< ? >) x).get() );
101             } catch ( ClassCastException ex2 ) {
102                 throw oops( "Binding needed", x );
103             }
104         }
105     }
106 
107     /**
108      * Casts the supplied Object to a Boolean.
109      *
110      * @param   x   an object to cast to a Boolean
111      * @return  an Boolean cast from the specified object
112      */
113     public static Boolean toBoolean( final Object x ) {
114         try {
115             if ( x != null ) {
116                 return (Boolean)x;
117             }
118             throw oops( "Boolean needed", x );
119         } catch ( ClassCastException ex ) {
120             try {
121                 return toBoolean( ((Deferred< ? >) x).get() );
122             } catch ( ClassCastException ex2 ) {
123                 throw oops( "Boolean needed", x );
124             }
125         }
126     }
127 
128     /**
129      * Casts the supplied Object to a Calendar.
130      *
131      * @param   x   an object to cast to an {@link java.util.Calendar}
132      * @return  a {@link java.util.Calendar} from the top of the stack
133      */
134     public static Calendar toCalendar( final Object x ) {
135         try {
136             if ( x != null ) {
137                 return (Calendar)x;
138             }
139             throw oops( "Date needed", x );
140         } catch ( ClassCastException ex ) {
141             try {
142                 return toCalendar( ((Deferred< ? >) x).get() );
143             } catch ( ClassCastException ex2 ) {
144                 throw oops( "Date needed", x );
145             }
146         }
147     }
148 
149     /**
150      * Casts the supplied Object to a Character.
151      *
152      * @param   x   an object to cast to an {@link Character}
153      * @return  an {@link Character} from the top of the stack
154      */
155     public static Character toCharacter( final Object x ) {
156         try {
157             if ( x != null ) {
158                 return (Character)x;
159             }
160             throw oops( "Character needed", x );
161         } catch ( ClassCastException ex ) {
162             try {
163                 return toCharacter( ((Deferred< ? >) x).get() );
164             } catch ( ClassCastException ex2 ) {
165                 throw oops( "Character needed", x );
166             }
167         }
168     }
169 
170     /**
171      * Casts the supplied Object to a DatabaseSource.
172      *
173      * @param   x   an object to cast to an {@link org.millscript.millscript.datatypes.DatabaseSource}
174      * @return  an {@link org.millscript.millscript.datatypes.DatabaseSource}
175      * from the top of the stack
176      */
177     public static DatabaseSource toDatabaseSource( final Object x ) {
178         try {
179             if ( x != null ) {
180                 return (DatabaseSource)x;
181             }
182             throw oops( "DataSource needed", x );
183         } catch ( ClassCastException ex ) {
184             try {
185                 return toDatabaseSource( ((Deferred< ? >) x).get() );
186             } catch ( ClassCastException ex2 ) {
187                 throw oops( "DataSource needed", x );
188             }
189         }
190     }
191 
192     /**
193      * Casts the supplied Object to a Fragment. This method can be used in
194      * instances where an XmlComment or XmlElement is acceptable.
195      *
196      * @param   x   an object to cast to a {@link Fragment}
197      * @return  a {@link Fragment} cast from the specified obect
198      */
199     public static Fragment toFragment( final Object x ) {
200         try {
201             if ( x != null ) {
202                 return (Fragment)x;
203             }
204             throw oops( "Fragment needed", x );
205         } catch ( ClassCastException ex ) {
206             try {
207                 return toFragment( ((Deferred< ? >) x).get() );
208             } catch ( ClassCastException ex2 ) {
209                 throw oops( "Fragment needed", x );
210             }
211         }
212     }
213 
214     /**
215      * Casts the supplied Object to a Function.
216      *
217      * @param   x   an object to cast to an {@link org.millscript.millscript.functions.Function}
218      * @return  an {@link org.millscript.millscript.functions.Function} from
219      * the top of the stack
220      */
221     public static Function toFunction( final Object x ) {
222         try {
223             if ( x != null ) {
224                 return (Function)x;
225             }
226             throw oops( "Function needed", x );
227         } catch ( ClassCastException ex ) {
228             try {
229                 return toFunction( ((Deferred< ? >) x).get() );
230             } catch ( ClassCastException ex2 ) {
231                 throw oops( "Function needed", x );
232             }
233         }
234     }
235 
236     /**
237      * Casts the supplied Object to a List.
238      *
239      * @param   x   an object to cast to an {@link IList}
240      * @return  an {@link IList} cast from the specified object
241      */
242     @SuppressWarnings( "unchecked" )
243     public static IList toIList( final Object x ) {
244         if ( x == null ) {
245             throw oops( "List needed", x );
246         } else if ( x instanceof IList ) {
247             return (IList) x;
248         } else if ( x instanceof List ) {
249             // TODO - I'm not sure if this is entirely correct... Should this
250             // kind of conversion be moved into a ConvertLibrary utility class?
251             // Or would that just mean the same as ListFactory.make()?
252             return new IJavaUtilList< Object >( (List) x );
253         } else {
254             try {
255                 return toIList( ((Deferred< ? >) x).get() );
256             } catch ( ClassCastException ex2 ) {
257                 throw oops( "List needed", x );
258             }
259         }
260     }
261 
262     /**
263      * Casts the supplied Object to an Image.
264      *
265      * @param   x   an object to cast to an {@link Image}
266      * @return  an {@link Image} from the top of the stack
267      */
268     public static Image toImage( final Object x ) {
269         try {
270             if ( x != null ) {
271                 return (Image)x;
272             }
273             throw oops( "Image needed", x );
274         } catch ( ClassCastException ex ) {
275             try {
276                 return toImage( ((Deferred< ? >) x).get() );
277             } catch ( ClassCastException ex2 ) {
278                 throw oops( "Image needed", x );
279             }
280         }
281     }
282 
283     /**
284      * Casts the supplied Object to a Map.
285      *
286      * @param   x   an object to cast to an {@link Map}
287      * @return  an {@link Map} cast from the specified object
288      */
289     @SuppressWarnings( "unchecked" )
290     public static IMap toIMap( final Object x ) {
291         if ( x == null ) {
292             throw oops( "Map needed", x );
293         } else if ( x instanceof IMap ) {
294             return (IMap) x;
295         } else if ( x instanceof Map ) {
296             // TODO - I'm not sure if this is entirely correct... Should this
297             // kind of conversion be moved into a ConvertLibrary utility class?
298             // Or would that just mean the same as MapFactory.make()?
299             return new IJavaUtilMap< Object, Object >( (Map) x );
300         } else {
301             try {
302                 return toIMap( ((Deferred< ? >) x).get() );
303             } catch ( ClassCastException ex2 ) {
304                 throw oops( "Map needed", x );
305             }
306         }
307     }
308 
309     /**
310      * Casts the supplied Object to an int value.
311      *
312      * @param   x   an object to converted to an int
313      * @return  an int from the specified object cast as an integer
314      */
315     public static int toInt( final Object x ) {
316         try {
317             if ( x != null ) {
318                 return ((Integer)x).intValue();
319             }
320             throw oops( "Integer needed", x );
321         } catch ( ClassCastException ex ) {
322             try {
323                 return toInt( ((Deferred< ? >) x).get() );
324             } catch ( ClassCastException ex2 ) {
325                 throw oops( "Integer needed", x );
326             }
327         }
328     }
329 
330     /**
331      * Casts the supplied Object to an Integer.
332      *
333      * @param   x   an object to cast to an {@link Integer}
334      * @return  an {@link Integer} from the top of the stack
335      */
336     public static Integer toInteger( final Object x ) {
337         try {
338             if ( x != null ) {
339                 return (Integer)x;
340             }
341             throw oops( "Integer needed", x );
342         } catch ( ClassCastException ex ) {
343             try {
344                 return toInteger( ((Deferred< ? >) x).get() );
345             } catch ( ClassCastException ex2 ) {
346                 throw oops( "Integer needed", x );
347             }
348         }
349     }
350 
351     /**
352      * Casts the supplied Object to an Object array.
353      *
354      * @param   x   an object to cast to an object array
355      * @return  an object array cast from the specified object
356      */
357     public static Object[] toObjectArray( final Object x ) {
358         try {
359             if ( x != null ) {
360                 return (Object [])x;
361             }
362             throw oops( "Object[] needed", x );
363         } catch ( ClassCastException ex ) {
364             try {
365                 return toObjectArray( ((Deferred< ? >) x).get() );
366             } catch ( ClassCastException ex2 ) {
367                 throw oops( "Object[] needed", x );
368             }
369         }
370     }
371 
372     /**
373      * Casts the supplied Object to an traditional regular expression Pattern.
374      *
375      * @param   x   an object to cast to a Pattern
376      * @return  an Pattern cast from the specified object
377      */
378     public static Pattern toPattern( final Object x ) {
379         try {
380             if ( x != null ) {
381                 return (Pattern)x;
382             }
383             throw oops( "Traditional regex needed", x );
384         } catch ( ClassCastException ex ) {
385             try {
386                 return toPattern( ((Deferred< ? >) x).get() );
387             } catch ( ClassCastException ex2 ) {
388                 throw oops( "Traditional regex needed", x );
389             }
390         }
391     }
392 
393     /**
394      * Casts the supplied Object to a Spice Class.
395      *
396      * @param   x   an object to cast to an {@link org.millscript.millscript.datatypes.SpiceClass}
397      * @return  an {@link org.millscript.millscript.datatypes.SpiceClass} from
398      * the top of the stack
399      */
400     public static SpiceClass toSpiceClass( final Object x ) {
401         try {
402             if ( x != null ) {
403                 return (SpiceClass)x;
404             }
405             throw oops( "Class needed", "A MillScript class is required", x );
406         } catch ( ClassCastException ex ) {
407             try {
408                 return toSpiceClass( ((Deferred< ? >) x).get() );
409             } catch ( ClassCastException ex2 ) {
410                 throw oops( "Class needed", "A MillScript class is required", x );
411             }
412         }
413     }
414 
415     /**
416      * Casts the supplied Object to a SpiceClassConstructorFunction.
417      *
418      * @param   x   an object to cast to an {@link org.millscript.millscript.functions.SpiceClassConstructorFunction}
419      * @return  an {@link org.millscript.millscript.functions.SpiceClassConstructorFunction} from
420      * the top of the stack
421      */
422     public static SpiceClassConstructorFunction toSpiceClassConstructorFunction( final Object x ) {
423         try {
424             if ( x != null ) {
425                 return (SpiceClassConstructorFunction)x;
426             }
427             throw oops( "Initialiser needed", x );
428         } catch ( ClassCastException ex ) {
429             try {
430                 return toSpiceClassConstructorFunction( ((Deferred< ? >) x).get() );
431             } catch ( ClassCastException ex2 ) {
432                 throw oops( "Initialiser needed", x );
433             }
434         }
435     }
436 
437     /**
438      * Casts the supplied Object to a Spice Object.
439      *
440      * @param   x   an object to cast to an {@link org.millscript.millscript.datatypes.SpiceObject}
441      * @return  an {@link org.millscript.millscript.datatypes.SpiceObject} from
442      * the top of the stack
443      */
444     public static SpiceObject toSpiceObject( final Object x ) {
445         try {
446             if ( x != null ) {
447                 return (SpiceObject)x;
448             }
449             throw oops( "Object needed", "An instance of a MillScript class is required", x );
450         } catch ( ClassCastException ex ) {
451             try {
452                 return toSpiceObject( ((Deferred< ? >) x).get() );
453             } catch ( ClassCastException ex2 ) {
454                 throw oops( "Object needed", "An instance of a MillScript class is required", x );
455             }
456         }
457     }
458 
459     /**
460      * Casts the supplied Object to a String.
461      *
462      * @param   x   an object to cast to an {@link String}
463      * @return  an {@link String} cast from the specified object
464      */
465     public static String toString( final Object x ) {
466         try {
467             if ( x != null ) {
468                 return (String)x;
469             }
470             throw oops( "String needed", x );
471         } catch ( ClassCastException ex ) {
472             try {
473                 return toString( ((Deferred< ? >) x).get() );
474             } catch ( ClassCastException ex2 ) {
475                 throw oops( "String needed", x );
476             }
477         }
478     }
479 
480     /**
481      * Casts the supplied Object to a URL.
482      *
483      * @param   x   an object to cast to a URL
484      * @return  an object array cast from the specified object
485      */
486     public static Page toURL( final Object x ) {
487         try {
488             if ( x != null ) {
489                 return (Page) x;
490             }
491             throw oops( "URL needed", x );
492         } catch ( ClassCastException ex ) {
493             try {
494                 return toURL( ((Deferred< ? >) x).get() );
495             } catch ( ClassCastException ex2 ) {
496                 throw oops( "URL needed", x );
497             }
498         }
499     }
500 
501     /**
502      * Casts the supplied Object to a VEntry.
503      *
504      * @param   x   an object to cast to a {@link VEntry}
505      * @return  a {@link VEntry} cast from the specified obect
506      */
507     public static VEntry toVEntry( final Object x ) {
508         try {
509             if ( x != null ) {
510                 return (VFile)x;
511             }
512             throw oops( "Virtual filesystem entry needed", x );
513         } catch ( ClassCastException ex ) {
514             try {
515                 return toVEntry( ((Deferred< ? >) x).get() );
516             } catch ( ClassCastException ex2 ) {
517                 throw oops( "Virtual filesystem entry needed", x );
518             }
519         }
520     }
521 
522     /**
523      * Casts the supplied Object to a VFile.
524      *
525      * @param   x   an object to cast to a {@link VFile}
526      * @return  a {@link VFile} cast from the specified obect
527      */
528     public static VFile toVFile( final Object x ) {
529         try {
530             if ( x != null ) {
531                 return (VFile)x;
532             }
533             throw oops( "Virtual file needed", x );
534         } catch ( ClassCastException ex ) {
535             try {
536                 return toVFile( ((Deferred< ? >) x).get() );
537             } catch ( ClassCastException ex2 ) {
538                 throw oops( "Virtual file needed", x );
539             }
540         }
541     }
542 
543     /**
544      * Casts the supplied Object to a VFolder.
545      *
546      * @param   x   an object to cast to a {@link VFolder}
547      * @return  a {@link VFolder} cast from the specified obect
548      */
549     public static VFolder toVFolder( final Object x ) {
550         try {
551             if ( x != null ) {
552                 return (VFolder)x;
553             }
554             throw oops( "Virtual folder needed", x );
555         } catch ( ClassCastException ex ) {
556             try {
557                 return toVFolder( ((Deferred< ? >) x).get() );
558             } catch ( ClassCastException ex2 ) {
559                 throw oops( "Virtual folder needed", x );
560             }
561         }
562     }
563 
564     /**
565      * Casts the supplied Object to an XmlComment.
566      *
567      * @param   x   an object to cast to an {@link XmlComment}
568      * @return  an {@link XmlComment} cast from the specified object
569      */
570     public static XmlComment toXmlComment( final Object x ) {
571         try {
572             if ( x != null ) {
573                 return (XmlComment)x;
574             }
575             throw oops( "Comment needed", x );
576         } catch ( ClassCastException ex ) {
577             try {
578                 return toXmlComment( ((Deferred< ? >) x).get() );
579             } catch ( ClassCastException ex2 ) {
580                 throw oops( "Comment needed", x );
581             }
582         }
583     }
584 
585     /**
586      * Casts the supplied Object to an XmlElement.
587      *
588      * @param   x   an object to cast to an {@link XmlElement}
589      * @return  an {@link XmlElement} cast from the specified object
590      */
591     public static XmlElement toXmlElement( final Object x ) {
592         try {
593             if ( x != null ) {
594                 return (XmlElement)x;
595             }
596             throw oops( "Element needed", x );
597         } catch ( ClassCastException ex ) {
598             try {
599                 return toXmlElement( ((Deferred< ? >) x).get() );
600             } catch ( ClassCastException ex2 ) {
601                 throw oops( "Element needed", x );
602             }
603         }
604     }
605 
606     /**
607      * Hidden constructor.
608      */
609     private CastLibrary() {
610     }
611 
612 }