001/*- 002 ******************************************************************************* 003 * Copyright (c) 2011, 2016 Diamond Light Source Ltd. 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the Eclipse Public License v1.0 006 * which accompanies this distribution, and is available at 007 * http://www.eclipse.org/legal/epl-v10.html 008 * 009 * Contributors: 010 * Peter Chang - initial API and implementation and/or initial documentation 011 *******************************************************************************/ 012 013package org.eclipse.january.metadata; 014 015import java.io.ByteArrayInputStream; 016import java.io.ByteArrayOutputStream; 017import java.io.ObjectInputStream; 018import java.io.ObjectOutputStream; 019import java.io.Serializable; 020import java.util.Collection; 021import java.util.Collections; 022import java.util.HashMap; 023import java.util.LinkedHashMap; 024import java.util.Map; 025import java.util.Map.Entry; 026 027import org.eclipse.january.MetadataException; 028import org.eclipse.january.dataset.ShapeUtils; 029 030 031/** 032 * Basic implementation of metadata 033 */ 034public class Metadata implements IMetadata { 035 private static final long serialVersionUID = IMetadata.serialVersionUID; 036 037 private Map<String, ? extends Serializable> metadata; 038 // NOTE shapes is LinkedHashMap here because the names collection 039 // maintained order. Now that we do not need this collection but if we 040 // do not keep the shapes in a LinkedHashMap, we lose order. 041 private Map<String,int[]> shapes = new LinkedHashMap<String,int[]>(7); 042 private Collection<Serializable> userObjects; 043 private String filePath; 044 045 046 public Metadata() { 047 } 048 049 public Metadata(Map<String, ? extends Serializable> metadata) { 050 initialize(metadata); 051 } 052 053 @Override 054 public void initialize(Map<String, ? extends Serializable> metadata) { 055 this.metadata = metadata; 056 } 057 058 @Override 059 public void addNames(Collection<String> names) { 060 if (names != null) { 061 for (String n : names) { 062 shapes.put(n, null); 063 } 064 } 065 } 066 067 /** 068 * Set metadata map 069 * @param metadata 070 */ 071 @Override 072 public void setMetadata(Map<String, ? extends Serializable> metadata) { 073 this.metadata = metadata; 074 } 075 076 /** 077 * Internal use only 078 * @return metadata map 079 */ 080 protected Map<String, ? extends Serializable> getInternalMetadata() { 081 return metadata; 082 } 083 084 /** 085 * Set user objects 086 * @param objects 087 */ 088 public void setUserObjects(Collection<Serializable> objects) { 089 userObjects = objects; 090 } 091 092 public void addDataInfo(String name, int... shape) { 093 shapes.put(name, shape); 094 } 095 096 @Override 097 public Collection<String> getDataNames() { 098 return Collections.unmodifiableCollection(shapes.keySet()); 099 } 100 101 @Override 102 public Map<String, int[]> getDataShapes() { 103 return Collections.unmodifiableMap(shapes); 104 } 105 106 @Override 107 public Map<String, Integer> getDataSizes() { 108 Map<String, Integer> sizes = new HashMap<String, Integer>(1); 109 for (Entry<String, int[]> e : shapes.entrySet()) { 110 int[] shape = e.getValue(); 111 if (shape != null && shape.length > 1) 112 sizes.put(e.getKey(), ShapeUtils.calcSize(shape)); 113 else 114 sizes.put(e.getKey(), null); 115 } 116 if (sizes.size() > 0) { 117 return Collections.unmodifiableMap(sizes); 118 } 119 return null; 120 } 121 122 @Override 123 public Serializable getMetaValue(String key) throws MetadataException { 124 return metadata == null ? null : metadata.get(key); 125 } 126 127 @SuppressWarnings("unchecked") 128 @Override 129 public Collection<String> getMetaNames() throws MetadataException { 130 return metadata == null ? (Collection<String>) Collections.EMPTY_SET : Collections.unmodifiableCollection(metadata.keySet()); 131 } 132 133 @Override 134 public Collection<Serializable> getUserObjects() { 135 return userObjects; 136 } 137 138 @Override 139 public IMetadata clone() { 140 Metadata c = null; 141 try { 142 c = (Metadata) super.clone(); 143 if (metadata != null) { 144 HashMap<String, Serializable> md = new HashMap<String, Serializable>(); 145 c.metadata = md; 146 ByteArrayOutputStream os = new ByteArrayOutputStream(512); 147 for (String k : metadata.keySet()) { 148 Serializable v = metadata.get(k); 149 if (v != null) { 150 try (ObjectOutputStream oos = new ObjectOutputStream(os)) { 151 oos.writeObject(v); 152 try (ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(os.toByteArray()))) { 153 Serializable nv = (Serializable) ois.readObject(); 154 md.put(k, nv); 155 } 156 } 157 os.reset(); 158 } else { 159 md.put(k, null); 160 } 161 } 162 } 163 c.shapes = new HashMap<String, int[]>(1); 164 for (Entry<String, int[]> e : shapes.entrySet()) { 165 int[] s = e.getValue(); 166 c.shapes.put(e.getKey(), s == null ? null : s.clone()); 167 } 168 } catch (CloneNotSupportedException e) { 169 // Allowed for some objects not to be cloned. 170 } catch (Throwable e) { 171 if (e instanceof ClassNotFoundException) { 172 // Fix to http://jira.diamond.ac.uk/browse/SCI-1644 173 // Happens when cloning meta data with GridPreferences 174 } if (e instanceof RuntimeException ) { 175 throw (RuntimeException)e; 176 } 177 } 178 return c; 179 } 180 181 @Override 182 public String getFilePath() { 183 return filePath; 184 } 185 186 @Override 187 public void setFilePath(String filePath) { 188 this.filePath = filePath; 189 } 190}