1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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
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 }