/* * Copyright (c) 1998-2011 Caucho Technology -- all rights reserved * * This file is part of Resin(R) Open Source * * Each copy or derived work must preserve the copyright notice and this * notice unmodified. * * Resin Open Source 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 2 of the License, or * (at your option) any later version. * * Resin Open Source 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, or any warranty * of NON-INFRINGEMENT. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with Resin Open Source; if not, write to the * * Free Software Foundation, Inc. * 59 Temple Place, Suite 330 * Boston, MA 02111-1307 USA * * @author Scott Ferguson */ package com.caucho.amber.cfg; import com.caucho.amber.field.AmberField; import com.caucho.amber.field.ManyToManyField; import com.caucho.amber.field.ManyToOneField; import com.caucho.amber.field.OneToManyField; import com.caucho.amber.field.ElementCollectionField; import com.caucho.amber.manager.AmberPersistenceUnit; import com.caucho.amber.table.AmberTable; import com.caucho.amber.table.ForeignColumn; import com.caucho.amber.table.LinkColumns; import com.caucho.amber.type.*; import com.caucho.bytecode.JType; import com.caucho.bytecode.JTypeWrapper; import com.caucho.util.L10N; import java.lang.reflect.AccessibleObject; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.HashMap; import javax.persistence.*; /** * JPA 2.0 element collection */ class ElementCollectionConfig extends AbstractConfig { private static final L10N L = new L10N(ElementCollectionConfig.class); private EntityType _sourceType; private AccessibleObject _field; private String _fieldName; private Class _fieldType; private Class _targetClass; private FetchType _fetch = FetchType.EAGER; private CollectionTableConfig _collectionTable; ElementCollectionConfig(EntityType sourceType, AccessibleObject field, String fieldName, Class fieldType) { _sourceType = sourceType; _field = field; _fieldName = fieldName; _fieldType = fieldType; setFetch(FetchType.LAZY); introspect(); } public Class getTargetClass() { return _targetClass; } public void setTargetClass(Class targetClass) { _targetClass = targetClass; } public FetchType getFetch() { return _fetch; } public void setFetch(FetchType fetch) { _fetch = fetch; } public boolean isFetchLazy() { return _fetch == FetchType.LAZY; } private void introspect() { introspectTypes(); ElementCollection elementCollectionAnn = _field.getAnnotation(ElementCollection.class); if (elementCollectionAnn != null) introspectElementCollection(elementCollectionAnn); CollectionTable collectionTableAnn = _field.getAnnotation(CollectionTable.class); if (collectionTableAnn != null) _collectionTable = new CollectionTableConfig(collectionTableAnn); else { _collectionTable = new CollectionTableConfig(getRelatedType().getName(), _fieldName); } /* OrderBy orderByAnn = _field.getAnnotation(OrderBy.class); if (orderByAnn != null) _orderBy = orderByAnn.value(); */ } private void introspectTypes() { Type retType; if (_field instanceof Field) retType = ((Field) _field).getGenericType(); else retType = ((Method) _field).getGenericReturnType(); ClassLoader loader = _sourceType.getPersistenceUnit().getTempClassLoader(); JType type = JTypeWrapper.create(retType, loader); JType []typeArgs = type.getActualTypeArguments(); if (typeArgs.length > 0) setTargetClass(typeArgs[0].getRawType().getJavaClass()); } private void introspectElementCollection(ElementCollection eltCollection) { Class targetClass = eltCollection.targetClass(); if (! void.class.equals(targetClass)) setTargetClass(targetClass); setFetch(eltCollection.fetch()); } @Override public EntityType getRelatedType() { return _sourceType; } @Override public void complete() { AmberPersistenceUnit persistenceUnit = _sourceType.getPersistenceUnit(); Class targetClass = getTargetClass(); if (targetClass == null || void.class.equals(targetClass)) throw error(_field, L.l("Can't determine targetEntity for {0}. @OneToMany properties must target @Entity beans.", _fieldName)); AmberType targetType = persistenceUnit.createType(targetClass); if (targetType == null) { throw error(_field, L.l("targetClass '{0}' is not a known element collection class for {1}. The targetClass of a @ElementCollection must be a basic class.", targetClass.getName(), _fieldName)); } /* if (_orderBy != null) calculateOrderBy(_orderBy); */ addCollection(targetType); } private void addCollection(AmberType targetType) { ElementCollectionField eltCollectionField; eltCollectionField = new ElementCollectionField(_sourceType, _fieldName); eltCollectionField.setType(targetType); eltCollectionField.setLazy(isFetchLazy()); CollectionTableConfig collectionTableConfig = _collectionTable; AmberPersistenceUnit persistenceUnit = _sourceType.getPersistenceUnit(); String sqlTable = collectionTableConfig.getName(); AmberTable mapTable = persistenceUnit.createTable(sqlTable); HashMap<String, JoinColumnConfig> joinColumnsConfig = collectionTableConfig.getJoinColumnMap(); ArrayList<ForeignColumn> sourceColumns = null; sourceColumns = calculateColumns(_field, _fieldName, mapTable, _sourceType.getTable().getName() + "_", _sourceType, joinColumnsConfig); eltCollectionField.setAssociationTable(mapTable); eltCollectionField.setTable(sqlTable); eltCollectionField.setSourceLink(new LinkColumns(mapTable, _sourceType.getTable(), sourceColumns)); _sourceType.addField(eltCollectionField); } }