Source code: joelib/desc/ResultFactory.java
1 ///////////////////////////////////////////////////////////////////////////////
2 // Filename: $RCSfile: ResultFactory.java,v $
3 // Purpose: Factory class to get loader/writer classes.
4 // Language: Java
5 // Compiler: JDK 1.4
6 // Authors: Joerg K. Wegner
7 // Version: $Revision: 1.29 $
8 // $Date: 2003/08/22 15:56:16 $
9 // $Author: wegner $
10 //
11 // Copyright (c) Dept. Computer Architecture, University of Tuebingen, Germany
12 //
13 // This program is free software; you can redistribute it and/or modify
14 // it under the terms of the GNU General Public License as published by
15 // the Free Software Foundation version 2 of the License.
16 //
17 // This program is distributed in the hope that it will be useful,
18 // but WITHOUT ANY WARRANTY; without even the implied warranty of
19 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 // GNU General Public License for more details.
21 ///////////////////////////////////////////////////////////////////////////////
22 package joelib.desc;
23
24 import joelib.data.JOEGenericData;
25 import joelib.data.JOEGlobalDataBase;
26 import joelib.data.JOEPairData;
27
28 import joelib.desc.result.StringResult;
29
30 import joelib.io.types.cml.ResultCMLProperties;
31
32 import joelib.molecule.JOEMol;
33
34 import joelib.util.JOEHelper;
35
36 import joelib.util.types.StringPattern;
37 import joelib.util.types.StringString;
38
39 import wsi.ra.tool.PropertyHolder;
40
41 /*==========================================================================*
42 * IMPORTS
43 *========================================================================== */
44 import java.util.Enumeration;
45 import java.util.Hashtable;
46 import java.util.Properties;
47 import java.util.Vector;
48 import java.util.regex.Matcher;
49 import java.util.regex.Pattern;
50
51 import org.apache.log4j.Category;
52
53
54 /*==========================================================================*
55 * CLASS DECLARATION
56 *========================================================================== */
57
58 /**
59 * Factory class to get descriptor results and faciliate the parsing of descriptor entries.
60 * The definition file can be defined in the
61 * <tt>joelib.data.ResultFactory.resourceFile</tt> property in the {@link wsi.ra.tool.PropertyHolder}.
62 * The {@link wsi.ra.tool.ResourceLoader} loads the <tt>joelib.properties</tt> file for default.
63 *
64 * <p>
65 * Let's have a look at a <tt>knownResults.txt</tt> example file:
66 * <blockquote><pre>
67 * $JOELIB_RESULT$ joelib.desc.result.IntResult
68 * #
69 * # PETRA descriptors
70 * #
71 * E_CHARGE
72 * E_DELTAHF
73 * E_HASH
74 * E_POLARIZABILITY
75 * #
76 * # Molconn Z 350
77 * #
78 * id
79 * nvx
80 * nrings
81 * ncirc
82 * nelem
83 * $REGEXP$ nas\p{Upper}\p{Lower}*
84 * $REGEXP$ nd\d
85 * $REGEXP$ ne\d+
86 * </pre></blockquote>
87 * This means all descriptors of the type nd1, nd2, nd3, ..., nd9 are {@link joelib.desc.result.IntResult}
88 * descriptors. Also the E_CHARGE, E_DELTAHF, E_HASH, E_POLARIZABILITY, id, nvx, ... descriptors.<br>
89 * For a detailed description for regular expressions patterns have a look at the
90 * {@link java.util.regex.Pattern} class.
91 *
92 * <p>
93 * Speed optimization (for external descriptors):
94 * <ul>
95 * <li> Use as much explicit descriptor name entries as possible. They will be stored in a look up
96 * table ({@link java.util.Hashtable}) with fast access predicates.
97 * <li> Use regular expressions only if there can be a lot of descriptors described with these expressions.
98 * Still, there will be all regular expressions checked, until the first one, which matches the given descriptor,
99 * will be found. But this will be always much more expensier than getting descriptor result
100 * (representation classes for descriptor values) directly from the {@link java.util.Hashtable}.
101 * </ul>
102 * External descriptors will be descriptors, which are known in JOELib, but can not be calculated. All
103 * internal descriptor result classes will be always stored explicitly.
104 *
105 * <p>
106 * Default:<br>
107 * joelib.desc.ResultFactory.resourceFile=<a href="http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/joelib/joelib/src/joelib/data/plain/knownResults.txt?rev=HEAD&content-type=text/vnd.viewcvs-markup">joelib/data/plain/knownResults.txt</a>
108 *
109 * @author wegnerj
110 * @license GPL
111 * @cvsversion $Revision: 1.29 $, $Date: 2003/08/22 15:56:16 $
112 * @see wsi.ra.tool.PropertyHolder
113 * @see wsi.ra.tool.ResourceLoader
114 */
115 public class ResultFactory extends JOEGlobalDataBase
116 {
117 //~ Static fields/initializers /////////////////////////////////////////////
118
119 /*-------------------------------------------------------------------------*
120 * private static member variables
121 *-------------------------------------------------------------------------*/
122
123 // Obtain a suitable logger.
124 private static Category logger = Category.getInstance(
125 "joelib.desc.ResultFactory");
126 private final static String DEFAULT_RESOURCE = "joelib/data/plain/knownResults.txt";
127 private final static String IDENTIFIER = "$JOELIB_RESULT$";
128 private final static String REGEXP = "$REGEXP$";
129 private static ResultFactory instance;
130
131 //~ Instance fields ////////////////////////////////////////////////////////
132
133 /*-------------------------------------------------------------------------*
134 * private member variables
135 *-------------------------------------------------------------------------*/
136 private Hashtable representation;
137 private String actRep;
138 private Vector regExp;
139
140 //~ Constructors ///////////////////////////////////////////////////////////
141
142 /*-------------------------------------------------------------------------*
143 * constructor
144 *-------------------------------------------------------------------------*/
145
146 /**
147 * Constructor for the ResultFactory.
148 */
149 private ResultFactory()
150 {
151 initialized = false;
152
153 Properties prop = PropertyHolder.instance().getProperties();
154 resourceFile = prop.getProperty(this.getClass().getName() +
155 ".resourceFile", DEFAULT_RESOURCE);
156
157 representation = new Hashtable(100, 50);
158 regExp = new Vector(30);
159 actRep = null;
160 }
161
162 //~ Methods ////////////////////////////////////////////////////////////////
163
164 /*-------------------------------------------------------------------------*
165 * public methods
166 *-------------------------------------------------------------------------*/
167
168 /**
169 * Description of the Method
170 *
171 * @return Description of the Return Value
172 */
173 public static synchronized ResultFactory instance()
174 {
175 if (instance == null)
176 {
177 instance = new ResultFactory();
178 }
179
180 return instance;
181 }
182
183 /**
184 * Gets the descResult attribute of the ResultFactory class
185 *
186 * @param descName Description of the Parameter
187 * @return The descResult value
188 * @exception DescriptorException Description of the Exception
189 */
190 public DescResult getDescResult(String descName) throws DescriptorException
191 {
192 if (!initialized)
193 {
194 init();
195 }
196
197 String resultRepr = null;
198
199 // try to load Descriptor representation class
200 DescResult descResult = null;
201
202 // exist calculateable descriptor ?
203 DescriptorInfo descInfo = DescriptorHelper.instance().getDescInfo(descName);
204
205 // if no calculateable descriptor exists look in known results
206 if (descInfo == null)
207 {
208 resultRepr = (String) representation.get(descName);
209
210 if (resultRepr == null)
211 {
212 // o.k., now there is no result type defined for this descriptor
213 // let's try to guess one
214 resultRepr = guessDescResult(descName);
215
216 if (resultRepr == null)
217 {
218 return null;
219 }
220 }
221
222 /* DescriptorInfo(String _name,
223 String dataType,
224 int _typeDimension,
225 String _representation,
226 String _descriptionFile,
227 String _initialization,
228 String _result)*/
229 descInfo = new DescriptorInfo(descName,
230 DescriptorInfo.TYPE_UNKNOWN, "", "", null, resultRepr);
231
232 // throw new DescriptorException("Descriptor '"+name+"' is not defined");
233 }
234 else
235 {
236 resultRepr = descInfo.getResult();
237 }
238
239 try
240 {
241 // works only for construtor without arguments
242 descResult = (DescResult) Class.forName(resultRepr).newInstance();
243
244 // for descriptor with arguments
245 // Class cls = Class.forName(resultRepr);
246 // Constructor constructor[] = cls.getDeclaredConstructors();
247 // for (int i = 0; i < constructor.length; i++)
248 // {
249 // Class[] params = constructor[i].getParameterTypes();
250 // if (params.length == 1)
251 // {
252 // Object[] inputs = {descInfo};
253 // descResult = (DescResult) constructor[i].newInstance(inputs);
254 // }
255 // }
256 }
257 catch (ClassNotFoundException ex)
258 {
259 throw new DescriptorException(descInfo.getResult() + " not found.");
260 }
261 catch (InstantiationException ex)
262 {
263 throw new DescriptorException(descInfo.getResult() +
264 " can not be instantiated.");
265 }
266 catch (IllegalAccessException ex)
267 {
268 throw new DescriptorException(descInfo.getResult() +
269 " can't be accessed.");
270 }
271
272 // catch (InvocationTargetException ex)
273 // {
274 // ex.printStackTrace();
275 // throw new DescriptorException("InvocationTargetException.");
276 // }
277 if (descResult == null)
278 {
279 throw new DescriptorException("DescResult class " + resultRepr +
280 " does'nt exist.");
281 }
282 else
283 {
284 return descResult;
285 }
286 }
287
288 /**
289 * Description of the Method
290 *
291 * @param buffer Description of the Parameter
292 */
293 public void parseLine(String buffer)
294 {
295 // skip command lines
296 String trimmed = buffer.trim();
297
298 if (!trimmed.equals("") && (buffer.charAt(0) != '#'))
299 {
300 if (trimmed.charAt(0) == '$')
301 {
302 int index;
303
304 if ((index = trimmed.indexOf(IDENTIFIER)) != -1)
305 {
306 actRep = trimmed.substring(index + 1 + IDENTIFIER.length())
307 .trim();
308 }
309 else if ((index = trimmed.indexOf(REGEXP)) != -1)
310 {
311 String tmp = trimmed.substring(index + 1 + REGEXP.length())
312 .trim();
313 regExp.add(new StringPattern(actRep, Pattern.compile(tmp)));
314 }
315 }
316 else if (actRep != null)
317 {
318 // System.out.println(buffer.trim()+" is of type "+actRep);
319 representation.put(trimmed, actRep);
320 }
321 }
322 }
323
324 /**
325 * Description of the Method
326 *
327 * @param mol Description of the Parameter
328 * @param descName Description of the Parameter
329 * @param data Description of the Parameter
330 * @return Description of the Return Value
331 */
332 public JOEPairData parsePairData(JOEMol mol, String descName,
333 JOEGenericData data)
334 {
335 DescResult result;
336
337 try
338 {
339 result = getDescResult(descName);
340 }
341 catch (Exception ex)
342 {
343 ex.printStackTrace();
344
345 return null;
346 }
347
348 if (result == null)
349 {
350 if (logger.isDebugEnabled())
351 {
352 logger.debug("No data result type found for '" + descName +
353 "'. Supposed String value.");
354 }
355
356 return null;
357 }
358
359 // check if descriptor has already been calculated
360 // and if it's not a unparsed descriptor entry in
361 // the StringResult
362 // If the StringResult descriptor contains CML element attributes
363 // copy these attributes
364 JOEPairData pairData = (JOEPairData) data;
365
366 if (pairData.getValue() instanceof DescResult &&
367 ((pairData.getValue() instanceof StringResult) == false))
368 {
369 if (logger.isDebugEnabled())
370 {
371 logger.debug("Descriptor '" + descName +
372 "' is (parsed) PairData");
373 }
374
375 return pairData;
376 }
377 else
378 {
379 // StringReult descriptor
380 // convert StringReult descriptor to Int, Double, ...
381 // descriptor, if data type is known
382 if ((pairData.getValue() instanceof StringResult))
383 {
384 StringResult sResult = ((StringResult) pairData.getValue());
385
386 if (logger.isDebugEnabled())
387 {
388 logger.debug("Descriptor '" + descName +
389 "'is (unparsed) StringResult");
390 logger.debug("Descriptor '" + descName +
391 "'will forced to be " + result.getClass().getName());
392 logger.debug(descName + "=" + sResult.value);
393 }
394
395 pairData.setValue(sResult.value);
396
397 try
398 {
399 //System.out.println("INPUT:"+IOTypeHolder.instance().getIOType("CML")+" data:"+ pairData);
400 if (!result.fromPairData(mol.getInputType(), pairData))
401 {
402 logger.error("Descriptor '" + descName +
403 "' could not be parsed.");
404 }
405
406 //result.fromPairData(IOTypeHolder.instance().getIOType("CML"), pairData);
407 // copy CML element attributes
408 if (JOEHelper.hasInterface(result, "ResultCMLProperties") &&
409 JOEHelper.hasInterface(sResult,
410 "ResultCMLProperties"))
411 {
412 Enumeration enum = sResult.getCMLProperties();
413
414 if (enum != null)
415 {
416 if (logger.isDebugEnabled())
417 {
418 logger.debug("Copy CML attribute properties");
419 }
420
421 StringString ss;
422 ResultCMLProperties cmlProp = ((ResultCMLProperties) result);
423
424 for (; enum.hasMoreElements();)
425 {
426 ss = (StringString) enum.nextElement();
427 cmlProp.addCMLProperty(ss);
428 }
429 }
430
431 // else
432 // {
433 // if (logger.isDebugEnabled())
434 // logger.debug("No CML attribute properties defined");
435 // }
436 }
437
438 // else
439 // {
440 // if (logger.isDebugEnabled())
441 // logger.debug("No CML attribute property acceptor");
442 // }
443 }
444 catch (Exception ex)
445 {
446 logger.error("Parsing error: " + ex.getMessage());
447
448 //ex.printStackTrace();
449 logger.error(" at descriptor '" + descName +
450 "' in molecule: " + mol.getTitle());
451
452 return null;
453 }
454 }
455
456 // String
457 else
458 {
459 if (logger.isDebugEnabled())
460 {
461 logger.debug("Descriptor '" + descName +
462 "'is (unparsed) String");
463 logger.debug("Descriptor '" + descName +
464 "'will forced to be " + result.getClass().getName());
465 logger.debug(descName + "=" + pairData);
466 }
467
468 try
469 {
470 //System.out.println("INPUT:"+IOTypeHolder.instance().getIOType("CML")+" data:"+ pairData);
471 //System.out.println("Forceed to be:"+result.getClass().getName());
472 if (!result.fromPairData(mol.getInputType(), pairData))
473 {
474 logger.error("Descriptor '" + descName +
475 "' could not be parsed.");
476 }
477
478 //result.fromPairData(IOTypeHolder.instance().getIOType("CML"), pairData);
479 }
480 catch (NumberFormatException ex)
481 {
482 logger.error(ex.toString());
483 ex.printStackTrace();
484 logger.error("At descriptor '" + descName +
485 "' in molecule: " + mol.getTitle());
486
487 return null;
488 }
489 }
490
491 // replace old data
492 mol.deleteData(descName);
493 mol.addData((JOEPairData) result);
494 }
495
496 return (JOEPairData) result;
497 }
498
499 /**
500 * Get descriptor result ype by using regular expressions.
501 *
502 * @param descName
503 * @return String
504 */
505 protected String guessDescResult(String descName)
506 {
507 StringPattern reg;
508 Matcher m;
509
510 for (int i = 0; i < regExp.size(); i++)
511 {
512 reg = (StringPattern) regExp.get(i);
513 m = reg.p.matcher(descName);
514
515 //System.out.println(descName+" matches "+reg.p.pattern()+"="+m.matches());
516 if (m.matches())
517 {
518 ///System.out.println(reg.s+" guessed from "+descName+" with "+reg.p.pattern());
519 return reg.s;
520 }
521 }
522
523 return null;
524 }
525 }
526 ///////////////////////////////////////////////////////////////////////////////
527 // END OF FILE.
528 ///////////////////////////////////////////////////////////////////////////////