/* Copyright 2013 The jeo project. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.jeo.util; import com.vividsolutions.jts.geom.Envelope; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.io.ParseException; import com.vividsolutions.jts.io.WKTReader; import io.jeo.geojson.GeoJSONReader; import io.jeo.geom.Bounds; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.io.StringReader; import java.lang.reflect.Array; import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; /** * Conversion utility class. * * @author Justin Deoliveira, OpenGeo */ public class Convert { public static <T> Optional<T> to(Object obj, Class<T> clazz) { return to(obj, clazz, true); } public static <T> Optional<T> to(Object obj, Class<T> clazz, boolean safe) { if (clazz.isInstance(obj)) { return Optional.of((T) obj); } if (clazz == String.class) { return (Optional<T>) toString(obj); } else if (Number.class.isAssignableFrom(clazz)) { return toNumber(obj, (Class)clazz); } else if (Boolean.class.isAssignableFrom(clazz)) { return (Optional<T>) toBoolean(obj); } else if (File.class.isAssignableFrom(clazz)) { return (Optional<T>) toFile(obj); } else if (Path.class.isAssignableFrom(clazz)) { return (Optional<T>) toPath(obj); } else if (URL.class.isAssignableFrom(clazz)) { return (Optional<T>) toURL(obj); } else if (URI.class.isAssignableFrom(clazz)) { return (Optional<T>) toURI(obj); } else if (!safe && obj != null) { //constructor trick T converted = null; try { try { converted = clazz.getConstructor(obj.getClass()).newInstance(obj); } catch(NoSuchMethodException e) { //try with string converted = clazz.getConstructor(String.class).newInstance(obj.toString()); } } catch(Exception e) { } return Optional.of(converted); } return Optional.empty(); } public static Optional<String> toString(Object obj) { if (obj != null) { return Optional.of(obj.toString()); } return Optional.empty(); } public static Optional<Boolean> toBoolean(Object obj) { if (obj instanceof Boolean) { return Optional.of((Boolean) obj); } if (obj instanceof String) { return Optional.of(Boolean.parseBoolean((String) obj)); } return Optional.empty(); } public static Optional<Path> toPath(Object obj) { return toPath(obj, false); } static Optional<Path> toPath(Object obj, boolean checkFile) { if (obj instanceof Path) { return Optional.of(((Path) obj)); } if (obj instanceof String) { return Optional.of(Paths.get((String)obj)); } if (checkFile) { Optional<File> file = toFile(obj, false); return file.map(new Function<File, Path>() { @Override public Path apply(File f) { return f.toPath(); } }); } return Optional.empty(); } public static Optional<File> toFile(Object obj) { return toFile(obj, true); } static Optional<File> toFile(Object obj, boolean checkPath) { if (obj instanceof File) { return Optional.of((File) obj); } if (obj instanceof Path) { return Optional.of(((Path)obj).toFile()); } if (obj instanceof String) { return Optional.of(new File((String)obj)); } if (checkPath) { return toPath(obj, false).map(new Function<Path, File>() { @Override public File apply(Path p) { return p.toFile(); } }); } return Optional.empty(); } public static Optional<URL> toURL(Object obj) { if (obj instanceof String) { try { return Optional.of(new URL(obj.toString())); } catch (MalformedURLException e) { } } return Optional.empty(); } public static Optional<URI> toURI(Object obj) { if (obj instanceof String) { try { return Optional.of(new URI(obj.toString())); } catch (URISyntaxException e) { } } return Optional.empty(); } public static <T extends Number> Optional<T> toNumber(Object obj, Class<T> clazz) { Optional<Number> n = toNumber(obj); if (!n.isPresent()) { return Optional.empty(); } if (clazz == Byte.class) { return Optional.of(clazz.cast(new Byte(n.get().byteValue()))); } if (clazz == Short.class) { return Optional.of(clazz.cast(new Short(n.get().shortValue()))); } if (clazz == Integer.class) { return Optional.of(clazz.cast(new Integer(n.get().intValue()))); } if (clazz == Long.class) { return Optional.of(clazz.cast(new Long(n.get().longValue()))); } if (clazz == Float.class) { return Optional.of(clazz.cast(new Float(n.get().floatValue()))); } if (clazz == Double.class) { return Optional.of(clazz.cast(new Double(n.get().doubleValue()))); } return Optional.empty(); } public static <T extends Number> Optional<List<T>> toNumbers(Object obj, Class<T> clazz) { Collection<Object> l = null; if (obj instanceof Collection) { l = (Collection<Object>) obj; } else if (obj.getClass().isArray()) { l = new ArrayList<Object>(); for (int i = 0; i < Array.getLength(obj); i++) { l.add(Array.get(obj, i)); } } else if (obj instanceof String) { l = (List) Arrays.asList(obj.toString().split(" ")); } if (l != null) { List<T> converted = new ArrayList<T>(); for (Object o : l) { Optional<T> num = toNumber(o, clazz); if (!num.isPresent()) { return (Optional) Optional.empty(); } converted.add(num.get()); } return Optional.of(converted); } return (Optional) Optional.empty(); } public static Optional<Number> toNumber(Object obj) { if (obj instanceof Number) { return Optional.of((Number) obj); } if (obj instanceof String) { String str = (String) obj; try { return Optional.of((Number)Long.parseLong(str)); } catch(NumberFormatException e) { try { return Optional.of((Number)Double.parseDouble(str)); } catch(NumberFormatException e1) { } } } return Optional.empty(); } public static Optional<Reader> toReader(Object obj) throws IOException { if (obj instanceof Reader) { return Optional.of((Reader) obj); } if (obj instanceof InputStream) { return Optional.of((Reader)new BufferedReader(new InputStreamReader((InputStream)obj, Util.UTF_8))); } if (obj instanceof File) { return Optional.of((Reader)Files.newBufferedReader(((File)obj).toPath(), Util.UTF_8)); } if (obj instanceof Path) { return Optional.of((Reader)Files.newBufferedReader(((Path)obj), Util.UTF_8)); } if (obj instanceof String) { return Optional.of((Reader) new StringReader((String) obj)); } return null; } public static Optional<Geometry> toGeometry(Object obj) { if (obj instanceof Geometry) { return Optional.of((Geometry)obj); } if (obj instanceof Envelope) { Envelope env = (Envelope) obj; return Optional.of((Geometry) Bounds.toPolygon(env)); } if (obj instanceof String) { String str = (String) obj; Geometry g = null; // wkt try { g = new WKTReader().read(str); } catch (ParseException e1) { // try geojson try { g = new GeoJSONReader().geometry(str); } catch(Exception e2) { } } return Optional.of(g); } return Optional.empty(); } public static Optional<Envelope> toEnvelope(Object obj) { if(obj instanceof Envelope) { return Optional.of((Envelope)obj); } if (obj instanceof String) { Envelope env = Bounds.parse(obj.toString()); if (env != null) { return Optional.of(env); } } return toGeometry(obj).map(new Function<Geometry, Envelope>() { @Override public Envelope apply(Geometry value) { return value.getEnvelopeInternal(); } }); } }