001/* 002 * Copyright 2010, 2011, 2012 Christopher Pheby 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.jadira.usertype.bindings; 017 018import java.io.Serializable; 019import java.lang.annotation.Annotation; 020import java.lang.reflect.InvocationTargetException; 021import java.sql.PreparedStatement; 022import java.sql.ResultSet; 023import java.sql.SQLException; 024import java.util.Properties; 025 026import org.hibernate.HibernateException; 027import org.hibernate.engine.spi.SharedSessionContractImplementor; 028import org.hibernate.usertype.EnhancedUserType; 029import org.hibernate.usertype.ParameterizedType; 030import org.jadira.bindings.core.api.Binding; 031import org.jadira.bindings.core.binder.BasicBinder; 032import org.jadira.usertype.spi.shared.AbstractHeuristicUserType; 033 034/** 035 * Allows dynamic invocation of any class by mapping it using a binding type. 036 */ 037public class PersistentBoundClass extends AbstractHeuristicUserType implements ParameterizedType, EnhancedUserType, Serializable { 038 039 private static final long serialVersionUID = 3094384329334123541L; 040 041 private static final BasicBinder BINDING = new BasicBinder(); 042 043 private Class<?> javaClass; 044 045 private Class<? extends Annotation> qualifier; 046 047 @SuppressWarnings("rawtypes") 048 private Binding binding; 049 050 public void setParameterValues(Properties parameters) { 051 052 if (parameters.containsKey("javaClass")) { 053 String mappedClassName = parameters.getProperty("javaClass"); 054 try { 055 this.javaClass = Class.forName(mappedClassName); 056 } catch (ClassNotFoundException e) { 057 throw new HibernateException("Specified Java class could not be found", e); 058 } 059 } 060 061 if (parameters.containsKey("hibernateClass")) { 062 String mappedClassName = parameters.getProperty("hibernateClass"); 063 try { 064 super.setIdentifierType((Class<?>) Class.forName(mappedClassName)); 065 } catch (ClassNotFoundException e) { 066 throw new HibernateException("Specified Hibernate class could not be found", e); 067 } 068 } 069 070 if (parameters.containsKey("qualifier")) { 071 String mappedClassName = parameters.getProperty("qualifier"); 072 try { 073 @SuppressWarnings("unchecked") 074 final Class<? extends Annotation> myQualifier = ((Class<? extends Annotation>) Class.forName(mappedClassName)); 075 qualifier = myQualifier; 076 } catch (ClassNotFoundException e) { 077 throw new HibernateException("Specified Qualifier class could not be found", e); 078 } 079 } 080 081 if (javaClass == null) { 082 throw new HibernateException("Java class was not defined"); 083 } 084 if (super.getIdentifierType() == null) { 085 throw new HibernateException("Hibernate class was not defined"); 086 } 087 088 super.setParameterValues(parameters); 089 090 binding = BINDING.findBinding(javaClass, getIdentifierType(), qualifier); 091 092 if (binding == null) { 093 throw new HibernateException("Could not resolve binding instance"); 094 } 095 } 096 097 @Override 098 public Class<?> returnedClass() { 099 return javaClass; 100 } 101 102 @Override 103 public Object doNullSafeGet(ResultSet rs, String[] names, SharedSessionContractImplementor session, Object owner) throws HibernateException, SQLException, IllegalArgumentException, IllegalAccessException, InvocationTargetException { 104 105 Object identifier = getType().get(rs, names[0], session); 106 107 if (rs.wasNull()) { 108 return null; 109 } 110 111 @SuppressWarnings("unchecked") 112 final Object result = binding.unmarshal(identifier); 113 return result; 114 } 115 116 @Override 117 public void doNullSafeSet(PreparedStatement preparedStatement, Object value, int index, SharedSessionContractImplementor session) throws SQLException, IllegalArgumentException, IllegalAccessException, InvocationTargetException { 118 119 if (value == null) { 120 preparedStatement.setNull(index, getType().sqlType()); 121 } else { 122 123 @SuppressWarnings("unchecked") 124 final Object identifier = binding.marshal(value); 125 getType().nullSafeSet(preparedStatement, identifier, index, session); 126 } 127 } 128}