/**
* <copyright>
*
* Copyright (c) 2005, 2006, 2007, 2008 Springsite BV (The Netherlands) and others
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Martin Taal
* </copyright>
*
* $Id: IdentifierUtil.java,v 1.7 2008/06/28 22:41:47 mtaal Exp $
*/
package org.eclipse.emf.teneo.hibernate.mapping.identifier;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Hashtable;
import org.eclipse.emf.teneo.classloader.ClassLoaderResolver;
import org.eclipse.emf.teneo.classloader.StoreClassLoadException;
import org.eclipse.emf.teneo.hibernate.HbMapperException;
import org.hibernate.engine.ForeignKeys;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.impl.SessionImpl;
import org.hibernate.type.NullableType;
import org.hibernate.type.Type;
/**
* Different identifier related utilities. The current Elver store representation does not use the
* EMF id concept but uses the underlying hibernate identifier. This allows more flexibility than
* the EMF identifier.
*
* @author <a href="mailto:mtaal@elver.org">Martin Taal</a>
* @version $Revision: 1.7 $
*/
public class IdentifierUtil {
/** The logger */
// private static Log log = LogFactory.getLog(IdentifierUtil.class);
/** Separator used in encoding the class name and value */
private static final String ENCODING_SEPARATOR = ";";
/** HashTable with identifier types hashed by entityname */
private static final Hashtable<String, Type> identifierTypeCache = new Hashtable<String, Type>();
/** HashTable with cached constructors */
private static final Hashtable<String, Constructor<?>> constructorCache = new Hashtable<String, Constructor<?>>();
/** Returns the identifiertype on the basis of the class of the passed object */
public static Type getIdentifierType(String className, SessionImplementor session) {
Type type = identifierTypeCache.get(className);
if (type != null) {
return type;
}
final Type identifierType =
((SessionImpl) session).getFactory().getClassMetadata(className).getIdentifierType();
identifierTypeCache.put(className, identifierType);
return identifierType;
}
/** Converts an id to a string representation */
public static String idToString(Object object, SessionImplementor session) {
return createIDString(getIdentifierType(object.getClass().getName(), session), getID(object, session));
}
/** String to id */
public static Serializable stringToId(String className, SessionImplementor Session, String idStr) {
return extractID(getIdentifierType(className, Session), idStr);
}
/** Creates the serializable id object from a string */
private static Serializable extractID(Type type, String idString) {
// first handle the most common case
if (type instanceof NullableType) {
final NullableType ntype = (NullableType) type;
return (Serializable) ntype.fromStringValue(idString);
}
// for all other cases the classname of the type is encoded into the
// field
final String className = idString.substring(0, idString.indexOf(ENCODING_SEPARATOR));
final String strValue = idString.substring(1 + idString.indexOf(ENCODING_SEPARATOR));
Constructor<?> constructor = constructorCache.get(className);
if (constructor == null) {
try {
final Class<?> clazz = ClassLoaderResolver.classForName(className);
constructor = clazz.getConstructor(new Class[] { String.class });
} catch (StoreClassLoadException e) {
throw new HbMapperException("Class " + className + " not found");
} catch (NoSuchMethodException e) {
throw new HbMapperException("Class " + className +
" does not have a constructor with a String parameter!");
}
}
if (constructor == null) {
throw new HbMapperException("Class " + className + " does not have a constructor with a String parameter!");
}
try {
return (Serializable) constructor.newInstance(new Object[] { strValue });
} catch (InvocationTargetException e) {
throw new HbMapperException("Can not instantiate: " + className + " using value " + strValue);
} catch (InstantiationException e) {
throw new HbMapperException("Can not instantiate: " + className + " using value " + strValue);
} catch (IllegalAccessException e) {
throw new HbMapperException("Can not instantiate: " + className + " using value " + strValue);
}
}
/** Returns the id of the passed object */
public static Serializable getID(Object object, SessionImplementor session) {
Serializable id = session.getContextEntityIdentifier(object);
if (id != null) {
return id;
}
// now with entity name
final String entityName = session.bestGuessEntityName(object);
id = ForeignKeys.getEntityIdentifierIfNotUnsaved(entityName, object, session);
if (id != null) {
return id;
}
// now the slow way
return (Serializable) IdentifierCacheHandler.getInstance().getID(object);
}
/** Creates an id string from a serializable object */
private static String createIDString(Type type, Serializable id) {
if (type instanceof NullableType) {
final NullableType ntype = (NullableType) type;
return ntype.toString(id);
}
return id.getClass().getName() + ENCODING_SEPARATOR + id.toString();
}
}