/*- ******************************************************************************* * Copyright (c) 2011, 2014 Diamond Light Source Ltd. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Peter Chang - initial API and implementation and/or initial documentation *******************************************************************************/ package org.eclipse.dawnsci.analysis.api.message; import java.io.Serializable; import java.util.HashMap; import java.util.Hashtable; import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; import java.util.TreeSet; import org.eclipse.dawnsci.analysis.api.fitting.functions.IFunction; import org.eclipse.dawnsci.analysis.api.roi.IROI; import org.eclipse.january.dataset.IDataset; import org.eclipse.january.metadata.IMetadata; /** * This class is similar to a DataHolder in the scisoft diamond * plugins. * * It is simpler and less subject to use else where. It is the main thing * which is passed around in the workflow system. * * It contains data and provenance, meta data, RIOs and functions. * * @author gerring * */ public class DataMessageComponent implements Serializable { /** * */ private static final long serialVersionUID = -4322907913441650831L; public enum VALUE_TYPE { /** * Adds one string value to another if two are * in one list */ ADDITIVE_STRING, /** * Overwrites the value if it exists already. */ OVERWRITE_STRING } /** * The data is either primitive array or IDataset */ private Map<String,Serializable> list; /** * What we did to the data in the pipeline */ private Map<String,String> scalar; /** * The data extends ROIBase */ private Map<String,Serializable> rois; /** * The data extends AFunction */ private Map<String,Serializable> functions; /** * User objects, any serializable object. */ private Map<String,Object> userObjects; /** * A set of source meta data which may be altered * to add more information if needed. */ private IMetadata meta; /** * */ private Map<String,VALUE_TYPE> valueTypes; /** * Indicates if the message was generated during an error stream. * */ private boolean error = false; private long time; public DataMessageComponent() { time = System.currentTimeMillis(); } public Map<String, Serializable> getList() { return list; } public Object getList(final String key) { if (list!=null) return list.get(key); return null; } public void setList(Map<String, Serializable> data) { this.list = data; } public IMetadata getMeta() { return meta; } public void setMeta(IMetadata metaData) { this.meta = metaData; } public void setList(final IDataset set) { if (list==null) list = new LinkedHashMap<String,Serializable>(1); String name = set.getName(); if (name==null||"".equals(name)) name = "Unknown"; putUnique(list, name, set); } public void clearList() { if (list!=null) list.clear(); } /** * * @param data * @param key * @param value */ private static <V> void putUnique(Map<String, V> data, String key, V value) { if (data.containsKey(key)) { key = getUniqueKey(data.keySet(), key); } data.put(key, value); } private static String getUniqueKey(Set<String> keySet, String key) { int num = 1; while(keySet.contains(key+num)) num++; return key+num; } /** * Renames a list in the DataMessageComponent * @param existing * @param name * @return true if the name replaced was already there. */ public boolean renameList(String existing, String name) { if (list==null) return false; Map<String,Serializable> map = new LinkedHashMap<String,Serializable>(1); map.putAll(list); final Serializable set = map.remove(existing); if (set instanceof IDataset) { ((IDataset)set).setName(name); } boolean replaced = map.put(name, set) != null; this.list = map; return replaced; } public void addScalar(final Map<String,String> f) { if (f==null) return; addScalar(f, true); } public void addScalar(final Map<String, String> toAdd, boolean overwrite) { if (toAdd==null) return; if (scalar==null) scalar = new Hashtable<String,String>(toAdd.size()); if (overwrite) { for (String key : toAdd.keySet()) { if (toAdd.get(key)!=null) { scalar.remove(key); scalar.put(key, toAdd.get(key)); } } } else { final Map<String, String> copy = new HashMap<String,String>(toAdd); copy.keySet().removeAll(scalar.keySet()); for (String key : copy.keySet()) { if (copy.get(key)!=null) scalar.put(key, copy.get(key)); } } } public void putScalar(final String key, final String value) { if (key==null) return; if (value == null) { if (scalar!=null) scalar.remove(key); return; } if (scalar==null) scalar = new Hashtable<String,String>(1); scalar.put(key,value); } public Map<String,String> getScalar() { return scalar; } public String getScalar(final String key) { if (scalar==null) return null; return scalar.get(key); } @Override public String toString() { StringBuilder buf = new StringBuilder(""); if (list!=null&&!list.isEmpty()) { // Sorts the key set of the list Set<String> keySetList = new TreeSet<String>(list.keySet()); for (String name: keySetList) { if (list.get(name)==null) continue; buf.append(this.formatString(name, list.get(name).toString())); buf.append("\n"); } } if (scalar!=null&&!scalar.isEmpty()) { // Sorts the key set of the scalars Set<String> keySetList = new TreeSet<String>(scalar.keySet()); for (String name: keySetList) { buf.append(this.formatString(name, scalar.get(name).toString())); buf.append("\n"); } } if (meta!=null) { buf.append(meta.toString()); } if ("".equals(buf.toString())) return super.toString(); return buf.toString(); } /** * This private method format a given name and value to: * 'name : value [eventually trunkated]' * @param name * @param value */ private String formatString(String name, String value) { int maxStringLength = 60; int tabStop = 20; String objectName = name; String objectString = value.replaceAll("\n", ""); if (objectName.length() < tabStop) objectName = String.format("%1$-" + tabStop + "s", objectName); if (objectString.length() > maxStringLength) objectString = objectString.substring(0, maxStringLength) + "..."; return objectName + " : " + objectString; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + (error ? 1231 : 1237); result = prime * result + ((functions == null) ? 0 : functions.hashCode()); result = prime * result + ((list == null) ? 0 : list.hashCode()); result = prime * result + ((rois == null) ? 0 : rois.hashCode()); result = prime * result + ((scalar == null) ? 0 : scalar.hashCode()); result = prime * result + ((userObjects == null) ? 0 : userObjects.hashCode()); result = prime * result + ((valueTypes == null) ? 0 : valueTypes.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; DataMessageComponent other = (DataMessageComponent) obj; if (error != other.error) return false; if (functions == null) { if (other.functions != null) return false; } else if (!functions.equals(other.functions)) return false; if (list == null) { if (other.list != null) return false; } else if (!list.equals(other.list)) return false; if (rois == null) { if (other.rois != null) return false; } else if (!rois.equals(other.rois)) return false; if (scalar == null) { if (other.scalar != null) return false; } else if (!scalar.equals(other.scalar)) return false; if (userObjects == null) { if (other.userObjects != null) return false; } else if (!userObjects.equals(other.userObjects)) return false; if (valueTypes == null) { if (other.valueTypes != null) return false; } else if (!valueTypes.equals(other.valueTypes)) return false; return true; } public VALUE_TYPE getValueType(String key) { if (valueTypes==null) return VALUE_TYPE.OVERWRITE_STRING; return valueTypes.get(key); } public void setValueType(final String key, final VALUE_TYPE type) { if (valueTypes==null) valueTypes = new Hashtable<String,VALUE_TYPE>(7); valueTypes.put(key, type); } public void add(DataMessageComponent a) { if (a.list!=null) { if (list==null) list = new LinkedHashMap<String, Serializable>(a.list.size()); list.putAll(a.list); } if (a.scalar!=null) { if (scalar==null) scalar = new Hashtable<String, String>(a.scalar.size()); scalar.putAll(a.scalar); } if (a.meta!=null) meta = a.meta; if (a.valueTypes!=null) { if (valueTypes==null) valueTypes = new Hashtable<String, VALUE_TYPE>(a.valueTypes.size()); valueTypes.putAll(a.valueTypes); } if (a.rois!=null) { for (String key : a.rois.keySet()) { addROI(key, a.getROI(key)); } } if (a.functions!=null) { for (String key : a.functions.keySet()) { addFunction(key, a.getFunction(key)); } } } public boolean isScalarOnly() { return (list==null || list.isEmpty()) && scalar!=null && scalar.size()>0; } public void addList(String name, IDataset a) { if (list==null) list = new LinkedHashMap<String,Serializable>(1); list.put(name, a); } public boolean isError() { return error; } public void setError(boolean error) { this.error = error; } // ROI Methods public void addROI(String name, IROI roi) { if (rois == null) rois = new LinkedHashMap<String,Serializable>(1); rois.put(name, roi); } public IROI getROI(String name) { if (rois == null) return null; return (IROI) rois.get(name); } public Map<String,Serializable> getROIs(){ return rois; } public void clearROI() { if (rois!=null) rois.clear(); rois = null; } public Map<String, Serializable> getRois() { return rois; } public void addList(Map<String, Serializable> data) { if (data==null) return; if (list==null) list = new LinkedHashMap<String,Serializable>(1); this.list.putAll(data); } public void addRois(final Map<String, Serializable> rdata) { if (rdata==null) return; if (rois==null) rois = new LinkedHashMap<String,Serializable>(1); this.rois.putAll(rdata); } public void addFunctions(Map<String, Serializable> functions2) { if (functions2==null) return; if (functions==null) functions = new LinkedHashMap<String,Serializable>(1); this.functions.putAll(functions2); } // Function Methods public void addFunction(String name, IFunction function) { if (functions == null) functions = new LinkedHashMap<String,Serializable>(1); functions.put(name, function); } // Function Methods public void addUserObject(String name, Object userObject) { if (userObjects == null) userObjects = new LinkedHashMap<String,Object>(1); userObjects.put(name, userObject); } public Object getUserObject(String name) { if (userObjects == null) return null; return userObjects.get(name); } public IFunction getFunction(String name) { if (functions == null) return null; return (IFunction) functions.get(name); } public Map<String,Serializable> getFunctions(){ return functions; } public void clearFunctions() { if (functions!=null) functions.clear(); functions = null; } public long getTime() { return time; } public void setTime(long time) { this.time = time; } }