Source code: com/flexstor/flexdbserver/services/asset/XMLService.java
1 /*
2 * XMLService.java
3 *
4 * Copyright $Date: 2003/08/11 02:22:29 $ 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;
12
13 import java.io.File;
14 import java.io.IOException;
15 import java.util.Date;
16 import java.util.Enumeration;
17 import java.util.Hashtable;
18 import java.util.Vector;
19
20 import org.apache.xerces.parsers.DOMParser;
21 import org.w3c.dom.Document;
22 import org.w3c.dom.Node;
23 import org.w3c.dom.NodeList;
24 import org.xml.sax.SAXException;
25
26 import com.flexstor.common.constants.BucketConstantsI;
27 import com.flexstor.common.constants.SequenceConstantsI;
28 import com.flexstor.common.data.ActionData;
29 import com.flexstor.common.data.ActionResult;
30 import com.flexstor.common.data.ejb.disguiserecord.AssetRoleData;
31 import com.flexstor.common.data.ejb.disguiserecord.DisguiseAssetRecordData;
32 import com.flexstor.common.data.ejb.disguiserecord.DisguiseBucketRecordData;
33 import com.flexstor.common.data.ejb.disguiserecord.DisguiseElementRecordData;
34 import com.flexstor.common.data.ejb.disguiserecord.DisguiseRecordData;
35 import com.flexstor.common.data.ejb.disguiserecord.HighresRoleData;
36 import com.flexstor.common.data.ejb.disguiserecord.ThumbnailRoleData;
37 import com.flexstor.common.errorlogger.FlexError;
38 import com.flexstor.common.gateway.SequenceGateway;
39 import com.flexstor.common.gateway.exceptions.TransactionFailedException;
40 import com.flexstor.common.importprocessor.ImportCtlData;
41 import com.flexstor.common.importprocessor.ImportData;
42 import com.flexstor.common.importprocessor.ImportResult;
43 import com.flexstor.common.services.ServiceArgumentsI;
44 import com.flexstor.common.util.Diagnostic;
45 import com.flexstor.common.util.DiagnosticBase;
46 import com.flexstor.ejb.bucket.persist.ServerBucketExtendData;
47 import com.flexstor.ejb.disguise.persist.ServerDisguiseExtendData;
48 import com.flexstor.ejb.field.persist.ServerFieldExtendData;
49 import com.flexstor.flexdbserver.disguise.DisguiseLoader;
50 import com.flexstor.flexdbserver.services.Service;
51 import com.flexstor.flexdbserver.services.ServiceContext;
52
53
54 /**
55 * <P>
56 * BookXMLService <BR>
57 * <BLOCKQUOTE>
58 * Creates an Import Data object from an XML file. This service wound up being
59 * fairly customer specific and should probably be deprecated. The more general
60 * XML asset creation service, which should be used in favor of this one, is the
61 * XMLActionDataService.
62 * </BLOCKQUOTE>
63 * </P>
64 *
65 * <P>
66 * Configurable Properties in services.config <BR>
67 * <BLOCKQUOTE>
68 * None
69 * </BLOCKQUOTE>
70 * </P>
71 *
72 * <P>
73 * Configurable Properties in Hot Directory Control File <BR>
74 * <BLOCKQUOTE>
75 * FieldToSplitForSLF: If the value is booktechGenerate, the value for the server
76 * is set to be the same as the server value where the XML file resides; the
77 * location is generated by appending a number (based on the number contained
78 * in the file name) to the HighFileListBase from the hotdirectory control file;
79 * and the file name is made by appending .pdf onto the system_segment1 XML field.<br>
80 * Otherwise, if the value is that of an XML tag in the file, the format for
81 * the data in that tag must be of the form: http://server/location/filename<br>
82 * Note: Early August emails from the customer confirmed that the full URL wouldn't be
83 * provided. That is why the other process was created. <br>
84 * Legal values: booktechGenerate or an XML tag in the file<br>
85 * </BLOCKQUOTE>
86 * <BLOCKQUOTE>
87 * makeXMLTemp: This is used to inform the service if the XML file itself should
88 * be set to TEMP.
89 * The default is to set it to TEMP.<br>
90 * Legal values: N or Y<br>
91 * </BLOCKQUOTE>
92 * </P>
93 *
94 * Configurable Properties in roletype_services.config <BR>
95 *
96 * <!-- THE ACTUAL TABLE: -->
97 *
98 * <TABLE BORDER="1" CELLPADDING="3" CELLSPACING="3">
99 * <CAPTION ALIGN=TOP>
100 * <B> In/Out Properties for Assets </B>
101 * </CAPTION>
102 * <TR>
103 * <FONT SIZE=+1><B>
104 * <TH WIDTH="120">Attribute</TH>
105 * <TH WIDTH="30">IN</TH> <TH WIDTH="30">OUT</TH> <TH WIDTH="30">Default IN</TH> <TH WIDTH="30">Default OUT</TH>
106 * </B></FONT>
107 * </TR>
108 * <TR>
109 * <TH ALIGN=LEFT><FONT SIZE=+1><B>ROLE</B></FONT></TH>
110 * <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER> ALL </TD> <TD ALIGN=CENTER> ALL </TD></TR>
111 * </TR>
112 * <TR><TH> Highres </TH> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD></TR>
113 * <TR><TH> Lowres </TH> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD></TR>
114 * <TR><TH> Thumbnail </TH> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD></TR>
115 * <TR><TH> Layout </TH> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD></TR>
116 * <TR><TH> Video </TH> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD></TR>
117 * <TR><TH> Audio </TH> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD></TR>
118 * <TR>
119 * <TH ALIGN=LEFT><FONT SIZE=+1><B>TYPE</B></FONT></TH>
120 * <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD></TR>
121 * </TR>
122 * <TR>
123 * <TH ALIGN=LEFT><FONT SIZE=+1><B>FLAG</B></FONT></TH>
124 * </TR>
125 * <TR><TH> PARENT </TH> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER>   </TD></TR>
126 * <TR><TH> CHLDREN </TH> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD></TR>
127 * <TR><TH> ALL </TH> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD></TR>
128 * <TR><TH> TEMP_PARENT </TH> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER> X </TD></TR>
129 * <TR><TH> TEMP_CHILDREN </TH> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD></TR>
130 * <TR><TH> TEMP_ALL </TH> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD></TR>
131 * </TABLE>
132 *
133 * <P>
134 *
135 * More Configurable Properties in roletype_services.config
136 * <BLOCKQUOTE>
137 * <P>
138 * rlocation<I>X</I>: The "real" location. Numerous settings can be used. Start with X=0.<BR>
139 * </P>
140 * <P>
141 * vlocation<I>X</I>: The "virtual" location to use in place of the "real" location. <BR>
142 * </P>
143 * <P>
144 * rserver<I>X</I>: The "real" server. Numerous settings can be used. Start with X=0.<BR>
145 * </P>
146 * <P>
147 * vserver<I>X</I>: The "virtual" server to use in place of the "real" server. <BR>
148 * </P>
149 * </BLOCKQUOTE>
150 *
151 * <P>
152 * Input Data Object <BR>
153 * <BLOCKQUOTE>
154 * com.flexstor.common.importprocessor.ImportData
155 * </BLOCKQUOTE>
156 * </P>
157 *
158 * <P>
159 * Output Data Object <BR>
160 * <BLOCKQUOTE>
161 * com.flexstor.common.importprocessor.ImportResult
162 * </BLOCKQUOTE>
163 * </P>
164 *
165 */
166 public class XMLService
167 implements Service
168 {
169
170 protected Hashtable servers = new Hashtable();
171 protected Hashtable locations = new Hashtable();
172
173 // Used for logging errors
174 public final static String IDENTIFIER = "$Id: XMLService.java,v 1.4 2003/08/11 02:22:29 aleric Exp $";
175 private String sThisService = "XMLService";
176 protected ServiceContext context;
177
178 String sRoleOut = null;
179 String sTypeOut = null;
180 String sFlagOut = null;
181
182 // The data object
183 private ImportData refImportData = null;
184 private ServerDisguiseExtendData myServDisgExtend = null;
185 private DisguiseRecordData refDisguiseRecord = null;
186 private DisguiseBucketRecordData refCurrentBucket = null;
187 private ServerBucketExtendData [] allBucketExtend = null;
188
189 private SequenceGateway seqGateway = null;
190
191 private static String sDisguise = new String();
192
193 private static String sServerLocationFilename = null;
194
195 // asset level info to be used when creating assets
196 private static Date receivedDate = null;
197 private static String ctlUserId = null;
198 private static String sOurServer = null;
199 private static String sHighFileListBase = null;
200
201 protected boolean shouldMakeXMLTemp = true;
202 protected boolean bMajorFailure = false;
203 protected boolean bThisIsJitem = false;
204
205 protected boolean successful = true;
206
207 /**
208 * Calls before the service is initialized (before initData is called) to
209 * pass information about the environment in which the service is running.
210 * This environment consists of information about the properties set for the
211 * service in one of these files (services.config, roletype_services.config,
212 * or *.ctl), plus methods to access other information such as an instance
213 * of the service broker to invoke other services, the transaction id for
214 * the service, file separator character and local path for the installation
215 * directory and configuration directory.
216 *
217 * @param context Holds information about the environment in which the service
218 * is running.
219 */
220 public void setServiceContext( ServiceContext context )
221 {
222 this.context = context;
223 }
224
225 /**
226 * Data initialization method called at the beginning of the service.
227 *
228 * @param Action is the super class of the data wrapper object
229 * which contains all the information for executing the service.
230 */
231 public void initData( ActionData actionData )
232 {
233 refImportData = (ImportData) actionData;
234
235 // Get some info from the .ctl file. This should all be in the refImportData
236 ImportCtlData refCtlData = refImportData.getCtlDataRef();
237 sDisguise = refCtlData.getValuePerKey("application name");
238
239 ctlUserId = refCtlData.getValuePerKey("userid");
240
241 sServerLocationFilename = refCtlData.getValuePerKey("FieldToSplitForSLF");
242 sHighFileListBase = refCtlData.getValuePerKey("highfilelistbase");
243
244 for ( int i = 0;; i++ )
245 {
246 if ( context.getProperty( "rlocation" + i ) != null )
247 {
248 if ( context.getProperty( "vlocation" + i ) != null )
249 locations.put( context.getProperty( "rlocation" + i ), context.getProperty( "vlocation" + i ) );
250 }
251 else
252 break;
253 }
254
255 for ( int i = 0;; i++ )
256 {
257 if ( context.getProperty( "rserver" + i ) != null )
258 {
259 if ( context.getProperty( "vserver" + i ) != null )
260 servers.put( context.getProperty( "rserver" + i ), context.getProperty( "vserver" + i ) );
261 }
262 else
263 break;
264 }
265
266 String sXMLTemp = refCtlData.getValuePerKey("makeXMLTemp").toUpperCase();
267
268 if (sXMLTemp.equals("N")) {
269 shouldMakeXMLTemp = false;
270 } else {
271 shouldMakeXMLTemp = true;
272 }
273 }
274
275
276
277 /**
278 * Start of the Service
279 *
280 * @return a Result object with an updated data object.
281 */
282 public ActionResult go()
283 {
284 DisguiseAssetRecordData aXMLFileAsset = null;
285
286 BGPDebug("XMLService Started");
287
288 successful = true;
289
290 // get the input assets, according to the role, type and flag specified
291 // in remote_server.config or TypeServiceDat.config
292 String sRoleIn = context.getProperty(ServiceArgumentsI.ROLE_DATA_SOURCE);
293 String sTypeIn = context.getProperty(ServiceArgumentsI.TYPE_DATA_SOURCE);
294 String sFlagIn = context.getProperty(ServiceArgumentsI.FLAG_DATA_SOURCE);
295
296 BGPDebug("XML:Role(in) = " + sRoleIn);
297 BGPDebug("XML:Type(in) = " + sTypeIn);
298 BGPDebug("XML:Flag(in) = " + sFlagIn);
299
300 sRoleOut = context.getProperty(ServiceArgumentsI.ROLE_DATA_DESTINATION);
301 sTypeOut = context.getProperty(ServiceArgumentsI.TYPE_DATA_DESTINATION);
302 sFlagOut = context.getProperty(ServiceArgumentsI.FLAG_DATA_DESTINATION);
303
304 BGPDebug("XML:Role(out) = " + sRoleOut);
305 BGPDebug("XML:Type(out) = " + sTypeOut);
306 BGPDebug("XML:Flag(out) = " + sFlagOut);
307
308
309
310 ImportResult result = null;
311
312 if( refImportData == null )
313 {
314 result = new ImportResult(false);
315 return result;
316 }
317
318 // Get the reference to the DisguiseRecordData
319 refDisguiseRecord = refImportData.getDisguiseRecordRef();
320 if( refDisguiseRecord == null ) {
321 successful = false;
322 }
323
324
325 try {
326 myServDisgExtend = DisguiseLoader.getDisguise(sDisguise);
327 }
328 catch (Exception e) {
329 BGPDebug("Exception getting disguise: " + e);
330 e.printStackTrace();
331 }
332
333
334 // This is a vector of ServerBucketExtendData Objects (all our buckets)
335 Vector myBucketDataObjects = myServDisgExtend.getBucketDataObjects();
336
337 // I'd like an array of SBEDs for all buckets, please.
338 allBucketExtend = new ServerBucketExtendData[myBucketDataObjects.size()];
339
340 for (int i=0; i<allBucketExtend.length; i++) {
341 allBucketExtend[i] = (ServerBucketExtendData) myBucketDataObjects.elementAt(i);
342 }
343
344 Vector vAssetsIn = null;
345 if( sRoleIn==null || sTypeIn==null || sFlagIn==null )
346 {
347 successful = false;
348 }
349 else
350 {
351 vAssetsIn = refDisguiseRecord.getAssets(sRoleIn, sTypeIn, sFlagIn);
352 if( vAssetsIn != null )
353 {
354 Enumeration assets = vAssetsIn.elements();
355
356 // Process each asset in each element in ImportData
357 while(assets.hasMoreElements())
358 {
359 aXMLFileAsset = (DisguiseAssetRecordData)assets.nextElement();
360
361 String assetFileName = aXMLFileAsset.getFileName();
362 String fullPathName = "/" + aXMLFileAsset.getLocation() + assetFileName;
363 BGPDebug("An asset is found: "+fullPathName);
364
365 receivedDate = aXMLFileAsset.getReceived();
366 sOurServer = aXMLFileAsset.getServer();
367
368 // if we set the XML file to be temp, it won't import and we can DeleteTEMP it
369 if (shouldMakeXMLTemp == true) {
370 BGPDebug("the XML file will be set to temp");
371 // the XML file should be a TEMP_PARENT (ADD something to the .ctl file to
372 // determine if we should set temp...)
373 AssetRoleData theAssetRole = aXMLFileAsset.getAssetRole();
374 theAssetRole.setTempRole(true);
375 aXMLFileAsset.setAssetRole(theAssetRole);
376 } // else it will import.
377
378 try
379 {
380 // reset this to 0 for each document I parse
381 iLevel = 0;
382 iPrevLevel = 0;
383 iPrevType = 0;
384 sPrevValue = null;
385 iPrimaryParentLevel = 0;
386
387 // variables should be initialized to default values before
388 // each XML file is parsed.
389 bThisIsJitem = false;
390
391 parseXMLfile(fullPathName);
392 // if we had a major failure we were not successful
393 if (bMajorFailure == true)
394 successful = false;
395 else
396 successful = true;
397 }
398 catch (Exception e)
399 {
400 BGPDebug("Exception parsing XML file: " + e);
401 e.printStackTrace();
402 successful = false;
403 }
404 }
405 }
406 else
407 successful = false;
408
409 }
410
411
412
413
414 BGPDebug("Done with XML service");
415
416 if( successful == false )
417 {
418 result = new ImportResult(false);
419 } else {
420 result = new ImportResult(true);
421 result.setImportData(refImportData);
422 }
423
424 return result;
425 }
426
427
428
429
430
431 /*
432 * parseXMLfile -
433 */
434 private void parseXMLfile(String pathToFile) throws IOException, SAXException
435 {
436 DOMParser parser = new DOMParser();
437 //InputSource inSource = new InputSource(new FileReader(pathToFile));
438 parser.parse(pathToFile);
439 Document document = parser.getDocument();
440
441 XMLprocess(document);
442
443
444 return;
445 }
446
447
448
449
450 /*
451 * I want to keep these variables close to where I use them
452 * so I can remember their names. After a while they can be
453 * moved back to the top.
454 */
455 static String sCurrentTag = null;
456 static String sPreviousTag = null;
457 static int iLevel = 0;
458 static int iEntries = 0;
459 static int iNormalBuckets = 0;
460 static int iAssets = 0;
461 static boolean bDefViewDone = false;
462
463 static int iPrimaryParentLevel = 0;
464 static int iPreviousTagLevel = 0;
465
466 static Hashtable dataHash = new Hashtable();
467
468 static DisguiseAssetRecordData [] assetArray = new DisguiseAssetRecordData[30];
469 static DisguiseElementRecordData refElement = null;
470
471 static int iPrevLevel = 0;
472 static int iPrevType = 0;
473 static String sPrevValue = null;
474
475
476 /*
477 * XMLprocess -
478 */
479 private void XMLprocess(Node node)
480 {
481
482 if (node == null) return;
483
484 iLevel++;
485
486 int iCurrType = node.getNodeType();
487 String sCurrVal = node.getNodeValue();
488
489 // If the current type equals the previous type AND
490 // the current level equals the previous level
491 // Then we're looking at special character handling so start appending.
492 if ((iCurrType == iPrevType) && (iPrevLevel == iLevel)) {
493 //BGPDebug(" Previous and Current types AND levels match. Perhaps a '&' or '<'.");
494 //BGPDebug(" sCurrVal is "+sCurrVal);
495 sCurrVal = sPrevValue.concat(sCurrVal);
496 //BGPDebug(" new sCurrVal is "+sCurrVal);
497 }
498 iPrevLevel = iLevel;
499 iPrevType = iCurrType;
500 sPrevValue = sCurrVal;
501
502 switch(iCurrType) {
503 case Node.DOCUMENT_NODE:
504 {
505 XMLprocess(((Document)node).getDocumentElement());
506 // That's it, i think we're done
507 //BGPDebug(" DOCUMENT_NODE ["+node.getNodeName()+"] found");
508 break;
509 }
510 case Node.ELEMENT_NODE:
511 {
512 String sNodeName = node.getNodeName();
513 sCurrentTag = sNodeName;
514
515 if (!sNodeName.equals("page"))
516 {
517 sCurrentTag = sNodeName;
518 //BGPDebug(" xmlelement node [" + sNodeName + "]");
519 }
520
521
522 if (sNodeName.equals("entry"))
523 {
524 if (iEntries > 0) {
525 BGPDebug(" !!!!! This is not our first entry!");
526 // handle it!
527 }
528 iEntries++;
529 iNormalBuckets = 0;
530 iAssets = 0;
531 }
532 else if (sNodeName.equals("normal") || sNodeName.equals("element"))
533 {
534 // The first time we encounter "normal" we'll be starting our
535 // first bucket. Don't bother to do much yet.
536
537 // If we just finished our first bucket, we are at the
538 // top level and will need to add our recently gathered
539 // data to refDisguiseRecord via an addBucket call.
540 if (iNormalBuckets == 1)
541 {
542 BGPDebug(" ---- adding first bucket");
543 refCurrentBucket = createBucket();
544 refDisguiseRecord.addBucket(refCurrentBucket);
545 }
546 // otherwise we've just finished an additional bucket
547 // and we should process what we just gathered
548 else if (iNormalBuckets > 1)
549 {
550 BGPDebug(" ---- adding child bucket");
551 DisguiseBucketRecordData prevBucket = refCurrentBucket;
552 refCurrentBucket = createBucket();
553 prevBucket.addBucketChild(refCurrentBucket);
554 }
555
556 iNormalBuckets++;
557 dataHash.clear();
558 }
559 else if (sNodeName.equals("asset"))
560 {
561 if (iNormalBuckets == 1)
562 {
563 BGPDebug(" ---- adding first bucket because there was only one!");
564 refCurrentBucket = createBucket();
565 refDisguiseRecord.addBucket(refCurrentBucket);
566 }
567
568 BGPDebug(" ---- adding element");
569 // we just finished the element (or it is possible that there was
570 // no element); so create it and add it to latest bucket.
571 refElement = createElement();
572 refElement.setRecordId(getSequence());
573 refCurrentBucket.addElement(refElement);
574 dataHash.clear();
575 }
576 else if (sNodeName.equals("primary_parent"))
577 {
578 iAssets++;
579
580 BGPDebug(" asset(pp) is " + sNodeName );
581 // There must only be one primary parent
582 iPrimaryParentLevel = iLevel;
583 }
584 else if (sNodeName.equals("parent") || sNodeName.equals("default"))
585 {
586 //BGPDebug(" level #"+iLevel+" is <"+sNodeName+">");
587 if (iAssets == 1) // we just finished our primary parent
588 {
589 BGPDebug(" ---- adding primary parent");
590 assetArray[iPrimaryParentLevel] = createAsset(sPreviousTag);
591 //BGPDebug(" - attach directly to the refElement");
592 refElement.setParentAsset(assetArray[iPrimaryParentLevel]);
593 }
594 // otherwise we've just finished an additional parent/default
595 // and we should process what we previously gathered
596 else if (iAssets > 1)
597 {
598 // we're done with an asset (either parent or default)
599 BGPDebug(" ---- done with a "+sPreviousTag);
600 // BGPDebug(" - belongs on #"+iPreviousTagLevel+
601 // " and attaches to #"+(iPreviousTagLevel-1));
602 // Create it (this will also fill it with data)
603 assetArray[iPreviousTagLevel] = createAsset(sPreviousTag);
604 // Attach it to its parent
605 assetArray[iPreviousTagLevel-1].addChildAsset(assetArray[iPreviousTagLevel]);
606 }
607
608 iAssets++;
609 dataHash.clear();
610
611 sPreviousTag = sCurrentTag;
612 iPreviousTagLevel = iLevel;
613 }
614 else // we must have found a data tag
615 {
616 // BGPDebug(" sNodeName is " + sNodeName );
617 sCurrentTag = sNodeName;
618 }
619
620
621 // Process the kids.
622 NodeList children = node.getChildNodes();
623 if( children!=null )
624 {
625 int length = children.getLength();
626 for(int i=0;i<length;i++)
627 {
628 //BGPDebug(" :: GOING to process child "+(i+1)+" of "+length);
629 XMLprocess(children.item(i));
630 //BGPDebug(" :: DONE processing child "+i+" at level "+iLevel);
631 iLevel--;
632 }
633 }
634
635
636 // We have to remember to process the last asset
637 if (iPrimaryParentLevel == iLevel) {
638 if (sPreviousTag == null) {
639 // if we have no previous tag, this is the primary parent
640 BGPDebug(" ---- (lastly) adding primary parent");
641 assetArray[iPrimaryParentLevel] = createAsset(sPreviousTag);
642 BGPDebug(" - attach directly to the refElement");
643 refElement.setParentAsset(assetArray[iPrimaryParentLevel]);
644 } else {
645 // otherwise we've already done the primary parent
646 BGPDebug(" ---- (lastly) done with a "+sPreviousTag);
647 //BGPDebug(" - belongs on #"+iPreviousTagLevel+
648 // " and attaches to #"+(iPreviousTagLevel-1));
649 // Create it (this will also fill it with data)
650 assetArray[iPreviousTagLevel] = createAsset(sPreviousTag);
651 // Attach it to its parent
652 assetArray[iPreviousTagLevel-1].addChildAsset(assetArray[iPreviousTagLevel]);
653 }
654 }
655
656 break;
657 }
658 case Node.TEXT_NODE:
659 {
660 // We'll trim() off the whitespace at the beginning and end.
661 String value = sCurrVal.trim();
662 // and that may leave us with an empty string, but such is life.
663 if(!value.equals(""))
664 {
665 //BGPDebug("Text found for "+sCurrentTag+",value ["+value+"]");
666
667 // put the data into our hashtable
668 dataHash.put(sCurrentTag,value);
669 }
670 break;
671 }
672 case Node.ATTRIBUTE_NODE:
673 case Node.CDATA_SECTION_NODE:
674 case Node.COMMENT_NODE:
675 case Node.DOCUMENT_FRAGMENT_NODE:
676 case Node.DOCUMENT_TYPE_NODE:
677 case Node.ENTITY_NODE:
678 case Node.ENTITY_REFERENCE_NODE:
679 case Node.NOTATION_NODE:
680 case Node.PROCESSING_INSTRUCTION_NODE:
681 {
682 BGPDebug(" ignored case.");
683 break;
684 }
685 default:
686 {
687 BGPDebug(" Unanticipated case.");
688 break;
689 }
690 }
691 }
692
693
694
695 /*
696 * createBucket()
697 */
698 DisguiseBucketRecordData createBucket()
699 {
700 //BGPDebug(" >>>> Create a bucket");
701
702 DisguiseBucketRecordData tmpBucket = new DisguiseBucketRecordData();
703 ServerFieldExtendData tmpSFED = null;
704 String sTmpLabel = null;
705 String sTmpValue = null;
706
707 // We need the bucket label in order to retrieve extend info.
708 // precondition: the hashtable must not be empty
709 // because we wouldn't know what bucket to create
710
711 String sBucketLabel = (String) dataHash.keys().nextElement();
712 // How about some error checking for indexOf? what if there's no '.'?
713 sBucketLabel = sBucketLabel.substring(0,(sBucketLabel.indexOf('.')));
714
715 // Retrieve the extend info for this bucket
716 ServerBucketExtendData refExtendBucket = findBucket(sBucketLabel);
717
718 Vector vExtendFields = refExtendBucket.getFieldDataObjects();
719
720 // bucket id is necessary
721 tmpBucket.setBucketStructId(refExtendBucket.getId());
722
723 // fill in the field data
724 for (int i=0; i<vExtendFields.size(); i++) {
725 tmpSFED = (ServerFieldExtendData) vExtendFields.elementAt(i);
726 sTmpLabel = tmpSFED.getLabel();
727 //BGPDebug(" . . . field label for "+sBucketLabel+" is "+sTmpLabel);
728
729 // The XML has the Bucket name and a period preceding
730 // the Field name, so we need to fix it up. (Also fix Spaces)
731 sTmpLabel = sBucketLabel + "." + spaceToSpecial(sTmpLabel);
732
733 // fetch the value from the hashtable
734 sTmpValue = (String) dataHash.get(sTmpLabel);
735 if (sTmpValue == null) {
736 tmpBucket.addValue("");
737 } else {
738 tmpBucket.addValue(sTmpValue);
739 BGPDebug(" + "+tmpSFED.getLabel()+" is >"+sTmpValue+"<");
740 }
741 }
742 printHashtable(dataHash,"Bucket");
743
744 return tmpBucket;
745 }
746
747 /*
748 * createElement()
749 */
750 DisguiseElementRecordData createElement()
751 {
752 //BGPDebug(" >>>> Create an element");
753
754 DisguiseElementRecordData tmpElement = new DisguiseElementRecordData();
755 ServerFieldExtendData tmpSFED = null;
756 String sTmpLabel = null;
757 String sTmpValue = null;
758
759 ServerBucketExtendData refExtendBucket = findBucket(BucketConstantsI.ELEMENT_BUCKET);
760
761 Vector vExtendFields = refExtendBucket.getFieldDataObjects();
762
763 // bucket id is necessary
764 tmpElement.setBucketStructId(refExtendBucket.getId());
765
766 // if there is no element data, don't bother filling in the fields.
767 if (!dataHash.isEmpty()) {
768 // fill in the field data
769 for (int i=0; i<vExtendFields.size(); i++) {
770 tmpSFED = (ServerFieldExtendData) vExtendFields.elementAt(i);
771 sTmpLabel = tmpSFED.getLabel();
772 //BGPDebug(" . . . field label for ELEMENT is "+sTmpLabel);
773
774 // The XML has the Bucket name and a period preceding
775 // the Field name, so we need to fix it up. (Also fix Spaces)
776 sTmpLabel = "ELEMENT." + spaceToSpecial(sTmpLabel);
777
778 // fetch the value from the hashtable
779 sTmpValue = (String) dataHash.get(sTmpLabel);
780 if (sTmpValue == null) {
781 tmpElement.addValue("");
782 } else {
783 tmpElement.addValue(sTmpValue);
784 BGPDebug(" + "+tmpSFED.getLabel()+" is >"+sTmpValue+"<");
785 }
786 }
787 }
788 //printHashtable(dataHash,"Element");
789
790 return tmpElement;
791 }
792
793 /*
794 * createAsset(parent_or_default)
795 * The "sAssetRole" fed into this createAsset() is not a true AssetRoleData
796 * it is merely a string "parent" or "default" used as an XML tag and interpreted
797 * as either a highres or thumbnail
798 */
799 DisguiseAssetRecordData createAsset(String sAssetRole)
800 {
801 //BGPDebug(" >>>> Create an asset ; role is "+sAssetRole);
802
803 DisguiseAssetRecordData tmpAsset = new DisguiseAssetRecordData();
804 ServerFieldExtendData tmpSFED = null;
805 String sTmpLabel = null;
806 String sRealLabel = null;
807 String sTmpValue = null;
808
809
810 ServerBucketExtendData refExtendBucket = findBucket(BucketConstantsI.ASSET_BUCKET);
811
812 Vector vExtendFields = refExtendBucket.getFieldDataObjects();
813
814 // the bucketstruct id is necessary
815 tmpAsset.setBucketStructId(refExtendBucket.getId());
816
817 tmpAsset.setReceived(receivedDate);
818 tmpAsset.setUserId(ctlUserId);
819
820 // If we were not told what kind of asset this is, it must
821 // be the first one and we will declare it a parent (highres).
822 if (sAssetRole == null) sAssetRole = new String("parent");
823
824 // a "parent" is a highres; a "default" is a thumbnail
825 if (sAssetRole.equals("parent")) {
826 //BGPDebug(" This is a parent. Set role to Highres.");
827 tmpAsset.setAssetRole(new HighresRoleData());
828 tmpAsset.setAssetFileType(sTypeOut);
829 } else if (sAssetRole.equals("default")) {
830 BGPDebug(" This is a default. Set role to Thumbnail.");
831 tmpAsset.setAssetRole(new ThumbnailRoleData());
832 // Check if we have set a Default View before. If so, don't set it again.
833 if (!bDefViewDone) {
834 tmpAsset.setDefaultView(true);
835 bDefViewDone = true;
836 }
837 } else {
838 BGPDebug("Untold type of asset role (parent/default/etc). This is not right.");
839 }
840
841 // if this is a J-item, the children (which represent A-items) should be TEMP.
842 // (this won't change the actual J-item PDF file because the bThisIsJitem variable
843 // is set after this is checked.
844 if (bThisIsJitem == true) {
845 BGPDebug(" ::::::: next assets listed are part of a J-item");
846 /*
847 AssetRoleData theAssetRole = tmpAsset.getAssetRole();
848 theAssetRole.setTempRole(true);
849 tmpAsset.setAssetRole(theAssetRole);
850 */
851 }
852
853 // if there is no asset data then it'll be hard to create a meaningful asset
854 // (we should probably drop an error
855 if (dataHash.isEmpty()) {
856 BGPDebug("An empty XML asset was found. This is probably not good.");
857 } else {
858 // fill in the field data
859 for (int i=0; i<vExtendFields.size(); i++) {
860 tmpSFED = (ServerFieldExtendData) vExtendFields.elementAt(i);
861 sRealLabel = tmpSFED.getLabel();
862 //BGPDebug(" . . . field label for ASSET is "+sTmpLabel);
863
864 // The XML has the Bucket name and a period preceding
865 // the Field name, so we need to fix it up. (Also fix Spaces)
866 sTmpLabel = "ASSET." + spaceToSpecial(sRealLabel);
867
868 // fetch the value from the hashtable
869 sTmpValue = (String) dataHash.get(sTmpLabel);
870 if (sTmpValue == null) {
871 //tmpAsset.addValue("");
872 // if a user-defined field has been left blank, I should put an
873 // empty string into the hashtable. (Don't bother with system fields)
874 if (!tmpSFED.isSystemRequired()) {
875 if (sRealLabel.indexOf(" ") == -1) {
876 //BGPDebug(sTmpLabel + " must be a user field.");
877 dataHash.put(sTmpLabel,"");
878 tmpAsset.addUserData(sRealLabel,"");
879 }// else {
880 // BGPDebug("["+sTmpLabel + "] has a space in it! skip.");
881 //}
882 }
883 } else {
884 tmpAsset.addValue(sTmpValue);
885 dataHash.put(sTmpLabel,sTmpValue);
886 tmpAsset.addUserData(sRealLabel,sTmpValue);
887 BGPDebug("adding user data("+sRealLabel+"==="+sTmpValue+")");
888 //BGPDebug(" + "+tmpSFED.getLabel()+" is >"+sTmpValue+"<");
889 }
890 }
891 }
892
893
894 // We need to handle the SERVER/location/filename
895 // if it has been placed in a URL format.
896
897 if (sServerLocationFilename.length() == 0) {
898 BGPDebug(" * SLF is empty");
899 } else {
900 BGPDebug(" * SLF is "+sServerLocationFilename);
901 if (sServerLocationFilename.equals("booktechGenerate")) {
902 // Then we need to generate the server, location, and filename
903
904 // for server: use the server info from whatever server we got the XML file
905 tmpAsset.setServer(sOurServer);
906 BGPDebug("the server is now: " + tmpAsset.getServer());
907
908 // for filename: use system_segment1 with ".pdf" appended
909 String sFileGuess = ((String)dataHash.get("ASSET.system_segment1")) + ".pdf";
910 tmpAsset.setFileName(sFileGuess);
911 BGPDebug("the filename is now: " + tmpAsset.getFileName());
912
913 // for location: compute the "numbered directory" for the A-item number
914 // and append it to the sHighFileListBase
915 String sLocationGuess = (String)dataHash.get("ASSET.system_segment1");
916 // check to make sure we didn't get a null or a zero length string
917 if ( (sLocationGuess == null) || (sLocationGuess.length() == 0) ) {
918 BGPDebug("!unable to generate numbered directory!");
919 bMajorFailure = true;
920 } else {
921 sLocationGuess = sLocationGuess.substring(1);
922 // Mail message from Mike Perera on Fri, 4 Aug 2000 gives formula as:
923 // 0-1000 = subdirectory 1
924 // 1001-2000 = 2
925 // 2001-3000 = 3
926 // 3001-4000 = 4
927 // which gets turned into (((Number - 1) / 1000) + 1)
928 int numberedDirectory = ((int)((Integer.parseInt(sLocationGuess) -1) / 1000)) +1;
929 sLocationGuess = sHighFileListBase + String.valueOf(numberedDirectory) + "/";
930 tmpAsset.setLocation(sLocationGuess);
931 BGPDebug("the location is now: " + tmpAsset.getLocation());
932
933 // If this is a J-item, the file will not exist, so that's okay.
934 if (sFileGuess.startsWith("J")) {
935 // Also, if this is a J-item, the children should be TEMP.
936 bThisIsJitem = true;
937 BGPDebug("This is a J-item");
938 // else this is not a J-item, so the file should actually exist.
939 } else {
940 // test if the file actually exists. If it doesn't, fail the service.
941 File PDFile = new File("/" + sLocationGuess + sFileGuess);
942 if (!(PDFile.isFile() && PDFile.canRead())) {
943 // If this is not a J-item
944 BGPDebug("File "+PDFile.getPath()+" doesn't exist or can't be read.");
945 // 6070=File %%1 does not exist or permission (read/write) denied
946 new FlexError(FlexError.CRITICAL, sThisService, IDENTIFIER, 6070,
947 new String[] { PDFile.getPath() } );
948 bMajorFailure = true;
949 } //else carry on.
950 }
951 }
952 } else {
953 sTmpLabel = "ASSET." + spaceToSpecial(sServerLocationFilename);
954 sTmpValue = (String) dataHash.get(sTmpLabel);
955 if (sTmpValue != null) {
956 String sServer = null;
957 String sLocation = null;
958 String sFilename = null;
959
960 // 07-14-2000 Various emails inform me that the ServerLocationFilename
961 // will be of the form http://SERVER/LOCA/TION/FILENAME
962 sTmpValue = (String) dataHash.get(sTmpLabel);
963 // Some error checking would be good throughout to make sure it is valid.
964
965 // strip off the http://
966 if (sTmpValue.startsWith("http://")) {
967 sTmpValue = sTmpValue.substring(7);
968 }
969
970 // obtain the server
971 // How about some error checking for indexOf? what if there's no '/'?
972 int iSlashIndex1 = sTmpValue.indexOf("/");
973 sServer = sTmpValue.substring(0,iSlashIndex1);
974 //BGPDebug(" sServer: "+sServer);
975 tmpAsset.setServer(sServer);
976
977 // obtain the location
978 // How about some error checking for indexOf? what if there's no '/'?
979 int iSlashIndex2 = sTmpValue.lastIndexOf("/");
980 sLocation = sTmpValue.substring(iSlashIndex1,iSlashIndex2);
981 //BGPDebug(" sLocation: "+sLocation);
982 tmpAsset.setLocation(sLocation);
983
984 // obtain the filename
985 sFilename = sTmpValue.substring((iSlashIndex2) + 1);
986 //BGPDebug(" sFilename: "+sFilename);
987 tmpAsset.setFileName(sFilename);
988 }
989 }
990 }
991
992 sTmpLabel = new String("Server");
993 sTmpLabel = "ASSET." + spaceToSpecial(sTmpLabel);
994 sTmpValue = (String) dataHash.get(sTmpLabel);
995 if (sTmpValue != null) {
996 tmpAsset.setServer(sTmpValue);
997 }
998 // We need to handle the server/LOCATION/filename
999 sTmpLabel = new String("Location");
1000 sTmpLabel = "ASSET." + spaceToSpecial(sTmpLabel);
1001 sTmpValue = (String) dataHash.get(sTmpLabel);
1002 if (sTmpValue != null) {
1003 tmpAsset.setLocation(sTmpValue);
1004 }
1005 // We need to handle the server/location/FILENAME
1006 sTmpLabel = new String("File Name");
1007 sTmpLabel = "ASSET." + spaceToSpecial(sTmpLabel);
1008 sTmpValue = (String) dataHash.get(sTmpLabel);
1009 if (sTmpValue != null) {
1010 tmpAsset.setFileName(sTmpValue);
1011 }
1012
1013 //printHashtable(dataHash,"Asset");
1014
1015 return tmpAsset;
1016 }
1017
1018 /*
1019 * specialToSpace()
1020 */
1021 String specialToSpace(String sSomeString)
1022 {
1023 return sSomeString.replace('_',' ');
1024 }
1025
1026 /*
1027 * spaceToSpecial()
1028 */
1029 String spaceToSpecial(String sSomeString)
1030 {
1031 return sSomeString.replace(' ','_');
1032 }
1033
1034 /*
1035 * printHashtable()
1036 */
1037 public void printHashtable(Hashtable hTable, String sLabel)
1038 {
1039 Enumeration dataKeys = hTable.keys();
1040 String keyString;
1041 String valString;
1042
1043 if (hTable.size() > 0) {
1044 while(dataKeys.hasMoreElements()) {
1045 keyString = (String) dataKeys.nextElement();
1046 valString = (String) hTable.get(keyString);
1047 BGPDebug("\t==="+sLabel+"===> " + keyString + " = " + valString);
1048 }
1049 } else {
1050 BGPDebug("\t==="+sLabel+"=== has no data");
1051 }
1052 }
1053
1054
1055 /**
1056 * Return the BucketExtendData of the bucket matching a given label
1057 */
1058 ServerBucketExtendData findBucket(String sBucketLabel) {
1059
1060 for (int i=0; i<allBucketExtend.length; i++) {
1061 if (sBucketLabel.equalsIgnoreCase(allBucketExtend[i].getLabel()) == true)
1062 return allBucketExtend[i];
1063 }
1064 // if we make it this far, we didn't find a bucket with that label
1065 BGPDebug("Inavlid bucket. No bucket found with label {"+sBucketLabel+"}");
1066 return null;
1067 }
1068
1069
1070 /**
1071 * Return the BucketExtendData of the bucket matching a given type
1072 */
1073 ServerBucketExtendData findBucket(int typeToSearchFor) {
1074
1075 for (int i=0; i<allBucketExtend.length; i++) {
1076 if ((allBucketExtend[i].getBucketType()) == typeToSearchFor)
1077 return allBucketExtend[i];
1078 }
1079 // if we make it this far, we didn't find a bucket of that type
1080 BGPDebug("Inavlid bucket. No bucket found of type {"+typeToSearchFor+"}");
1081 return null;
1082 }
1083
1084
1085 /*
1086 * BGPDebug(String of debug text)
1087 */
1088 void BGPDebug(String sSomeString)
1089 {
1090 boolean printMessages = true;
1091 if (printMessages == true)
1092 Diagnostic.trace(DiagnosticBase.APPSERVER_IMPORT, sSomeString);
1093 }
1094
1095
1096 /*
1097 * This method originally written by dnickel for booktech service
1098 */
1099 String translateServer( String serv )
1100 {
1101 if ( servers.get( serv ) != null )
1102 return (String)servers.get( serv );
1103
1104 return serv;
1105 }
1106
1107 /*
1108 * This method originally written by dnickel for booktech service
1109 */
1110 String translateLocation( String loc )
1111 {
1112 Enumeration e = locations.keys();
1113 String rloc = null;
1114
1115 while ( e.hasMoreElements() )
1116 {
1117 rloc = (String)e.nextElement();
1118 if ( loc.startsWith(rloc) )
1119 {
1120 String offsetPath = loc.substring( rloc.length() );
1121 rloc = (String)locations.get( rloc ) + offsetPath;
1122 System.out.println("ERPUpdate: Virtual Location Detected [" + loc + "] >> [" + rloc + "]");
1123 return rloc;
1124 }
1125 }
1126 return loc;
1127 }
1128
1129
1130
1131 /**
1132 *
1133 */
1134 private long getSequence()
1135 {
1136 long nAssetId = -1;
1137 try
1138 {
1139 if ( seqGateway == null )
1140 {
1141 seqGateway = new SequenceGateway();
1142 seqGateway.connect();
1143 }
1144 nAssetId = seqGateway.getSequence( SequenceConstantsI.ASSET_ID, "ALL_ASSET_RECORD", "ASSET_ID" );
1145 //BGPDebug("####### Sequence number is " + nAssetId);
1146 }
1147 catch(TransactionFailedException rtfe) {}
1148 return nAssetId;
1149 }
1150
1151}
1152