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