001 /*
002 Copyright (c) 2009 Olivier Chafik, All Rights Reserved
003
004 This file is part of JNAerator (http://jnaerator.googlecode.com/).
005
006 JNAerator is free software: you can redistribute it and/or modify
007 it under the terms of the GNU General Public License as published by
008 the Free Software Foundation, either version 3 of the License, or
009 (at your option) any later version.
010
011 JNAerator is distributed in the hope that it will be useful,
012 but WITHOUT ANY WARRANTY; without even the implied warranty of
013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014 GNU General Public License for more details.
015
016 You should have received a copy of the GNU General Public License
017 along with JNAerator. If not, see <http://www.gnu.org/licenses/>.
018 */
019 package com.ochafik.lang;
020
021 import java.io.File;
022 import java.lang.reflect.Constructor;
023 import java.lang.reflect.Method;
024 import java.lang.reflect.Modifier;
025 import java.net.MalformedURLException;
026 import java.net.URI;
027 import java.net.URL;
028 import java.text.DateFormat;
029 import java.text.ParseException;
030 import java.util.Collections;
031 import java.util.Date;
032 import java.util.HashMap;
033 import java.util.Iterator;
034 import java.util.LinkedHashMap;
035 import java.util.Map;
036 import java.util.NoSuchElementException;
037
038 import org.w3c.dom.Node;
039 import org.w3c.dom.NodeList;
040
041
042 public class SyntaxUtils {
043 public static <T> T[] array(T... elements) {
044 return elements;
045 }
046
047 public static <T> boolean equal(T a, T b) {
048 if (a == null)
049 return b == null;
050 if (b == null)
051 return false;
052 return a.equals(b);
053 }
054
055 public static <T> T as(Object value, Class<T> c) {
056 if (value == null)
057 return null;
058 if (c.isAssignableFrom(value.getClass()))
059 return c.cast(value);
060 return null;
061 }
062
063 interface Converter<T> {
064 public T convert(Object value) throws Exception;
065 }
066
067 public static <T> void registerConverter(Class<T> c, Converter<T> converter) {
068 converters.put(c, converter);
069 }
070
071 static Map<Class<?>, Converter<?>> converters = new HashMap<Class<?>, Converter<?>>();
072 static {
073 registerConverter(Date.class, new Converter<Date>() {
074 public Date convert(Object value) throws ParseException {
075 String s = value.toString();
076 Date date = DateFormat.getDateTimeInstance().parse(s);
077 if (date == null)
078 date = DateFormat.getDateInstance().parse(s);
079 return date;
080 }
081 });
082
083 registerConverter(Double.class, new Converter<Double>() {
084 public Double convert(Object value) throws ParseException {
085 if (value instanceof Number)
086 return ((Number)value).doubleValue();
087 String s = value.toString();
088 if (s.length() == 0)
089 return 0.0;
090
091 return Double.parseDouble(s);
092 }
093 });
094 registerConverter(Float.class, new Converter<Float>() {
095 public Float convert(Object value) throws ParseException {
096 if (value instanceof Number)
097 return ((Number)value).floatValue();
098 String s = value.toString();
099 if (s.length() == 0)
100 return 0f;
101
102 return Float.parseFloat(s);
103 }
104 });
105 registerConverter(Long.class, new Converter<Long>() {
106 public Long convert(Object value) throws ParseException {
107 if (value instanceof Number)
108 return ((Number)value).longValue();
109 String s = value.toString();
110 if (s.length() == 0)
111 return 0l;
112
113 return Long.parseLong(s);
114 }
115 });
116 registerConverter(Integer.class, new Converter<Integer>() {
117 public Integer convert(Object value) throws ParseException {
118 if (value instanceof Number)
119 return ((Number)value).intValue();
120 String s = value.toString();
121 if (s.length() == 0)
122 return 0;
123
124 return Integer.parseInt(s);
125 }
126 });
127 registerConverter(Short.class, new Converter<Short>() {
128 public Short convert(Object value) throws ParseException {
129 if (value instanceof Number)
130 return ((Number)value).shortValue();
131 String s = value.toString();
132 if (s.length() == 0)
133 return 0;
134
135 return Short.parseShort(s);
136 }
137 });
138 registerConverter(String.class, new Converter<String>() {
139 public String convert(Object value) throws ParseException {
140 if (value instanceof Date)
141 return DateFormat.getDateInstance().format((Date)value);
142 return value.toString();
143 }
144 });
145 registerConverter(File.class, new Converter<File>() {
146 public File convert(Object value) throws ParseException {
147 if (value instanceof URI)
148 try {
149 value = ((URI)value).toURL();
150 } catch (MalformedURLException e1) {}
151
152 if (value instanceof String) {
153 try {
154 value = new URL((String)value);
155 } catch (MalformedURLException e) {}
156 }
157 if (value instanceof URL)
158 return new File(((URL)value).getFile());
159
160 String s = value.toString();
161 if (s.length() == 0)
162 return null;
163
164 return new File(s);
165 }
166 });
167 registerConverter(URL.class, new Converter<URL>() {
168 public URL convert(Object value) {
169 if (value instanceof URI)
170 try {
171 return ((URI)value).toURL();
172 } catch (MalformedURLException e1) {}
173
174 if (value instanceof File)
175 try {
176 return ((File)value).toURI().toURL();
177 } catch (MalformedURLException e1) {}
178
179 String s = value.toString();
180 if (s.length() == 0)
181 return null;
182
183 try {
184 return new URL(s);
185 } catch (MalformedURLException e) {}
186
187 try {
188 return new File(s).toURI().toURL();
189 } catch (MalformedURLException e) {}
190
191 return null;
192 }
193 });
194 }
195
196 @SuppressWarnings("unchecked")
197 public static <T> T convert(Object value, Class<T> c) {
198 if (value == null)
199 return null;
200
201 Class<?> type = value.getClass();
202 if (c.isAssignableFrom(type))
203 return c.cast(value);
204
205 Converter<T> converter = (Converter<T>)converters.get(c);
206 if (converter != null)
207 try {
208 return converter.convert(value);
209 } catch (Exception e) {
210 e.printStackTrace();
211 }
212
213 for (Constructor<?> cons : c.getConstructors()) {
214 Class<?>[] parameterTypes = cons.getParameterTypes();
215 if (parameterTypes.length == 1 && parameterTypes[0].isAssignableFrom(type)) {
216 try {
217 return (T)cons.newInstance(value);
218 } catch (Exception e) {
219 e.printStackTrace();
220 }
221 }
222 }
223
224 for (Method meth : c.getMethods()) {
225 String name = meth.getName();
226 if ((meth.getModifiers() & Modifier.STATIC) == 0)
227 continue;
228
229 if (!" parse createInstance newInstance ".contains(" " + name + " "))
230 continue;
231
232 Class<?>[] parameterTypes = meth.getParameterTypes();
233 if (parameterTypes.length == 1 && parameterTypes[0].isAssignableFrom(type)) {
234 try {
235 return (T)meth.invoke(null, value);
236 } catch (Exception e) {
237 e.printStackTrace();
238 }
239 }
240 }
241 return null;
242 }
243
244 public static class EasyMap<K, V> extends LinkedHashMap<K, V> {
245 private static final long serialVersionUID = -3087972422440202407L;
246
247 public EasyMap<K, V> add(K key, V value) {
248 put(key, value);
249 return this;
250 }
251 }
252 public static <K, V> EasyMap<K, V> map(K key, V value) {
253 return new EasyMap<K, V>().add(key, value);
254 }
255
256 @SuppressWarnings("unchecked")
257 public static Iterable<Node> iterable(final NodeList list) {
258 if (list == null)
259 return Collections.EMPTY_LIST;
260
261 return new Iterable<Node>() {
262 int nextPos = 0;
263 public Iterator<Node> iterator() {
264 return new Iterator<Node>() {
265 public Node next() {
266 if (nextPos >= list.getLength())
267 throw new NoSuchElementException();
268 return list.item(nextPos++);
269 }
270 public boolean hasNext() {
271 return nextPos < list.getLength();
272 }
273 public void remove() {
274 throw new UnsupportedOperationException();
275 }
276 };
277 }
278 };
279 }
280 }