001: /*
002: * This file is part of JGAP.
003: *
004: * JGAP offers a dual license model containing the LGPL as well as the MPL.
005: *
006: * For licensing information please see the file license.txt included with JGAP
007: * or have a look at the top of class org.jgap.Chromosome which representatively
008: * includes the JGAP license policy applicable for any file delivered with JGAP.
009: */
010: package org.jgap.impl;
011:
012: import java.io.*;
013: import java.util.*;
014: import org.jgap.*;
015: import org.jgap.util.*;
016: import org.apache.commons.lang.builder.*;
017:
018: /**
019: * Central factory for creating default objects to use, e.g. random generators.
020: * Could be made configurable. An instance of JGAPFactory can be accessed via<p>
021: * <code>Genotype.getConfiguration().getJGAPFactory();</code><p>
022: * To use your own factory class instead, use:<p>
023: * <code>
024: * System.setProperty(Configuration.PROPERTY_JGAPFACTORY_CLASS, "myFactory");<p>
025: * </code>
026: * with "myFactory" representing the name of your class to use.
027: *
028: * @author Klaus Meffert
029: * @since 2.6
030: */
031: public class JGAPFactory implements IJGAPFactory, Serializable,
032: ICloneable, Comparable {
033: /** String containing the CVS revision. Read out via reflection!*/
034: private final static String CVS_REVISION = "$Revision: 1.18 $";
035:
036: private List m_parameters;
037:
038: private List m_cloneHandlers;
039:
040: private List m_initer;
041:
042: private List m_compareHandlers;
043:
044: private ICloneHandler m_defaultCloneHandler;
045:
046: private IInitializer m_defaultIniter;
047:
048: private ICompareToHandler m_defaultComparer;
049:
050: private IGeneticOperatorConstraint m_geneticOpConstraint;
051:
052: private transient LRUCache m_cache;
053:
054: private boolean m_useCaching;
055:
056: public JGAPFactory(boolean a_useCaching) {
057: m_initer = new Vector();
058: m_cache = new LRUCache(50);
059: m_useCaching = a_useCaching;
060: m_cloneHandlers = new Vector();
061: m_compareHandlers = new Vector();
062: // Construct default handlers at the beginning to avoid multi-threading
063: // conflicts in getXXXFor methods.
064: m_defaultCloneHandler = new DefaultCloneHandler();
065: m_defaultIniter = new DefaultInitializer();
066: m_defaultComparer = new DefaultCompareToHandler();
067: }
068:
069: /**
070: * Allows setting (generic because unknown) parameters for creating objects.
071: *
072: * @param a_parameters Collection of generic parameters
073: *
074: * @author Klaus Meffert
075: * @since 2.6
076: */
077: public void setParameters(final Collection a_parameters) {
078: m_parameters = new Vector(a_parameters);
079: }
080:
081: /**
082: * @return Collection of generic parameters
083: *
084: * @author Klaus Meffert
085: * @since 3.0
086: */
087: public Collection getParameters() {
088: return m_parameters;
089: }
090:
091: public RandomGenerator createRandomGenerator() {
092: return new StockRandomGenerator();
093: }
094:
095: /**
096: * Registers a clone handler that could be retrieved by
097: * getCloneHandlerFor(Class).
098: *
099: * @param a_cloneHandler the ICloneHandler to register
100: * @return index of the added clone handler, needed when removeCloneHandler
101: * will be called
102: *
103: * @author Klaus Meffert
104: * @since 2.6
105: */
106: public int registerCloneHandler(final ICloneHandler a_cloneHandler) {
107: m_cloneHandlers.add(a_cloneHandler);
108: return m_cloneHandlers.size() - 1;
109: }
110:
111: /**
112: * Removes a clone handler at a given index (which is obtained from
113: * registerCloneHandler).
114: *
115: * @param a_index the index of the clone handler to remove
116: * @return the removed ICloneHandler, or Exception if not successfull
117: *
118: * @author Klaus Meffert
119: * @since 2.6
120: */
121: public ICloneHandler removeCloneHandler(final int a_index) {
122: return (ICloneHandler) m_cloneHandlers.remove(a_index);
123: }
124:
125: /**
126: * Retrieves a clone handler capable of clone the given class.
127: *
128: * @param a_obj the object to clone (maybe null)
129: * @param a_classToClone the class to clone an object of (maybe null)
130: * @return the clone handler found capable of clone the given
131: * class, or null if none registered
132: *
133: * @author Klaus Meffert
134: * @since 2.6
135: */
136: public ICloneHandler getCloneHandlerFor(final Object a_obj,
137: final Class a_classToClone) {
138: return (ICloneHandler) findHandlerFor(a_obj, a_classToClone,
139: m_cloneHandlers, m_defaultCloneHandler, "clone");
140: }
141:
142: /**
143: * Registers an initializer that could be retrieved by
144: * getInitializerFor(Class).
145: *
146: * @param a_chromIniter the IChromosomeInitializer to register
147: * @return index of the added initializer, needed when
148: * removeChromosomeInitializer will be called
149: *
150: * @author Klaus Meffert
151: * @since 2.6
152: */
153: public int registerInitializer(final IInitializer a_chromIniter) {
154: m_initer.add(a_chromIniter);
155: return m_initer.size() - 1;
156: }
157:
158: /**
159: * Removes an initializer at a given index (which is obtained from
160: * registerInitializer).
161: *
162: * @param a_index the index of the initializer to remove
163: * @return the removed IInitializer, or null if not successfull
164: *
165: * @author Klaus Meffert
166: * @since 2.6
167: */
168: public IInitializer removeInitializer(final int a_index) {
169: return (IInitializer) m_initer.remove(a_index);
170: }
171:
172: /**
173: * Retrieves an initializer capable of initializing the Object of the given
174: * class.
175: *
176: * @param a_obj the object to init (maybe null)
177: * @param a_class the object class to init (maybe null)
178: * @return new instance (should be!) of initialized object
179: *
180: * @author Klaus Meffert
181: * @since 2.6
182: */
183: public IInitializer getInitializerFor(final Object a_obj,
184: final Class a_class) {
185: return (IInitializer) findHandlerFor(a_obj, a_class, m_initer,
186: m_defaultIniter, "init");
187: }
188:
189: public void setGeneticOperatorConstraint(
190: final IGeneticOperatorConstraint a_constraint) {
191: m_geneticOpConstraint = a_constraint;
192: }
193:
194: public IGeneticOperatorConstraint getGeneticOperatorConstraint() {
195: return m_geneticOpConstraint;
196: }
197:
198: /**
199: * Retrieves a handler capable of comparing two instances of the given class.
200: *
201: * @param a_obj the object to compare (maybe null)
202: * @param a_classToCompareTo the class instances to compare (maybe null)
203: * @return the handler found capable of comparing instances
204: * of the given class, or null if none registered
205: *
206: * @author Klaus Meffert
207: * @since 2.6
208: */
209: public ICompareToHandler getCompareToHandlerFor(Object a_obj,
210: Class a_classToCompareTo) {
211: return (ICompareToHandler) findHandlerFor(a_obj,
212: a_classToCompareTo, m_compareHandlers,
213: m_defaultComparer, "compare");
214: }
215:
216: /**
217: * Registers a compareTo-handler that could be retrieved by
218: * getCompareToHandlerFor(Class).
219: *
220: * @param a_compareToHandler the ICompareToHandler to register
221: * @return index of the added handler, needed when removeCompareToHandler
222: * will be called
223: *
224: * @author Klaus Meffert
225: * @since 2.6
226: */
227: public int registerCompareToHandler(
228: ICompareToHandler a_compareToHandler) {
229: m_compareHandlers.add(a_compareToHandler);
230: return m_compareHandlers.size() - 1;
231: }
232:
233: /**
234: * Removes a compareTo-handler at a given index (which is obtained from
235: * registerCompareToHandler).
236: *
237: * @param a_index the index of the handler to remove
238: * @return the removed handler, or Exception if not successfull
239: *
240: * @author Klaus Meffert
241: * @since 2.6
242: */
243: public ICompareToHandler removeCompareToHandler(final int a_index) {
244: return (ICompareToHandler) m_compareHandlers.remove(a_index);
245: }
246:
247: /**
248: * Helper: Finds a handler for a given Object or Class, returns the default
249: * handler, if one is provided. Uses an LRU cache to speedup things!
250: *
251: * @param a_obj the object to find a handler for (maybe null)
252: * @param a_class the class to find a handler for (maybe null)
253: * @param a_list list of available handlers
254: * @param a_default a default handler to return in none other is found
255: * @param a_listID arbitrary unique string for accessing the cache
256: * @return the handler found, or null if none registered
257: *
258: * @author Klaus Meffert
259: * @since 2.6
260: */
261: protected IHandler findHandlerFor(final Object a_obj,
262: final Class a_class, final List a_list,
263: final IHandler a_default, final String a_listID) {
264: String key = null;
265: String key1, key2;
266: if (m_useCaching) {
267: // Construct key for cache lookup:
268: // Class name of list + a_class-Name + a_obj.hashCode()
269: // ----------------------------------------------------
270: if (a_class == null) {
271: key1 = "null";
272: } else {
273: key1 = a_class.getName();
274: }
275: if (a_obj == null) {
276: key2 = "null";
277: } else {
278: key2 = a_obj.getClass().getName();
279: }
280: key = a_listID + "/" + key1 + "/" + key2;
281: // Lookup cache.
282: // -------------
283: Object handler = m_cache.get(key);
284: if (handler != null) {
285: return (IHandler) handler;
286: }
287: // Not found in cache. Search initially.
288: // -------------------------------------
289: }
290: IHandler result = null;
291: Iterator it = a_list.iterator();
292: while (it.hasNext()) {
293: IHandler initer = (IHandler) it.next();
294: if (initer.isHandlerFor(a_obj, a_class)) {
295: result = initer;
296: break;
297: }
298: }
299: if (result == null) {
300: // No registered handler found. Try the default handler.
301: // -----------------------------------------------------
302: if (a_default != null) {
303: if (a_default.isHandlerFor(a_obj, a_class)) {
304: result = a_default;
305: }
306: }
307: }
308: if (m_useCaching) {
309: // Add to cache.
310: // -------------
311: if (result != null) {
312: m_cache.put(key, result);
313: }
314: }
315: return result;
316: }
317:
318: /**
319: * @return true: caching used, false: no caching used
320: *
321: * @author Klaus Meffert
322: * @since 3.0
323: */
324: public boolean isUseCaching() {
325: return m_useCaching;
326: }
327:
328: public Object clone() {
329: try {
330: /**@todo check if it works this way*/
331: return super .clone();
332: } catch (CloneNotSupportedException cex) {
333: throw new CloneException(cex);
334: }
335: }
336:
337: /**
338: * The equals-method
339: * @param a_other sic
340: * @return sic
341: *
342: * @author Klaus Meffert
343: * @since 3.2
344: */
345: public boolean equals(Object a_other) {
346: try {
347: return compareTo(a_other) == 0;
348: } catch (ClassCastException cex) {
349: return false;
350: }
351: }
352:
353: /**
354: * @param a_other other object to compare
355: * @return as always
356: *
357: * @author Klaus Meffert
358: * @since 3.2
359: */
360: public int compareTo(Object a_other) {
361: if (a_other == null) {
362: return 1;
363: } else {
364: // Do not consider m_parameters, m_cache and m_useCaching.
365: // -------------------------------------------------------
366: JGAPFactory other = (JGAPFactory) a_other;
367: return new CompareToBuilder().append(
368: m_cloneHandlers.toArray(),
369: other.m_cloneHandlers.toArray()).append(
370: m_initer.toArray(), other.m_initer.toArray())
371: .append(m_compareHandlers.toArray(),
372: other.m_compareHandlers.toArray()).append(
373: m_defaultCloneHandler,
374: other.m_defaultCloneHandler).append(
375: m_defaultComparer, other.m_defaultComparer)
376: .append(m_geneticOpConstraint,
377: other.m_geneticOpConstraint).toComparison();
378: }
379: }
380: }
|