package org.marketcetera.module; import org.marketcetera.util.misc.ClassVersion; import org.marketcetera.util.log.I18NBoundMessage3P; import java.util.HashMap; import java.util.Map; /* $License$ */ /** * Tracks module instances and searches through them. * * <p> * This class is thread-safe. All of its methods employ locking * to ensure that the concurrent modifications to the instance's state * do not corrupt it. * * @author anshul@marketcetera.com * @version $Id: ModuleInstanceTracker.java 16154 2012-07-14 16:34:05Z colin $ * @since 1.0.0 */ @ClassVersion("$Id: ModuleInstanceTracker.java 16154 2012-07-14 16:34:05Z colin $") //$NON-NLS-1$ class ModuleInstanceTracker { @Override public synchronized String toString() { return mModules.toString(); } /** * Adds a new module instance to be tracked. * * @param inModule the module instance to track. */ synchronized void add(Module inModule) { mModules.put(inModule.getURN(), inModule); } /** * All the module URNs tracked by this class. * * @return the module URNs tracked by this class. */ synchronized ModuleURN[] getAllURNs() { return mModules.keySet().toArray( new ModuleURN[mModules.size()]); } /** * The module instance corresponding to the supplied URN. * * @param inURN the module URN * * @return the module instance corresponding to the supplied URN, null * if no module with the supplied URN was found. */ synchronized Module get(ModuleURN inURN) { return mModules.get(inURN); } /** * if a module with the specified URN exists. * * @param inURN the module URN to test. * * @return if a module with the specified URN exists. */ synchronized boolean has(ModuleURN inURN) { return mModules.containsKey(inURN); } /** * Removes the module with the specified URN and returns it. * * @param inURN the module URN * * @return the removed module instance. null, if no module instance * corresponding to the supplied module URN was found. */ synchronized Module remove(ModuleURN inURN) { return mModules.remove(inURN); } /** * Searches for a module matching the supplied URN. * if a module instance that matches the supplied URN exactly is found * it is returned. * * Otherwise, an attempt is made to find the first module that has * the same URN elements as the ones that are specified in the supplied * URN and return it. * * For example, if the supplied URN is <code>metc:mytype</code>, * this method will return the first module that is found to have a * URN with the providerType 'mytype'. * * Do note that this method doesn't do implement an efficient search * as it iterates through the URNs of all the modules. This may not * be a huge issue, if the number of modules is small. However, if the * number of modules grows, we might want to use different data * structures to make the search more efficient. * * @param inURN the module URN * * @return a module matching the supplied URN, null if no matching module * could be found * * @throws ModuleNotFoundException if multiple modules matching * the supplied URN were found. */ synchronized Module search(ModuleURN inURN) throws ModuleNotFoundException { Module m; //Look for an exact match m = get(inURN); if(m != null) { return m; } //Figure out which elements of the URN are specified. boolean noProviderType = inURN.providerType() == null || inURN.providerType().isEmpty(); boolean noProviderName = inURN.providerName() == null || inURN.providerName().isEmpty(); boolean noInstanceName = inURN.instanceName() == null || inURN.instanceName().isEmpty(); //Match the first instance that matches all the specified fields //of the URN Module returnValue = null; for(ModuleURN i: mModules.keySet()) { if((noProviderType || inURN.providerType().equals(i.providerType())) && (noProviderName || inURN.providerName().equals(i.providerName())) && (noInstanceName || inURN.instanceName().equals(i.instanceName()))) { if (returnValue == null) { returnValue = get(i); } else { throw new ModuleNotFoundException(new I18NBoundMessage3P( Messages.MULTIPLE_MODULES_MATCH_URN, inURN.getValue(), returnValue.getURN().getValue(), get(i).getURN().getValue())); } } } return returnValue; } private final Map<ModuleURN,Module> mModules = new HashMap<ModuleURN, Module>(); }