/* DefaultSignalMLCodecManager.java created 2007-09-17 * */ package org.signalml.codec; import java.io.File; import java.io.IOException; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Vector; import javax.swing.event.EventListenerList; import org.apache.log4j.Logger; import org.signalml.app.config.SignalMLCodecConfiguration; import org.signalml.app.config.SignalMLCodecDescriptor; import org.signalml.util.Util; import com.thoughtworks.xstream.XStream; /** DefaultSignalMLCodecManager * * * @author Michal Dobaczewski © 2007-2008 CC Otwarte Systemy Komputerowe Sp. z o.o. */ public class DefaultSignalMLCodecManager implements SignalMLCodecManager { protected static final Logger logger = Logger.getLogger(DefaultSignalMLCodecManager.class); private Vector<SignalMLCodec> codecs = new Vector<SignalMLCodec>(); private Map<String,SignalMLCodec> codecsByFormatName = new HashMap<String,SignalMLCodec>(); private Map<String,SignalMLCodec> codecsByUID = new HashMap<String,SignalMLCodec>(); private File profileDir; private XStream streamer; private EventListenerList listenerList = new EventListenerList(); @Override public int getCodecCount() { synchronized (this) { return codecs.size(); } } @Override public SignalMLCodec getCodecAt(int index) { synchronized (this) { return codecs.elementAt(index); } } @Override public SignalMLCodec getCodecForFormat(String formatName) { synchronized (this) { return codecsByFormatName.get(formatName); } } @Override public SignalMLCodec getCodecByUID(String uid) { SignalMLCodec ret = codecsByUID.get(uid); if (ret == null && uid.startsWith("org.signalml.codec.precompiled.")) { ret = StaticCodec.forSourceName(uid); } return ret; } @Override public void registerSignalMLCodec(SignalMLCodec codec) { synchronized (this) { if (codecs.contains(codec)) { logger.warn("ignoring duplicate codec: " + codec); return; } int index = registerSignalMLCodecInternal(codec); fireCodecAdded(codec, index); } } private int registerSignalMLCodecInternal(SignalMLCodec codec) { String registerAsFormatName = codec.getFormatName(); logger.info("registering codec " + registerAsFormatName + ": " + codec); assert registerAsFormatName != null; SignalMLCodec uidCodec = codecsByUID.get(codec.getSourceUID()); if (uidCodec != null && uidCodec != codec) { codecsByFormatName.remove(uidCodec.getFormatName()); codecsByUID.remove(codec.getSourceUID()); codecs.remove(uidCodec); } SignalMLCodec oldCodec = codecsByFormatName.get(registerAsFormatName); if (oldCodec != null) { codecsByFormatName.remove(registerAsFormatName); codecsByUID.remove(oldCodec.getSourceUID()); codecs.remove(oldCodec); } codecs.add(codec); codecsByFormatName.put(registerAsFormatName,codec); codecsByUID.put(codec.getSourceUID(),codec); return codecs.indexOf(codec); } @Override public int getIndexOfCodec(SignalMLCodec codec) { synchronized (this) { return codecs.indexOf(codec); } } @Override public void removeSignalMLCodec(SignalMLCodec codec) { logger.info("unregistering codec " + codec.getFormatName()); synchronized (this) { if (!codecs.contains(codec)) { return; } codecsByFormatName.remove(codec.getFormatName()); codecsByUID.remove(codec.getSourceUID()); int index = codecs.indexOf(codec); codecs.remove(codec); fireCodecRemoved(codec, index); } } @Override public void removeSignalMLCodecAt(int index) { synchronized (this) { removeSignalMLCodec(codecs.get(index)); } } private void clear() { synchronized (this) { codecs.clear(); codecsByFormatName.clear(); fireCodecsChanged(); } } public void writeToPersistence(File file) throws IOException { SignalMLCodecDescriptor[] descr; synchronized (this) { descr = new SignalMLCodecDescriptor[codecs.size()]; for (int i=0; i<descr.length; i++) { descr[i] = new SignalMLCodecDescriptor(codecs.get(i)); } } SignalMLCodecConfiguration config = new SignalMLCodecConfiguration(descr); config.writeToXML((file == null) ? config.getStandardFile(profileDir) : file, streamer); } public void readFromPersistence(File file) throws IOException, CodecException { SignalMLCodecConfiguration config = new SignalMLCodecConfiguration();; if (file == null) { file = config.getStandardFile(profileDir); } config.readFromXML(file,streamer); synchronized (this) { clear(); SignalMLCodecDescriptor[] descr = config.getCodecs(); SignalMLCodec codec; for (int i=0; i<descr.length; i++) { codec = descr[i].getCodec(); codec.setFormatName(descr[i].getFormatName()); registerSignalMLCodecInternal(codec); } fireCodecsChanged(); } } public File getProfileDir() { synchronized (this) { return profileDir; } } public void setProfileDir(File profileDir) { synchronized (this) { this.profileDir = profileDir; } } public XStream getStreamer() { synchronized (this) { return streamer; } } public void setStreamer(XStream streamer) { synchronized (this) { this.streamer = streamer; } } public void verify() { synchronized (this) { logger.debug("Verifying codec manager"); Iterator<SignalMLCodec> it = codecs.iterator(); while (it.hasNext()) { SignalMLCodec codec = it.next(); if (codec instanceof XMLSignalMLCodec) { XMLSignalMLCodec xmlCodec = (XMLSignalMLCodec) codec; File expectedPath = new File(xmlCodec.getRepositoryDir(), "smlcache-" + System.getProperty("user.name") + Util.FILE_SEP + xmlCodec.getCacheDirName()); logger.debug("Codec [" + codec.getFormatName() + "] expected at [" + expectedPath.getAbsolutePath() + "]"); if (!expectedPath.exists()) { logger.warn("Codec directory lost, removing codec"); codecsByFormatName.remove(codec.getFormatName()); it.remove(); continue; } } logger.debug("Codec ok"); } logger.debug("Verification complete"); } } public void cleanUp() { synchronized (this) { logger.debug("Cleaning up codec repository - not implemented"); // TODO cleanup stale dirs from profile cache logger.debug("Cleaning up complete"); } } protected void fireCodecAdded(SignalMLCodec codec, int index) { Object[] listeners = listenerList.getListenerList(); SignalMLCodecManagerEvent e = null; for (int i = listeners.length-2; i>=0; i-=2) { if (listeners[i]==SignalMLCodecManagerListener.class) { if (e == null) { e = new SignalMLCodecManagerEvent(this,codec,index); } ((SignalMLCodecManagerListener)listeners[i+1]).codecAdded(e); } } } protected void fireCodecRemoved(SignalMLCodec codec, int index) { Object[] listeners = listenerList.getListenerList(); SignalMLCodecManagerEvent e = null; for (int i = listeners.length-2; i>=0; i-=2) { if (listeners[i]==SignalMLCodecManagerListener.class) { if (e == null) { e = new SignalMLCodecManagerEvent(this,codec,index); } ((SignalMLCodecManagerListener)listeners[i+1]).codecRemoved(e); } } } protected void fireCodecsChanged() { Object[] listeners = listenerList.getListenerList(); SignalMLCodecManagerEvent e = null; for (int i = listeners.length-2; i>=0; i-=2) { if (listeners[i]==SignalMLCodecManagerListener.class) { if (e == null) { e = new SignalMLCodecManagerEvent(this); } ((SignalMLCodecManagerListener)listeners[i+1]).codecsChanged(e); } } } public void addSignalMLCodecManagerListener(SignalMLCodecManagerListener listener) { synchronized (this) { listenerList.add(SignalMLCodecManagerListener.class, listener); } } public void removeSignalMLCodecManagerListener(SignalMLCodecManagerListener listener) { synchronized (this) { listenerList.remove(SignalMLCodecManagerListener.class, listener); } } }