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 */