/* * Hibernate, Relational Persistence for Idiomatic Java * * JBoss, Home of Professional Open Source * Copyright 2010-2011 Red Hat Inc. and/or its affiliates and other contributors * as indicated by the @authors tag. All rights reserved. * See the copyright.txt in the distribution for a * full listing of individual contributors. * * This copyrighted material is made available to anyone wishing to use, * modify, copy, or redistribute it subject to the terms and conditions * of the GNU Lesser General Public License, v. 2.1. * This program is distributed in the hope that it will be useful, but WITHOUT A * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General Public License, * v.2.1 along with this distribution; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301, USA. */ package org.hibernate.ogm.type; import java.util.Arrays; import org.hibernate.EntityMode; import org.hibernate.HibernateException; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.ogm.datastore.spi.Tuple; import org.hibernate.ogm.util.impl.ArrayHelper; import org.hibernate.type.Type; /** * @author Emmanuel Bernard */ public class ComponentType extends GridTypeDelegatingToCoreType implements GridType { private final org.hibernate.type.ComponentType componentType; private final int propertySpan; private final GridType[] propertyTypes; public ComponentType(org.hibernate.type.ComponentType componentType, TypeTranslator typeTranslator) { super(componentType); this.componentType = componentType; this.propertySpan = componentType.getPropertyNames().length; final Type[] coreSubtypes = componentType.getSubtypes(); this.propertyTypes = new GridType[propertySpan]; for ( int i = 0 ; i < propertySpan ; i++ ) { this.propertyTypes[i] = typeTranslator.getType( coreSubtypes[i] ); } } @Override public Object nullSafeGet(Tuple rs, String[] names, SessionImplementor session, Object owner) throws HibernateException { return resolve( hydrate( rs, names, session, owner ), session, owner ) ; } @Override public Object nullSafeGet(Tuple rs, String name, SessionImplementor session, Object owner) throws HibernateException { return nullSafeGet( rs, new String[] {name}, session, owner ); } @Override public void nullSafeSet(Tuple resultset, Object value, String[] names, boolean[] settable, SessionImplementor session) throws HibernateException { Object[] subvalues = nullSafeGetValues( value, componentType.getEntityMode() ); //TODO in the original componentType begin and loc are different (namely begin only counts settable slots //I don't think that's relevant for us int columnCurrentIndex = 0; for ( int i = 0; i < propertySpan; i++ ) { int columnSpanOnProperty = propertyTypes[i].getColumnSpan( session.getFactory() ); if ( columnSpanOnProperty == 0 ) { //no-op } else if ( columnSpanOnProperty == 1 ) { if ( settable[columnCurrentIndex] ) { propertyTypes[i].nullSafeSet( resultset, subvalues[i], new String[] { names[columnCurrentIndex] }, session ); } } else { final boolean[] subsettable = new boolean[columnSpanOnProperty]; System.arraycopy( settable, columnCurrentIndex, subsettable, 0, columnSpanOnProperty ); final String[] subnames = new String[columnSpanOnProperty]; System.arraycopy( names, columnCurrentIndex, subnames, 0, columnSpanOnProperty ); propertyTypes[i].nullSafeSet( resultset, subvalues[i], subnames, subsettable, session ); } columnCurrentIndex += columnSpanOnProperty; } } @Override public void nullSafeSet(Tuple resultset, Object value, String[] names, SessionImplementor session) throws HibernateException { final boolean[] trueSettable = new boolean[names.length]; Arrays.fill( trueSettable, true); nullSafeSet( resultset, value, names, trueSettable, session ); } @Override public Object hydrate(Tuple rs, String[] names, SessionImplementor session, Object owner) throws HibernateException { int begin = 0; boolean notNull = false; Object[] values = new Object[propertySpan]; for ( int i = 0; i < propertySpan; i++ ) { int length = propertyTypes[i].getColumnSpan( session.getFactory() ); String[] range = ArrayHelper.slice( names, begin, length ); //cache this Object val = propertyTypes[i].hydrate( rs, range, session, owner ); if ( val == null ) { if ( componentType.isKey() ) { return null; //different nullability rules for pk/fk } } else { notNull = true; } values[i] = val; begin += length; } return notNull ? values : null; } //utility methods private Object[] nullSafeGetValues(Object value, EntityMode entityMode) throws HibernateException { if ( value == null ) { return new Object[propertySpan]; } else { return componentType.getPropertyValues( value, entityMode ); } } }