package org.hypergraphdb.util; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import org.hypergraphdb.HGException; import org.hypergraphdb.HGHandleFactory; import org.hypergraphdb.HGPersistentHandle; import org.hypergraphdb.type.HGAtomType; /** * * <p> * Utility to read and hold configuration of predefined HyperGraphDB types. * A predefined types configuration file is a text file with the following format: * <ul> * <li>Each line contains a single predefined type as a list of space-separated * fields.</li> * <li> * <li> * The first field is the string representation of the persistent handle of the type. * </li> * <li> * The second field is the Java class implementing the type. It must be a default * constructible implementation of the {@link HGAtomType} interface. * </li> * <li> * Finally, zero or more fields list every Java class that this type maps to. * </li> * <li> * Lines starting with the pound sign # are ignored. * </li> * </ul> * </p> * * @author Borislav Iordanov * */ public class PredefinedTypesConfig { private static ArrayList<String> readIt(InputStream in) { try { ArrayList<String> L = new ArrayList<String>(); BufferedReader reader = new BufferedReader(new InputStreamReader(in)); for (String line = reader.readLine(); line != null; line = reader.readLine()) if (line.trim().length() > 0 && !line.startsWith("#")) L.add(line.trim()); return L; } catch (IOException ex) { throw new HGException(ex); } } private TwoWayMap<HGPersistentHandle, Class<? extends HGAtomType>> handleToImpl = new TwoWayMap<HGPersistentHandle, Class<? extends HGAtomType>>(); private HashMap<HGPersistentHandle, List<Class<?>>> handleToTargets = new HashMap<HGPersistentHandle, List<Class<?>>>(); @SuppressWarnings("unchecked") private void loadTypes(HGHandleFactory handleFactory, ArrayList<String> L) { for (String line : L) { String [] A = line.split("\\s+"); HGPersistentHandle handle = handleFactory.makeHandle(A[0]); String typeClassName = A[1]; Class<? extends HGAtomType> typeClass = null; try { typeClass = (Class<? extends HGAtomType>) Class.forName(typeClassName); handleToImpl.add(handle, typeClass); } catch (Exception ex) { System.err.println("[HYPERGRAPHDB WARNING]: unable to load type class '" + typeClassName + "'"); } ArrayList<Class<?>> targets = new ArrayList<Class<?>>(); handleToTargets.put(handle, targets); for (int i = 2; i < A.length; i++) { Class<?> cl = null; try { cl = Class.forName(A[i]); targets.add(cl); } catch (Exception ex) { System.err.println("[HYPERGRAPHDB WARNING]: unable to load class '" + A[i] + "' for HG type " + "'" + typeClassName + "'"); } } } } private PredefinedTypesConfig() { } public Collection<HGPersistentHandle> getHandles() { return handleToImpl.getXSet(); } public HGPersistentHandle getHandleOf(Class<? extends HGAtomType> typeImplementation) { return handleToImpl.getX(typeImplementation); } public Class<? extends HGAtomType> getTypeImplementation(HGPersistentHandle typeHandle) { return handleToImpl.getY(typeHandle); } public List<Class<?>> getMappedClasses(HGPersistentHandle typeHandle) { return handleToTargets.get(typeHandle); } public static PredefinedTypesConfig loadFromResource(HGHandleFactory handleFactory, String resource) { InputStream in = PredefinedTypesConfig.class.getResourceAsStream(resource); try { PredefinedTypesConfig config = new PredefinedTypesConfig(); config.loadTypes(handleFactory, readIt(in)); return config; } catch (Exception ex) { throw new HGException(ex); } finally { try {in.close();}catch (Throwable t) {} } } public static PredefinedTypesConfig loadFromFile(HGHandleFactory handleFactory, File file) { InputStream in = null; try { in = new FileInputStream(file); PredefinedTypesConfig config = new PredefinedTypesConfig(); config.loadTypes(handleFactory, readIt(in)); return config; } catch (Exception ex) { throw new HGException(ex); } finally { try {if (in != null) in.close();}catch (Throwable t) {} } } }