Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/flexstor/flexdbserver/services/asset/destination/MappedStructure.java


1   /*
2    * MappedStructure.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.ArrayList;
14  import java.util.Enumeration;
15  import java.util.Hashtable;
16  import java.util.Iterator;
17  import java.util.TreeMap;
18  import java.util.Vector;
19  
20  import com.flexstor.common.constants.ActionPropertiesI;
21  import com.flexstor.common.data.ejb.disguiserecord.DisguiseAssetRecordData;
22  import com.flexstor.common.data.ejb.disguiserecord.DisguiseBucketRecordData;
23  import com.flexstor.common.data.ejb.disguiserecord.DisguiseFieldRecordData;
24  import com.flexstor.common.data.ejb.disguiserecord.DisguiseRecordData;
25  import com.flexstor.common.data.ejb.search.MultiValueData;
26  import com.flexstor.common.errorlogger.FlexError;
27  import com.flexstor.common.gateway.SearchResultGateway;
28  import com.flexstor.common.gateway.exceptions.TransactionFailedException;
29  import com.flexstor.common.importprocessor.ImportCtlData;
30  import com.flexstor.common.importprocessor.ImportData;
31  import com.flexstor.common.importprocessor.ImportResult;
32  import com.flexstor.common.io.xfile.FlexXFile;
33  import com.flexstor.common.resources.Resources;
34  import com.flexstor.common.services.ServiceArgumentsI;
35  import com.flexstor.common.util.Diagnostic;
36  import com.flexstor.ejb.bucket.persist.ServerBucketExtendData;
37  import com.flexstor.ejb.disguise.persist.ServerDisguiseExtendData;
38  import com.flexstor.ejb.field.persist.ServerFieldExtendData;
39  import com.flexstor.flexdbserver.disguise.DisguiseLoader;
40  import com.flexstor.flexdbserver.disguise.DisguiseLoaderException;
41  
42  
43  public class MappedStructure
44  {
45     // To get the version number from MKS
46     public final static String IDENTIFIER="$Id: MappedStructure.java,v 1.5 2003/08/11 02:22:34 aleric Exp $";
47  
48     private final static int VALUES_MISMATCH   = -1;
49     private final static int DATABASE_VALUES   = 0;
50     private final static int DATAOBJECT_VALUES = 1;
51  
52     private  String                     sThisService;
53     private  String                     fileSeparator;
54     private  String                     sDestination;
55     private  String                     sCtlFileName;
56     private  boolean                    bDoExactMatch;
57     private  ServerDisguiseExtendData disguise;
58     
59     /**
60      * Keep bucket ids in order of appearance in [mapfolders] section.
61      * Note that a bucket can appear in two or more consecutive levels; however this
62      * object only keeps the order of appearance once.
63      * This object is needed when comparing the traversal path of an asset with the
64      * buckets defined in the [mapfolders] section.
65      */
66     private  ArrayList      alBuckets         = new ArrayList();
67     /**
68      * Holds a list of field ids present for each bucket in the [mapfolders] section.
69      * key = bucket structure id; value = ArrayList of field ids
70      * Used for retrieving field values when calling the retrieval bean.
71      * ArrayList is also used to construct path.
72      */
73     private  Hashtable      htFields          = new Hashtable();
74     /**
75      * Holds a list of Bucket record ids grouped by bucket structure id.
76      * key = bucket structure id; value = ArrayList of record ids
77      * Used for retrieving field values when calling the retrieval bean.
78      */
79     private  Hashtable      htBucketIds       = new Hashtable();
80     /**
81      * Holds a list of field values per bucket record id.
82      * key = bucket record id; value = MultivalueFieldData[]
83      * Used when creating the path for each asset.
84      */
85     private  Hashtable      htValuesPerRecord = new Hashtable();
86     /**
87      * Holds a list of field values per bucket. (No bucket id)
88      * key = bucket (DisguiseBucketRecordData object); value = MultivalueFieldData[]
89      * Used when creating the path for each asset.
90      */
91     private  Hashtable      htValuesPerBucket = new Hashtable();
92     
93     /**
94      * If true, ignore values in the data object and only use those in the database to
95      * set the destination path
96      */
97     private  boolean        bUseDBValuesOnly;
98  
99     public ImportResult setPaths( ImportData importData, Hashtable htProperties )
100    {
101       sThisService    = (String) htProperties.get("servicename");
102       fileSeparator   = System.getProperty("file.separator");
103       
104       String sBoolean = (String) htProperties.get("UseDBValuesOnly");
105       bUseDBValuesOnly = sBoolean == null ? false : Boolean.valueOf(sBoolean).booleanValue();
106 
107       // Get Role, Type and Flag values from property list (AssetService)
108       String sRoleIn   = (String) htProperties.get(ServiceArgumentsI.ROLE_DATA_SOURCE);
109       String sTypeIn   = (String) htProperties.get(ServiceArgumentsI.TYPE_DATA_SOURCE);
110       String sFlagIn   = (String) htProperties.get(ServiceArgumentsI.FLAG_DATA_SOURCE);
111 
112       try
113       {
114          sDestination = (String) htProperties.get("destinationbase");
115          if ( !sDestination.endsWith(fileSeparator) )
116             sDestination += fileSeparator;
117       }
118       catch ( NullPointerException npe )
119       {
120          //6518=Destination directory not specified. Cannot proceed.
121          importData.addErrorRecord( new FlexError(FlexError.CRITICAL, sThisService, IDENTIFIER, 6518 ) );
122          ImportResult result = new ImportResult(false);
123          result.setImportData(importData);
124          return result;
125       }
126 
127       // Retrieve the exactMatch property. If not specified defaults to false so we don't do
128       // an exact match.
129       bDoExactMatch = (new Boolean((String)htProperties.get("exactMatch"))).booleanValue();
130 
131       boolean bResult = true;
132       DisguiseRecordData disguiseRecord;
133       if ( importData != null && (disguiseRecord = importData.getDisguiseRecordRef()) != null )
134       {
135          Vector vAssetsIn  = disguiseRecord.getAssets( sRoleIn, sTypeIn, sFlagIn );
136          if ( vAssetsIn != null && vAssetsIn.size() > 0 )
137          {
138             //setInfo( vAssetsIn );
139             StringBuffer sbError = new StringBuffer("");
140 
141             // Create an ArrayList which will hold the structure id for each bucket in the tmLevels TreeMap
142             // preserving the order assigned in the TreeMap and then a Hashtable that holds the field ids
143             // for each bucket. The ArrayList will be used to compare the position of the buckets in the
144             // ctl file with those in the traversal path of the asset; if the positions don't match, then
145             // exclude the asset from being processed. The Hashtable will be used to query the database and
146             // retrieving the values for those fields, which will be used to create the destination path
147             // of the asset.
148             String sError = getBucketAndFieldsInfo( (TreeMap) htProperties.get("levels") );
149             if ( sError == null )
150             {
151                // Parse through each asset, retrieve the traversal paths and compare them with the alBuckets to
152                // find out if the buckets match. If they do, retrieve the record id of each one and store them
153                // in a Hashtable that will hold the record id for each bucket. This Hashtable will be later use
154                // in conjunction with the htFields Hashtable to retrieve the field values from the database. If
155                // the buckets don't match for an asset, then exclude it from being processed.
156                sError = retrieveRecordIdsForBuckets( vAssetsIn, disguiseRecord );
157                if ( !vAssetsIn.isEmpty() )
158                {
159                   if ( sError != null )
160                      sbError.append( sError + "\r\n" );
161 
162                   // Query the database and get field values
163                   sError = retrieveFieldValues();
164                   if ( sError == null )
165                   {
166                      // Now create the destination path for each asset
167                      sError = createPaths( vAssetsIn, disguiseRecord );
168                      if ( sError != null )
169                         sbError.append( sError + "\r\n" );
170 
171                      ImportCtlData ctlData = importData.getCtlDataRef();
172                      ctlData.removeItem( "HIGHFILELISTBASE", ctlData.getValuePerKey("HIGHFILELISTBASE") );
173                      ctlData.addValuePerKey( "HIGHFILELISTBASE" , (new FlexXFile(sDestination)).getLocalPath() );
174 
175                      if ( sbError.length() > 0 )
176                         importData.addErrorRecord( new FlexError(FlexError.CRITICAL, sThisService, IDENTIFIER, sbError.toString()) );
177 
178                      if ( vAssetsIn.isEmpty() )
179                         bResult = false;
180 
181                      sError = null;
182                   }
183                }
184             }
185             if ( sError != null )
186             {
187                importData.addErrorRecord( new FlexError(FlexError.CRITICAL, sThisService, IDENTIFIER, sError) );
188                bResult = false;
189             }
190          }
191          else
192          {
193             //6290=Could not find assets of the following role, type and flag: %%1 %%2 %%3
194             importData.addErrorRecord( new FlexError(FlexError.CRITICAL, sThisService, IDENTIFIER, 6290, new String[] { sRoleIn, sTypeIn, sFlagIn } ) );
195             bResult = false;
196          }
197       }
198       else
199       {
200          //6291=Cannot operate on an empty data object
201          importData.addErrorRecord( new FlexError(FlexError.CRITICAL, sThisService, IDENTIFIER, 6291 ) );
202          bResult = false;
203       }
204 
205       ImportResult result = new ImportResult(bResult);
206       result.setImportData(importData);
207       return result;
208    }
209 
210    private String getBucketAndFieldsInfo( TreeMap tmLevels )
211    {
212       try
213       {
214          // Get the ctl file name for later use
215          // also remove this element from the TreeMap since we don't need it anymore
216          sCtlFileName = (String) tmLevels.remove( tmLevels.firstKey() );
217          Diagnostic.trace(Diagnostic.APPSERVER_SERVICES, "Ctl File Name is: " + sCtlFileName );
218 
219          // Get the application name to load the disguise
220          // also remove this element from the TreeMap since we don't need it anymore
221          String sAppName = (String) tmLevels.remove( tmLevels.firstKey() );
222          Diagnostic.trace(Diagnostic.APPSERVER_SERVICES, "Application Name is: " + sAppName );
223          // Load it
224          disguise = DisguiseLoader.getDisguise( sAppName );
225          if ( disguise == null )
226             //6287=%%1 Application could not be loaded.
227             return Resources.get( 6287, sAppName );
228       }
229       catch ( DisguiseLoaderException rdle )
230       {
231          return rdle.toString();
232       }
233 
234       // Retrieve the bucket id for each bucket specified and store it in the ArrayList
235       // also retrieve the field labels and store its id in the Hashtable
236       String sValue, sBucket, sField;
237       Integer nBucketId, nFieldId;
238       Vector vBuckets = disguise.getBucketDataObjects();
239       Vector vFields;
240       ServerBucketExtendData bucket = null;
241       ServerFieldExtendData field = null;
242       ArrayList alField;
243       for ( Iterator i = tmLevels.values().iterator(); i.hasNext(); )
244       {
245          sValue = (String) i.next();
246          sBucket = sValue.substring(0, sValue.indexOf(','));
247          sField = sValue.substring(sValue.indexOf(',') + 1);
248          Diagnostic.trace(Diagnostic.APPSERVER_SERVICES, "Bucket Label is: " + sBucket );
249          Diagnostic.trace(Diagnostic.APPSERVER_SERVICES, "Field Label is: " + sField );
250          // Trim values, in case there are blank spaces
251          sBucket = sBucket.trim();
252          sField = sField.trim();
253 
254          if ( bucket == null || !bucket.getLabel().equals(sBucket) )
255          {
256             for ( Iterator j = vBuckets.iterator(); j.hasNext(); )
257             {
258                bucket = (ServerBucketExtendData) j.next();
259                if ( bucket.getLabel().equals(sBucket) )
260                   break;
261                else
262                   bucket = null;
263             }
264 
265             if ( bucket == null )
266                // 6926=%%1 is not a valid bucket label in configuration file %%2.
267                return Resources.get( 6926, sBucket, sCtlFileName );
268          }
269 
270          nBucketId = new Integer(bucket.getId());
271          Diagnostic.trace(Diagnostic.APPSERVER_SERVICES, "Bucket Id is: " + nBucketId.intValue() );
272          if ( !alBuckets.contains(nBucketId) )
273          {
274             alBuckets.add( nBucketId );
275             htFields.put( nBucketId, new ArrayList() );
276          }
277 
278          vFields = bucket.getFieldDataObjects();
279          for ( Iterator k = vFields.iterator(); k.hasNext(); )
280          {
281             field = (ServerFieldExtendData) k.next();
282             if ( field.getLabel().equals(sField) )
283                break;
284             else
285                field = null;
286          }
287 
288          if ( field == null )
289             // 6927=%%1 is not a valid field labed for %%2 bucket in configuration file %%3.
290             return Resources.get( 6927, sField, sBucket, sCtlFileName );
291 
292          nFieldId = new Integer(field.getId());
293          Diagnostic.trace(Diagnostic.APPSERVER_SERVICES, "Field Id is: " + nFieldId.intValue() );
294          alField = (ArrayList) htFields.get(nBucketId);
295          alField.add(nFieldId);
296       }
297       return null;
298    }
299 
300    private String retrieveRecordIdsForBuckets( Vector vAssetsIn, DisguiseRecordData disguiseRecord )
301    {
302       Vector vFailedFiles = new Vector(); // for logging
303       DisguiseAssetRecordData asset;
304       DisguiseBucketRecordData bucket;
305       Vector vTraversalPath;
306       Long nRecordId;
307       Integer nBucketId;
308       for ( Iterator i = vAssetsIn.iterator(); i.hasNext(); )
309       {
310          asset = (DisguiseAssetRecordData) i.next();
311          vTraversalPath = asset.getTraversalPath();
312          // Traversal path contains element bucket, which is not included in the alBuckets ArrayList,
313          // that's why we do vTraversalPath.size() - 1
314          // If the number of buckets in the traversal path is greater than in the [mapfolders] section
315          // we should stop processing this asset, since the bucket structure don't match; however if
316          // the number of buckets in the traversal path is less or equal to the ones in [mapfolders]
317          // then we can process it only if this is not an exact match.
318          if ( (vTraversalPath.size() - 1) > alBuckets.size() ||
319                (bDoExactMatch && (vTraversalPath.size() - 1) != alBuckets.size()) )
320          {
321             vFailedFiles.addElement( fileSeparator + asset.getLocation() + asset.getFileName() );
322             disguiseRecord.deleteAsset( asset );
323             i.remove();
324             continue; // failed; structure are not the same
325          }
326 
327          for ( int j = 0; j < (vTraversalPath.size() - 1); j++ )
328          {
329             bucket = (DisguiseBucketRecordData) vTraversalPath.elementAt(j);
330 
331             if ( bucket.getBucketStructId() != ((Integer)alBuckets.get(j)).intValue() )
332             {
333                vFailedFiles.addElement( fileSeparator + asset.getLocation() + asset.getFileName() );
334                disguiseRecord.deleteAsset( asset );
335                i.remove();
336                break; // failed; structure are not the same
337             }
338 
339             if ( bucket.getRecordId() > 0 )
340             {
341                nRecordId = new Long( bucket.getRecordId() );
342                //Get the structure id and create an entry in htBucketIds if it doesn't exist
343                nBucketId = new Integer( bucket.getBucketStructId() );
344                if ( !htBucketIds.containsKey( nBucketId ) )
345                   htBucketIds.put( nBucketId, new ArrayList() );
346 
347                ArrayList alRecordIds = (ArrayList) htBucketIds.get( nBucketId );
348                if ( !alRecordIds.contains( nRecordId ) )
349                   alRecordIds.add( nRecordId );
350             }
351          }
352       }
353 
354       if ( vFailedFiles.isEmpty() )
355          return null;
356       else
357       {
358          // 6928=Bucket Structure for assets don't match that defined in configuration file %%1.
359          StringBuffer sb = new StringBuffer( Resources.get(6928, sCtlFileName) + "\r\n" );
360          for ( int i = 0; i < vFailedFiles.size(); i++ )
361             sb.append( (String) vFailedFiles.elementAt(i) + "\r\n" );
362 
363          return sb.toString();
364       }
365    }
366 
367    private String retrieveFieldValues()
368    {
369       // Query the database and get the field values for each bucket's record id that we have
370       SearchResultGateway searchGateway = null;
371       ArrayList alRecordIds;
372       Integer nBucketId;
373       try
374       {
375          for ( Enumeration e = htBucketIds.keys(); e.hasMoreElements(); )
376          {
377             nBucketId = (Integer) e.nextElement();
378             alRecordIds = (ArrayList) htBucketIds.get( nBucketId );
379             if ( !alRecordIds.isEmpty() )
380             {
381                Object[] LaRecordIds = alRecordIds.toArray();
382                // convert to long[]
383                long[] laRecordIds = new long[ LaRecordIds.length ];
384                for ( int i = 0; i < LaRecordIds.length; i++ )
385                   laRecordIds[i] = ((Long)LaRecordIds[i]).longValue();
386 
387                Object[] IaFieldIds = ((ArrayList)htFields.get(nBucketId)).toArray();
388                // convert to int[]
389                int[] iaFieldIds = new int[ IaFieldIds.length ];
390                for ( int j = 0; j < IaFieldIds.length; j++ )
391                   iaFieldIds[j] = ((Integer)IaFieldIds[j]).intValue();
392 
393                if ( searchGateway == null )
394                {
395                   searchGateway = new SearchResultGateway();
396                   searchGateway.connect();
397                }
398                Hashtable htValues = searchGateway.retrieveBucketData( iaFieldIds, laRecordIds );
399                if ( htValues != null )
400                   htValuesPerRecord.putAll( htValues );
401             }
402          }
403       }
404       catch(TransactionFailedException rtfe)
405       {
406          return rtfe.toString();
407       }
408       finally
409       {
410          if ( searchGateway != null )
411             searchGateway.dispose();
412       }
413 
414       return null;
415    }
416 
417    private String createPaths( Vector vAssetsIn, DisguiseRecordData disguiseRecord )
418    {
419       // Will hold the name of each subfolder for later constructing the path
420       ArrayList alSubFolders = new ArrayList();
421       DisguiseAssetRecordData asset;
422       DisguiseBucketRecordData bucket;
423       Vector vTraversalPath;
424       MultiValueData[] objectValues = null, dbValues = null;
425       Long nRecordId;
426       Vector vFailedFiles = new Vector();
427       boolean bConstructPath;
428 
429       for ( Iterator i = vAssetsIn.iterator(); i.hasNext(); )
430       {
431          asset = (DisguiseAssetRecordData) i.next();
432          vTraversalPath = asset.getTraversalPath();
433          bConstructPath = true;
434          alSubFolders = new ArrayList();
435 
436          // do vTraversalPath.size() - 1 since last object is element and we are only handling buckets
437          for ( int j = 0; j < (vTraversalPath.size() - 1); j++ )
438          {
439             bucket = (DisguiseBucketRecordData) vTraversalPath.elementAt(j);
440 
441             if ( !bUseDBValuesOnly )
442                objectValues = getValuesFromBucket( bucket, (ArrayList)htFields.get(new Integer(bucket.getBucketStructId())) );
443 
444             if ( bucket.getRecordId() > 0 )
445             {
446                nRecordId = new Long( bucket.getRecordId() );
447                //Load field values from htValuesPerRecord
448                dbValues = (MultiValueData[]) htValuesPerRecord.get( nRecordId );
449             }
450             else
451                dbValues = null;
452 
453             int nPick = bUseDBValuesOnly ? DATABASE_VALUES : pickValues( dbValues, objectValues );
454             if ( nPick == DATABASE_VALUES )
455             {
456                Diagnostic.trace(Diagnostic.APPSERVER_SERVICES, "Using DATABASE_VALUES!!!!" );
457                // Use database values to create path for asset
458                for ( int k = 0; k < dbValues.length; k++ )
459                   alSubFolders.add( (dbValues[k].getFieldData())[0] );
460             }
461             else if ( nPick == DATAOBJECT_VALUES )
462             {
463                Diagnostic.trace(Diagnostic.APPSERVER_SERVICES, "Using DATAOBJECT_VALUES!!!!" );
464                // Use database values to create path for asset
465                for ( int k = 0; k < objectValues.length; k++ )
466                   alSubFolders.add( (objectValues[k].getFieldData())[0] );
467             }
468             else
469             {
470                Diagnostic.trace(Diagnostic.APPSERVER_SERVICES, "VALUES_MISMATCH!!!!" );
471                vFailedFiles.addElement( fileSeparator + asset.getLocation() + asset.getFileName() );
472                disguiseRecord.deleteAsset( asset );
473                i.remove();
474                bConstructPath = false;
475                break; // failed; values mismatched
476             }
477          }
478 
479          if ( bConstructPath )
480             constructPath( asset, alSubFolders );
481       }
482 
483       if ( vFailedFiles.isEmpty() )
484          return null;
485       else
486       {
487          // 6929=No field values where found to construct path.
488          StringBuffer sb = new StringBuffer( Resources.get(6929) + "\r\n" );
489          for ( int i = 0; i < vFailedFiles.size(); i++ )
490             sb.append( (String) vFailedFiles.elementAt(i) + "\r\n" );
491 
492          return sb.toString();
493       }
494 
495    }
496 
497    private MultiValueData[] getValuesFromBucket( DisguiseBucketRecordData bucket, ArrayList alFieldIds )
498    {
499       MultiValueData[] values = (MultiValueData[]) htValuesPerBucket.get( bucket );
500       if ( values != null )
501          return values;
502 
503       DisguiseFieldRecordData[] aFieldRecords = bucket.getValues();
504       if ( aFieldRecords != null )
505       {
506          values = new MultiValueData[ alFieldIds.size() ];
507          ServerFieldExtendData field;
508          int i = 0, j = 0;
509          int nFields = alFieldIds.size();
510          // Repeat the for loop until all field ids in alFieldIds are processed; the foor loop
511          // is wrapped around a while loop because the ids in alFieldIds might not be in the same
512          // order as the ids in field.
513          while ( i != nFields )
514          {
515             for ( Enumeration fieldEnum = disguise.getBucketFields(bucket.getBucketStructId()); fieldEnum.hasMoreElements(); )
516             {
517                field = (ServerFieldExtendData) fieldEnum.nextElement();
518                if ( field.getId() == ((Integer)alFieldIds.get(i)).intValue() )
519                {
520                   if ( aFieldRecords[j] != null && aFieldRecords[j].getValue() != null && !(aFieldRecords[j].getValue().equals("")) )
521                      values[i] = new MultiValueData( new String[] { aFieldRecords[j].getValue() } );
522                   else
523                      values[i] = new MultiValueData( new String[] { new String() } );
524                   if ( ++i == nFields )
525                      break;
526                }
527                j++;
528             }
529             j = 0;
530          }
531          htValuesPerBucket.put( bucket, values );
532          return values;
533       }
534       return null;
535    }
536 
537    /*
538     * Whether to use the values from the database or from the data object will depend on
539     * the following rules:
540     * 1.- If both arrays are null, return failure.
541     * 2.- If database array is null, but data object array isn't; check values of data
542     *        object array, and if at least one is empty, return failure; otherwise use it.
543     * 3.- Id data object array is null, but database array isn't; check values of database
544     *        array, and if at least one is empty, return failure; otherwise use it.
545     * 4.- If both arrays aren't null, compare all values from each array, index per index:
546     *        a.- If elements at index i in both array are empty, return failure
547     *        b.- If element[i] in database array is empty, but element[i] in data object
548     *               isn't, mark database array as unusable and if data object array is already
549     *               marked as unusable, return failure; otherwise, continue.
550     *        c.- If element[i] in data object array is empty, but element[i] in database
551     *               isn't, mark data object array as unusable and if database array is already
552     *               marked as unusable, return failure; otherwise, continue.
553     *        d.- If both elements aren't empty, but they are not equal, return failure,
554     *               otherwise, continue.
555     *        e.- After all elements are compared and there is no failure so far:
556     *               I.-   If both arrays are marked as usable, use database array.
557     *               II.-  If database array is marked usable, but data object array isn't, use
558     *                        database array.
559     *               III.- If data object array is marked usable, but database array isn't, use
560     *                        data object array.
561     *               IV.-  If both arrays are marked as unusable, return failure.
562     */
563    private int pickValues( MultiValueData[] dbValues, MultiValueData[] objectValues )
564    {
565       if ( dbValues == null && objectValues == null )
566          return VALUES_MISMATCH;
567       else if ( dbValues == null )
568       {
569          // If at least one value is not set, return; cannot construct the path
570          Diagnostic.trace(Diagnostic.APPSERVER_SERVICES, "Values from data object:" );
571          String sFieldValue;
572          for ( int i = 0; i < objectValues.length; i++ )
573          {
574             sFieldValue = (objectValues[i].getFieldData())[0];
575             Diagnostic.trace(Diagnostic.APPSERVER_SERVICES, "    " + sFieldValue );
576             if ( sFieldValue.equals("") )
577                return VALUES_MISMATCH;
578          }
579          return DATAOBJECT_VALUES;
580       }
581       else if ( objectValues == null )
582       {
583          // If at least one value is not set, return; cannot construct the path
584          Diagnostic.trace(Diagnostic.APPSERVER_SERVICES, "Values from database:" );
585          String sFieldValue;
586          for ( int i = 0; i < dbValues.length; i++ )
587          {
588             sFieldValue = (dbValues[i].getFieldData())[0];
589             Diagnostic.trace(Diagnostic.APPSERVER_SERVICES, "    " + sFieldValue );
590             if ( sFieldValue.equals("") )
591                return VALUES_MISMATCH;
592          }
593          return DATABASE_VALUES;
594       }
595       else
596       {
597          // If at least one value is not set, return; cannot construct the path
598          String sDBValue, sObjectValue;
599          boolean bUseDBValues = true, bUseObjectValues = true;
600          Diagnostic.trace(Diagnostic.APPSERVER_SERVICES, "Values from both object and database:" );
601          for ( int i = 0; i < dbValues.length; i++ )
602          {
603             sDBValue = (dbValues[i].getFieldData())[0];
604             sObjectValue = (objectValues[i].getFieldData())[0];
605             Diagnostic.trace(Diagnostic.APPSERVER_SERVICES, "    database: " + sDBValue );
606             Diagnostic.trace(Diagnostic.APPSERVER_SERVICES, "    object:   " + sObjectValue );
607             if ( sDBValue.equals("") && sObjectValue.equals("") )
608                return VALUES_MISMATCH;
609             else if ( sDBValue.equals("") )
610             {
611                bUseDBValues = false;
612                if (!bUseObjectValues )
613                   return VALUES_MISMATCH;
614             }
615             else if ( sObjectValue.equals("") )
616             {
617                bUseObjectValues = false;
618                if ( !bUseDBValues )
619                   return VALUES_MISMATCH;
620             }
621             else if ( !sObjectValue.equals(sDBValue) )
622                return VALUES_MISMATCH;
623          }
624 
625          if ( bUseDBValues && bUseObjectValues )
626             return DATABASE_VALUES;
627          else if ( bUseDBValues )
628             return DATABASE_VALUES;
629          else if ( bUseObjectValues )
630             return DATAOBJECT_VALUES;
631          else
632             return VALUES_MISMATCH;
633       }
634    }
635 
636    private void constructPath( DisguiseAssetRecordData asset, ArrayList alSubFolders )
637    {
638       StringBuffer sbSubFolders = new StringBuffer("");
639       for ( int i = 0; i < alSubFolders.size(); i++ )
640          sbSubFolders.append( (String)alSubFolders.get(i) + fileSeparator );
641 
642       Diagnostic.trace(Diagnostic.APPSERVER_SERVICES, "Destination for " + asset.getFileName() + " is " + sDestination + sbSubFolders.toString() );
643       asset.addProperty( ActionPropertiesI.DESTINATION_LOCATION, sDestination + sbSubFolders.toString() );
644    }
645 }