KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > openharmonise > rm > factory > HarmoniseObjectFactory


1 /*
2  * The contents of this file are subject to the
3  * Mozilla Public License Version 1.1 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at http://www.mozilla.org/MPL/
6  *
7  * Software distributed under the License is distributed on an "AS IS"
8  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
9  * See the License for the specific language governing rights and
10  * limitations under the License.
11  *
12  * The Initial Developer of the Original Code is Simulacra Media Ltd.
13  * Portions created by Simulacra Media Ltd are Copyright (C) Simulacra Media Ltd, 2004.
14  *
15  * All Rights Reserved.
16  *
17  * Contributor(s):
18  */

19 package org.openharmonise.rm.factory;
20
21 import java.io.FileReader JavaDoc;
22 import java.util.*;
23 import java.util.logging.*;
24
25 import javax.xml.transform.*;
26 import javax.xml.transform.dom.*;
27 import javax.xml.transform.stream.StreamSource JavaDoc;
28
29 import org.openharmonise.commons.cache.CacheException;
30 import org.openharmonise.commons.dsi.*;
31 import org.openharmonise.commons.xml.*;
32 import org.openharmonise.rm.PopulateException;
33 import org.openharmonise.rm.commands.AbstractCmd;
34 import org.openharmonise.rm.config.ConfigSettings;
35 import org.openharmonise.rm.dsi.DataStoreInterfaceFactory;
36 import org.openharmonise.rm.metadata.Profile;
37 import org.openharmonise.rm.publishing.*;
38 import org.openharmonise.rm.resources.*;
39 import org.openharmonise.rm.resources.lifecycle.Editable;
40 import org.openharmonise.rm.resources.publishing.WebPage;
41 import org.w3c.dom.*;
42
43
44
45 /**
46  * Factory class which provides a single point of access to instances of the
47  * core Harmonise objects, providing various methods for returning instances
48  * based on either class names or XML elements. This class uses the factory XSLT
49  * file to find class name and cache key information from XML element names. This file
50  * will contain templates such as the following:
51  *
52  * <code>
53  * <xsl:template match="User">
54  * <org.openharmonise.rm.resources.users.User cacheKeyType="id"/>
55  * </xsl:template>
56  * </code>
57  *
58  * @author Michael Bell
59  * @version $Revision: 1.5 $
60  *
61  */

62 public class HarmoniseObjectFactory {
63     //XML constants
64

65     /**
66      * Attribute used to specify the cache key type in factory.xsl
67      */

68     public static final String JavaDoc ATTRIB_CACHE_KEY_TYPE = "cacheKeyType";
69     
70     /**
71      * Attribute used to specifiy the class name of the <code>ClassFinder</code>
72      * class for a given XML element.
73      */

74     public static final String JavaDoc ATTRIB_CLASS_FINDER = "classFinder";
75     
76     /**
77      * Configuration property name for the property which specifies the
78      * name of the factory XSLT file
79      */

80     private static String JavaDoc PNAME_CLASS_FACTORY_XSL = "CLASS_FACTORY_XSL";
81     
82     /**
83      * Constant value used for the cache key attribute to specify that
84      * the object does not get cached
85      */

86     public static final String JavaDoc NOT_APPLICABLE = "NA";
87     
88     /**
89      * The file path of the factory XSLT file
90      */

91     private static String JavaDoc factory_xsl_path = null;
92     
93     /**
94      * The factory XSLT <code>Templates</code> object
95      */

96     private static Templates factory_templates = null;
97     
98     /**
99      * Cache of element name to class name mappings
100      */

101     private static Map m_classname_cache = Collections.synchronizedMap(new HashMap());
102
103     /**
104      * Logger for this class
105      */

106     private static final Logger m_logger = Logger.getLogger(HarmoniseObjectFactory.class.getName());
107     
108     //static initialiser black
109
static {
110         try {
111             factory_xsl_path = ConfigSettings.getProperty(PNAME_CLASS_FACTORY_XSL);
112
113             if (factory_xsl_path == null) {
114                 throw new HarmoniseFactoryException("Error getting factory.xsl path");
115             }
116         } catch (Exception JavaDoc e) {
117             m_logger.log(Level.WARNING, e.getLocalizedMessage(), e);
118         }
119     }
120
121     /**
122      * Returns an instance of <code>AbstractObject</code> of the specified class name and
123      * path using the given data store interface.
124      *
125      * @param dbinterf the data store interface
126      * @param sClassname the class name
127      * @param sPath the harmonise path of the desired object
128      * @return an instance of <code>AbstractObject</code> of the specified class name and
129      * path
130      * @throws HarmoniseFactoryException if any errors occur
131      */

132     public static AbstractObject instantiateHarmoniseObject(AbstractDataStoreInterface dbinterf,
133                                                  String JavaDoc sClassname,
134                                                  String JavaDoc sPath)
135                                           throws HarmoniseFactoryException {
136         AbstractObject ohObj = null;
137
138         try {
139             ohObj = (AbstractObject) instantiateObject(dbinterf, sClassname, sPath);
140         } catch (ClassCastException JavaDoc e) {
141             throw new HarmoniseFactoryException("Object not an HarmoniseObject", e);
142         }
143
144         return ohObj;
145     }
146
147     /**
148      * Returns an instance of <code>Publishable<code> of the specified class name and
149      * path using the given data store interface.
150      *
151      * @param dbinterf the data store interface
152      * @param sClassname the class name
153      * @param sPath the harmonise path of the desired object
154      * @return an instance of <code>Publishable<code> of the specified class name and
155      * path
156      * @throws HarmoniseFactoryException if any errors occur
157      */

158     public static Publishable instantiatePublishableObject(AbstractDataStoreInterface dbinterf,
159                                                                  String JavaDoc sClassname,
160                                                                  String JavaDoc sPath)
161         throws HarmoniseFactoryException {
162         Publishable pubObj = null;
163
164         try {
165             pubObj = (Publishable) instantiateObject(dbinterf, sClassname,
166                                                            sPath);
167         } catch (ClassCastException JavaDoc e) {
168             throw new HarmoniseFactoryException("Object not a PublishableObject", e);
169         }
170
171         return pubObj;
172     }
173
174     /**
175      * Returns an instance of <code>AbstractObject</code> of the specified class name and
176      * id using the given data store interface.
177      *
178      * @param dbinterf the data store interface
179      * @param sClassname the class name
180      * @param nId the object id
181      * @return an instance of <code>AbstractObject</code> of the specified class name and
182      * id
183      * @throws HarmoniseFactoryException if any errors occur
184      */

185     public static AbstractObject instantiateHarmoniseObject(AbstractDataStoreInterface dbinterf,
186                                                  String JavaDoc sClassname, int nId)
187                                           throws HarmoniseFactoryException {
188         AbstractObject obj = null;
189
190         try {
191             obj = (AbstractObject) instantiateObject(dbinterf, sClassname, nId);
192         
193             //ensure object really exists if the id is greater than 0
194
if(nId > 0 && obj.exists() == false) {
195                 obj = null;
196             }
197         
198         } catch (ClassCastException JavaDoc e) {
199             throw new HarmoniseFactoryException("Object not an HarmoniseObject", e);
200         }
201
202         return obj;
203     }
204
205     /**
206      * Returns an instance of <code>Publishable<code> of the specified class name and
207      * id using the given data store interface.
208      *
209      * @param dbinterf the data store interface
210      * @param sClassname the class name
211      * @param nId the object id
212      * @return an instance of <code>Publishable<code> of the specified class name and
213      * id
214      * @throws HarmoniseFactoryException if any errors occur
215      */

216     public static Publishable instantiatePublishableObject(AbstractDataStoreInterface dbinterf,
217                                                                  String JavaDoc sClassname,
218                                                                  int nId)
219         throws HarmoniseFactoryException {
220         Publishable pubObj = null;
221
222         try {
223             pubObj = (Publishable) instantiateObject(dbinterf, sClassname,
224                                                            nId);
225         } catch (ClassCastException JavaDoc e) {
226             throw new HarmoniseFactoryException("Object not a PublishableObject", e);
227         }
228
229         return pubObj;
230     }
231
232     /**
233      * Returns an instance of <code>AbstractObject</code> which matches the
234      * the given XML element, taking any necessary additional information from the
235      * <code>State</code> object given.
236      *
237      * @param dbinterf the data store interface
238      * @param element the XML element representing the object to be instantiated
239      * @param state the state represenation
240      * @return an instance of <code>AbstractObject</code> which matches the
241      * the given XML element
242      * @throws HarmoniseFactoryException if any errors occur
243      */

244     public static AbstractObject instantiateHarmoniseObject(AbstractDataStoreInterface dbinterf,
245                                                  Element element,
246                                                  State state)
247                                           throws HarmoniseFactoryException {
248         AbstractObject ohObj = null;
249
250         try {
251             ohObj = (AbstractObject) instantiateObject(dbinterf, element, state);
252         } catch (ClassCastException JavaDoc e) {
253             throw new HarmoniseFactoryException("Object not an HarmoniseObject", e);
254         }
255
256         return ohObj;
257     }
258
259     /**
260      * Returns an instance of <code>Publishable</code> which matches the
261      * the given XML element, taking any necessary additional information from the
262      * <code>State</code> object given.
263      *
264      * @param dbinterf the data store interface
265      * @param element the XML element representing the object to be instantiated
266      * @param state the state represenation
267      * @return an instance of <code>Publishable</code> which matches the
268      * the given XML element
269      * @throws HarmoniseFactoryException
270      */

271     public static Publishable instantiatePublishableObject(AbstractDataStoreInterface dbinterf,
272                                                                  Element element,
273                                                                  State state)
274         throws HarmoniseFactoryException {
275         Publishable ohObj = null;
276
277
278         ohObj = (Publishable) instantiateObject(dbinterf, element, state);
279
280         return ohObj;
281     }
282
283     /**
284      * Returns a list of objects from the WorkflowObject XML element.
285      *
286      * @param dbinterf the data store interface
287      * @param wf_root the WorkflowObject XML element
288      * @param state the state representation
289      * @return a list of objects
290      * @throws HarmoniseFactoryException if any errors occur
291      */

292     public static List instantiateWorkflowObjects(AbstractDataStoreInterface dbinterf,
293                                                     Element wf_root,
294                                                     State state)
295                                              throws HarmoniseFactoryException {
296         Vector wrkflwObjs = new Vector(16);
297
298         Element state_profile = null;
299
300         NodeList profile_nodes = state.getElementsByTagName(Profile.TAG_PROFILE);
301
302         for (int i = 0; i < profile_nodes.getLength(); i++) {
303             if (((Element) profile_nodes.item(i)).getAttribute(
304                         WebPage.ATTRIB_NAME).equalsIgnoreCase("Profile") ||
305                     ((Element) profile_nodes.item(i)).getAttribute(
306                             WebPage.ATTRIB_NAME).equalsIgnoreCase("Default")) {
307                 state_profile = (Element) profile_nodes.item(i);
308             }
309         }
310
311         NodeList wf_nodes = wf_root.getChildNodes();
312
313         for (int i = 0; i < wf_nodes.getLength(); i++) {
314             // ignore non-element nodes
315
if (wf_nodes.item(i).getNodeType() != Node.ELEMENT_NODE) {
316                 continue;
317             }
318
319             Element workflow_element = (Element) wf_nodes.item(i);
320
321             //skip Event tags
322
if (workflow_element.getTagName().equalsIgnoreCase(AbstractCmd.TAG_COMMAND)) {
323                 continue;
324             }
325             List vObjElements = state.findElements(workflow_element);
326
327             if (vObjElements.size() == 0) {
328                 vObjElements.add(workflow_element);
329             }
330
331             Editable wrkflwObj = null;
332
333             for (int j = 0; j < vObjElements.size(); j++) {
334                 Element elTemp = (Element) vObjElements.get(j);
335
336                 wrkflwObj = (Editable) instantiateObject(dbinterf, elTemp,
337                                                                state);
338
339                 if (wrkflwObj != null) {
340                     try {
341                         ((Publishable) wrkflwObj).populate(elTemp,state);
342                     } catch (PopulateException e) {
343                         throw new HarmoniseFactoryException("Populate error",e);
344                     }
345
346                     wrkflwObjs.addElement(wrkflwObj);
347                 }
348             }
349         }
350
351         if (m_logger.isLoggable(Level.FINE)) {
352             m_logger.logp(Level.FINE, HarmoniseObjectFactory.class.getName(), "instantiateWorkflowObjects", "Got following WorkflowObjects from cache: " +
353                                wrkflwObjs);
354         }
355
356         return wrkflwObjs;
357     }
358     
359     /*-----------------------------------------------------------------------------
360          Private methods
361          ------------------------------------------------------------------------------*/

362     
363
364     /**
365      * Returns an instance of an object of the given class name and id using
366      * the given data store interface.
367      *
368      * @param dbinterf the data store interface
369      * @param sClassname the class name
370      * @param nId the object id
371      * @return an instance of an object of the given class name and id
372      * @throws HarmoniseFactoryException if any errors occur
373      */

374     private static Object JavaDoc instantiateObject(AbstractDataStoreInterface dbinterf,
375                                             String JavaDoc sClassname, int nId)
376                                      throws HarmoniseFactoryException {
377         Object JavaDoc obj;
378         try {
379             obj =
380                 (Object JavaDoc) CacheHandler.getInstance(dbinterf).getObject(
381                     sClassname,
382                     nId);
383         } catch (CacheException e) {
384             throw new HarmoniseFactoryException("Error getting object from cache",e);
385         }
386         
387         if(m_logger.isLoggable(Level.FINER)) {
388             m_logger.logp(Level.FINER, HarmoniseObjectFactory.class.getName(), "insantiateObject", "instantiating " + sClassname + " with id " + nId);
389         }
390
391         return obj;
392     }
393
394     /**
395      * Returns an instance of an object of the given class name and path using
396      * the given data store interface.
397      *
398      * @param dbinterf the data store interface
399      * @param sClassname the class name
400      * @param sPath the harmonise path of the desired object
401      * @return an instance of an object of the given class name and path
402      * @throws HarmoniseFactoryException if any errors occur
403      */

404     private static Object JavaDoc instantiateObject(AbstractDataStoreInterface dbinterf,
405                                             String JavaDoc sClassname, String JavaDoc sPath)
406                                      throws HarmoniseFactoryException {
407         AbstractObject ohObj;
408         try {
409             ohObj =
410                 (AbstractObject) CacheHandler.getInstance(
411                     dbinterf).getObjectFromPath(
412                     sClassname,
413                     sPath);
414         } catch (CacheException e) {
415             throw new HarmoniseFactoryException("Error getting object from cache" ,e);
416         }
417
418         if(m_logger.isLoggable(Level.FINER)) {
419             m_logger.logp(Level.FINER, HarmoniseObjectFactory.class.getName(), "insantiateObject", "instantiating " + sClassname + " with path " + sPath);
420         }
421         
422         return ohObj;
423     }
424
425     /**
426      * Returns an instance of an object which matches the
427      * the given XML element, taking any necessary additional information from the
428      * <code>State</code> object given.
429      *
430      * @param dbinterf the data store interface
431      * @param element the XML element representing the object to be instantiated
432      * @param state the state representation
433      * @return an instance of an object which matches the
434      * the given XML element
435      * @throws HarmoniseFactoryException if any errors occur
436      */

437     private static Object JavaDoc instantiateObject(AbstractDataStoreInterface dbinterf,
438                                             Element element, State state)
439                                      throws HarmoniseFactoryException {
440         Object JavaDoc Obj = null;
441         boolean bUsingPath = false;
442
443         Element classElement = getClassElement(dbinterf, element);
444
445         String JavaDoc sClassName = classElement.getTagName();
446         
447         if(m_logger.isLoggable(Level.FINE)) {
448             m_logger.logp(Level.FINE, HarmoniseObjectFactory.class.getName(), "instantiateObject", "Instantiating object from XML: element - " + sClassName + " and state");
449         }
450         
451         String JavaDoc sCacheKeyType = classElement.getAttribute(ATTRIB_CACHE_KEY_TYPE);
452         String JavaDoc sClassFinder = classElement.getAttribute(ATTRIB_CLASS_FINDER);
453
454         if (sCacheKeyType.equalsIgnoreCase(NOT_APPLICABLE) == true) {
455             try {
456                 Obj = GeneralCache.createObject(dbinterf, sClassName);
457             } catch (CacheException e) {
458                 throw new HarmoniseFactoryException("Error getting object from cache",e);
459             }
460         } else {
461             String JavaDoc sCacheKey = element.getAttribute(sCacheKeyType);
462
463             // if we didn't find a key, first try the path, then if we don't have that
464
// get the first one off the state
465
if ((sCacheKey == null) || (sCacheKey.length() == 0)) {
466                 String JavaDoc sPath = findObjectPath(element, state);
467
468                 if ((sPath != null) && (sPath.length() > 0)) {
469                     sCacheKey = sPath;
470                     bUsingPath = true;
471                 }
472
473                 if ((bUsingPath == false) && (state != null)) {
474                     Element el = state.findElement(element);
475
476                     if (el != null) {
477                         sCacheKey = el.getAttribute(sCacheKeyType);
478
479                         if ((sCacheKey == null) ||
480                                 (sCacheKey.length() == 0)) {
481                             sCacheKey = findObjectPath(el, state);
482                             bUsingPath = true;
483                         }
484                     }
485                 }
486             }
487
488             // ids are ints, everything other type of key is a String
489
if (bUsingPath) {
490                 try {
491                     Obj = (Object JavaDoc) CacheHandler.getInstance(dbinterf)
492                                                    .getObjectFromPath(sClassName,
493                                                                       sCacheKey);
494                 } catch (CacheException e) {
495                     throw new HarmoniseFactoryException("Error getting object from cache",e);
496                 }
497             } else if (sCacheKeyType.equals(AbstractObject.ATTRIB_ID)) {
498                 int nId = -1;
499
500                 if (sCacheKey != null) {
501                     try {
502                         nId = Integer.parseInt(sCacheKey);
503                     } catch (NumberFormatException JavaDoc e) {
504                         nId = -1;
505                     }
506                 }
507
508                 if ((sClassFinder != null) && (sClassFinder.length() > 0)) {
509                     try {
510                         ClassFinder finder = ClassFinderFactory.getInstance(
511                                                      dbinterf)
512                                                                .getClassFinder(sClassFinder);
513                         sClassName = finder.getClass(nId);
514                     } catch (ClassFinderException e) {
515                         throw new HarmoniseFactoryException("Exception",e);
516                     }
517                 }
518
519
520                 try {
521                     Obj = (Object JavaDoc) CacheHandler.getInstance(dbinterf)
522                                                    .getObject(sClassName, nId);
523                 } catch (CacheException e) {
524                     throw new HarmoniseFactoryException("Error getting object from cache",e);
525                 }
526             } else {
527                 try {
528                     Obj = (Object JavaDoc) CacheHandler.getInstance(dbinterf)
529                                                    .getObject(sClassName, sCacheKey);
530                 } catch (CacheException e) {
531                     throw new HarmoniseFactoryException("Error getting object from cache",e);
532                 }
533             }
534         }
535
536         if (m_logger.isLoggable(Level.FINER)) {
537             m_logger.logp(Level.FINER, HarmoniseObjectFactory.class.getName(), "instantiateObject", "Got following Object from cache: " + Obj);
538         }
539
540         return Obj;
541     }
542
543     /**
544      * Returns the class name associated to the given XML element, taken
545      * from the factory XSLT.
546      *
547      * @param dbintrf the data store interface
548      * @param element the XML element
549      * @return the class name associated to the given XML element
550      * @throws HarmoniseFactoryException if any errors occur
551      */

552     public static String JavaDoc getClassName(AbstractDataStoreInterface dbintrf,
553                                       Element element)
554                                throws HarmoniseFactoryException {
555         String JavaDoc sTagName = XMLUtils.getElementName(element);
556         String JavaDoc sClassname = (String JavaDoc) m_classname_cache.get(sTagName);
557         
558         //double checked synchonized block
559
if(sClassname == null) {
560             synchronized (m_classname_cache) {
561                 if(sClassname == null) {
562                     sClassname = getClassElement(dbintrf, element).getTagName();
563                     
564                     m_classname_cache.put(sTagName, sClassname);
565                 }
566             }
567         }
568         
569         return sClassname;
570     }
571
572     /**
573      * Returns the XML element from the factory XSLT whose tag name is
574      * the class name associated to the given XML element.
575      *
576      * @param dbintrf the data store interface
577      * @param element the XML element
578      * @return the XML element from the factory XSLT whose tag name is
579      * the class name associated to the given XML element
580      * @throws HarmoniseFactoryException if any errors occur
581      */

582     private static Element getClassElement(AbstractDataStoreInterface dbintrf,
583                                            Element element)
584                                     throws HarmoniseFactoryException {
585         Element classElement = null;
586
587         try {
588             XMLDocument inputDoc = new XMLDocument();
589             Element classNameEl = inputDoc.createElement(XMLUtils.getElementName(element));
590             inputDoc.appendChild(classNameEl);
591
592             XMLDocument outputDoc = new XMLDocument();
593             
594             StreamSource JavaDoc ssource = new StreamSource JavaDoc(new FileReader JavaDoc(factory_xsl_path));
595             
596             factory_templates = org.apache.xalan.xsltc.trax.TransformerFactoryImpl
597             .newInstance().newTemplates(ssource);
598             
599             Transformer trans = factory_templates.newTransformer();
600
601             DOMSource ds = new DOMSource(inputDoc.getDocumentElement());
602
603             DOMResult res = new DOMResult();
604
605             res.setNode(outputDoc);
606
607             trans.transform(ds, res);
608
609             classElement = outputDoc.getDocumentElement();
610
611             
612         } catch (Exception JavaDoc e) {
613             throw new HarmoniseFactoryException(e);
614         }
615
616         if (classElement == null) {
617             throw new HarmoniseFactoryException("No class found for element " +
618                                           element.getTagName());
619         }
620
621         return classElement;
622     }
623
624     /**
625      * Returns the absolute harmonise path from the given XML element which represents
626      * a harmonise object, taking context from the given <code>State</code> to
627      * resolve any relative path references found in the 'Path' child element
628      * of the given element.
629      *
630      * @param element the object XML element
631      * @param state the state context
632      * @return the absolute harmonise path from the given XML element
633      * @throws HarmoniseFactoryException if any errors occur
634      */

635     private static String JavaDoc findObjectPath(Element element, State state)
636                                   throws HarmoniseFactoryException {
637         String JavaDoc sPath = null;
638         NodeList nodes = element.getChildNodes();
639
640         for (int i = 0; i < nodes.getLength(); i++) {
641             if (nodes.item(i).getNodeType() != Node.ELEMENT_NODE) {
642                 continue;
643             }
644
645             Element el = (Element) nodes.item(i);
646
647             if (el.getTagName().equals(AbstractChildObject.TAG_PATH)) {
648                 Text txt = (Text) el.getFirstChild();
649
650                 if (txt != null) {
651                     sPath = txt.getNodeValue().trim();
652
653                     // resolve relative paths, if necessary
654
if ((state != null) && sPath.startsWith(".")) {
655                         try {
656                             sPath = state.resolveRelativePath(element.getTagName(),
657                                                               sPath);
658                         } catch (Exception JavaDoc e) {
659                             throw new HarmoniseFactoryException("Error resolving relative path:" + e.getLocalizedMessage());
660                         }
661                     }
662                 }
663
664                 break;
665             }
666         }
667
668         return sPath;
669     }
670
671     /**
672      * @param xmlElement
673      * @return
674      */

675     public static String JavaDoc getClassName(Element xmlElement) throws HarmoniseFactoryException {
676         
677         
678         AbstractDataStoreInterface dsi = null;
679         
680         try {
681             dsi = DataStoreInterfaceFactory.getDataStoreInterface();
682         } catch (DataStoreException e) {
683             throw new HarmoniseFactoryException(e);
684         }
685         
686         return getClassName(dsi, xmlElement);
687     }
688 }
Popular Tags