View Javadoc

1   ////////////////////////////////////////////////////////////////////////////////
2   // MillScript: an Open Spice interpreter and batch website creation tool
3   // Some portions copyright (C) 2001-2004 Open World Ltd
4   // Copyright (C) 2005 Kevin Rogers
5   //
6   // This file is part of MillScript.
7   //
8   // MillScript is free software; you can redistribute it and/or modify it under
9   // the terms of the GNU General Public License as published by the Free
10  // Software Foundation; either version 2 of the License, or (at your option)
11  // any later version.
12  //
13  // MillScript is distributed in the hope that it will be useful, but WITHOUT
14  // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15  // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
16  // more details.
17  //
18  // You should have received a copy of the GNU General Public License along with
19  // MillScript; if not, write to the Free Software Foundation, Inc., 59 Temple
20  // Place, Suite 330, Boston, MA  02111-1307  USA
21  ////////////////////////////////////////////////////////////////////////////////
22  package org.millscript.millscript.functions;
23  
24  import org.millscript.commons.util.IList;
25  import org.millscript.commons.util.ListIterator;
26  import org.millscript.millscript.vm.Package;
27  
28  import java.util.Set;
29  import java.util.TreeSet;
30  
31  /**
32   * This class provides the basic methods required for a function generating
33   * files in the script output.
34   */
35  public abstract class AbstractOutputFileFunction extends AbstractOutputFunction {
36  
37      /**
38       * The set of previously written pages. This is used to avoid writing
39       * duplicate pages into the output.
40       */
41      // TODO - Revisit this to use MillScript-Util
42      private static final Set< String > STEMS = new TreeSet< String >();
43  
44      /**
45       * Constructs a new abstract output file function for the specified
46       * package.
47       *
48       * @param pack  the package this function belongs to
49       */
50      protected AbstractOutputFileFunction( final Package pack ) {
51          super( pack );
52      }
53  
54      /**
55       * Adds the specified stem as a unique page of script output. This method
56       * will return <code>true</code> if the stem doesn't already exist in the
57       * script output. Subsequent calls to this method with the same stem will
58       * return <code>false</code>.
59       *
60       * @param stem  the new stem to try and add to the script output
61       * @return  <code>true</code> if the stem does not already exist and
62       * <code>false</code> otherwise
63       */
64      public static final boolean addNewPage( final String stem ) {
65          return STEMS.add( stem );
66      }
67  
68      /**
69       * Returns the default extension for this type of file.
70       *
71       * @return  the default extension for this type of file as a String
72       */
73      public abstract String getDefaultExtension();
74  
75      /**
76       * Returns a new Page for a file with the specified name and default extension
77       * for this function, to be made in the current working output folder.
78       *
79       * @param name  the new file name
80       * @return  a Page for the specified output file
81       */
82      public final Page newPage( final String name ) {
83          return newPage( name, this.getDefaultExtension() );
84      }
85  
86      /**
87       * Returns a new Page for a file with the specified name and extension, to
88       * be made in the current working output folder.
89       *
90       * @param name  the new file name
91       * @param extn  the new file name extension
92       * @return  a Page for the specified output file
93       */
94      public final Page newPage( final String name, final String extn ) {
95          return newPage( this.getCurrentWorkingFolderList(), name, extn );
96      }
97  
98      /**
99       * Returns a new Page for a file with the specified name and extension, to
100      * be made in the specified folder. If a page has already been made for the
101      * specified file, a new unique filename will be found and a Page object
102      * returned for this new filename.
103      *
104      * @param folder    the folder for the new file
105      * @param name  the new file name
106      * @param extn  the new file name extension
107      * @return  a Page for the specified output file
108      */
109     public final Page newPage( final IList folder, final String name, final String extn ) {
110         final String path = squash( folder );
111         String fname = (
112             name +
113             "." +
114             extn
115         );
116         String suggested = path + fname;
117         if ( STEMS.add( suggested ) ) {
118             return new Page( suggested, this.getWorkingFolder( folder ).getVFile( fname ) );
119         } else {
120             return newUniquePage( path, folder, name, extn );
121         }
122     }
123 
124     /**
125      * Returns a new unique Page for a file based on the specified path,
126      * folder, filename and extension.
127      *
128      * @param path  the path the new file should be made in, relative to the
129      * output folder
130      * @param folder    the output folder the file should be made in
131      * @param name  the name to base the unique filename on
132      * @param extn  the extension for the resulting file
133      * @return  a new unique Page based on the specified values
134      */
135     private Page newUniquePage( final String path, final IList folder, final String name, final String extn ) {
136         for ( int k = 1;; k++ ) {
137             String fname = (
138                 name +
139                 Integer.toString( k ) +
140                 "." +
141                 extn
142             );
143             String suggested = path + fname;
144             if ( STEMS.add( suggested ) ) {
145                 return new Page( suggested, this.getWorkingFolder( folder ).getVFile( fname ) );
146             }
147         }
148     }
149 
150     /**
151      * Returns the String representation of the specified output folder. This
152      * is done by concatenating each item in the list with a <code>/</code>.
153      *
154      * @param folder    the folder to squash
155      * @return  a String representation of the specified folder
156      */
157     private String squash( final IList folder ) {
158         StringBuffer sofar = new StringBuffer( "/" );
159         ListIterator it = folder.iterator( true );
160         while ( it.hasNext() ) {
161             sofar.append( (String)it.nextValue() );
162             sofar.append( '/' );
163         }
164         return sofar.toString();
165     }
166 
167     /**
168      * Returns a Page for the specified object. If the object is already a Page
169      * it will be returned, otherwise the object is considered to be a
170      * filename.
171      *
172      * @param obj   the object to convert to a Page
173      * @return  a Page for the specified object
174      */
175     public final Page toPage( final Object obj ) {
176         if ( obj instanceof Page ) {
177             return (Page) obj;
178         } else {
179             String f = obj.toString();
180             int n = f.lastIndexOf( '.' );
181             if ( n < 0 ) {
182                 return newPage( f );
183             } else {
184                 return (
185                     newPage(
186                         f.substring( 0, n ),
187                         f.substring( n + 1 )
188                     )
189                 );
190             }
191         }
192     }
193 
194 }