/*
* Copyright (c) 2009, SQL Power Group Inc.
*
* This file is part of SQL Power Library.
*
* SQL Power Library is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* SQL Power Library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package ca.sqlpower.dao.session;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.geom.Point2D;
import java.io.File;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.URI;
import java.sql.Date;
import java.sql.Time;
import java.sql.Timestamp;
import java.text.Format;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.xml.namespace.QName;
import ca.sqlpower.object.SPObject;
import ca.sqlpower.sql.DataSourceCollection;
import ca.sqlpower.sql.JDBCDataSource;
import ca.sqlpower.sql.SPDataSource;
import ca.sqlpower.sql.SpecificDataSourceCollection;
import ca.sqlpower.util.SQLPowerUtils;
/**
* Converts any known object into a simple type of object that can be
* pushed through an HTTP request and persisted on the server. This also
* contains a way to get the object back based on the simple type that can be
* passed and stored.
*/
public class SessionPersisterSuperConverter {
protected final SPObjectConverter spObjectConverter;
private final FormatConverter formatConverter = new FormatConverter();
private final Point2DConverter point2DConverter = new Point2DConverter();
private final RectangleConverter rectangleConverter = new RectangleConverter();
private final DimensionConverter dimensionConverter = new DimensionConverter();
private final ColorConverter colorConverter = new ColorConverter();
private final DateConverter dateConverter = new DateConverter();
private final StringArrayConverter stringArrayConverter = new StringArrayConverter();
private final ClassConverter classConverter = new ClassConverter();
private final FileConverter fileConverter = new FileConverter();
private final ListConverter listConverter = new ListConverter();
private final LocaleConverter localeConverter = new LocaleConverter();
private final QNameConverter qnameConverter = new QNameConverter();
private final URIConverter uriConverter = new URIConverter();
protected final DataSourceCollection <JDBCDataSource> dsCollection;
/**
* This converter will allow changes between any complex object in the
* session's workspace and a simple type that can be passed between
* persisters.
*
* @param session
* The session used to find necessary parts for converting
* between simple and complex types. The session may be used to
* look up connections, cubes, and {@link SPObject}s in the
* workspace.
*/
public SessionPersisterSuperConverter(DataSourceCollection<? extends SPDataSource> dsCollection,
SPObject root) {
spObjectConverter = new SPObjectConverter(root);
this.dsCollection = new SpecificDataSourceCollection(dsCollection, JDBCDataSource.class);
}
/**
* Converts a complex object to a basic type or reference value that can
* then be passed on to other persisters. To reverse this process, see
* {@link #convertToComplexType}. If a basic object is given to this method
* it will be returned without modification.
*
* @param convertFrom
* The value to convert to a basic type
* @param fromType
* The type that the basic type will be defined as
* @param additionalInfo
* Any additional information that is required by the converters
* for specific object types. The ONLY class that currently
* requires an additional type is the cube converter. If we can
* remove the need to pass the data source type with the cube
* then this value can go away.
* @returns The basic type representation of the given object.
*/
public Object convertToBasicType(Object convertFrom, Object ... additionalInfo) {
if (convertFrom == null) {
return null;
} else if (convertFrom instanceof SPObject) {
SPObject spo = (SPObject) convertFrom;
return spObjectConverter.convertToSimpleType(spo);
} else if (convertFrom instanceof String) {
return convertFrom;
} else if (convertFrom instanceof Integer) {
return convertFrom;
} else if (convertFrom instanceof Double) {
return convertFrom;
} else if (convertFrom instanceof Boolean) {
return convertFrom;
} else if (convertFrom instanceof Long) {
return convertFrom;
} else if (convertFrom instanceof Short) {
return convertFrom;
} else if (convertFrom instanceof Float) {
return convertFrom;
} else if (convertFrom instanceof BigDecimal) {
return ((BigDecimal) convertFrom).toPlainString();
} else if (convertFrom instanceof BigInteger) {
return ((BigInteger) convertFrom).toString();
} else if (convertFrom instanceof Timestamp) {
return ((Timestamp) convertFrom).toString();
} else if (convertFrom instanceof Time) {
return ((Time) convertFrom).toString();
} else if (convertFrom instanceof Date) {
return ((Date) convertFrom).toString();
} else if (convertFrom instanceof Character) {
Character c = (Character) convertFrom;
String s = new String(new char[]{c.charValue()});
return s;
} else if (convertFrom.getClass().isEnum() || (convertFrom.getClass().isAnonymousClass() && convertFrom.getClass().getSuperclass().isEnum())) {
return new EnumConverter(convertFrom.getClass()).convertToSimpleType((Enum) convertFrom);
} else if (convertFrom instanceof JDBCDataSource) {
return ((JDBCDataSource) convertFrom).getName();
} else if (convertFrom instanceof Format) {
return formatConverter.convertToSimpleType((Format) convertFrom);
} else if (convertFrom instanceof Point2D) {
Point2D p = (Point2D) convertFrom;
return point2DConverter.convertToSimpleType(p);
} else if (convertFrom instanceof Rectangle) {
Rectangle r = (Rectangle) convertFrom;
return rectangleConverter.convertToSimpleType(r);
} else if (convertFrom instanceof Dimension) {
Dimension d = (Dimension) convertFrom;
return dimensionConverter.convertToSimpleType(d);
} else if (convertFrom instanceof Color) {
Color c = (Color) convertFrom;
return colorConverter.convertToSimpleType(c);
} else if (convertFrom instanceof Class<?>) {
Class<?> c = (Class<?>) convertFrom;
return classConverter.convertToSimpleType(c);
} else if (convertFrom instanceof java.util.Date) {
java.util.Date d = (java.util.Date) convertFrom;
return dateConverter.convertToSimpleType(d);
} else if (convertFrom instanceof File) {
File file = (File) convertFrom;
return fileConverter.convertToSimpleType(file);
} else if (convertFrom instanceof String[]) {
String[] array = (String[]) convertFrom;
return stringArrayConverter.convertToSimpleType(array);
} else if (convertFrom instanceof Exception) {
String exceptionString = SQLPowerUtils.exceptionStackToString((Exception) convertFrom);
//This exception name will be placed back on when the string is converted back to an object.
exceptionString = exceptionString.replace(Exception.class.getName() + ": ", "");
return exceptionString;
} else if (convertFrom instanceof List<?>) {
return listConverter.convertToSimpleType((List<Object>)convertFrom);
} else if (convertFrom instanceof Locale) {
return localeConverter.convertToSimpleType((Locale) convertFrom);
} else if (convertFrom instanceof QName) {
return qnameConverter.convertToSimpleType((QName) convertFrom);
} else if (convertFrom instanceof URI) {
return uriConverter.convertToSimpleType((URI) convertFrom);
} else {
throw new IllegalArgumentException("Cannot convert " + convertFrom + " of type " +
convertFrom.getClass());
}
}
/**
* Converts a basic type to a complex type that can then be passed to other
* persisters. To reverse this process, see
* {@link #convertToBasicType(Object, Object...)}.
*
* @param o
* The value to convert to a complex type.
* @param type
* The type that the complex type will be defined as
* @return The complex type representation of the given object.
*/
public Object convertToComplexType(Object o, Class<? extends Object> type) {
if (o == null) {
return null;
} else if (SPObject.class.isAssignableFrom(type)) {
return spObjectConverter.convertToComplexType((String) o);
} else if (String.class.isAssignableFrom(type)) {
return (String) o;
} else if (Integer.class.isAssignableFrom(type)) {
return (Integer) o;
} else if (Double.class.isAssignableFrom(type)) {
if (o instanceof BigDecimal) {
return ((BigDecimal) o).doubleValue();
} else {
return (Double) o;
}
} else if (Boolean.class.isAssignableFrom(type)) {
return (Boolean) o;
} else if (Long.class.isAssignableFrom(type)) {
return (Long) o;
} else if (Short.class.isAssignableFrom(type)) {
return (Short) o;
} else if (Float.class.isAssignableFrom(type)) {
return (Float) o;
} else if (Character.class.isAssignableFrom(type)) {
return ((String) o).charAt(0);
} else if (BigDecimal.class.isAssignableFrom(type)) {
return new BigDecimal((String) o);
} else if (BigInteger.class.isAssignableFrom(type)) {
return new BigInteger((String) o);
} else if (Timestamp.class.isAssignableFrom(type)) {
return Timestamp.valueOf((String) o);
} else if (Time.class.isAssignableFrom(type)) {
return Time.valueOf((String) o);
} else if (Date.class.isAssignableFrom(type)) {
return Date.valueOf((String) o);
} else if (Enum.class.isAssignableFrom(type)) {
if (type.isAnonymousClass() && Enum.class.isAssignableFrom(type.getSuperclass())) {
return new EnumConverter(type.getSuperclass()).convertToComplexType((String) o);
} else {
return new EnumConverter(type).convertToComplexType((String) o);
}
} else if (JDBCDataSource.class.isAssignableFrom(type)) {
if (((String) o).equals("PlayPen Database")) {
return new JDBCDataSource(dsCollection);
} else {
return dsCollection.getDataSource((String) o, JDBCDataSource.class);
}
} else if (Format.class.isAssignableFrom(type)) {
return formatConverter.convertToComplexType((String) o);
} else if (Point.class.isAssignableFrom(type)) {
Point2D p2d = point2DConverter.convertToComplexType((String) o);
return new Point((int) p2d.getX(), (int) p2d.getY());
} else if (Point2D.class.isAssignableFrom(type)) {
return point2DConverter.convertToComplexType((String) o);
} else if (Rectangle.class.isAssignableFrom(type)) {
return rectangleConverter.convertToComplexType((String) o);
} else if (Color.class.isAssignableFrom(type)) {
return colorConverter.convertToComplexType((String) o);
} else if (Class.class.isAssignableFrom(type)) {
return classConverter.convertToComplexType((String) o);
} else if (java.util.Date.class.isAssignableFrom(type)) {
return dateConverter.convertToComplexType((String) o);
} else if (File.class.isAssignableFrom(type)) {
return fileConverter.convertToComplexType((String) o);
} else if (Dimension.class.isAssignableFrom(type)) {
return dimensionConverter.convertToComplexType((String) o);
} else if (String[].class.isAssignableFrom(type)) {
return stringArrayConverter.convertToComplexType((String) o);
} else if (Exception.class.isAssignableFrom(type)) {
return new Exception((String) o);
} else if (List.class.isAssignableFrom(type)) {
return listConverter.convertToComplexType((String) o);
} else if (Locale.class.isAssignableFrom(type)) {
return localeConverter.convertToComplexType((String) o);
} else if (QName.class.isAssignableFrom(type)) {
return qnameConverter.convertToComplexType((String) o);
} else if (URI.class.isAssignableFrom(type)) {
return uriConverter.convertToComplexType((String) o);
} else {
throw new IllegalArgumentException("Cannot convert " + o + " of type " +
o.getClass() + " to the type " + type);
}
}
public void setUUIDCache(Map<String, SPObject> lookupCache) {
spObjectConverter.setUUIDCache(lookupCache);
}
public void removeUUIDCache() {
spObjectConverter.removeUUIDCache();
}
}