/*************************************************** * * cismet GmbH, Saarbruecken, Germany * * ... and it just works. * ****************************************************/ package de.cismet.commons.gui.protocol; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import org.jdom.Element; import org.openide.util.Lookup; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import de.cismet.commons.gui.protocol.listener.ProtocolHandlerListener; import de.cismet.commons.gui.protocol.listener.ProtocolHandlerListenerEvent; import de.cismet.tools.configuration.Configurable; import de.cismet.tools.configuration.NoWriteError; /** * DOCUMENT ME! * * @author jruiz * @version $Revision$, $Date$ */ public class ProtocolHandler implements Configurable { //~ Static fields/initializers --------------------------------------------- private static final transient org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger( ProtocolHandler.class); private static ProtocolHandler INSTANCE; //~ Instance fields -------------------------------------------------------- private final LinkedList<ProtocolStep> storage = new LinkedList<ProtocolStep>(); private final ProtocolHandlerListenerHandler listenerHandler = new ProtocolHandlerListenerHandler(); private final ObjectMapper objectMapper = new ObjectMapper(); private final Map<String, ProtocolStepConfiguration> configMap = new HashMap<String, ProtocolStepConfiguration>(); private final List<ProtocolStepToolbarItem> toolbarItems = new ArrayList<ProtocolStepToolbarItem>(); private boolean recordEnabled = false; //~ Constructors ----------------------------------------------------------- /** * Creates a new ProtocolHandler object. */ private ProtocolHandler() { objectMapper.enable(SerializationFeature.INDENT_OUTPUT); // objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); final Collection<? extends ProtocolStepConfiguration> configs = Lookup.getDefault() .lookupAll(ProtocolStepConfiguration.class); for (final ProtocolStepConfiguration config : configs) { final String configKey = config.getProtocolStepKey(); if (configKey != null) { configMap.put(configKey, config); } } final Collection<? extends ProtocolStepToolbarItem> toolbarItems = Lookup.getDefault() .lookupAll(ProtocolStepToolbarItem.class); for (final ProtocolStepToolbarItem toolbarItem : toolbarItems) { if (toolbarItem.isVisible()) { this.toolbarItems.add(toolbarItem); } } Collections.sort(this.toolbarItems, new Comparator<ProtocolStepToolbarItem>() { @Override public int compare(final ProtocolStepToolbarItem o1, final ProtocolStepToolbarItem o2) { return o1.getSorterString().compareTo(o2.getSorterString()); } }); } //~ Methods ---------------------------------------------------------------- /** * DOCUMENT ME! * * @return DOCUMENT ME! */ public static ProtocolHandler getInstance() { if (INSTANCE == null) { INSTANCE = new ProtocolHandler(); } return INSTANCE; } /** * DOCUMENT ME! * * @param listener DOCUMENT ME! * * @return DOCUMENT ME! */ public boolean addProtocolHandlerListener(final ProtocolHandlerListener listener) { return listenerHandler.addProtocolHandlerListener(listener); } /** * DOCUMENT ME! * * @param listener DOCUMENT ME! * * @return DOCUMENT ME! */ public boolean removeProtocolHandlerListener(final ProtocolHandlerListener listener) { return listenerHandler.removeProtocolHandlerListener(listener); } /** * DOCUMENT ME! * * @param stepKey DOCUMENT ME! * * @return DOCUMENT ME! */ public ProtocolStepConfiguration getProtocolStepConfiguration(final String stepKey) { return configMap.get(stepKey); } /** * DOCUMENT ME! * * @param recordEnabled DOCUMENT ME! */ public void setRecordEnabled(final boolean recordEnabled) { LOG.info("protocol globally enabled: " + recordEnabled); this.recordEnabled = recordEnabled; fireRecordStateChanged(new ProtocolHandlerListenerEvent( this, ProtocolHandlerListenerEvent.PROTOCOL_RECORD_STATE)); } /** * DOCUMENT ME! * * @return DOCUMENT ME! */ public boolean isRecordEnabled() { return recordEnabled; } /** * DOCUMENT ME! * * @param protocolStep DOCUMENT ME! */ public void removeStep(final ProtocolStep protocolStep) { storage.remove(protocolStep); fireStepRemoved(new ProtocolHandlerListenerEvent( this, protocolStep, ProtocolHandlerListenerEvent.PROTOCOL_STEP_REMOVED)); } /** * DOCUMENT ME! * * @param protocolStep DOCUMENT ME! * * @return DOCUMENT ME! */ public boolean recordStep(final ProtocolStep protocolStep) { return recordStep(protocolStep, true); } /** * DOCUMENT ME! * * @param protocolStep DOCUMENT ME! * @param checkIfRecordIsEnabled DOCUMENT ME! * * @return DOCUMENT ME! */ public boolean recordStep(final ProtocolStep protocolStep, final boolean checkIfRecordIsEnabled) { if (!checkIfRecordIsEnabled || isRecordEnabled()) { synchronized (storage) { storage.add(protocolStep); } fireStepAdded(new ProtocolHandlerListenerEvent( this, protocolStep, ProtocolHandlerListenerEvent.PROTOCOL_STEP_ADDED)); new Thread(new Runnable() { @Override public void run() { protocolStep.init(); } }).start(); if (LOG.isDebugEnabled()) { LOG.debug("protocol step '" + protocolStep.getMetaInfo().getKey() + "' added."); } return true; } else { LOG.warn("protocol step '" + protocolStep.getMetaInfo().getKey() + "' not added: protocol globally disabled!"); return false; } } /** * DOCUMENT ME! * * @return DOCUMENT ME! */ public ProtocolStep getLastStep() { return storage.getLast(); } /** * DOCUMENT ME! * * @return DOCUMENT ME! */ public List<ProtocolStep> getAllSteps() { return new ArrayList<ProtocolStep>(storage); } /** * DOCUMENT ME! * * @return DOCUMENT ME! */ public List<ProtocolStepToolbarItem> getToolbarItems() { return new ArrayList<ProtocolStepToolbarItem>(toolbarItems); } /** * DOCUMENT ME! */ public void clearSteps() { synchronized (storage) { storage.clear(); } if (LOG.isDebugEnabled()) { LOG.debug("all protocol step cleared"); } fireStepsCleared(new ProtocolHandlerListenerEvent(this, ProtocolHandlerListenerEvent.PROTOCOL_STEPS_CLEARED)); } /** * DOCUMENT ME! * * @return DOCUMENT ME! * * @throws JsonProcessingException DOCUMENT ME! */ public String toJsonString() throws JsonProcessingException { if (LOG.isDebugEnabled()) { LOG.debug("saving " + storage.size() + " protocol objects to JSON"); } return objectMapper.writerWithType(new TypeReference<Collection<ProtocolStep>>() { }).writeValueAsString(storage); } /** * DOCUMENT ME! * * @param jsonString DOCUMENT ME! * * @throws IOException DOCUMENT ME! * @throws ClassNotFoundException DOCUMENT ME! */ public void fromJsonString(final String jsonString) throws IOException, ClassNotFoundException { final Collection<ProtocolStep> loadedStorage = objectMapper.readValue( jsonString, new TypeReference<Collection<ProtocolStep>>() { }); if (LOG.isDebugEnabled()) { LOG.debug(loadedStorage.size() + " protocol objects restored from JSON"); } synchronized (storage) { storage.clear(); storage.addAll(loadedStorage); } fireStepsRestored(new ProtocolHandlerListenerEvent(this, ProtocolHandlerListenerEvent.PROTOCOL_STEPS_RESTORED)); } /** * DOCUMENT ME! * * @param file DOCUMENT ME! * * @throws IOException DOCUMENT ME! * @throws ClassNotFoundException DOCUMENT ME! */ public void readFromFile(final File file) throws IOException, ClassNotFoundException { final BufferedReader br = new BufferedReader(new FileReader(file)); try { final StringBuilder sb = new StringBuilder(); String line = br.readLine(); while (line != null) { sb.append(line); sb.append("\n"); line = br.readLine(); } fromJsonString(sb.toString()); } finally { br.close(); } } /** * DOCUMENT ME! * * @param file DOCUMENT ME! * * @throws IOException DOCUMENT ME! */ public void writeToFile(final File file) throws IOException { final FileWriter fw = new FileWriter(file); fw.write(toJsonString()); fw.close(); } /** * DOCUMENT ME! * * @param event DOCUMENT ME! */ protected void fireRecordStateChanged(final ProtocolHandlerListenerEvent event) { listenerHandler.recordStateChanged(event); } /** * DOCUMENT ME! * * @param event DOCUMENT ME! */ protected void fireStepAdded(final ProtocolHandlerListenerEvent event) { listenerHandler.stepAdded(event); } /** * DOCUMENT ME! * * @param event DOCUMENT ME! */ protected void fireStepRemoved(final ProtocolHandlerListenerEvent event) { listenerHandler.stepRemoved(event); } /** * DOCUMENT ME! * * @param event DOCUMENT ME! */ protected void fireStepsCleared(final ProtocolHandlerListenerEvent event) { listenerHandler.stepsCleared(event); } /** * DOCUMENT ME! * * @param event DOCUMENT ME! */ protected void fireStepsRestored(final ProtocolHandlerListenerEvent event) { listenerHandler.stepsRestored(event); } @Override public void configure(final Element parent) { final Element root = parent.getChild("protocolHandler"); final Element steps = root.getChild("protocolSteps"); for (final String key : configMap.keySet()) { try { final ProtocolStepConfiguration config = configMap.get(key); config.configure(steps); } catch (final Exception ex) { LOG.warn("error while configuration of " + key, ex); } } } @Override public void masterConfigure(final Element parent) { configure(parent); } @Override public Element getConfiguration() throws NoWriteError { final Element root = new Element("protocolHandler"); final Element steps = new Element("protocolSteps"); root.addContent(steps); for (final Configurable config : configMap.values()) { try { final Element element = config.getConfiguration(); if (element != null) { steps.addContent(element); } } catch (final Exception t) { LOG.warn("error while writing config part", t); // NOI18N } } return root; } //~ Inner Classes ---------------------------------------------------------- /** * DOCUMENT ME! * * @version $Revision$, $Date$ */ private class ProtocolHandlerListenerHandler implements ProtocolHandlerListener { //~ Instance fields ---------------------------------------------------- private final Collection<ProtocolHandlerListener> listeners = new ArrayList<ProtocolHandlerListener>(); //~ Methods ------------------------------------------------------------ /** * DOCUMENT ME! * * @param listener DOCUMENT ME! * * @return DOCUMENT ME! */ public boolean addProtocolHandlerListener(final ProtocolHandlerListener listener) { return listeners.add(listener); } /** * DOCUMENT ME! * * @param listener DOCUMENT ME! * * @return DOCUMENT ME! */ public boolean removeProtocolHandlerListener(final ProtocolHandlerListener listener) { return listeners.remove(listener); } @Override public void recordStateChanged(final ProtocolHandlerListenerEvent event) { for (final ProtocolHandlerListener listener : listeners) { listener.recordStateChanged(event); } } @Override public void stepAdded(final ProtocolHandlerListenerEvent event) { for (final ProtocolHandlerListener listener : listeners) { listener.stepAdded(event); } } @Override public void stepRemoved(final ProtocolHandlerListenerEvent event) { for (final ProtocolHandlerListener listener : listeners) { listener.stepRemoved(event); } } @Override public void stepsCleared(final ProtocolHandlerListenerEvent event) { for (final ProtocolHandlerListener listener : listeners) { listener.stepsCleared(event); } } @Override public void stepsRestored(final ProtocolHandlerListenerEvent event) { for (final ProtocolHandlerListener listener : listeners) { listener.stepsRestored(event); } } } }