/** * Create a new default factory with an expected number of registered * classes and an interface provider. The interface provider is used when * registering an implementation without a specified interface {@link * #register(Class)}. * * @param interfaceProvider provides the interfaces of a given * implementation class * @param n the expected number of constructors that will be * stored. * @see #DynamicFactory(int) */ public DynamicFactory(InterfaceProvider interfaceProvider, int n) { if (n < 0) throw new IllegalArgumentException("cannot create factory with negative size"); if (interfaceProvider == null) throw new IllegalArgumentException("null interface provider"); this.interfaceProvider = interfaceProvider; int size = n > 3 ? n + n / 3 : n + 1; // double for the cache to account for subclass constructor caching // (e.g. Atom(Atom) -> Atom(Element) cache = new HashMap<ConstructorKey, Creator<?>>(size * 2); lookup = new ConstructorLookup(size); }
/** * Register a constructor key with a defined {@link Creator}. The key * defines the interface and parameters of the creation and the creator * actually creates the object. * * <pre>{@code * // import static org.openscience.cdk.DynamicFactory.key; * factory.register(key(IBond.class, IAtom[].class), * new BasicCreator<IAtom>(null) { * public IAtom create(Object[] objects) { * return new Bond((IAtom[]) objects); * } * }); * }</pre> * * @param key construction key, defines interface and parameter types * @param creator creates the actual object * @param <T> type of object that will be created * @return the registered creator - null if not registered */ public <T> Creator<T> register(ConstructorKey key, Creator<T> creator) { if (creator == null) return null; // make sure we don't register a constructor over an existing key if (cache.containsKey(key)) throw new IllegalArgumentException("cannot register " + key + " suppressed " + cache.get(key)); lookup.put(key.intf(), key); cache.put(key, creator); return creator; }
for (ConstructorKey candidate : lookup.getCandidates(key)) { if (key.isAssignable(candidate)) { return get(candidate);
for (ConstructorKey candidate : lookup.getCandidates(key)) { if (key.isAssignable(candidate)) { return get(candidate);
/** * Register a constructor key with a defined {@link Creator}. The key * defines the interface and parameters of the creation and the creator * actually creates the object. * * <pre>{@code * // import static org.openscience.cdk.DynamicFactory.key; * factory.register(key(IBond.class, IAtom[].class), * new BasicCreator<IAtom>(null) { * public IAtom create(Object[] objects) { * return new Bond((IAtom[]) objects); * } * }); * }</pre> * * @param key construction key, defines interface and parameter types * @param creator creates the actual object * @param <T> type of object that will be created * @return the registered creator - null if not registered */ public <T> Creator<T> register(ConstructorKey key, Creator<T> creator) { if (creator == null) return null; // make sure we don't register a constructor over an existing key if (cache.containsKey(key)) throw new IllegalArgumentException("cannot register " + key + " suppressed " + cache.get(key)); lookup.put(key.intf(), key); cache.put(key, creator); return creator; }
/** * Create a new default factory with an expected number of registered * classes and an interface provider. The interface provider is used when * registering an implementation without a specified interface {@link * #register(Class)}. * * @param interfaceProvider provides the interfaces of a given * implementation class * @param n the expected number of constructors that will be * stored. * @see #DynamicFactory(int) */ public DynamicFactory(InterfaceProvider interfaceProvider, int n) { if (n < 0) throw new IllegalArgumentException("cannot create factory with negative size"); if (interfaceProvider == null) throw new IllegalArgumentException("null interface provider"); this.interfaceProvider = interfaceProvider; int size = n > 3 ? n + n / 3 : n + 1; // double for the cache to account for subclass constructor caching // (e.g. Atom(Atom) -> Atom(Element) cache = new HashMap<ConstructorKey, Creator<?>>(size * 2); lookup = new ConstructorLookup(size); }
/** * Access a set of candidates for a given key. Candidates match the * interface an number of parameters for the constructors. A key may * match when it's parameters are subclasses. * * @param key the key to find possible candidates for * @return set of constructors which 'could' match the given key */ public Set<ConstructorKey> getCandidates(ConstructorKey key) { return getCandidates(key.intf(), key.n()); }
/** * Access a set of candidates for a given key. Candidates match the * interface an number of parameters for the constructors. A key may * match when it's parameters are subclasses. * * @param key the key to find possible candidates for * @return set of constructors which 'could' match the given key */ public Set<ConstructorKey> getCandidates(ConstructorKey key) { return getCandidates(key.intf(), key.n()); }