Source code: com/flexstor/flexdbserver/services/asset/destination/SetDestinationService.java
1 /*
2 * SetDestinationService.java
3 *
4 * Copyright $Date: 2003/08/11 02:22:34 $ FLEXSTOR.net Inc.
5 *
6 * This work is licensed for use and distribution under license terms found at
7 * http://www.flexstor.org/license.html
8 *
9 */
10
11 package com.flexstor.flexdbserver.services.asset.destination;
12
13 import java.util.Hashtable;
14 import java.util.TreeMap;
15 import java.util.Vector;
16
17 import com.flexstor.common.data.ActionData;
18 import com.flexstor.common.data.ActionResult;
19 import com.flexstor.common.importprocessor.ImportCtlData;
20 import com.flexstor.common.importprocessor.ImportData;
21 import com.flexstor.common.resources.Resources;
22 import com.flexstor.flexdbserver.services.Service;
23 import com.flexstor.flexdbserver.services.ServiceContext;
24
25
26 /**
27 * <P>
28 * SetDestinationService <BR>
29 * <BLOCKQUOTE>
30 * Create destination paths for assets according to the mode selected.
31 * Destination paths can be retrieved by invoking the method call: <BR>
32 * String destination = (String) asset.getProperty( String key ); <BR>
33 * where asset is an instance of DisguiseAssetRecordData. <BR>
34 *
35 * Possible modes are: <BR>
36 * <BLOCKQUOTE>
37 * fromMapfolders: <BR>
38 * - Files are part of a mapfolders structure and the new destination will
39 * be another folder. This new destination folder can either preserve
40 * the mapped structure defined for the hot directory (this is the
41 * default behavior), or not preserve its hot directory structure (so
42 * that all files are copied into a single folder). <BR>
43 * toMapfolders: <BR>
44 * - Files are not under a mapfolders structure and new destination will be a folder where a new
45 * mapped structure will be created following the properties ([mapfolders] section) loaded
46 * into the ImportData object from an input control (*.ctl) file. <BR>
47 * toSequencefolders: <BR>
48 * - Files might or might not be in a mapfolders structure. New destination will
49 * be a sequence of numbered folders, each one containing a maximum number of files. No mapfolders
50 * structure is preserved. <BR>
51 * </BLOCKQUOTE>
52 * </BLOCKQUOTE>
53 * </P>
54 *
55 * Configurable Properties in roletype_services.config (or *.ctl file if run as a preservice) <BR>
56 *
57 * <TABLE BORDER="1" CELLPADDING="3" CELLSPACING="3">
58 * <CAPTION ALIGN=TOP>
59 * <B> In/Out Properties for Assets </B>
60 * </CAPTION>
61 * <TR>
62 * <FONT SIZE=+1><B>
63 * <TH WIDTH="120">Attribute</TH>
64 * <TH WIDTH="30">IN</TH> <TH WIDTH="30">OUT</TH> <TH WIDTH="30">Default IN</TH> <TH WIDTH="30">Default OUT</TH>
65 * </B></FONT>
66 * </TR>
67 * <TR>
68 * <TH ALIGN=LEFT><FONT SIZE=+1><B>ROLE</B></FONT></TH>
69 * <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER> ALL </TD> <TD ALIGN=CENTER>   </TD>
70 * </TR>
71 * <TR><TH> Highres </TH> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD></TR>
72 * <TR><TH> Lowres </TH> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD></TR>
73 * <TR><TH> Thumbnail </TH> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD></TR>
74 * <TR><TH> Layout </TH> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD></TR>
75 * <TR><TH> Video </TH> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD></TR>
76 * <TR><TH> Audio </TH> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD></TR>
77 * <TR>
78 * <TH ALIGN=LEFT><FONT SIZE=+1><B>TYPE</B></FONT></TH>
79 * <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER> ALL </TD> <TD ALIGN=CENTER>   </TD></TR>
80 * </TR>
81 * <TR>
82 * <TH ALIGN=LEFT><FONT SIZE=+1><B>FLAG</B></FONT></TH>
83 * </TR>
84 * <TR><TH> PARENT </TH> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER>   </TD></TR>
85 * <TR><TH> CHLDREN </TH> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD></TR>
86 * <TR><TH> ALL </TH> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD></TR>
87 * <TR><TH> TEMP_PARENT </TH> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD></TR>
88 * <TR><TH> TEMP_CHILDREN </TH> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD></TR>
89 * <TR><TH> TEMP_ALL </TH> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD></TR>
90 * </TABLE>
91 *
92 * <P>
93 * mode: See description of service above (defaults to fromMapfolders). <BR>
94 * Legal values: fromMapfolders, toMapfolders, or toSequencefolders
95 * </P>
96 * <P>
97 * exactMatch: If set to true, the service will succeed setting the path of an asset
98 * only if the number of buckets in the traversal path of the asset is equal to the
99 * number of buckets set in the [mapfolders] section of the *.ctl file. If set to false,
100 * it will succeed if the number of buckets in the traversal path is less or equal to
101 * the number of buckets in the [mapfolders] section. Please note that a single bucket
102 * can be set in more than one level in the [mapfolders] section, if so, it will only
103 * be counted once for the effects of setting the path (it will default to false if not
104 * specified) <BR>
105 * Legal values: true or false
106 * </P>
107 * <P>
108 * destinationbase: Destination path for files. If SetDestinationService is specified
109 * as a preservice in the input control (*.ctl) file and this property is not declared,
110 * it will default to either the lowcopybase or highcopybase property (depending on role)
111 * in the input control file. If SetDestinationService is not defined as a preservice,
112 * this property must be declared. <BR>
113 * Configure this property for mode = fromMapfolders and toMapfolders <BR>
114 * Legal values: Full path
115 * </P>
116 * <P>
117 * originalbase: Base path where original files reside. If SetDestinationService is
118 * specified as a preservice in the input control file and this property is not declared,
119 * it will default to either the lowfilelistbase or highfilelistbase property (depending
120 * on role) in the input control file. If SetDestinationService is not defined as a
121 * preservice, this property must be declared. <BR>
122 * Configure this property for mode = fromMapfolders <BR>
123 * Legal values: Full path
124 * </P>
125 * <P>
126 * flatmode: Indicates if destination location will duplicate all, none, or part
127 * of the original location under the destinationbase path. For instance, if the
128 * original path is /base/path/job/page/file.jpg, destinationbase is /dest, and
129 * flatmode is set to true, the destination path for the file will be /dest/file.jpg.
130 * If the original path is defined as /base/path and flatmode is set to false, the
131 * destination path will be /dest/job/page.file.jpg. If no original path is defined
132 * and no default is found, the destination path will be /dest/base/path/job/page/file.jpg
133 * (optional; defaults to false if service defined as a preservice; true otherwise). <BR>
134 * Configure this property for mode = fromMapfolders <BR>
135 * Legal values: true or false
136 * </P>
137 * <P>
138 * max_no_of_files: The maximum number of files allowed per destination folder if mode is toSequenceFolders. This
139 * property must be defined if mode = toSequenceFolders; for all other modes, this property is ignored. <BR>
140 * Legal values: Any positive number
141 * </P>
142 * <P>
143 * map_sequence_to: Map the sequence numbered folder to a field in the bucket specified in this property. The syntax for
144 * this property is <I>bucket name, field name</I>, where the field name must exist in the specified bucket. <BR>
145 * Legal values: A valid bucket name and field name for the application being used.
146 * </P>
147 *
148 * <P>
149 * Input Data Object <BR>
150 * <BLOCKQUOTE>
151 * com.flexstor.common.importprocessor.ImportData
152 * </BLOCKQUOTE>
153 * </P>
154 *
155 * <P>
156 * Output Data Object <BR>
157 * <BLOCKQUOTE>
158 * com.flexstor.common.importprocessor.ImportResult
159 * </BLOCKQUOTE>
160 * </P>
161 */
162 public class SetDestinationService
163 implements Service
164 {
165 // To get the version number from MKS
166 public final static String IDENTIFIER="$Id: SetDestinationService.java,v 1.3 2003/08/11 02:22:34 aleric Exp $";
167
168 // Modes for this service
169 private final static String FROMMAPFOLDERS = "FROMMAPFOLDERS";
170 private final static String TOSEQUENCEFOLDERS = "TOSEQUENCEFOLDERS";
171
172 protected ServiceContext context;
173 protected int id = -1;
174 private ImportData importData;
175 private String sThisService;
176 private Hashtable htProperties;
177
178 /**
179 * Calls before the service is initialized (before initData is called) to
180 * pass information about the environment in which the service is running.
181 * This environment consists of information about the properties set for the
182 * service in one of these files (services.config, roletype_services.config,
183 * or *.ctl), plus methods to access other information such as an instance
184 * of the service broker to invoke other services, the transaction id for
185 * the service, file separator character and local path for the installation
186 * directory and configuration directory.
187 *
188 * @param context Holds information about the environment in which the service
189 * is running.
190 */
191 public void setServiceContext( ServiceContext context )
192 {
193 this.context = context;
194 id = context.getTransactionId();
195 }
196
197 public void initData(ActionData actionData)
198 {
199 importData = (ImportData) actionData;
200
201 // If some other service is calling this service, preserve
202 // the caller information to be passed in case of errors.
203 sThisService = importData.getString("caller");
204 if ( sThisService == null )
205 {
206 //6921=Set Destination Service
207 sThisService = Resources.get(6921) + " (" + id + ")";
208 }
209
210 // Get properties defined in configuration files.
211 htProperties = context.getProperties();
212 htProperties.put( "servicename", sThisService );
213 }
214
215 public ActionResult go()
216 {
217 // First step is to determine the mode of this destination service.
218 // Mode availables are:
219 // FROMMAPFOLDERS (default, files are already mapped to a mapfolder structure
220 // and they might or might not keep the structure according
221 // to flatmode flag )
222 // TOMAPFOLDERS (files might or might not be mapped to a mapfolder structure
223 // and a new mapping will be used as defined in ctl file)
224 // TOSEQUENCEFOLDERS (files might or might not be mapped to a mapfolder structure
225 // and they will be placed in sequential numbered folders)
226 //
227 // If flatmode flag is set to true, the mode will be set to FROMMAPFOLDERS regardless
228 // of its previous setting.
229 String sMode = (String)htProperties.get( "mode" );
230 String sFlatMode = (String)htProperties.get("flatmode");
231 if ( sMode == null || sMode.equals("") || (sFlatMode != null && sFlatMode.equalsIgnoreCase("true")) )
232 sMode = FROMMAPFOLDERS;
233
234 sMode = sMode.toUpperCase();
235
236 if ( !sMode.equals(TOSEQUENCEFOLDERS) && isMapStructured(sMode) )
237 {
238 if ( sMode.equals(FROMMAPFOLDERS) )
239 return (new Mapfolder()).setPaths( importData, htProperties );
240 else
241 return (new MappedStructure()).setPaths( importData, htProperties );
242 }
243 else
244 return (new UnmappedStructure()).setPaths( importData, htProperties );
245 }
246
247 /**
248 * Determines if the assets stored in the ImportData object are to be treated as
249 * mapped structure. If the ImportCtlData object inside ImportData contains the
250 * [mapfolders] section of the *.ctl file and this section contains the leveln
251 * properties then it is structured.
252 */
253 private boolean isMapStructured( String sMode )
254 {
255 ImportCtlData ctlData = importData.getCtlDataRef();
256
257 // Determine if [mapfolders] section is defined in ctl file
258 Vector vMapfolders = ctlData.getVectorSectionData("mapfolders");
259 if ( vMapfolders == null || vMapfolders.isEmpty() )
260 return false; // NO MAPPED!!!!
261 else if ( sMode.equals("FROMMAPFOLDERS") )
262 return true; // No need to get the levels info
263
264 // Now find out if there are leveln properties defined
265 TreeMap tmLevels = new TreeMap();
266 // Read each element of the Vector; if an element starts with the string 'level',
267 // read the number that immediately follows and store the value of the property
268 // in the tmLevels TreeMap
269 String sLine;
270 int nPos;
271 for ( int i = 0; i < vMapfolders.size(); i++ )
272 {
273 sLine = (String) vMapfolders.elementAt(i);
274 if ( sLine.regionMatches( true, 0, "level", 0, 5 ) )
275 {
276 try
277 {
278 // Add the value to the TreeMap, where the key is the level number (in leveln) + 1 and
279 // the value is the value of the leveln property.
280 nPos = Integer.parseInt( sLine.substring(5, 6) );
281 tmLevels.put( new Integer( ++nPos ), ctlData.getCommandValue(sLine) );
282 }
283 catch ( NumberFormatException nfe )
284 {
285 // Ignore, this mean that the property is not a valid level
286 }
287 }
288 }
289
290 if ( tmLevels.isEmpty() )
291 return false;
292 else
293 {
294 // Add the ctl file name in the first position of the TreeMap
295 tmLevels.put( new Integer(0), ctlData.getValuePerKey("ctlfilename") );
296
297 // Add the Application name in the second position of the TreeMap
298 tmLevels.put( new Integer(1), ctlData.getValuePerKey("application name") );
299
300 htProperties.put( "levels", tmLevels );
301 return true;
302 }
303 }
304 }