    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.ArrayList;
    015import java.util.HashMap;
    016import java.util.List;
    017import java.util.Map;
    018
    019import org.eclipse.january.MetadataException;
    020import org.eclipse.january.dataset.LazyDatasetBase;
    021import org.eclipse.january.metadata.internal.AxesMetadataImpl;
    022import org.eclipse.january.metadata.internal.DimensionMetadataImpl;
    023import org.eclipse.january.metadata.internal.ErrorMetadataImpl;
    024import org.eclipse.january.metadata.internal.MaskMetadataImpl;
    025import org.eclipse.january.metadata.internal.OriginMetadataImpl;
    026import org.eclipse.january.metadata.internal.PeemMetadataImpl;
    027import org.eclipse.january.metadata.internal.StatisticsMetadataImpl;
    028import org.eclipse.january.metadata.internal.UnitMetadataImpl;
    029
    030public class MetadataFactory {
    031
    032        private MetadataFactory() {
    033        }
    034
    035        static Map<Class<? extends MetadataType>, Class<? extends MetadataType>> metadataClasses = createMap();
    036        private static Map<Class<? extends MetadataType>, Class<? extends MetadataType>> createMap() {
    037                Map<Class<? extends MetadataType>, Class<? extends MetadataType>> map = new HashMap<Class<? extends MetadataType>, Class<? extends MetadataType>>();
    038                map.put(IMetadata.class, Metadata.class);
    039                map.put(ErrorMetadata.class, ErrorMetadataImpl.class);
    040                map.put(AxesMetadata.class, AxesMetadataImpl.class);
    041                map.put(DimensionMetadata.class, DimensionMetadataImpl.class);
    042                map.put(MaskMetadata.class, MaskMetadataImpl.class);
    043                map.put(OriginMetadata.class, OriginMetadataImpl.class);
    044                map.put(PeemMetadata.class, PeemMetadataImpl.class);
    045                map.put(StatisticsMetadata.class, StatisticsMetadataImpl.class);
    046                map.put(UnitMetadata.class, UnitMetadataImpl.class);
    047                return map;
    048        }
    049
    050
    051        /**
    052         * Create a metadata object of given class with given arguments
    053         * @param clazz
    054         * @param arguments these must match the arguments given in the initialize method specified in the class
    055         * @return metadata object or null if type not available
    056         * @throws MetadataException if the class cannot be instantiated, the initialize method does not exist, or
    057         *  the initialize method could not be called successfully
    058         */
    059        public static <T extends MetadataType> T createMetadata(Class<T> clazz, Object... arguments) throws MetadataException {
    060                @SuppressWarnings("unchecked")
    061                Class<T> mdClass = (Class<T>) metadataClasses.get(clazz);
    062                if (mdClass == null) {
    063                        return null;
    064                }
    065
    066                T obj = null;
    067                try {
    068                        obj = mdClass.newInstance();
    069                } catch (Exception e) {
    070                        throw new MetadataException("Could not create metadata object", e);
    071                }
    072
    073                List<Method> inits = new ArrayList<Method>();
    074                for (Method m : mdClass.getMethods()) {
    075                        if (m.getName().equals("initialize")) {
    076                                inits.add(m);
    077                        }
    078                }
    079
    080                if (inits.isEmpty()) {
    081                        return obj;
    082                }
    083
    084                int n = arguments == null ? 0 : arguments.length;
    085                try {
    086                        for (Method m : inits) {
    087                                if (m.getParameterTypes().length == n) {
    088                                        m.invoke(obj, arguments);
    089                                        return obj;
    090                                }
    091                        }
    092                } catch (Exception e) {
    093                        throw new MetadataException("Could not initialize object", e);
    094                }
    095                throw new MetadataException("Could not find initialize method that allows the given number of arguments");
    096        }
    097
    098        /**
    099         * Register metadata class
    100         * @param clazz
    101         */
    102        public static <T extends MetadataType> void registerClass(Class<T> clazz) {
    103                Class<? extends MetadataType> iClass = LazyDatasetBase.findMetadataTypeSubInterfaces(clazz);
    104
    105                metadataClasses.put(iClass, clazz);
    106        }
    107}