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 <T> metadata type 054 * @param clazz 055 * @param arguments these must match the arguments given in the initialize method specified in the class 056 * @return metadata object or null if type not available 057 * @throws MetadataException if the class cannot be instantiated, the initialize method does not exist, or 058 * the initialize method could not be called successfully 059 */ 060 public static <T extends MetadataType> T createMetadata(Class<T> clazz, Object... arguments) throws MetadataException { 061 @SuppressWarnings("unchecked") 062 Class<T> mdClass = (Class<T>) metadataClasses.get(clazz); 063 if (mdClass == null) { 064 return null; 065 } 066 067 T obj = null; 068 try { 069 obj = mdClass.newInstance(); 070 } catch (Exception e) { 071 throw new MetadataException("Could not create metadata object", e); 072 } 073 074 List<Method> inits = new ArrayList<Method>(); 075 for (Method m : mdClass.getMethods()) { 076 if (m.getName().equals("initialize")) { 077 inits.add(m); 078 } 079 } 080 081 if (inits.isEmpty()) { 082 return obj; 083 } 084 085 int n = arguments == null ? 0 : arguments.length; 086 try { 087 for (Method m : inits) { 088 if (m.getParameterTypes().length == n) { 089 m.invoke(obj, arguments); 090 return obj; 091 } 092 } 093 } catch (Exception e) { 094 throw new MetadataException("Could not initialize object", e); 095 } 096 throw new MetadataException("Could not find initialize method that allows the given number of arguments"); 097 } 098 099 /** 100 * Register metadata class 101 * @param <T> metadata type 102 * @param clazz 103 */ 104 public static <T extends MetadataType> void registerClass(Class<T> clazz) { 105 Class<? extends MetadataType> iClass = LazyDatasetBase.findMetadataTypeSubInterfaces(clazz); 106 107 metadataClasses.put(iClass, clazz); 108 } 109}