001/*******************************************************************************
002 * Copyright (c) 2016 Diamond Light Source Ltd. and others.
003 * All rights reserved. This program and the accompanying materials
004 * are made available under the terms of the Eclipse Public License v1.0
005 * which accompanies this distribution, and is available at
006 * http://www.eclipse.org/legal/epl-v10.html
007 *
008 * Contributors:
009 *     Diamond Light Source Ltd - initial API and implementation
010 *******************************************************************************/
011package org.eclipse.january.metadata;
012
013import java.lang.reflect.Method;
014import java.util.HashMap;
015import java.util.Map;
016
017import org.eclipse.january.MetadataException;
018import org.eclipse.january.dataset.LazyDatasetBase;
019import org.eclipse.january.metadata.internal.AxesMetadataImpl;
020import org.eclipse.january.metadata.internal.DimensionMetadataImpl;
021import org.eclipse.january.metadata.internal.ErrorMetadataImpl;
022import org.eclipse.january.metadata.internal.MaskMetadataImpl;
023import org.eclipse.january.metadata.internal.OriginMetadataImpl;
024import org.eclipse.january.metadata.internal.PeemMetadataImpl;
025import org.eclipse.january.metadata.internal.StatisticsMetadataImpl;
026import org.eclipse.january.metadata.internal.UnitMetadataImpl;
027
028public class MetadataFactory {
029
030        private MetadataFactory() {
031        }
032
033        static Map<Class<? extends MetadataType>, Class<? extends MetadataType>> metadataClasses = createMap();
034        private static Map<Class<? extends MetadataType>, Class<? extends MetadataType>> createMap() {
035                Map<Class<? extends MetadataType>, Class<? extends MetadataType>> map = new HashMap<Class<? extends MetadataType>, Class<? extends MetadataType>>();
036                map.put(IMetadata.class, Metadata.class);
037                map.put(ErrorMetadata.class, ErrorMetadataImpl.class);
038                map.put(AxesMetadata.class, AxesMetadataImpl.class);
039                map.put(DimensionMetadata.class, DimensionMetadataImpl.class);
040                map.put(MaskMetadata.class, MaskMetadataImpl.class);
041                map.put(OriginMetadata.class, OriginMetadataImpl.class);
042                map.put(PeemMetadata.class, PeemMetadataImpl.class);
043                map.put(StatisticsMetadata.class, StatisticsMetadataImpl.class);
044                map.put(UnitMetadata.class, UnitMetadataImpl.class);
045                return map;
046        }
047
048        
049        /**
050         * Create a metadata object of given class with given arguments
051         * @param clazz
052         * @param arguments these must match the arguments given in the initialize method specified in the class
053         * @return metadata object or null if type not available
054         * @throws MetadataException if the class cannot be instantiated, the initialize method does not exist, or
055         *  the initialize method could not be called successfully
056         */
057        public static <T extends MetadataType> T createMetadata(Class<T> clazz, Object... arguments) throws MetadataException {
058                @SuppressWarnings("unchecked")
059                Class<T> mdClass = (Class<T>) metadataClasses.get(clazz);
060                if (mdClass == null) {
061                        return null;
062                }
063
064                T obj = null;
065                try {
066                        obj = mdClass.newInstance();
067                } catch (Exception e) {
068                        throw new MetadataException("Could not create metadata object", e);
069                }
070
071                try {
072                        for (Method m : mdClass.getMethods()) {
073                                if (m.getName().equals("initialize")) {
074                                        m.invoke(obj, arguments);
075                                        return obj;
076                                }
077                        }
078                } catch (Exception e) {
079                        throw new MetadataException("Could not initialize object", e);
080                }
081                throw new MetadataException("Could not find initialize method");
082        }
083
084        /**
085         * Register metadata class
086         * @param clazz
087         */
088        public static <T extends MetadataType> void registerClass(Class<T> clazz) {
089                Class<? extends MetadataType> iClass = LazyDatasetBase.findMetadataTypeSubInterfaces(clazz);
090
091                metadataClasses.put(iClass, clazz);
092        }
093}