001 /* 002 * Copyright (C) 2012 eXo Platform SAS. 003 * 004 * This is free software; you can redistribute it and/or modify it 005 * under the terms of the GNU Lesser General Public License as 006 * published by the Free Software Foundation; either version 2.1 of 007 * the License, or (at your option) any later version. 008 * 009 * This software is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * You should have received a copy of the GNU Lesser General Public 015 * License along with this software; if not, write to the Free 016 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 017 * 02110-1301 USA, or see the FSF site: http://www.fsf.org. 018 */ 019 020 package org.crsh.cli.type; 021 022 import java.util.Collections; 023 import java.util.Iterator; 024 import java.util.LinkedHashSet; 025 import java.util.ServiceConfigurationError; 026 import java.util.ServiceLoader; 027 import java.util.logging.Level; 028 import java.util.logging.Logger; 029 030 /** 031 * A factory for value types. 032 */ 033 public class ValueTypeFactory { 034 035 /** A value type factory instance that provides a predefined set of value types. */ 036 public static final ValueTypeFactory DEFAULT = new ValueTypeFactory(); 037 038 /** The known types. */ 039 private final ValueType<?>[] types; 040 041 private ValueTypeFactory() { 042 this.types = new ValueType<?>[]{ ValueType.STRING, ValueType.INTEGER, ValueType.BOOLEAN, 043 ValueType.ENUM, ValueType.PROPERTIES, ValueType.OBJECT_NAME, ValueType.THREAD, ValueType.FILE}; 044 } 045 046 /** 047 * Create a value type factory for the the default value types and the value types that the specified 048 * classloader will load. 049 * 050 * @param loader the loader 051 * @throws NullPointerException if the loader is null 052 */ 053 public ValueTypeFactory(ClassLoader loader) throws NullPointerException { 054 if (loader == null) { 055 throw new NullPointerException("No null loader accepted"); 056 } 057 058 // 059 LinkedHashSet<ValueType> types = new LinkedHashSet<ValueType>(); 060 Collections.addAll(types, DEFAULT.types); 061 Iterator<ValueType> sl = ServiceLoader.load(ValueType.class, loader).iterator(); 062 while (sl.hasNext()) { 063 try { 064 ValueType type = sl.next(); 065 types.add(type); 066 } 067 catch (ServiceConfigurationError e) { 068 // Log it 069 Logger logger = Logger.getLogger(ValueTypeFactory.class.getName()); 070 logger.log(Level.WARNING, "Could not load value type factory", e); 071 } 072 } 073 074 // 075 this.types = types.toArray(new ValueType[types.size()]); 076 } 077 078 public <T, S extends T> ValueType<T> get(Class<S> clazz) { 079 ValueType<?> bestType = null; 080 int bestDegree = Integer.MAX_VALUE; 081 for (ValueType<?> type : types) { 082 int degree = type.getDistance(clazz); 083 if (degree != -1 && degree < bestDegree) { 084 bestType = type; 085 bestDegree = degree; 086 } 087 } 088 return (ValueType<T>)bestType; 089 } 090 }