/*
This file belongs to the Servoy development and deployment environment, Copyright (C) 1997-2010 Servoy BV
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Affero General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your option) any
later version.
This program 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License along
with this program; if not, see http://www.gnu.org/licenses or write to the Free
Software Foundation,Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
*/
package com.servoy.j2db.util.serialize;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import com.servoy.j2db.util.Debug;
/**
* @author rgansevles
*
*/
public class ReplacedObject implements Serializable
{
private static Map<String, Map<Class< ? extends IWriteReplace>, Short>> classMapping = new HashMap<String, Map<Class< ? extends IWriteReplace>, Short>>();
private static Map<String, Map<Short, Class< ? extends IWriteReplace>>> typeMapping = new HashMap<String, Map<Short, Class< ? extends IWriteReplace>>>();
private final short t; // type
private final Object o; // object
private final String d; // domain;
public ReplacedObject(String domain, Class< ? > cls, Object o)
{
this.d = domain;
this.t = getType(domain, cls);
this.o = o;
}
public static void installClassMapping(String domain, Map<Class< ? extends IWriteReplace>, Short> map)
{
classMapping.put(domain, map);
}
public static Collection<Class< ? extends IWriteReplace>> getDomainClasses(String domain)
{
Map<Class< ? extends IWriteReplace>, Short> domainMapping = classMapping.get(domain);
if (domainMapping == null)
{
throw new IllegalStateException("Classmapping for domain " + domain + " not installed"); //$NON-NLS-1$ //$NON-NLS-2$
}
return domainMapping.keySet();
}
private static short getType(String domain, Class< ? > cls)
{
Map<Class< ? extends IWriteReplace>, Short> domainMapping = classMapping.get(domain);
if (domainMapping == null)
{
throw new IllegalStateException("Classmapping for domain " + domain + " not installed"); //$NON-NLS-1$ //$NON-NLS-2$
}
Short type = domainMapping.get(cls);
if (type == null)
{
throw new IllegalArgumentException("No class mapping defined for serialization for class " + cls.getName() + " in domain " + domain); //$NON-NLS-1$ //$NON-NLS-2$
}
return type.shortValue();
}
private static Class< ? extends IWriteReplace> getClass(String domain, short type)
{
Map<Short, Class< ? extends IWriteReplace>> domainTypeMapping = typeMapping.get(domain);
if (domainTypeMapping == null)
{
domainTypeMapping = new HashMap<Short, Class< ? extends IWriteReplace>>();
Map<Class< ? extends IWriteReplace>, Short> domainMapping = classMapping.get(domain);
if (domainMapping == null)
{
throw new IllegalStateException("Classmapping for domain " + domain + " not installed"); //$NON-NLS-1$ //$NON-NLS-2$
}
for (Entry<Class< ? extends IWriteReplace>, Short> entry : domainMapping.entrySet())
{
domainTypeMapping.put(entry.getValue(), entry.getKey());
}
typeMapping.put(domain, domainTypeMapping);
}
Class< ? extends IWriteReplace> cls = domainTypeMapping.get(Short.valueOf(type));
if (cls == null)
{
throw new IllegalStateException("Class name not found for type " + type + " in domain " + domain); //$NON-NLS-1$ //$NON-NLS-2$
}
return cls;
}
protected Object readResolve()
{
try
{
Class< ? extends IWriteReplace> cls = getClass(d, t);
Constructor< ? extends IWriteReplace> constructor = cls.getConstructor(new Class[] { getClass() });
return constructor.newInstance(new Object[] { this });
}
catch (Exception e)
{
Debug.error("Error resolving replaced object", e); //$NON-NLS-1$
throw new RuntimeException("Error resolving replaced object in domain " + d + " of type " + t + ':' + o, e); //$NON-NLS-1$ //$NON-NLS-2$
}
}
/**
* @return
*/
public Object getObject()
{
return o;
}
/** Utility method to convert array type and copy elements.
* @param array
* @param componentClass
* @return
*/
public static Object[] convertArray(Object[] array, Class< ? > componentClass)
{
if (array == null)
{
return null;
}
Object[] res = (Object[])java.lang.reflect.Array.newInstance(componentClass, array.length);
System.arraycopy(array, 0, res, 0, array.length);
return res;
}
}