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 org.crsh.cli.completers.EmptyCompleter; 023 import org.crsh.cli.completers.EnumCompleter; 024 import org.crsh.cli.spi.Completer; 025 026 import javax.management.ObjectName; 027 import java.util.Properties; 028 import java.util.StringTokenizer; 029 030 /** 031 * A type for values. 032 * 033 * @param <V> the generic value type 034 */ 035 public abstract class ValueType<V> { 036 037 /** . */ 038 public static final ValueType<String> STRING = new ValueType<String>(String.class) { 039 @Override 040 public <S extends String> S parse(Class<S> type, String s) throws Exception { 041 return type.cast(s); 042 } 043 }; 044 045 /** . */ 046 public static final ValueType<Integer> INTEGER = new ValueType<Integer>(Integer.class) { 047 @Override 048 public <S extends Integer> S parse(Class<S> type, String s) throws Exception { 049 return type.cast(Integer.parseInt(s)); 050 } 051 }; 052 053 /** . */ 054 public static final ValueType<Boolean> BOOLEAN = new ValueType<Boolean>(Boolean.class) { 055 @Override 056 public <S extends Boolean> S parse(Class<S> type, String s) throws Exception { 057 return type.cast(Boolean.parseBoolean(s)); 058 } 059 }; 060 061 /** . */ 062 public static final ValueType<Enum> ENUM = new ValueType<Enum>(Enum.class, EnumCompleter.class) { 063 @Override 064 public <S extends Enum> S parse(Class<S> type, String s) { 065 // We cannot express S extends Enum<S> type 066 // so we need this necessary cast to make the java compiler happy 067 S s1 = (S)Enum.valueOf(type, s); 068 return s1; 069 } 070 }; 071 072 /** . */ 073 public static final ValueType<Properties> PROPERTIES = new ValueType<Properties>(Properties.class) { 074 @Override 075 public <S extends Properties> S parse(Class<S> type, String s) throws Exception { 076 java.util.Properties props = new java.util.Properties(); 077 StringTokenizer tokenizer = new StringTokenizer(s, ";", false); 078 while(tokenizer.hasMoreTokens()){ 079 String token = tokenizer.nextToken(); 080 if(token.contains("=")) { 081 String key = token.substring(0, token.indexOf('=')); 082 String value = token.substring(token.indexOf('=') + 1, token.length()); 083 props.put(key, value); 084 } 085 } 086 return type.cast(props); 087 } 088 }; 089 090 /** . */ 091 public static final ValueType<ObjectName> OBJECT_NAME = new ValueType<ObjectName>(ObjectName.class) { 092 @Override 093 public <S extends ObjectName> S parse(Class<S> type, String s) throws Exception { 094 return type.cast(ObjectName.getInstance(s)); 095 } 096 }; 097 098 /** . */ 099 protected final Class<V> type; 100 101 /** . */ 102 protected final Class<? extends Completer> completer; 103 104 protected ValueType(Class<V> type, Class<? extends Completer> completer) throws NullPointerException { 105 if (type == null) { 106 throw new NullPointerException("No null value type accepted"); 107 } 108 if (completer == null) { 109 throw new NullPointerException("No null completer accepted"); 110 } 111 112 // 113 this.completer = completer; 114 this.type = type; 115 } 116 117 protected ValueType(Class<V> type) throws NullPointerException { 118 if (type == null) { 119 throw new NullPointerException("No null value type accepted"); 120 } 121 122 // 123 this.completer = EmptyCompleter.class; 124 this.type = type; 125 } 126 127 final int getDistance(Class<?> clazz) { 128 if (type == clazz) { 129 return 0; 130 } else if (type.isAssignableFrom(clazz)) { 131 int degree = 0; 132 for (Class<?> current = clazz;current != type;current = current.getSuperclass()) { 133 degree++; 134 } 135 return degree; 136 } else { 137 return -1; 138 } 139 } 140 141 @Override 142 public final int hashCode() { 143 return type.hashCode(); 144 } 145 146 @Override 147 public final boolean equals(Object obj) { 148 if (obj == null) { 149 return false; 150 } else { 151 if (obj == this) { 152 return true; 153 } else { 154 if (obj.getClass() == ValueType.class) { 155 ValueType that = (ValueType)obj; 156 return type == that.type; 157 } else { 158 return false; 159 } 160 } 161 } 162 } 163 164 public Class<? extends Completer> getCompleter() { 165 return completer; 166 } 167 168 public final Class<V> getType() { 169 return type; 170 } 171 172 public final V parse(String s) throws Exception { 173 return parse(type, s); 174 } 175 176 public abstract <S extends V> S parse(Class<S> type, String s) throws Exception; 177 178 }