1 /*
2 wsmo4j - a WSMO API and Reference Implementation
3
4 Copyright (c) 2004-2005, OntoText Lab. / SIRMA
5
6 This library is free software; you can redistribute it and/or modify it under
7 the terms of the GNU Lesser General Public License as published by the Free
8 Software Foundation; either version 2.1 of the License, or (at your option)
9 any later version.
10 This library is distributed in the hope that it will be useful, but WITHOUT
11 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
13 details.
14 You should have received a copy of the GNU Lesser General Public License along
15 with this library; if not, write to the Free Software Foundation, Inc.,
16 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18
19 /**
20 * <p>Title: WSMO4J</p>
21 * <p>Description: WSMO API and a Reference Implementation</p>
22 * <p>Copyright: Copyright (c) 2004-2005</p>
23 * <p>Company: OntoText Lab. / SIRMA </p>
24 */
25
26 package org.wsmo.factory;
27
28 import java.io.*;
29 import java.lang.reflect.*;
30 import java.util.*;
31
32 import org.wsmo.datastore.*;
33 import org.wsmo.locator.*;
34 import org.wsmo.validator.WsmlValidator;
35 import org.wsmo.wsml.*;
36
37 /**
38 * Factory interface
39 * The Factory is both a factory (creates objects) and a meta-factory (creates factories)
40 * Factory is <b>final</b>
41 * @author not attributable
42 * @version $Revision: 1946 $ $Date: 2007-04-02 15:13:28 +0300 (Mon, 02 Apr 2007) $
43 */
44
45 /**
46 * @stereotype factory*/
47 public final class Factory {
48
49 public final static String PROVIDER_CLASS = "provider";
50
51 public static final String WSMO_PARSER = "wsmo_parser";
52 public static final String WSMO_SERIALIZER = "wsmo_serializer";
53 public static final String WSML_VALIDATOR = "wsml_validator";
54 public static final String LE_FACTORY = "le_factory";
55 public static final String WSMO_FACTORY = "wsmo_factory";
56 public static final String DATA_FACTORY = "data_factory";
57
58 private static LocatorManager locManager;
59
60 private static boolean cachingEnabled;
61
62 private static Map <Map <String, Object>, Object> objectCache;
63
64 private static Properties defaultImplMap;
65 private static final String propertiesFile = "wsmo4j.properties";
66
67 static {
68 locManager = new LocatorManager();
69
70 //cache by default; we may add setCaching(boolean) later
71 cachingEnabled = true;
72
73 //DON'T use weak refs
74 objectCache = new HashMap <Map <String, Object>, Object>();
75
76 defaultImplMap = new Properties();
77
78 InputStream inProps = Thread.currentThread().getContextClassLoader()
79 .getResourceAsStream(propertiesFile);
80 if (inProps == null) {
81 inProps = Factory.class.getClassLoader().getResourceAsStream(propertiesFile);
82 }
83
84 if (inProps == null){
85 throw new RuntimeException("Error loading config file "+propertiesFile+" from class path");
86 }
87 try {
88 defaultImplMap.load(inProps);
89 }
90 catch(IOException ioe) {
91 throw new RuntimeException("Error loading config file ", ioe);
92 }
93 }
94
95 //singleton
96 private Factory(){
97 }
98
99 /**
100 * Creates a datastore based on the supplied preferences.
101 * At least one preference should be supplied - the provider class
102 * @see #PROVIDER_CLASS
103 * @param properties the preferences for the datastore. Such preferences
104 * should provide all the necessary information for the data store
105 * initialisation (e.g. provider class, connection URL,...,
106 * etc.)
107 * @return a reference to a datastore
108 */
109 public static DataStore createDatastore(Map properties) {
110
111 //0. preconditions
112 if (null == properties || false == properties.containsKey(Factory.PROVIDER_CLASS)) {
113 throw new IllegalArgumentException("Datastore class was not specified. There is NO default datastore implementation...");
114 }
115
116 Object result = _createObject(properties);
117
118 assert null != result;
119
120 //post-conditions
121 if (false == result instanceof DataStore) {
122 throw new RuntimeException(properties.get(Factory.PROVIDER_CLASS) + " does not implement the org.wsmo.datastore.Datastore interface");
123 }
124
125 return (DataStore)result;
126 }
127
128 /**
129 * Creates a WsmlValidator based on the supplied preferences.
130 * The properties map can contain the factories to be used as Strings or as
131 * instances. The WsmlValidator Constructor needs to check this and
132 * needs to create an instance of a given factory, if only the String
133 * is supplied.
134 * At least one preference should be supplied - the provider class.
135 *
136 * The validator can either only check a given TopEntity for validity,
137 * or it can also check all imported ontologies. By default, the validator
138 * does not check the imported ontologies.
139 * This feature can be
140 * enabled by adding a property to the properties map when creating the
141 * WsmlValidator. Another preference can be set, which references a map
142 * containing a mapping from logical URIs to physical locations:
143 * HashMap prefs = new HashMap();
144 * prefs.put(WsmlValidator.VALIDATE_IMPORTS, new Boolean(true));
145 * prefs.put(Locator.URI_MAPPING, mapping);
146 *
147 * @see #PROVIDER_CLASS
148 * @param properties the preferences for the validator.
149 * @return a wsmlValidator
150 */
151 public static WsmlValidator createWsmlValidator(Map <String, Object> properties) {
152
153 //preconditions
154 if (null == properties) {
155 properties = new HashMap <String, Object>();
156 }
157
158 //check provider
159 if (!properties.containsKey(Factory.PROVIDER_CLASS)) {
160 //set default Wsml Validator
161 properties.put(Factory.PROVIDER_CLASS,
162 defaultImplMap.getProperty(Factory.WSML_VALIDATOR));
163 }
164
165 // check LE factory
166 if (!properties.containsKey(Factory.LE_FACTORY)) {
167 //set default LogExpr factory
168 properties.put(Factory.LE_FACTORY,
169 defaultImplMap.getProperty(Factory.LE_FACTORY));
170 }
171
172 Object result = _createObject(properties);
173
174 assert null != result;
175
176 //post-conditions
177 if (false == result instanceof WsmlValidator) {
178 throw new RuntimeException(properties.get(Factory.PROVIDER_CLASS) +
179 " does not implement the org.wsmo.validator.WsmlValidator interface");
180 }
181
182 return (WsmlValidator) result;
183 }
184
185 /**
186 * Creates a parser based on the supplied preferences.
187 * The properties map can contain the factories to be used as Strings or as
188 * instances. The Parser Constructor needs to check this and
189 * needs to create an instance of a given factory, if only the String
190 * is supplied.
191 * At least one preference should be supplied - the provider class
192 * @see #PROVIDER_CLASS
193 * @see #PARSER_FACTORY
194 * @param properties the preferences for the parser. Such preferences
195 * should provide all the necessary information for the parser
196 * initialisation (e.g. provider class, factory to be used, file type, grammar version,
197 * etc.)
198 * @return a Parser
199 */
200 public static Parser createParser(Map <String, Object> properties) {
201
202 //preconditions
203 if (null == properties) {
204 properties = new HashMap <String, Object>();
205 }
206
207 //check provider
208 if (false == properties.containsKey(Factory.PROVIDER_CLASS)) {
209 //set default parser
210 properties.put(Factory.PROVIDER_CLASS,
211 defaultImplMap.getProperty(Factory.WSMO_PARSER));
212 }
213
214 //check WSMO factory
215 if (false == properties.containsKey(Factory.WSMO_FACTORY)) {
216 //set default WSMO factory
217 properties.put(Factory.WSMO_FACTORY,
218 defaultImplMap.getProperty(Factory.WSMO_FACTORY));
219 }
220
221 //check LE factory
222 if (false == properties.containsKey(Factory.LE_FACTORY)) {
223 //set default LogExpr factory
224 properties.put(Factory.LE_FACTORY,
225 defaultImplMap.getProperty(Factory.LE_FACTORY));
226 }
227
228 Object result = _createObject(properties);
229
230 assert null != result;
231
232 //post-conditions
233 if (false == result instanceof Parser) {
234 throw new RuntimeException(properties.get(Factory.PROVIDER_CLASS) + " does not implement the org.wsmo.wsml.Parser interface");
235 }
236
237 return (Parser)result;
238 }
239
240 /**
241 * Creates a serialiser based on the supplied preferences.
242 * At least one preference should be supplied - the provider class
243 * @see #PROVIDER_CLASS
244 * @param properties the preferences for the parser. Such preferences
245 * should provide all the necessary information for the parser
246 * initialisation (e.g. provider class, factory to be used, file type, grammar version,
247 * etc.)
248 * @return a Parser
249 */
250 public static Serializer createSerializer(Map <String, Object> properties) {
251
252 //preconditions
253 if (null == properties) {
254 properties = new HashMap <String, Object>();
255 }
256
257 //check provider
258 if (false == properties.containsKey(Factory.PROVIDER_CLASS)) {
259 //set default parser
260 properties.put(Factory.PROVIDER_CLASS,
261 defaultImplMap.getProperty(Factory.WSMO_SERIALIZER));
262 }
263
264 Object result = _createObject(properties);
265
266 assert null != result;
267
268 //post-conditions
269 if (false == result instanceof Serializer) {
270 throw new RuntimeException(properties.get(Factory.PROVIDER_CLASS) + " does not implement the org.wsmo.wsml.Serialiser interface");
271 }
272
273 return (Serializer)result;
274 }
275
276 /**
277 * Creates a WsmoFactory based on the supplied preferences.
278 * At least one preference should be supplied - the provider class
279 * @see #PROVIDER_CLASS
280 * @param properties the preferences for the WSMO factory. Such preferences
281 * should provide all the necessary information for the factory
282 * initialisation (e.g. provider class, etc.)
283 * @return a WsmoFactory
284 */
285 public static WsmoFactory createWsmoFactory(Map <String, Object> properties) {
286
287 //preconditions
288 if (null == properties) {
289 properties = new HashMap <String, Object>();
290 }
291
292 //check provider
293 if (false == properties.containsKey(Factory.PROVIDER_CLASS)) {
294 //use default WSMO factory
295 properties.put(Factory.PROVIDER_CLASS,
296 defaultImplMap.getProperty(Factory.WSMO_FACTORY));
297 }
298
299 Object result = _createFactory(properties);
300
301 assert null != result;
302
303 //post-conditions
304 if (false == result instanceof WsmoFactory) {
305 throw new RuntimeException(properties.get(Factory.PROVIDER_CLASS) + " does not implement the org.wsmo.factory.WsmoFactory interface");
306 }
307
308 return (WsmoFactory)result;
309 }
310
311
312 /**
313 * Creates a DataFactory based on the supplied preferences.
314 * The properties map can contain the factories to be used as Strings or as
315 * instances. The DataFactory Constructor needs to check this and
316 * needs to create an instance of a given factory, if only the String
317 * is supplied.
318 * At least one preference should be supplied - the provider class
319 * @see #PROVIDER_CLASS
320 * @param properties the preferences for the Data factory. Such preferences
321 * should provide all the necessary information for the factory
322 * initialisation (e.g. provider class, etc.)
323 * @return a DataFactory
324 */
325 public static DataFactory createDataFactory(Map <String, Object> properties) {
326
327 //preconditions
328 if (null == properties) {
329 properties = new HashMap <String, Object> ();
330 }
331
332 //check provider
333 if (false == properties.containsKey(Factory.PROVIDER_CLASS)) {
334 //use default data factory
335 properties.put(Factory.PROVIDER_CLASS,
336 defaultImplMap.getProperty(Factory.DATA_FACTORY));
337 }
338
339 Object result = _createFactory(properties);
340
341 assert null != result;
342
343 //post-conditions
344 if (false == result instanceof DataFactory) {
345 throw new RuntimeException(properties.get(Factory.PROVIDER_CLASS) + " does not implement the org.wsmo.factory.DataFactory interface");
346 }
347
348 return (DataFactory)result;
349 }
350
351 /**
352 * Creates a LogicalExpressionFactory based on the supplied preferences.
353 * The properties map can contain the factories to be used as Strings or as
354 * instances. The LogicalExpressionFactory Constructor needs to check this and
355 * needs to create an instance of a given factory, if only the String
356 * is supplied.
357 * At least one preference should be supplied - the provider class
358 * @see #PROVIDER_CLASS
359 * @param properties the preferences for the LogicalExpression factory. Such preferences
360 * should provide all the necessary information for the factory
361 * initialisation (e.g. provider class, etc.)
362 * @return a LogicalExpressionFactory
363 */
364 public static LogicalExpressionFactory createLogicalExpressionFactory(Map <String, Object> properties) {
365 //preconditions
366 if (null == properties) {
367 properties = new HashMap <String, Object> ();
368 }
369
370 //check provider
371 if (false == properties.containsKey(Factory.PROVIDER_CLASS)) {
372 //use default WSMO factory
373 properties.put(Factory.PROVIDER_CLASS,
374 defaultImplMap.getProperty(Factory.LE_FACTORY));
375 }
376
377 Object result = _createFactory(properties);
378
379 assert null != result;
380
381 //post-conditions
382 if (false == result instanceof LogicalExpressionFactory) {
383 throw new RuntimeException(properties.get(Factory.PROVIDER_CLASS) + " does not implement the org.wsmo.factory.LogicalExpressionFactory interface");
384 }
385
386 return (LogicalExpressionFactory)result;
387 }
388
389 /**
390 * Returns a LocatorManager. This LocatorManager is used to create a Locator,
391 * which then can be added to / removed from the LocatorManager. The locator
392 * is used to lookup wsmo entities based on their IRI. The default locator does
393 * also accept a mapping from logical URIs to physical locations, that can be
394 * used to locate ontologies:<br /><br />
395 * prefs.put(Locator.URI_MAPPING, mapping);<br />
396 * Locator locator = LocatorManager.createLocator(prefs);
397 *
398 * @return a LocatorManager
399 * @see Locator
400 */
401 public static LocatorManager getLocatorManager() {
402 return locManager;
403 }
404
405 private static Object _createObject(Map properties) {
406
407 Object result = null;
408
409 //0. preconditions
410 assert properties != null;
411 assert properties.containsKey(Factory.PROVIDER_CLASS);
412
413 String clazzName;
414 clazzName = (String)properties.get(Factory.PROVIDER_CLASS);
415 Class providerClass = null;
416
417 try {
418 providerClass = Class.forName(clazzName);
419 }
420 catch (ClassNotFoundException e) {
421 try {
422 providerClass = Class.forName(clazzName,
423 true,
424 Thread.currentThread().getContextClassLoader());
425 }
426 catch (ClassNotFoundException ne) {
427 throw new RuntimeException("Provider's class not found in classpath..."+clazzName, ne);
428 }
429 }
430
431 Constructor providerConstructor = null;
432
433 try {
434 Class[] param = new Class[] {java.util.Map.class};
435 providerConstructor = providerClass.getConstructor(param);
436 }
437 catch (NoSuchMethodException nsme) {
438 throw new RuntimeException(
439 "The provider class should have a constuctor which takes a single java.util.Map argument...",
440 nsme);
441 }
442
443 try {
444 result = providerConstructor.newInstance(new Object[] {properties});
445 }
446 catch (InvocationTargetException ite) {
447 throw new RuntimeException("cannot invoke the constructor a DataStore!", ite);
448 }
449 catch (IllegalAccessException ile) {
450 throw new RuntimeException("cannot access the constructor!", ile);
451 }
452 catch (InstantiationException inse) {
453 throw new RuntimeException("cannot instantiate a DataStore!", inse);
454 }
455
456 return result;
457 }
458
459
460 private static Object _createFactory(Map <String, Object> properties) {
461
462 //0. preconditions
463 assert properties != null;
464 assert properties.containsKey(Factory.PROVIDER_CLASS);
465
466 Object result = null;
467
468 if (Factory.cachingEnabled) {
469 //check cache
470 synchronized (Factory.objectCache) {
471
472 result = Factory.objectCache.get(properties);
473
474 if (null == result) {
475 //NOT FOUND, create new instance and add to cache
476 result = _createObject(properties);
477 Factory.objectCache.put(new HashMap <String, Object> (properties), result);
478 }
479 }
480 }
481 else {
482 //directly create a new instance
483 result = _createObject(properties);
484 }
485
486 assert null != result;
487 return result;
488 }
489
490 }
491
492 /*
493 * $Log$
494 * Revision 1.31 2007/04/02 12:13:15 morcen
495 * Generics support added to wsmo-api, wsmo4j and wsmo-test
496 *
497 * Revision 1.30 2006/11/27 11:36:08 nathaliest
498 * changed the validator to not import ontologies on its own and added documentation how to use the default locator to import ontologies
499 *
500 * Revision 1.29 2006/02/13 02:19:54 haselwanter
501 * The resource loading of the properties file consulted only the context classloader, which a less likely place than the current classloader.
502 *
503 * Revision 1.28 2006/02/06 01:44:21 haselwanter
504 * Added a fallback to the metafactory to retrieve classes via the context classloader if the current classloader is unable to deliver. Fixes #1314733
505 *
506 * Revision 1.27 2006/01/31 09:18:39 nathaliest
507 * small change at documentation
508 *
509 * Revision 1.26 2006/01/11 13:01:17 marin_dimitrov
510 * common constants moved to Factory
511 *
512 * Revision 1.25 2006/01/09 14:18:43 nathaliest
513 * javadoc added
514 *
515 * Revision 1.24 2006/01/05 14:57:48 nathaliest
516 * Validator uses leFactory taken in constructor from properties map
517 *
518 * Revision 1.23 2005/11/18 14:36:28 nathaliest
519 * added Factory.createWsmlValidator(Map properties) method for creating the validator
520 *
521 * Revision 1.22 2005/09/23 07:09:50 holgerlausen
522 * moved constanttransformer from API to implementation, removed dublicated constants in logicalexpression.constants
523 *
524 * Revision 1.21 2005/09/16 12:31:13 marin_dimitrov
525 * DataFactory can now be created from the meta factory
526 *
527 * Revision 1.20 2005/09/16 12:07:05 marin_dimitrov
528 * wsmo4j.properties moved
529 *
530 * Revision 1.19 2005/09/15 13:04:12 alex_simov
531 * 'config.ini' renamed to 'wsmo4j.properties'
532 *
533 * Revision 1.18 2005/09/15 11:23:24 alex_simov
534 * Factory's implementations info fields extracted in an external config file
535 *
536 * Revision 1.17 2005/09/06 18:19:23 holgerlausen
537 * better error message
538 *
539 * Revision 1.16 2005/09/02 15:25:33 alex_simov
540 * default log.expr. factory class relocated
541 *
542 * Revision 1.15 2005/07/11 10:19:26 vassil_momtchev
543 * createLocator method moved to LocatarManager class
544 *
545 * Revision 1.14 2005/07/06 11:43:06 marin_dimitrov
546 * factory caching
547 *
548 * Revision 1.13 2005/07/06 10:56:36 marin_dimitrov
549 * static constructor
550 *
551 * Revision 1.12 2005/07/06 07:10:13 vassil_momtchev
552 * Locators now are managed by LocatorManager (attribute of the Factory)
553 *
554 * Revision 1.11 2005/06/30 12:37:00 alex_simov
555 * Implementation class split: WSMLParserImpl/WSMLSerializerImpl
556 *
557 * Revision 1.10 2005/06/30 12:24:23 alex_simov
558 * Rename: Serialiser -> Serializer
559 *
560 * Revision 1.9 2005/06/30 12:21:07 alex_simov
561 * Rename: Serialiser -> Serializer
562 *
563 * Revision 1.8 2005/06/30 09:56:46 marin_dimitrov
564 * createSerialiser added
565 *
566 * Revision 1.7 2005/06/30 09:32:55 alex_simov
567 * refactoring: org.wsmo.parser -> org.wsmo.wsml.*
568 *
569 * Revision 1.6 2005/06/27 14:09:32 alex_simov
570 * refactoring: *.io.locator -> *.locator
571 * refactoring: *.io.parser -> *.parser
572 * refactoring: *.io.datastore -> *.datastore
573 *
574 * Revision 1.5 2005/06/27 08:51:49 alex_simov
575 * refactoring: *.io.locator -> *.locator
576 * refactoring: *.io.parser -> *.parser
577 * refactoring: *.io.datastore -> *.datastore
578 *
579 * Revision 1.4 2005/06/22 14:40:48 alex_simov
580 * Copyright header added/updated
581 *
582 * Revision 1.3 2005/06/02 14:22:47 alex_simov
583 * Default parser implementation fix
584 *
585 * Revision 1.2 2005/06/01 16:39:11 marin_dimitrov
586 * Datastore --> DataStore
587 *
588 * Revision 1.1 2005/06/01 10:34:43 marin_dimitrov
589 * v0.4.0
590 *
591 * Revision 1.10 2005/05/31 14:42:00 damian
592 * detDefault was not implemented
593 *
594 * Revision 1.9 2005/05/31 13:13:16 damian
595 * get/setDefaultLocator added
596 *
597 * Revision 1.8 2005/05/19 12:53:54 marin
598 * fixed factory package
599 *
600 * Revision 1.7 2005/05/18 14:30:31 marin
601 * implementation + javadoc comments
602 *
603 */