mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
Change license to Apache2 and reformat
This commit is contained in:
+329
-348
@@ -1,348 +1,329 @@
|
||||
/**
|
||||
* Copyright (C) 2006 Robin Bygrave
|
||||
*
|
||||
* This file is part of Ebean.
|
||||
*
|
||||
* Ebean is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Ebean 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package com.avaje.ebeaninternal.server.deploy.parse;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.JoinColumns;
|
||||
import javax.persistence.JoinTable;
|
||||
import javax.persistence.ManyToMany;
|
||||
import javax.persistence.MapKey;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.OrderBy;
|
||||
|
||||
import com.avaje.ebean.annotation.LdapAttribute;
|
||||
import com.avaje.ebean.annotation.PrivateOwned;
|
||||
import com.avaje.ebean.annotation.Where;
|
||||
import com.avaje.ebean.bean.BeanCollection.ModifyListenMode;
|
||||
import com.avaje.ebean.config.NamingConvention;
|
||||
import com.avaje.ebean.config.TableName;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptorManager;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanTable;
|
||||
import com.avaje.ebeaninternal.server.deploy.TableJoin;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocMany;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployTableJoin;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployTableJoinColumn;
|
||||
import com.avaje.ebeaninternal.server.lib.util.StringHelper;
|
||||
|
||||
/**
|
||||
* Read the deployment annotation for Assoc Many beans.
|
||||
*/
|
||||
public class AnnotationAssocManys extends AnnotationParser {
|
||||
|
||||
private final BeanDescriptorManager factory;
|
||||
|
||||
/**
|
||||
* Create with the DeployInfo.
|
||||
*/
|
||||
public AnnotationAssocManys(DeployBeanInfo<?> info, BeanDescriptorManager factory) {
|
||||
super(info);
|
||||
this.factory = factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the annotations.
|
||||
*/
|
||||
public void parse() {
|
||||
Iterator<DeployBeanProperty> it = descriptor.propertiesAll();
|
||||
while (it.hasNext()) {
|
||||
DeployBeanProperty prop = it.next();
|
||||
if (prop instanceof DeployBeanPropertyAssocMany<?>) {
|
||||
read((DeployBeanPropertyAssocMany<?>) prop);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void read(DeployBeanPropertyAssocMany<?> prop) {
|
||||
|
||||
OneToMany oneToMany = get(prop, OneToMany.class);
|
||||
if (oneToMany != null) {
|
||||
readToOne(oneToMany, prop);
|
||||
PrivateOwned privateOwned = get(prop, PrivateOwned.class);
|
||||
if (privateOwned != null){
|
||||
prop.setModifyListenMode(ModifyListenMode.REMOVALS);
|
||||
prop.getCascadeInfo().setDelete(privateOwned.cascadeRemove());
|
||||
}
|
||||
}
|
||||
ManyToMany manyToMany = get(prop, ManyToMany.class);
|
||||
if (manyToMany != null) {
|
||||
readToMany(manyToMany, prop);
|
||||
}
|
||||
|
||||
OrderBy orderBy = get(prop, OrderBy.class);
|
||||
if (orderBy != null) {
|
||||
prop.setFetchOrderBy(orderBy.value());
|
||||
}
|
||||
|
||||
MapKey mapKey = get(prop, MapKey.class);
|
||||
if (mapKey != null) {
|
||||
prop.setMapKey(mapKey.name());
|
||||
}
|
||||
|
||||
Where where = get(prop, Where.class);
|
||||
if (where != null) {
|
||||
prop.setExtraWhere(where.clause());
|
||||
}
|
||||
|
||||
// check for manually defined joins
|
||||
BeanTable beanTable = prop.getBeanTable();
|
||||
JoinColumn joinColumn = get(prop, JoinColumn.class);
|
||||
if (joinColumn != null) {
|
||||
prop.getTableJoin().addJoinColumn(true, joinColumn, beanTable);
|
||||
}
|
||||
|
||||
JoinColumns joinColumns = get(prop, JoinColumns.class);
|
||||
if (joinColumns != null) {
|
||||
prop.getTableJoin().addJoinColumn(true, joinColumns.value(), beanTable);
|
||||
}
|
||||
|
||||
JoinTable joinTable = get(prop, JoinTable.class);
|
||||
if (joinTable != null) {
|
||||
if (prop.isManyToMany()){
|
||||
// expected this
|
||||
readJoinTable(joinTable, prop);
|
||||
|
||||
} else {
|
||||
// OneToMany in theory
|
||||
prop.getTableJoin().addJoinColumn(true, joinTable.joinColumns(), beanTable);
|
||||
}
|
||||
}
|
||||
LdapAttribute ldapAttribute = get(prop, LdapAttribute.class);
|
||||
if (ldapAttribute != null) {
|
||||
// read ldap specific property settings
|
||||
readLdapAttribute(ldapAttribute, prop);
|
||||
}
|
||||
|
||||
if (prop.getMappedBy() != null){
|
||||
// the join is derived by reversing the join information
|
||||
// from the mapped by property.
|
||||
// Refer BeanDescriptorManager.readEntityRelationships()
|
||||
return;
|
||||
}
|
||||
|
||||
if (prop.isManyToMany()){
|
||||
manyToManyDefaultJoins(prop);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (!prop.getTableJoin().hasJoinColumns() && beanTable != null){
|
||||
|
||||
// use naming convention to define join (based on the bean name for this side of relationship)
|
||||
// A unidirectional OneToMany or OneToMany with no mappedBy property
|
||||
|
||||
NamingConvention nc = factory.getNamingConvention();
|
||||
|
||||
String fkeyPrefix = null;
|
||||
if (nc.isUseForeignKeyPrefix()){
|
||||
fkeyPrefix = nc.getColumnFromProperty(descriptor.getBeanType(), descriptor.getName());
|
||||
}
|
||||
|
||||
// Use the owning bean table to define the join
|
||||
BeanTable owningBeanTable = factory.getBeanTable(descriptor.getBeanType());
|
||||
owningBeanTable.createJoinColumn(fkeyPrefix, prop.getTableJoin(), false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Define the joins for a ManyToMany relationship.
|
||||
* <p>
|
||||
* This includes joins to the intersection table and from the intersection table
|
||||
* to the other side of the ManyToMany.
|
||||
* </p>
|
||||
*/
|
||||
private void readJoinTable(JoinTable joinTable, DeployBeanPropertyAssocMany<?> prop) {
|
||||
|
||||
String intTableName = getFullTableName(joinTable);
|
||||
// set the intersection table
|
||||
DeployTableJoin intJoin = new DeployTableJoin();
|
||||
intJoin.setTable(intTableName);
|
||||
|
||||
// add the source to intersection join columns
|
||||
intJoin.addJoinColumn(true, joinTable.joinColumns(), prop.getBeanTable());
|
||||
|
||||
// set the intersection to dest table join columns
|
||||
DeployTableJoin destJoin = prop.getTableJoin();
|
||||
destJoin.addJoinColumn(false, joinTable.inverseJoinColumns(), prop.getBeanTable());
|
||||
|
||||
intJoin.setType(TableJoin.LEFT_OUTER);
|
||||
|
||||
// reverse join from dest back to intersection
|
||||
DeployTableJoin inverseDest = destJoin.createInverse(intTableName);
|
||||
prop.setIntersectionJoin(intJoin);
|
||||
prop.setInverseJoin(inverseDest);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the full table name
|
||||
* @param joinTable
|
||||
* @return
|
||||
*/
|
||||
private String getFullTableName(JoinTable joinTable) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (!StringHelper.isNull(joinTable.catalog())){
|
||||
sb.append(joinTable.catalog()).append(".");
|
||||
}
|
||||
if (!StringHelper.isNull(joinTable.schema())){
|
||||
sb.append(joinTable.schema()).append(".");
|
||||
}
|
||||
sb.append(joinTable.name());
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Define intersection table and foreign key columns for ManyToMany.
|
||||
* <p>
|
||||
* Some of these (maybe all) have been already defined via @JoinTable
|
||||
* and @JoinColumns etc.
|
||||
* </p>
|
||||
*/
|
||||
private void manyToManyDefaultJoins(DeployBeanPropertyAssocMany<?> prop) {
|
||||
|
||||
String intTableName = null;
|
||||
|
||||
DeployTableJoin intJoin = prop.getIntersectionJoin();
|
||||
if (intJoin == null){
|
||||
intJoin = new DeployTableJoin();
|
||||
prop.setIntersectionJoin(intJoin);
|
||||
} else {
|
||||
// intersection table already defined (by @JoinTable)
|
||||
intTableName = intJoin.getTable();
|
||||
}
|
||||
|
||||
BeanTable localTable = factory.getBeanTable(descriptor.getBeanType());
|
||||
BeanTable otherTable = factory.getBeanTable(prop.getTargetType());
|
||||
|
||||
final String localTableName = localTable.getUnqualifiedBaseTable();
|
||||
final String otherTableName = otherTable.getUnqualifiedBaseTable();
|
||||
|
||||
if (intTableName == null){
|
||||
// define intersection table name
|
||||
intTableName = getM2MJoinTableName(localTable, otherTable);
|
||||
|
||||
intJoin.setTable(intTableName);
|
||||
intJoin.setType(TableJoin.LEFT_OUTER);
|
||||
}
|
||||
|
||||
DeployTableJoin destJoin = prop.getTableJoin();
|
||||
|
||||
|
||||
if (intJoin.hasJoinColumns() && destJoin.hasJoinColumns()){
|
||||
// already defined the foreign key columns etc
|
||||
return;
|
||||
}
|
||||
if (!intJoin.hasJoinColumns()){
|
||||
// define foreign key columns
|
||||
BeanProperty[] localIds = localTable.getIdProperties();
|
||||
for (int i = 0; i < localIds.length; i++) {
|
||||
// add the source to intersection join columns
|
||||
String fkCol = localTableName+"_"+localIds[i].getDbColumn();
|
||||
intJoin.addJoinColumn(new DeployTableJoinColumn(localIds[i].getDbColumn(), fkCol));
|
||||
}
|
||||
}
|
||||
|
||||
if (!destJoin.hasJoinColumns()){
|
||||
// define inverse foreign key columns
|
||||
BeanProperty[] otherIds = otherTable.getIdProperties();
|
||||
for (int i = 0; i < otherIds.length; i++) {
|
||||
// set the intersection to dest table join columns
|
||||
final String fkCol = otherTableName+"_"+otherIds[i].getDbColumn();
|
||||
destJoin.addJoinColumn(new DeployTableJoinColumn(fkCol, otherIds[i].getDbColumn()));
|
||||
}
|
||||
}
|
||||
|
||||
// reverse join from dest back to intersection
|
||||
DeployTableJoin inverseDest = destJoin.createInverse(intTableName);
|
||||
prop.setInverseJoin(inverseDest);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private String errorMsgMissingBeanTable(Class<?> type, String from) {
|
||||
return "Error with association to ["+type+"] from ["+from+"]. Is "+type+" registered?";
|
||||
}
|
||||
|
||||
private void readToMany(ManyToMany propAnn, DeployBeanPropertyAssocMany<?> manyProp) {
|
||||
|
||||
manyProp.setMappedBy(propAnn.mappedBy());
|
||||
manyProp.setFetchType(propAnn.fetch());
|
||||
|
||||
setCascadeTypes(propAnn.cascade(), manyProp.getCascadeInfo());
|
||||
|
||||
Class<?> targetType = propAnn.targetEntity();
|
||||
if (targetType.equals(void.class)) {
|
||||
// via reflection of generics type
|
||||
targetType = manyProp.getTargetType();
|
||||
} else {
|
||||
manyProp.setTargetType(targetType);
|
||||
}
|
||||
|
||||
// find the other many table (not intersection)
|
||||
BeanTable assoc = factory.getBeanTable(targetType);
|
||||
if (assoc == null) {
|
||||
String msg = errorMsgMissingBeanTable(targetType, manyProp.getFullBeanName());
|
||||
throw new RuntimeException(msg);
|
||||
}
|
||||
|
||||
manyProp.setManyToMany(true);
|
||||
manyProp.setModifyListenMode(ModifyListenMode.ALL);
|
||||
manyProp.setBeanTable(assoc);
|
||||
manyProp.getTableJoin().setType(TableJoin.LEFT_OUTER);
|
||||
}
|
||||
|
||||
private void readToOne(OneToMany propAnn, DeployBeanPropertyAssocMany<?> manyProp) {
|
||||
|
||||
manyProp.setMappedBy(propAnn.mappedBy());
|
||||
manyProp.setFetchType(propAnn.fetch());
|
||||
|
||||
setCascadeTypes(propAnn.cascade(), manyProp.getCascadeInfo());
|
||||
|
||||
Class<?> targetType = propAnn.targetEntity();
|
||||
if (targetType.equals(void.class)) {
|
||||
// via reflection of generics type
|
||||
targetType = manyProp.getTargetType();
|
||||
} else {
|
||||
manyProp.setTargetType(targetType);
|
||||
}
|
||||
|
||||
BeanTable assoc = factory.getBeanTable(targetType);
|
||||
if (assoc == null) {
|
||||
String msg = errorMsgMissingBeanTable(targetType, manyProp.getFullBeanName());
|
||||
throw new RuntimeException(msg);
|
||||
}
|
||||
|
||||
manyProp.setBeanTable(assoc);
|
||||
manyProp.getTableJoin().setType(TableJoin.LEFT_OUTER);
|
||||
}
|
||||
|
||||
|
||||
private String getM2MJoinTableName(BeanTable lhsTable, BeanTable rhsTable){
|
||||
|
||||
TableName lhs = new TableName(lhsTable.getBaseTable());
|
||||
TableName rhs = new TableName(rhsTable.getBaseTable());
|
||||
|
||||
TableName joinTable = namingConvention.getM2MJoinTableName(lhs, rhs);
|
||||
|
||||
return joinTable.getQualifiedName();
|
||||
}
|
||||
}
|
||||
package com.avaje.ebeaninternal.server.deploy.parse;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.JoinColumns;
|
||||
import javax.persistence.JoinTable;
|
||||
import javax.persistence.ManyToMany;
|
||||
import javax.persistence.MapKey;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.OrderBy;
|
||||
|
||||
import com.avaje.ebean.annotation.LdapAttribute;
|
||||
import com.avaje.ebean.annotation.PrivateOwned;
|
||||
import com.avaje.ebean.annotation.Where;
|
||||
import com.avaje.ebean.bean.BeanCollection.ModifyListenMode;
|
||||
import com.avaje.ebean.config.NamingConvention;
|
||||
import com.avaje.ebean.config.TableName;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptorManager;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanTable;
|
||||
import com.avaje.ebeaninternal.server.deploy.TableJoin;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocMany;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployTableJoin;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployTableJoinColumn;
|
||||
import com.avaje.ebeaninternal.server.lib.util.StringHelper;
|
||||
|
||||
/**
|
||||
* Read the deployment annotation for Assoc Many beans.
|
||||
*/
|
||||
public class AnnotationAssocManys extends AnnotationParser {
|
||||
|
||||
private final BeanDescriptorManager factory;
|
||||
|
||||
/**
|
||||
* Create with the DeployInfo.
|
||||
*/
|
||||
public AnnotationAssocManys(DeployBeanInfo<?> info, BeanDescriptorManager factory) {
|
||||
super(info);
|
||||
this.factory = factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the annotations.
|
||||
*/
|
||||
public void parse() {
|
||||
Iterator<DeployBeanProperty> it = descriptor.propertiesAll();
|
||||
while (it.hasNext()) {
|
||||
DeployBeanProperty prop = it.next();
|
||||
if (prop instanceof DeployBeanPropertyAssocMany<?>) {
|
||||
read((DeployBeanPropertyAssocMany<?>) prop);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void read(DeployBeanPropertyAssocMany<?> prop) {
|
||||
|
||||
OneToMany oneToMany = get(prop, OneToMany.class);
|
||||
if (oneToMany != null) {
|
||||
readToOne(oneToMany, prop);
|
||||
PrivateOwned privateOwned = get(prop, PrivateOwned.class);
|
||||
if (privateOwned != null){
|
||||
prop.setModifyListenMode(ModifyListenMode.REMOVALS);
|
||||
prop.getCascadeInfo().setDelete(privateOwned.cascadeRemove());
|
||||
}
|
||||
}
|
||||
ManyToMany manyToMany = get(prop, ManyToMany.class);
|
||||
if (manyToMany != null) {
|
||||
readToMany(manyToMany, prop);
|
||||
}
|
||||
|
||||
OrderBy orderBy = get(prop, OrderBy.class);
|
||||
if (orderBy != null) {
|
||||
prop.setFetchOrderBy(orderBy.value());
|
||||
}
|
||||
|
||||
MapKey mapKey = get(prop, MapKey.class);
|
||||
if (mapKey != null) {
|
||||
prop.setMapKey(mapKey.name());
|
||||
}
|
||||
|
||||
Where where = get(prop, Where.class);
|
||||
if (where != null) {
|
||||
prop.setExtraWhere(where.clause());
|
||||
}
|
||||
|
||||
// check for manually defined joins
|
||||
BeanTable beanTable = prop.getBeanTable();
|
||||
JoinColumn joinColumn = get(prop, JoinColumn.class);
|
||||
if (joinColumn != null) {
|
||||
prop.getTableJoin().addJoinColumn(true, joinColumn, beanTable);
|
||||
}
|
||||
|
||||
JoinColumns joinColumns = get(prop, JoinColumns.class);
|
||||
if (joinColumns != null) {
|
||||
prop.getTableJoin().addJoinColumn(true, joinColumns.value(), beanTable);
|
||||
}
|
||||
|
||||
JoinTable joinTable = get(prop, JoinTable.class);
|
||||
if (joinTable != null) {
|
||||
if (prop.isManyToMany()){
|
||||
// expected this
|
||||
readJoinTable(joinTable, prop);
|
||||
|
||||
} else {
|
||||
// OneToMany in theory
|
||||
prop.getTableJoin().addJoinColumn(true, joinTable.joinColumns(), beanTable);
|
||||
}
|
||||
}
|
||||
LdapAttribute ldapAttribute = get(prop, LdapAttribute.class);
|
||||
if (ldapAttribute != null) {
|
||||
// read ldap specific property settings
|
||||
readLdapAttribute(ldapAttribute, prop);
|
||||
}
|
||||
|
||||
if (prop.getMappedBy() != null){
|
||||
// the join is derived by reversing the join information
|
||||
// from the mapped by property.
|
||||
// Refer BeanDescriptorManager.readEntityRelationships()
|
||||
return;
|
||||
}
|
||||
|
||||
if (prop.isManyToMany()){
|
||||
manyToManyDefaultJoins(prop);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (!prop.getTableJoin().hasJoinColumns() && beanTable != null){
|
||||
|
||||
// use naming convention to define join (based on the bean name for this side of relationship)
|
||||
// A unidirectional OneToMany or OneToMany with no mappedBy property
|
||||
|
||||
NamingConvention nc = factory.getNamingConvention();
|
||||
|
||||
String fkeyPrefix = null;
|
||||
if (nc.isUseForeignKeyPrefix()){
|
||||
fkeyPrefix = nc.getColumnFromProperty(descriptor.getBeanType(), descriptor.getName());
|
||||
}
|
||||
|
||||
// Use the owning bean table to define the join
|
||||
BeanTable owningBeanTable = factory.getBeanTable(descriptor.getBeanType());
|
||||
owningBeanTable.createJoinColumn(fkeyPrefix, prop.getTableJoin(), false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Define the joins for a ManyToMany relationship.
|
||||
* <p>
|
||||
* This includes joins to the intersection table and from the intersection table
|
||||
* to the other side of the ManyToMany.
|
||||
* </p>
|
||||
*/
|
||||
private void readJoinTable(JoinTable joinTable, DeployBeanPropertyAssocMany<?> prop) {
|
||||
|
||||
String intTableName = getFullTableName(joinTable);
|
||||
// set the intersection table
|
||||
DeployTableJoin intJoin = new DeployTableJoin();
|
||||
intJoin.setTable(intTableName);
|
||||
|
||||
// add the source to intersection join columns
|
||||
intJoin.addJoinColumn(true, joinTable.joinColumns(), prop.getBeanTable());
|
||||
|
||||
// set the intersection to dest table join columns
|
||||
DeployTableJoin destJoin = prop.getTableJoin();
|
||||
destJoin.addJoinColumn(false, joinTable.inverseJoinColumns(), prop.getBeanTable());
|
||||
|
||||
intJoin.setType(TableJoin.LEFT_OUTER);
|
||||
|
||||
// reverse join from dest back to intersection
|
||||
DeployTableJoin inverseDest = destJoin.createInverse(intTableName);
|
||||
prop.setIntersectionJoin(intJoin);
|
||||
prop.setInverseJoin(inverseDest);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the full table name
|
||||
* @param joinTable
|
||||
* @return
|
||||
*/
|
||||
private String getFullTableName(JoinTable joinTable) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (!StringHelper.isNull(joinTable.catalog())){
|
||||
sb.append(joinTable.catalog()).append(".");
|
||||
}
|
||||
if (!StringHelper.isNull(joinTable.schema())){
|
||||
sb.append(joinTable.schema()).append(".");
|
||||
}
|
||||
sb.append(joinTable.name());
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Define intersection table and foreign key columns for ManyToMany.
|
||||
* <p>
|
||||
* Some of these (maybe all) have been already defined via @JoinTable
|
||||
* and @JoinColumns etc.
|
||||
* </p>
|
||||
*/
|
||||
private void manyToManyDefaultJoins(DeployBeanPropertyAssocMany<?> prop) {
|
||||
|
||||
String intTableName = null;
|
||||
|
||||
DeployTableJoin intJoin = prop.getIntersectionJoin();
|
||||
if (intJoin == null){
|
||||
intJoin = new DeployTableJoin();
|
||||
prop.setIntersectionJoin(intJoin);
|
||||
} else {
|
||||
// intersection table already defined (by @JoinTable)
|
||||
intTableName = intJoin.getTable();
|
||||
}
|
||||
|
||||
BeanTable localTable = factory.getBeanTable(descriptor.getBeanType());
|
||||
BeanTable otherTable = factory.getBeanTable(prop.getTargetType());
|
||||
|
||||
final String localTableName = localTable.getUnqualifiedBaseTable();
|
||||
final String otherTableName = otherTable.getUnqualifiedBaseTable();
|
||||
|
||||
if (intTableName == null){
|
||||
// define intersection table name
|
||||
intTableName = getM2MJoinTableName(localTable, otherTable);
|
||||
|
||||
intJoin.setTable(intTableName);
|
||||
intJoin.setType(TableJoin.LEFT_OUTER);
|
||||
}
|
||||
|
||||
DeployTableJoin destJoin = prop.getTableJoin();
|
||||
|
||||
|
||||
if (intJoin.hasJoinColumns() && destJoin.hasJoinColumns()){
|
||||
// already defined the foreign key columns etc
|
||||
return;
|
||||
}
|
||||
if (!intJoin.hasJoinColumns()){
|
||||
// define foreign key columns
|
||||
BeanProperty[] localIds = localTable.getIdProperties();
|
||||
for (int i = 0; i < localIds.length; i++) {
|
||||
// add the source to intersection join columns
|
||||
String fkCol = localTableName+"_"+localIds[i].getDbColumn();
|
||||
intJoin.addJoinColumn(new DeployTableJoinColumn(localIds[i].getDbColumn(), fkCol));
|
||||
}
|
||||
}
|
||||
|
||||
if (!destJoin.hasJoinColumns()){
|
||||
// define inverse foreign key columns
|
||||
BeanProperty[] otherIds = otherTable.getIdProperties();
|
||||
for (int i = 0; i < otherIds.length; i++) {
|
||||
// set the intersection to dest table join columns
|
||||
final String fkCol = otherTableName+"_"+otherIds[i].getDbColumn();
|
||||
destJoin.addJoinColumn(new DeployTableJoinColumn(fkCol, otherIds[i].getDbColumn()));
|
||||
}
|
||||
}
|
||||
|
||||
// reverse join from dest back to intersection
|
||||
DeployTableJoin inverseDest = destJoin.createInverse(intTableName);
|
||||
prop.setInverseJoin(inverseDest);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private String errorMsgMissingBeanTable(Class<?> type, String from) {
|
||||
return "Error with association to ["+type+"] from ["+from+"]. Is "+type+" registered?";
|
||||
}
|
||||
|
||||
private void readToMany(ManyToMany propAnn, DeployBeanPropertyAssocMany<?> manyProp) {
|
||||
|
||||
manyProp.setMappedBy(propAnn.mappedBy());
|
||||
manyProp.setFetchType(propAnn.fetch());
|
||||
|
||||
setCascadeTypes(propAnn.cascade(), manyProp.getCascadeInfo());
|
||||
|
||||
Class<?> targetType = propAnn.targetEntity();
|
||||
if (targetType.equals(void.class)) {
|
||||
// via reflection of generics type
|
||||
targetType = manyProp.getTargetType();
|
||||
} else {
|
||||
manyProp.setTargetType(targetType);
|
||||
}
|
||||
|
||||
// find the other many table (not intersection)
|
||||
BeanTable assoc = factory.getBeanTable(targetType);
|
||||
if (assoc == null) {
|
||||
String msg = errorMsgMissingBeanTable(targetType, manyProp.getFullBeanName());
|
||||
throw new RuntimeException(msg);
|
||||
}
|
||||
|
||||
manyProp.setManyToMany(true);
|
||||
manyProp.setModifyListenMode(ModifyListenMode.ALL);
|
||||
manyProp.setBeanTable(assoc);
|
||||
manyProp.getTableJoin().setType(TableJoin.LEFT_OUTER);
|
||||
}
|
||||
|
||||
private void readToOne(OneToMany propAnn, DeployBeanPropertyAssocMany<?> manyProp) {
|
||||
|
||||
manyProp.setMappedBy(propAnn.mappedBy());
|
||||
manyProp.setFetchType(propAnn.fetch());
|
||||
|
||||
setCascadeTypes(propAnn.cascade(), manyProp.getCascadeInfo());
|
||||
|
||||
Class<?> targetType = propAnn.targetEntity();
|
||||
if (targetType.equals(void.class)) {
|
||||
// via reflection of generics type
|
||||
targetType = manyProp.getTargetType();
|
||||
} else {
|
||||
manyProp.setTargetType(targetType);
|
||||
}
|
||||
|
||||
BeanTable assoc = factory.getBeanTable(targetType);
|
||||
if (assoc == null) {
|
||||
String msg = errorMsgMissingBeanTable(targetType, manyProp.getFullBeanName());
|
||||
throw new RuntimeException(msg);
|
||||
}
|
||||
|
||||
manyProp.setBeanTable(assoc);
|
||||
manyProp.getTableJoin().setType(TableJoin.LEFT_OUTER);
|
||||
}
|
||||
|
||||
|
||||
private String getM2MJoinTableName(BeanTable lhsTable, BeanTable rhsTable){
|
||||
|
||||
TableName lhs = new TableName(lhsTable.getBaseTable());
|
||||
TableName rhs = new TableName(rhsTable.getBaseTable());
|
||||
|
||||
TableName joinTable = namingConvention.getM2MJoinTableName(lhs, rhs);
|
||||
|
||||
return joinTable.getQualifiedName();
|
||||
}
|
||||
}
|
||||
|
||||
+227
-246
@@ -1,246 +1,227 @@
|
||||
/**
|
||||
* Copyright (C) 2006 Robin Bygrave
|
||||
*
|
||||
* This file is part of Ebean.
|
||||
*
|
||||
* Ebean is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Ebean 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package com.avaje.ebeaninternal.server.deploy.parse;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.persistence.AttributeOverride;
|
||||
import javax.persistence.AttributeOverrides;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Embedded;
|
||||
import javax.persistence.EmbeddedId;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.JoinColumns;
|
||||
import javax.persistence.JoinTable;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.OneToOne;
|
||||
|
||||
import com.avaje.ebean.annotation.EmbeddedColumns;
|
||||
import com.avaje.ebean.annotation.Where;
|
||||
import com.avaje.ebean.config.NamingConvention;
|
||||
import com.avaje.ebean.validation.NotNull;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptorManager;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanTable;
|
||||
import com.avaje.ebeaninternal.server.deploy.TableJoin;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocOne;
|
||||
import com.avaje.ebeaninternal.server.lib.util.StringHelper;
|
||||
|
||||
/**
|
||||
* Read the deployment annotations for Associated One beans.
|
||||
*/
|
||||
public class AnnotationAssocOnes extends AnnotationParser {
|
||||
|
||||
private final BeanDescriptorManager factory;
|
||||
|
||||
/**
|
||||
* Create with the deploy Info.
|
||||
*/
|
||||
public AnnotationAssocOnes(DeployBeanInfo<?> info, BeanDescriptorManager factory) {
|
||||
super(info);
|
||||
this.factory = factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the annotation.
|
||||
*/
|
||||
public void parse() {
|
||||
|
||||
Iterator<DeployBeanProperty> it = descriptor.propertiesAll();
|
||||
while (it.hasNext()) {
|
||||
DeployBeanProperty prop = it.next();
|
||||
if (prop instanceof DeployBeanPropertyAssocOne<?>) {
|
||||
readAssocOne((DeployBeanPropertyAssocOne<?>) prop);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void readAssocOne(DeployBeanPropertyAssocOne<?> prop) {
|
||||
|
||||
ManyToOne manyToOne = get(prop, ManyToOne.class);
|
||||
if (manyToOne != null) {
|
||||
readManyToOne(manyToOne, prop);
|
||||
}
|
||||
OneToOne oneToOne = get(prop, OneToOne.class);
|
||||
if (oneToOne != null) {
|
||||
readOneToOne(oneToOne, prop);
|
||||
}
|
||||
Embedded embedded = get(prop, Embedded.class);
|
||||
if (embedded != null) {
|
||||
readEmbedded(embedded, prop);
|
||||
}
|
||||
EmbeddedId emId = get(prop, EmbeddedId.class);
|
||||
if (emId != null) {
|
||||
prop.setEmbedded(true);
|
||||
prop.setId(true);
|
||||
prop.setNullable(false);
|
||||
}
|
||||
Column column = get(prop, Column.class);
|
||||
if (column != null && !isEmpty(column.name())) {
|
||||
// have this in for AssocOnes used on
|
||||
// Sql based beans...
|
||||
prop.setDbColumn(column.name());
|
||||
}
|
||||
|
||||
// May as well check for Id. Makes sense to me.
|
||||
Id id = get(prop, Id.class);
|
||||
if (id != null) {
|
||||
prop.setEmbedded(true);
|
||||
prop.setId(true);
|
||||
prop.setNullable(false);
|
||||
}
|
||||
|
||||
Where where = get(prop, Where.class);
|
||||
if (where != null) {
|
||||
// not expecting this to be used on assoc one properties
|
||||
prop.setExtraWhere(where.clause());
|
||||
}
|
||||
|
||||
NotNull notNull = get(prop, NotNull.class);
|
||||
if (notNull != null) {
|
||||
prop.setNullable(false);
|
||||
// overrides optional attribute of ManyToOne etc
|
||||
prop.getTableJoin().setType(TableJoin.JOIN);
|
||||
}
|
||||
|
||||
// check for manually defined joins
|
||||
BeanTable beanTable = prop.getBeanTable();
|
||||
JoinColumn joinColumn = get(prop, JoinColumn.class);
|
||||
if (joinColumn != null) {
|
||||
prop.getTableJoin().addJoinColumn(false, joinColumn, beanTable);
|
||||
if (!joinColumn.updatable()){
|
||||
prop.setDbUpdateable(false);
|
||||
}
|
||||
}
|
||||
|
||||
JoinColumns joinColumns = get(prop, JoinColumns.class);
|
||||
if (joinColumns != null) {
|
||||
prop.getTableJoin().addJoinColumn(false, joinColumns.value(), beanTable);
|
||||
}
|
||||
|
||||
JoinTable joinTable = get(prop, JoinTable.class);
|
||||
if (joinTable != null) {
|
||||
prop.getTableJoin().addJoinColumn(false, joinTable.joinColumns(), beanTable);
|
||||
}
|
||||
|
||||
info.setBeanJoinType(prop, prop.isNullable());
|
||||
|
||||
if (!prop.getTableJoin().hasJoinColumns() && beanTable != null) {
|
||||
|
||||
if (prop.getMappedBy() != null) {
|
||||
// the join is derived by reversing the join information
|
||||
// from the mapped by property.
|
||||
// Refer BeanDescriptorManager.readEntityRelationships()
|
||||
|
||||
} else {
|
||||
// use naming convention to define join.
|
||||
NamingConvention nc = factory.getNamingConvention();
|
||||
|
||||
String fkeyPrefix = null;
|
||||
if (nc.isUseForeignKeyPrefix()){
|
||||
fkeyPrefix = nc.getColumnFromProperty(beanType, prop.getName());
|
||||
}
|
||||
|
||||
beanTable.createJoinColumn(fkeyPrefix, prop.getTableJoin(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String errorMsgMissingBeanTable(Class<?> type, String from) {
|
||||
return "Error with association to [" + type + "] from [" + from + "]. Is " + type + " registered?";
|
||||
}
|
||||
|
||||
private void readManyToOne(ManyToOne propAnn, DeployBeanProperty prop) {
|
||||
|
||||
DeployBeanPropertyAssocOne<?> beanProp = (DeployBeanPropertyAssocOne<?>) prop;
|
||||
|
||||
setCascadeTypes(propAnn.cascade(), beanProp.getCascadeInfo());
|
||||
|
||||
BeanTable assoc = factory.getBeanTable(beanProp.getPropertyType());
|
||||
if (assoc == null) {
|
||||
String msg = errorMsgMissingBeanTable(beanProp.getPropertyType(), prop.getFullBeanName());
|
||||
throw new RuntimeException(msg);
|
||||
}
|
||||
beanProp.setBeanTable(assoc);
|
||||
beanProp.setDbInsertable(true);
|
||||
beanProp.setDbUpdateable(true);
|
||||
beanProp.setNullable(propAnn.optional());
|
||||
beanProp.setFetchType(propAnn.fetch());
|
||||
}
|
||||
|
||||
private void readOneToOne(OneToOne propAnn, DeployBeanPropertyAssocOne<?> prop) {
|
||||
|
||||
prop.setOneToOne(true);
|
||||
prop.setDbInsertable(true);
|
||||
prop.setDbUpdateable(true);
|
||||
prop.setNullable(propAnn.optional());
|
||||
prop.setFetchType(propAnn.fetch());
|
||||
prop.setMappedBy(propAnn.mappedBy());
|
||||
if (!"".equals(propAnn.mappedBy())) {
|
||||
prop.setOneToOneExported(true);
|
||||
}
|
||||
|
||||
setCascadeTypes(propAnn.cascade(), prop.getCascadeInfo());
|
||||
|
||||
BeanTable assoc = factory.getBeanTable(prop.getPropertyType());
|
||||
if (assoc == null) {
|
||||
String msg = errorMsgMissingBeanTable(prop.getPropertyType(), prop.getFullBeanName());
|
||||
throw new RuntimeException(msg);
|
||||
}
|
||||
|
||||
prop.setBeanTable(assoc);
|
||||
}
|
||||
|
||||
private void readEmbedded(Embedded propAnn, DeployBeanPropertyAssocOne<?> prop) {
|
||||
|
||||
prop.setEmbedded(true);
|
||||
prop.setDbInsertable(true);
|
||||
prop.setDbUpdateable(true);
|
||||
|
||||
EmbeddedColumns columns = get(prop, EmbeddedColumns.class);
|
||||
if (columns != null) {
|
||||
|
||||
// convert into a Map
|
||||
String propColumns = columns.columns();
|
||||
Map<String, String> propMap = StringHelper.delimitedToMap(propColumns, ",", "=");
|
||||
|
||||
prop.getDeployEmbedded().putAll(propMap);
|
||||
}
|
||||
|
||||
AttributeOverrides attrOverrides = get(prop, AttributeOverrides.class);
|
||||
if (attrOverrides != null) {
|
||||
HashMap<String, String> propMap = new HashMap<String, String>();
|
||||
AttributeOverride[] aoArray = attrOverrides.value();
|
||||
for (int i = 0; i < aoArray.length; i++) {
|
||||
String propName = aoArray[i].name();
|
||||
String columnName = aoArray[i].column().name();
|
||||
|
||||
propMap.put(propName, columnName);
|
||||
}
|
||||
|
||||
prop.getDeployEmbedded().putAll(propMap);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
package com.avaje.ebeaninternal.server.deploy.parse;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.persistence.AttributeOverride;
|
||||
import javax.persistence.AttributeOverrides;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Embedded;
|
||||
import javax.persistence.EmbeddedId;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.JoinColumns;
|
||||
import javax.persistence.JoinTable;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.OneToOne;
|
||||
|
||||
import com.avaje.ebean.annotation.EmbeddedColumns;
|
||||
import com.avaje.ebean.annotation.Where;
|
||||
import com.avaje.ebean.config.NamingConvention;
|
||||
import com.avaje.ebean.validation.NotNull;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptorManager;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanTable;
|
||||
import com.avaje.ebeaninternal.server.deploy.TableJoin;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocOne;
|
||||
import com.avaje.ebeaninternal.server.lib.util.StringHelper;
|
||||
|
||||
/**
|
||||
* Read the deployment annotations for Associated One beans.
|
||||
*/
|
||||
public class AnnotationAssocOnes extends AnnotationParser {
|
||||
|
||||
private final BeanDescriptorManager factory;
|
||||
|
||||
/**
|
||||
* Create with the deploy Info.
|
||||
*/
|
||||
public AnnotationAssocOnes(DeployBeanInfo<?> info, BeanDescriptorManager factory) {
|
||||
super(info);
|
||||
this.factory = factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the annotation.
|
||||
*/
|
||||
public void parse() {
|
||||
|
||||
Iterator<DeployBeanProperty> it = descriptor.propertiesAll();
|
||||
while (it.hasNext()) {
|
||||
DeployBeanProperty prop = it.next();
|
||||
if (prop instanceof DeployBeanPropertyAssocOne<?>) {
|
||||
readAssocOne((DeployBeanPropertyAssocOne<?>) prop);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void readAssocOne(DeployBeanPropertyAssocOne<?> prop) {
|
||||
|
||||
ManyToOne manyToOne = get(prop, ManyToOne.class);
|
||||
if (manyToOne != null) {
|
||||
readManyToOne(manyToOne, prop);
|
||||
}
|
||||
OneToOne oneToOne = get(prop, OneToOne.class);
|
||||
if (oneToOne != null) {
|
||||
readOneToOne(oneToOne, prop);
|
||||
}
|
||||
Embedded embedded = get(prop, Embedded.class);
|
||||
if (embedded != null) {
|
||||
readEmbedded(embedded, prop);
|
||||
}
|
||||
EmbeddedId emId = get(prop, EmbeddedId.class);
|
||||
if (emId != null) {
|
||||
prop.setEmbedded(true);
|
||||
prop.setId(true);
|
||||
prop.setNullable(false);
|
||||
}
|
||||
Column column = get(prop, Column.class);
|
||||
if (column != null && !isEmpty(column.name())) {
|
||||
// have this in for AssocOnes used on
|
||||
// Sql based beans...
|
||||
prop.setDbColumn(column.name());
|
||||
}
|
||||
|
||||
// May as well check for Id. Makes sense to me.
|
||||
Id id = get(prop, Id.class);
|
||||
if (id != null) {
|
||||
prop.setEmbedded(true);
|
||||
prop.setId(true);
|
||||
prop.setNullable(false);
|
||||
}
|
||||
|
||||
Where where = get(prop, Where.class);
|
||||
if (where != null) {
|
||||
// not expecting this to be used on assoc one properties
|
||||
prop.setExtraWhere(where.clause());
|
||||
}
|
||||
|
||||
NotNull notNull = get(prop, NotNull.class);
|
||||
if (notNull != null) {
|
||||
prop.setNullable(false);
|
||||
// overrides optional attribute of ManyToOne etc
|
||||
prop.getTableJoin().setType(TableJoin.JOIN);
|
||||
}
|
||||
|
||||
// check for manually defined joins
|
||||
BeanTable beanTable = prop.getBeanTable();
|
||||
JoinColumn joinColumn = get(prop, JoinColumn.class);
|
||||
if (joinColumn != null) {
|
||||
prop.getTableJoin().addJoinColumn(false, joinColumn, beanTable);
|
||||
if (!joinColumn.updatable()){
|
||||
prop.setDbUpdateable(false);
|
||||
}
|
||||
}
|
||||
|
||||
JoinColumns joinColumns = get(prop, JoinColumns.class);
|
||||
if (joinColumns != null) {
|
||||
prop.getTableJoin().addJoinColumn(false, joinColumns.value(), beanTable);
|
||||
}
|
||||
|
||||
JoinTable joinTable = get(prop, JoinTable.class);
|
||||
if (joinTable != null) {
|
||||
prop.getTableJoin().addJoinColumn(false, joinTable.joinColumns(), beanTable);
|
||||
}
|
||||
|
||||
info.setBeanJoinType(prop, prop.isNullable());
|
||||
|
||||
if (!prop.getTableJoin().hasJoinColumns() && beanTable != null) {
|
||||
|
||||
if (prop.getMappedBy() != null) {
|
||||
// the join is derived by reversing the join information
|
||||
// from the mapped by property.
|
||||
// Refer BeanDescriptorManager.readEntityRelationships()
|
||||
|
||||
} else {
|
||||
// use naming convention to define join.
|
||||
NamingConvention nc = factory.getNamingConvention();
|
||||
|
||||
String fkeyPrefix = null;
|
||||
if (nc.isUseForeignKeyPrefix()){
|
||||
fkeyPrefix = nc.getColumnFromProperty(beanType, prop.getName());
|
||||
}
|
||||
|
||||
beanTable.createJoinColumn(fkeyPrefix, prop.getTableJoin(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String errorMsgMissingBeanTable(Class<?> type, String from) {
|
||||
return "Error with association to [" + type + "] from [" + from + "]. Is " + type + " registered?";
|
||||
}
|
||||
|
||||
private void readManyToOne(ManyToOne propAnn, DeployBeanProperty prop) {
|
||||
|
||||
DeployBeanPropertyAssocOne<?> beanProp = (DeployBeanPropertyAssocOne<?>) prop;
|
||||
|
||||
setCascadeTypes(propAnn.cascade(), beanProp.getCascadeInfo());
|
||||
|
||||
BeanTable assoc = factory.getBeanTable(beanProp.getPropertyType());
|
||||
if (assoc == null) {
|
||||
String msg = errorMsgMissingBeanTable(beanProp.getPropertyType(), prop.getFullBeanName());
|
||||
throw new RuntimeException(msg);
|
||||
}
|
||||
beanProp.setBeanTable(assoc);
|
||||
beanProp.setDbInsertable(true);
|
||||
beanProp.setDbUpdateable(true);
|
||||
beanProp.setNullable(propAnn.optional());
|
||||
beanProp.setFetchType(propAnn.fetch());
|
||||
}
|
||||
|
||||
private void readOneToOne(OneToOne propAnn, DeployBeanPropertyAssocOne<?> prop) {
|
||||
|
||||
prop.setOneToOne(true);
|
||||
prop.setDbInsertable(true);
|
||||
prop.setDbUpdateable(true);
|
||||
prop.setNullable(propAnn.optional());
|
||||
prop.setFetchType(propAnn.fetch());
|
||||
prop.setMappedBy(propAnn.mappedBy());
|
||||
if (!"".equals(propAnn.mappedBy())) {
|
||||
prop.setOneToOneExported(true);
|
||||
}
|
||||
|
||||
setCascadeTypes(propAnn.cascade(), prop.getCascadeInfo());
|
||||
|
||||
BeanTable assoc = factory.getBeanTable(prop.getPropertyType());
|
||||
if (assoc == null) {
|
||||
String msg = errorMsgMissingBeanTable(prop.getPropertyType(), prop.getFullBeanName());
|
||||
throw new RuntimeException(msg);
|
||||
}
|
||||
|
||||
prop.setBeanTable(assoc);
|
||||
}
|
||||
|
||||
private void readEmbedded(Embedded propAnn, DeployBeanPropertyAssocOne<?> prop) {
|
||||
|
||||
prop.setEmbedded(true);
|
||||
prop.setDbInsertable(true);
|
||||
prop.setDbUpdateable(true);
|
||||
|
||||
EmbeddedColumns columns = get(prop, EmbeddedColumns.class);
|
||||
if (columns != null) {
|
||||
|
||||
// convert into a Map
|
||||
String propColumns = columns.columns();
|
||||
Map<String, String> propMap = StringHelper.delimitedToMap(propColumns, ",", "=");
|
||||
|
||||
prop.getDeployEmbedded().putAll(propMap);
|
||||
}
|
||||
|
||||
AttributeOverrides attrOverrides = get(prop, AttributeOverrides.class);
|
||||
if (attrOverrides != null) {
|
||||
HashMap<String, String> propMap = new HashMap<String, String>();
|
||||
AttributeOverride[] aoArray = attrOverrides.value();
|
||||
for (int i = 0; i < aoArray.length; i++) {
|
||||
String propName = aoArray[i].name();
|
||||
String columnName = aoArray[i].column().name();
|
||||
|
||||
propMap.put(propName, columnName);
|
||||
}
|
||||
|
||||
prop.getDeployEmbedded().putAll(propMap);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+31
-50
@@ -1,50 +1,31 @@
|
||||
/**
|
||||
* Copyright (C) 2006 Robin Bygrave
|
||||
*
|
||||
* This file is part of Ebean.
|
||||
*
|
||||
* Ebean is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Ebean 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package com.avaje.ebeaninternal.server.deploy.parse;
|
||||
|
||||
import com.avaje.ebean.config.TableName;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanTable;
|
||||
|
||||
/**
|
||||
* Read the annotations for BeanTable.
|
||||
* <p>
|
||||
* Refer to BeanTable but basically determining base table, table alias
|
||||
* and the unique id properties.
|
||||
* </p>
|
||||
*/
|
||||
public class AnnotationBeanTable extends AnnotationBase {
|
||||
|
||||
final DeployBeanTable beanTable;
|
||||
|
||||
public AnnotationBeanTable(DeployUtil util, DeployBeanTable beanTable){
|
||||
super(util);
|
||||
this.beanTable = beanTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the annotations.
|
||||
*/
|
||||
public void parse() {
|
||||
|
||||
TableName tableName = namingConvention.getTableName(beanTable.getBeanType());
|
||||
|
||||
beanTable.setBaseTable(tableName.getQualifiedName());
|
||||
}
|
||||
}
|
||||
package com.avaje.ebeaninternal.server.deploy.parse;
|
||||
|
||||
import com.avaje.ebean.config.TableName;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanTable;
|
||||
|
||||
/**
|
||||
* Read the annotations for BeanTable.
|
||||
* <p>
|
||||
* Refer to BeanTable but basically determining base table, table alias
|
||||
* and the unique id properties.
|
||||
* </p>
|
||||
*/
|
||||
public class AnnotationBeanTable extends AnnotationBase {
|
||||
|
||||
final DeployBeanTable beanTable;
|
||||
|
||||
public AnnotationBeanTable(DeployUtil util, DeployBeanTable beanTable){
|
||||
super(util);
|
||||
this.beanTable = beanTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the annotations.
|
||||
*/
|
||||
public void parse() {
|
||||
|
||||
TableName tableName = namingConvention.getTableName(beanTable.getBeanType());
|
||||
|
||||
beanTable.setBaseTable(tableName.getQualifiedName());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,244 +1,225 @@
|
||||
/**
|
||||
* Copyright (C) 2006 Robin Bygrave
|
||||
*
|
||||
* This file is part of Ebean.
|
||||
*
|
||||
* Ebean is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Ebean 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package com.avaje.ebeaninternal.server.deploy.parse;
|
||||
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.NamedQueries;
|
||||
import javax.persistence.NamedQuery;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.UniqueConstraint;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import javax.xml.bind.annotation.XmlType;
|
||||
|
||||
import com.avaje.ebean.Query.UseIndex;
|
||||
import com.avaje.ebean.annotation.CacheStrategy;
|
||||
import com.avaje.ebean.annotation.LdapDomain;
|
||||
import com.avaje.ebean.annotation.NamedUpdate;
|
||||
import com.avaje.ebean.annotation.NamedUpdates;
|
||||
import com.avaje.ebean.annotation.UpdateMode;
|
||||
import com.avaje.ebean.config.TableName;
|
||||
import com.avaje.ebeaninternal.server.core.CacheOptions;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor.EntityType;
|
||||
import com.avaje.ebeaninternal.server.deploy.CompoundUniqueContraint;
|
||||
import com.avaje.ebeaninternal.server.deploy.DeployNamedQuery;
|
||||
import com.avaje.ebeaninternal.server.deploy.DeployNamedUpdate;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
|
||||
|
||||
/**
|
||||
* Read the class level deployment annotations.
|
||||
*/
|
||||
public class AnnotationClass extends AnnotationParser {
|
||||
|
||||
public AnnotationClass(DeployBeanInfo<?> info) {
|
||||
super(info);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the class level deployment annotations.
|
||||
*/
|
||||
public void parse() {
|
||||
read(descriptor.getBeanType());
|
||||
setTableName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the table name if it has not already been set.
|
||||
*/
|
||||
private void setTableName() {
|
||||
|
||||
if (descriptor.isBaseTableType()) {
|
||||
|
||||
// default the TableName using NamingConvention.
|
||||
TableName tableName = namingConvention.getTableName(descriptor.getBeanType());
|
||||
|
||||
descriptor.setBaseTable(tableName);
|
||||
}
|
||||
}
|
||||
|
||||
private String[] parseLdapObjectclasses(String objectclasses) {
|
||||
|
||||
if (objectclasses == null || objectclasses.length() == 0){
|
||||
return null;
|
||||
}
|
||||
return objectclasses.split(",");
|
||||
}
|
||||
|
||||
private boolean isXmlElement(Class<?> cls) {
|
||||
XmlRootElement rootElement = cls.getAnnotation(XmlRootElement.class);
|
||||
if (rootElement != null){
|
||||
return true;
|
||||
}
|
||||
XmlType xmlType = cls.getAnnotation(XmlType.class);
|
||||
if (xmlType != null){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void read(Class<?> cls) {
|
||||
|
||||
LdapDomain ldapDomain = cls.getAnnotation(LdapDomain.class);
|
||||
if (ldapDomain != null) {
|
||||
descriptor.setName(cls.getSimpleName());
|
||||
descriptor.setEntityType(EntityType.LDAP);
|
||||
descriptor.setLdapBaseDn(ldapDomain.baseDn());
|
||||
descriptor.setLdapObjectclasses(parseLdapObjectclasses(ldapDomain.objectclass()));
|
||||
}
|
||||
|
||||
Entity entity = cls.getAnnotation(Entity.class);
|
||||
if (entity != null){
|
||||
//checkDefaultConstructor();
|
||||
if (entity.name().equals("")) {
|
||||
descriptor.setName(cls.getSimpleName());
|
||||
|
||||
} else {
|
||||
descriptor.setName(entity.name());
|
||||
}
|
||||
} else if (isXmlElement(cls)) {
|
||||
descriptor.setName(cls.getSimpleName());
|
||||
descriptor.setEntityType(EntityType.XMLELEMENT);
|
||||
}
|
||||
|
||||
Embeddable embeddable = cls.getAnnotation(Embeddable.class);
|
||||
if (embeddable != null){
|
||||
descriptor.setEntityType(EntityType.EMBEDDED);
|
||||
descriptor.setName("Embeddable:"+cls.getSimpleName());
|
||||
}
|
||||
|
||||
UniqueConstraint uc = cls.getAnnotation(UniqueConstraint.class);
|
||||
if (uc != null){
|
||||
descriptor.addCompoundUniqueConstraint(new CompoundUniqueContraint(uc.columnNames()));
|
||||
}
|
||||
|
||||
Table table = cls.getAnnotation(Table.class);
|
||||
if (table != null){
|
||||
UniqueConstraint[] uniqueConstraints = table.uniqueConstraints();
|
||||
if (uniqueConstraints != null){
|
||||
for (UniqueConstraint c : uniqueConstraints) {
|
||||
descriptor.addCompoundUniqueConstraint(new CompoundUniqueContraint(c.columnNames()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UpdateMode updateMode = cls.getAnnotation(UpdateMode.class);
|
||||
if (updateMode != null){
|
||||
descriptor.setUpdateChangesOnly(updateMode.updateChangesOnly());
|
||||
}
|
||||
|
||||
NamedQueries namedQueries = cls.getAnnotation(NamedQueries.class);
|
||||
if (namedQueries != null){
|
||||
readNamedQueries(namedQueries);
|
||||
}
|
||||
NamedQuery namedQuery = cls.getAnnotation(NamedQuery.class);
|
||||
if (namedQuery != null){
|
||||
readNamedQuery(namedQuery);
|
||||
}
|
||||
|
||||
NamedUpdates namedUpdates = cls.getAnnotation(NamedUpdates.class);
|
||||
if (namedUpdates != null){
|
||||
readNamedUpdates(namedUpdates);
|
||||
}
|
||||
|
||||
NamedUpdate namedUpdate = cls.getAnnotation(NamedUpdate.class);
|
||||
if (namedUpdate != null){
|
||||
readNamedUpdate(namedUpdate);
|
||||
}
|
||||
|
||||
CacheStrategy cacheStrategy = cls.getAnnotation(CacheStrategy.class);
|
||||
if (cacheStrategy != null){
|
||||
readCacheStrategy(cacheStrategy);
|
||||
}
|
||||
}
|
||||
|
||||
private void readCacheStrategy(CacheStrategy cacheStrategy){
|
||||
|
||||
CacheOptions cacheOptions = descriptor.getCacheOptions();
|
||||
cacheOptions.setUseCache(cacheStrategy.useBeanCache());
|
||||
cacheOptions.setReadOnly(cacheStrategy.readOnly());
|
||||
cacheOptions.setWarmingQuery(cacheStrategy.warmingQuery());
|
||||
if (cacheStrategy.naturalKey().length() > 0){
|
||||
String propName = cacheStrategy.naturalKey().trim();
|
||||
DeployBeanProperty beanProperty = descriptor.getBeanProperty(propName);
|
||||
if (beanProperty != null){
|
||||
beanProperty.setNaturalKey(true);
|
||||
cacheOptions.setNaturalKey(propName);
|
||||
}
|
||||
}
|
||||
|
||||
if (!UseIndex.DEFAULT.equals(cacheStrategy.useIndex())){
|
||||
// a specific text index strategy has been defined
|
||||
descriptor.setUseIndex(cacheStrategy.useIndex());
|
||||
}
|
||||
}
|
||||
|
||||
private void readNamedQueries(NamedQueries namedQueries) {
|
||||
NamedQuery[] queries = namedQueries.value();
|
||||
for (int i = 0; i < queries.length; i++) {
|
||||
readNamedQuery(queries[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private void readNamedQuery(NamedQuery namedQuery) {
|
||||
DeployNamedQuery q = new DeployNamedQuery(namedQuery);
|
||||
descriptor.add(q);
|
||||
}
|
||||
|
||||
private void readNamedUpdates(NamedUpdates updates) {
|
||||
NamedUpdate[] updateArray = updates.value();
|
||||
for (int i = 0; i < updateArray.length; i++) {
|
||||
readNamedUpdate(updateArray[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private void readNamedUpdate(NamedUpdate update) {
|
||||
DeployNamedUpdate upd = new DeployNamedUpdate(update);
|
||||
descriptor.add(upd);
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Check to see if the Entity bean has a default constructor.
|
||||
// * <p>
|
||||
// * If it does not then it is expected that this entity bean has an
|
||||
// * associated BeanFinder.
|
||||
// * </p>
|
||||
// */
|
||||
// private void checkDefaultConstructor() {
|
||||
//
|
||||
// Class<?> beanType = descriptor.getBeanType();
|
||||
//
|
||||
// Constructor<?> defaultConstructor;
|
||||
// try {
|
||||
// defaultConstructor = beanType.getConstructor((Class[]) null);
|
||||
// if (defaultConstructor == null) {
|
||||
// String m = "No default constructor on "+beanType;
|
||||
// throw new PersistenceException(m);
|
||||
// }
|
||||
// } catch (SecurityException e) {
|
||||
// String m = "Error checking for default constructor on "+beanType;
|
||||
// throw new PersistenceException(m, e);
|
||||
//
|
||||
// } catch (NoSuchMethodException e) {
|
||||
// String m = "No default constructor on "+beanType;
|
||||
// throw new PersistenceException(m);
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
package com.avaje.ebeaninternal.server.deploy.parse;
|
||||
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.NamedQueries;
|
||||
import javax.persistence.NamedQuery;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.UniqueConstraint;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import javax.xml.bind.annotation.XmlType;
|
||||
|
||||
import com.avaje.ebean.Query.UseIndex;
|
||||
import com.avaje.ebean.annotation.CacheStrategy;
|
||||
import com.avaje.ebean.annotation.LdapDomain;
|
||||
import com.avaje.ebean.annotation.NamedUpdate;
|
||||
import com.avaje.ebean.annotation.NamedUpdates;
|
||||
import com.avaje.ebean.annotation.UpdateMode;
|
||||
import com.avaje.ebean.config.TableName;
|
||||
import com.avaje.ebeaninternal.server.core.CacheOptions;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor.EntityType;
|
||||
import com.avaje.ebeaninternal.server.deploy.CompoundUniqueContraint;
|
||||
import com.avaje.ebeaninternal.server.deploy.DeployNamedQuery;
|
||||
import com.avaje.ebeaninternal.server.deploy.DeployNamedUpdate;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
|
||||
|
||||
/**
|
||||
* Read the class level deployment annotations.
|
||||
*/
|
||||
public class AnnotationClass extends AnnotationParser {
|
||||
|
||||
public AnnotationClass(DeployBeanInfo<?> info) {
|
||||
super(info);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the class level deployment annotations.
|
||||
*/
|
||||
public void parse() {
|
||||
read(descriptor.getBeanType());
|
||||
setTableName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the table name if it has not already been set.
|
||||
*/
|
||||
private void setTableName() {
|
||||
|
||||
if (descriptor.isBaseTableType()) {
|
||||
|
||||
// default the TableName using NamingConvention.
|
||||
TableName tableName = namingConvention.getTableName(descriptor.getBeanType());
|
||||
|
||||
descriptor.setBaseTable(tableName);
|
||||
}
|
||||
}
|
||||
|
||||
private String[] parseLdapObjectclasses(String objectclasses) {
|
||||
|
||||
if (objectclasses == null || objectclasses.length() == 0){
|
||||
return null;
|
||||
}
|
||||
return objectclasses.split(",");
|
||||
}
|
||||
|
||||
private boolean isXmlElement(Class<?> cls) {
|
||||
XmlRootElement rootElement = cls.getAnnotation(XmlRootElement.class);
|
||||
if (rootElement != null){
|
||||
return true;
|
||||
}
|
||||
XmlType xmlType = cls.getAnnotation(XmlType.class);
|
||||
if (xmlType != null){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void read(Class<?> cls) {
|
||||
|
||||
LdapDomain ldapDomain = cls.getAnnotation(LdapDomain.class);
|
||||
if (ldapDomain != null) {
|
||||
descriptor.setName(cls.getSimpleName());
|
||||
descriptor.setEntityType(EntityType.LDAP);
|
||||
descriptor.setLdapBaseDn(ldapDomain.baseDn());
|
||||
descriptor.setLdapObjectclasses(parseLdapObjectclasses(ldapDomain.objectclass()));
|
||||
}
|
||||
|
||||
Entity entity = cls.getAnnotation(Entity.class);
|
||||
if (entity != null){
|
||||
//checkDefaultConstructor();
|
||||
if (entity.name().equals("")) {
|
||||
descriptor.setName(cls.getSimpleName());
|
||||
|
||||
} else {
|
||||
descriptor.setName(entity.name());
|
||||
}
|
||||
} else if (isXmlElement(cls)) {
|
||||
descriptor.setName(cls.getSimpleName());
|
||||
descriptor.setEntityType(EntityType.XMLELEMENT);
|
||||
}
|
||||
|
||||
Embeddable embeddable = cls.getAnnotation(Embeddable.class);
|
||||
if (embeddable != null){
|
||||
descriptor.setEntityType(EntityType.EMBEDDED);
|
||||
descriptor.setName("Embeddable:"+cls.getSimpleName());
|
||||
}
|
||||
|
||||
UniqueConstraint uc = cls.getAnnotation(UniqueConstraint.class);
|
||||
if (uc != null){
|
||||
descriptor.addCompoundUniqueConstraint(new CompoundUniqueContraint(uc.columnNames()));
|
||||
}
|
||||
|
||||
Table table = cls.getAnnotation(Table.class);
|
||||
if (table != null){
|
||||
UniqueConstraint[] uniqueConstraints = table.uniqueConstraints();
|
||||
if (uniqueConstraints != null){
|
||||
for (UniqueConstraint c : uniqueConstraints) {
|
||||
descriptor.addCompoundUniqueConstraint(new CompoundUniqueContraint(c.columnNames()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UpdateMode updateMode = cls.getAnnotation(UpdateMode.class);
|
||||
if (updateMode != null){
|
||||
descriptor.setUpdateChangesOnly(updateMode.updateChangesOnly());
|
||||
}
|
||||
|
||||
NamedQueries namedQueries = cls.getAnnotation(NamedQueries.class);
|
||||
if (namedQueries != null){
|
||||
readNamedQueries(namedQueries);
|
||||
}
|
||||
NamedQuery namedQuery = cls.getAnnotation(NamedQuery.class);
|
||||
if (namedQuery != null){
|
||||
readNamedQuery(namedQuery);
|
||||
}
|
||||
|
||||
NamedUpdates namedUpdates = cls.getAnnotation(NamedUpdates.class);
|
||||
if (namedUpdates != null){
|
||||
readNamedUpdates(namedUpdates);
|
||||
}
|
||||
|
||||
NamedUpdate namedUpdate = cls.getAnnotation(NamedUpdate.class);
|
||||
if (namedUpdate != null){
|
||||
readNamedUpdate(namedUpdate);
|
||||
}
|
||||
|
||||
CacheStrategy cacheStrategy = cls.getAnnotation(CacheStrategy.class);
|
||||
if (cacheStrategy != null){
|
||||
readCacheStrategy(cacheStrategy);
|
||||
}
|
||||
}
|
||||
|
||||
private void readCacheStrategy(CacheStrategy cacheStrategy){
|
||||
|
||||
CacheOptions cacheOptions = descriptor.getCacheOptions();
|
||||
cacheOptions.setUseCache(cacheStrategy.useBeanCache());
|
||||
cacheOptions.setReadOnly(cacheStrategy.readOnly());
|
||||
cacheOptions.setWarmingQuery(cacheStrategy.warmingQuery());
|
||||
if (cacheStrategy.naturalKey().length() > 0){
|
||||
String propName = cacheStrategy.naturalKey().trim();
|
||||
DeployBeanProperty beanProperty = descriptor.getBeanProperty(propName);
|
||||
if (beanProperty != null){
|
||||
beanProperty.setNaturalKey(true);
|
||||
cacheOptions.setNaturalKey(propName);
|
||||
}
|
||||
}
|
||||
|
||||
if (!UseIndex.DEFAULT.equals(cacheStrategy.useIndex())){
|
||||
// a specific text index strategy has been defined
|
||||
descriptor.setUseIndex(cacheStrategy.useIndex());
|
||||
}
|
||||
}
|
||||
|
||||
private void readNamedQueries(NamedQueries namedQueries) {
|
||||
NamedQuery[] queries = namedQueries.value();
|
||||
for (int i = 0; i < queries.length; i++) {
|
||||
readNamedQuery(queries[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private void readNamedQuery(NamedQuery namedQuery) {
|
||||
DeployNamedQuery q = new DeployNamedQuery(namedQuery);
|
||||
descriptor.add(q);
|
||||
}
|
||||
|
||||
private void readNamedUpdates(NamedUpdates updates) {
|
||||
NamedUpdate[] updateArray = updates.value();
|
||||
for (int i = 0; i < updateArray.length; i++) {
|
||||
readNamedUpdate(updateArray[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private void readNamedUpdate(NamedUpdate update) {
|
||||
DeployNamedUpdate upd = new DeployNamedUpdate(update);
|
||||
descriptor.add(upd);
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Check to see if the Entity bean has a default constructor.
|
||||
// * <p>
|
||||
// * If it does not then it is expected that this entity bean has an
|
||||
// * associated BeanFinder.
|
||||
// * </p>
|
||||
// */
|
||||
// private void checkDefaultConstructor() {
|
||||
//
|
||||
// Class<?> beanType = descriptor.getBeanType();
|
||||
//
|
||||
// Constructor<?> defaultConstructor;
|
||||
// try {
|
||||
// defaultConstructor = beanType.getConstructor((Class[]) null);
|
||||
// if (defaultConstructor == null) {
|
||||
// String m = "No default constructor on "+beanType;
|
||||
// throw new PersistenceException(m);
|
||||
// }
|
||||
// } catch (SecurityException e) {
|
||||
// String m = "Error checking for default constructor on "+beanType;
|
||||
// throw new PersistenceException(m, e);
|
||||
//
|
||||
// } catch (NoSuchMethodException e) {
|
||||
// String m = "No default constructor on "+beanType;
|
||||
// throw new PersistenceException(m);
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,85 +1,66 @@
|
||||
/**
|
||||
* Copyright (C) 2006 Robin Bygrave
|
||||
*
|
||||
* This file is part of Ebean.
|
||||
*
|
||||
* Ebean is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Ebean 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package com.avaje.ebeaninternal.server.deploy.parse;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.PersistenceException;
|
||||
|
||||
import com.avaje.ebean.annotation.LdapAttribute;
|
||||
import com.avaje.ebean.config.ldap.LdapAttributeAdapter;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanCascadeInfo;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanDescriptor;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
|
||||
|
||||
/**
|
||||
* Base class for reading deployment annotations.
|
||||
*/
|
||||
public abstract class AnnotationParser extends AnnotationBase {
|
||||
|
||||
protected final DeployBeanInfo<?> info;
|
||||
|
||||
protected final DeployBeanDescriptor<?> descriptor;
|
||||
|
||||
protected final Class<?> beanType;
|
||||
|
||||
public AnnotationParser(DeployBeanInfo<?> info){
|
||||
super(info.getUtil());
|
||||
this.info = info;
|
||||
this.beanType = info.getDescriptor().getBeanType();
|
||||
this.descriptor = info.getDescriptor();
|
||||
}
|
||||
|
||||
/**
|
||||
* read the deployment annotations.
|
||||
*/
|
||||
public abstract void parse();
|
||||
|
||||
/**
|
||||
* Helper method to set cascade types to the CascadeInfo on BeanProperty.
|
||||
*/
|
||||
protected void setCascadeTypes(CascadeType[] cascadeTypes, BeanCascadeInfo cascadeInfo) {
|
||||
if (cascadeTypes != null && cascadeTypes.length > 0) {
|
||||
cascadeInfo.setTypes(cascadeTypes);
|
||||
}
|
||||
}
|
||||
|
||||
protected void readLdapAttribute(LdapAttribute ldapAttribute, DeployBeanProperty prop) {
|
||||
|
||||
if (!isEmpty(ldapAttribute.name())){
|
||||
prop.setDbColumn(ldapAttribute.name());
|
||||
}
|
||||
prop.setDbInsertable(ldapAttribute.insertable());
|
||||
prop.setDbUpdateable(ldapAttribute.updatable());
|
||||
|
||||
Class<?> adapterCls = ldapAttribute.adapter();
|
||||
|
||||
if (adapterCls != null && !void.class.equals(adapterCls)){
|
||||
try {
|
||||
LdapAttributeAdapter adapter = (LdapAttributeAdapter)adapterCls.newInstance();
|
||||
prop.setLdapAttributeAdapter(adapter);
|
||||
} catch (Exception e){
|
||||
String msg= "Error creating LdapAttributeAdapter for ["+prop.getFullBeanName()+"] "
|
||||
+"with class ["+adapterCls+"] using the default constructor.";
|
||||
throw new PersistenceException(msg, e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
package com.avaje.ebeaninternal.server.deploy.parse;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.PersistenceException;
|
||||
|
||||
import com.avaje.ebean.annotation.LdapAttribute;
|
||||
import com.avaje.ebean.config.ldap.LdapAttributeAdapter;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanCascadeInfo;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanDescriptor;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
|
||||
|
||||
/**
|
||||
* Base class for reading deployment annotations.
|
||||
*/
|
||||
public abstract class AnnotationParser extends AnnotationBase {
|
||||
|
||||
protected final DeployBeanInfo<?> info;
|
||||
|
||||
protected final DeployBeanDescriptor<?> descriptor;
|
||||
|
||||
protected final Class<?> beanType;
|
||||
|
||||
public AnnotationParser(DeployBeanInfo<?> info){
|
||||
super(info.getUtil());
|
||||
this.info = info;
|
||||
this.beanType = info.getDescriptor().getBeanType();
|
||||
this.descriptor = info.getDescriptor();
|
||||
}
|
||||
|
||||
/**
|
||||
* read the deployment annotations.
|
||||
*/
|
||||
public abstract void parse();
|
||||
|
||||
/**
|
||||
* Helper method to set cascade types to the CascadeInfo on BeanProperty.
|
||||
*/
|
||||
protected void setCascadeTypes(CascadeType[] cascadeTypes, BeanCascadeInfo cascadeInfo) {
|
||||
if (cascadeTypes != null && cascadeTypes.length > 0) {
|
||||
cascadeInfo.setTypes(cascadeTypes);
|
||||
}
|
||||
}
|
||||
|
||||
protected void readLdapAttribute(LdapAttribute ldapAttribute, DeployBeanProperty prop) {
|
||||
|
||||
if (!isEmpty(ldapAttribute.name())){
|
||||
prop.setDbColumn(ldapAttribute.name());
|
||||
}
|
||||
prop.setDbInsertable(ldapAttribute.insertable());
|
||||
prop.setDbUpdateable(ldapAttribute.updatable());
|
||||
|
||||
Class<?> adapterCls = ldapAttribute.adapter();
|
||||
|
||||
if (adapterCls != null && !void.class.equals(adapterCls)){
|
||||
try {
|
||||
LdapAttributeAdapter adapter = (LdapAttributeAdapter)adapterCls.newInstance();
|
||||
prop.setLdapAttributeAdapter(adapter);
|
||||
} catch (Exception e){
|
||||
String msg= "Error creating LdapAttributeAdapter for ["+prop.getFullBeanName()+"] "
|
||||
+"with class ["+adapterCls+"] using the default constructor.";
|
||||
throw new PersistenceException(msg, e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,61 +1,42 @@
|
||||
/**
|
||||
* Copyright (C) 2006 Robin Bygrave
|
||||
*
|
||||
* This file is part of Ebean.
|
||||
*
|
||||
* Ebean is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Ebean 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package com.avaje.ebeaninternal.server.deploy.parse;
|
||||
|
||||
import com.avaje.ebean.annotation.Sql;
|
||||
import com.avaje.ebean.annotation.SqlSelect;
|
||||
import com.avaje.ebeaninternal.server.deploy.DRawSqlMeta;
|
||||
|
||||
/**
|
||||
* Read the class level deployment annotations.
|
||||
*/
|
||||
public class AnnotationSql extends AnnotationParser {
|
||||
|
||||
public AnnotationSql(DeployBeanInfo<?> info) {
|
||||
super(info);
|
||||
}
|
||||
|
||||
public void parse() {
|
||||
Class<?> cls = descriptor.getBeanType();
|
||||
Sql sql = cls.getAnnotation(Sql.class);
|
||||
if (sql != null){
|
||||
setSql(sql);
|
||||
}
|
||||
|
||||
|
||||
SqlSelect sqlSelect = cls.getAnnotation(SqlSelect.class);
|
||||
if (sqlSelect != null){
|
||||
setSqlSelect(sqlSelect);
|
||||
}
|
||||
}
|
||||
|
||||
private void setSql(Sql sql) {
|
||||
SqlSelect[] select = sql.select();
|
||||
for (int i = 0; i < select.length; i++) {
|
||||
setSqlSelect(select[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private void setSqlSelect(SqlSelect sqlSelect) {
|
||||
|
||||
DRawSqlMeta rawSqlMeta = new DRawSqlMeta(sqlSelect);
|
||||
descriptor.add(rawSqlMeta);
|
||||
}
|
||||
}
|
||||
package com.avaje.ebeaninternal.server.deploy.parse;
|
||||
|
||||
import com.avaje.ebean.annotation.Sql;
|
||||
import com.avaje.ebean.annotation.SqlSelect;
|
||||
import com.avaje.ebeaninternal.server.deploy.DRawSqlMeta;
|
||||
|
||||
/**
|
||||
* Read the class level deployment annotations.
|
||||
*/
|
||||
public class AnnotationSql extends AnnotationParser {
|
||||
|
||||
public AnnotationSql(DeployBeanInfo<?> info) {
|
||||
super(info);
|
||||
}
|
||||
|
||||
public void parse() {
|
||||
Class<?> cls = descriptor.getBeanType();
|
||||
Sql sql = cls.getAnnotation(Sql.class);
|
||||
if (sql != null){
|
||||
setSql(sql);
|
||||
}
|
||||
|
||||
|
||||
SqlSelect sqlSelect = cls.getAnnotation(SqlSelect.class);
|
||||
if (sqlSelect != null){
|
||||
setSqlSelect(sqlSelect);
|
||||
}
|
||||
}
|
||||
|
||||
private void setSql(Sql sql) {
|
||||
SqlSelect[] select = sql.select();
|
||||
for (int i = 0; i < select.length; i++) {
|
||||
setSqlSelect(select[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private void setSqlSelect(SqlSelect sqlSelect) {
|
||||
|
||||
DRawSqlMeta rawSqlMeta = new DRawSqlMeta(sqlSelect);
|
||||
descriptor.add(rawSqlMeta);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,102 +1,83 @@
|
||||
/**
|
||||
* Copyright (C) 2006 Robin Bygrave
|
||||
*
|
||||
* This file is part of Ebean.
|
||||
*
|
||||
* Ebean is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Ebean 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package com.avaje.ebeaninternal.server.deploy.parse;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import com.avaje.ebeaninternal.server.deploy.TableJoin;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanDescriptor;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocOne;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployTableJoin;
|
||||
|
||||
/**
|
||||
* Wraps information about a bean during deployment parsing.
|
||||
*/
|
||||
public class DeployBeanInfo<T> {
|
||||
|
||||
/**
|
||||
* Holds TableJoins for secondary table properties.
|
||||
*/
|
||||
private final HashMap<String,DeployTableJoin> tableJoinMap = new HashMap<String, DeployTableJoin>();
|
||||
|
||||
private final DeployUtil util;
|
||||
|
||||
private final DeployBeanDescriptor<T> descriptor;
|
||||
|
||||
/**
|
||||
* Create with a DeployUtil and BeanDescriptor.
|
||||
*/
|
||||
public DeployBeanInfo(DeployUtil util, DeployBeanDescriptor<T> descriptor) {
|
||||
this.util = util;
|
||||
this.descriptor = descriptor;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return ""+descriptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the BeanDescriptor currently being processed.
|
||||
*/
|
||||
public DeployBeanDescriptor<T> getDescriptor() {
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the DeployUtil we are using.
|
||||
*/
|
||||
public DeployUtil getUtil() {
|
||||
return util;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appropriate TableJoin for a property mapped to a secondary table.
|
||||
*/
|
||||
public DeployTableJoin getTableJoin(String tableName) {
|
||||
|
||||
String key = tableName.toLowerCase();
|
||||
|
||||
DeployTableJoin tableJoin = (DeployTableJoin) tableJoinMap.get(key);
|
||||
if (tableJoin == null) {
|
||||
tableJoin = new DeployTableJoin();
|
||||
tableJoin.setTable(tableName);
|
||||
tableJoin.setType(TableJoin.JOIN);
|
||||
descriptor.addTableJoin(tableJoin);
|
||||
|
||||
tableJoinMap.put(key, tableJoin);
|
||||
}
|
||||
return tableJoin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a the join alias for a assoc one property.
|
||||
*/
|
||||
public void setBeanJoinType(DeployBeanPropertyAssocOne<?> beanProp, boolean outerJoin) {
|
||||
|
||||
String joinType = TableJoin.JOIN;
|
||||
if (outerJoin){// && util.isUseOneToOneOptional()) {
|
||||
joinType = TableJoin.LEFT_OUTER;
|
||||
}
|
||||
|
||||
DeployTableJoin tableJoin = beanProp.getTableJoin();
|
||||
tableJoin.setType(joinType);
|
||||
}
|
||||
|
||||
}
|
||||
package com.avaje.ebeaninternal.server.deploy.parse;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import com.avaje.ebeaninternal.server.deploy.TableJoin;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanDescriptor;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocOne;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployTableJoin;
|
||||
|
||||
/**
|
||||
* Wraps information about a bean during deployment parsing.
|
||||
*/
|
||||
public class DeployBeanInfo<T> {
|
||||
|
||||
/**
|
||||
* Holds TableJoins for secondary table properties.
|
||||
*/
|
||||
private final HashMap<String,DeployTableJoin> tableJoinMap = new HashMap<String, DeployTableJoin>();
|
||||
|
||||
private final DeployUtil util;
|
||||
|
||||
private final DeployBeanDescriptor<T> descriptor;
|
||||
|
||||
/**
|
||||
* Create with a DeployUtil and BeanDescriptor.
|
||||
*/
|
||||
public DeployBeanInfo(DeployUtil util, DeployBeanDescriptor<T> descriptor) {
|
||||
this.util = util;
|
||||
this.descriptor = descriptor;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return ""+descriptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the BeanDescriptor currently being processed.
|
||||
*/
|
||||
public DeployBeanDescriptor<T> getDescriptor() {
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the DeployUtil we are using.
|
||||
*/
|
||||
public DeployUtil getUtil() {
|
||||
return util;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appropriate TableJoin for a property mapped to a secondary table.
|
||||
*/
|
||||
public DeployTableJoin getTableJoin(String tableName) {
|
||||
|
||||
String key = tableName.toLowerCase();
|
||||
|
||||
DeployTableJoin tableJoin = (DeployTableJoin) tableJoinMap.get(key);
|
||||
if (tableJoin == null) {
|
||||
tableJoin = new DeployTableJoin();
|
||||
tableJoin.setTable(tableName);
|
||||
tableJoin.setType(TableJoin.JOIN);
|
||||
descriptor.addTableJoin(tableJoin);
|
||||
|
||||
tableJoinMap.put(key, tableJoin);
|
||||
}
|
||||
return tableJoin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a the join alias for a assoc one property.
|
||||
*/
|
||||
public void setBeanJoinType(DeployBeanPropertyAssocOne<?> beanProp, boolean outerJoin) {
|
||||
|
||||
String joinType = TableJoin.JOIN;
|
||||
if (outerJoin){// && util.isUseOneToOneOptional()) {
|
||||
joinType = TableJoin.LEFT_OUTER;
|
||||
}
|
||||
|
||||
DeployTableJoin tableJoin = beanProp.getTableJoin();
|
||||
tableJoin.setType(joinType);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+416
-435
@@ -1,435 +1,416 @@
|
||||
/**
|
||||
* Copyright (C) 2006 Robin Bygrave
|
||||
*
|
||||
* This file is part of Ebean.
|
||||
*
|
||||
* Ebean is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Ebean 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package com.avaje.ebeaninternal.server.deploy.parse;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Iterator;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
import javax.persistence.Transient;
|
||||
|
||||
import com.avaje.ebean.config.ScalarTypeConverter;
|
||||
import com.avaje.ebeaninternal.server.core.Message;
|
||||
import com.avaje.ebeaninternal.server.deploy.DetermineManyType;
|
||||
import com.avaje.ebeaninternal.server.deploy.ManyType;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanDescriptor;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocMany;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocOne;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyCompound;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertySimpleCollection;
|
||||
import com.avaje.ebeaninternal.server.type.CtCompoundType;
|
||||
import com.avaje.ebeaninternal.server.type.ScalaOptionTypeConverter;
|
||||
import com.avaje.ebeaninternal.server.type.ScalarType;
|
||||
import com.avaje.ebeaninternal.server.type.TypeManager;
|
||||
import com.avaje.ebeaninternal.server.type.reflect.CheckImmutableResponse;
|
||||
|
||||
/**
|
||||
* Create the properties for a bean.
|
||||
* <p>
|
||||
* This also needs to determine if the property is a associated many, associated
|
||||
* one or normal scalar property.
|
||||
* </p>
|
||||
*/
|
||||
public class DeployCreateProperties {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(DeployCreateProperties.class.getName());
|
||||
|
||||
private final Class<?> scalaOptionClass;
|
||||
/**
|
||||
* Use to wrap and unwrap Scala Option.
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
private final ScalarTypeConverter scalaOptionTypeConverter;
|
||||
|
||||
private final DetermineManyType determineManyType;
|
||||
|
||||
private final TypeManager typeManager;
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
public DeployCreateProperties(TypeManager typeManager) {
|
||||
this.typeManager = typeManager;
|
||||
|
||||
Class<?> tmpOptionClass = DetectScala.getScalaOptionClass();
|
||||
|
||||
if (tmpOptionClass == null){
|
||||
scalaOptionClass = null;
|
||||
scalaOptionTypeConverter = null;
|
||||
} else {
|
||||
scalaOptionClass = tmpOptionClass;
|
||||
scalaOptionTypeConverter = new ScalaOptionTypeConverter();
|
||||
}
|
||||
|
||||
this.determineManyType = new DetermineManyType(tmpOptionClass != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the appropriate properties for a bean.
|
||||
*/
|
||||
public void createProperties(DeployBeanDescriptor<?> desc) {
|
||||
|
||||
createProperties(desc, desc.getBeanType(), 0);
|
||||
desc.sortProperties();
|
||||
|
||||
// check the transient properties...
|
||||
Iterator<DeployBeanProperty> it = desc.propertiesAll();
|
||||
|
||||
while (it.hasNext()) {
|
||||
DeployBeanProperty prop = it.next();
|
||||
if (prop.isTransient()){
|
||||
if (prop.getWriteMethod() == null || prop.getReadMethod() == null){
|
||||
// Typically a helper method ... this is expected
|
||||
logger.finest("... transient: "+prop.getFullBeanName());
|
||||
} else {
|
||||
// dubious, possible error...
|
||||
String msg = Message.msg("deploy.property.nofield", desc.getFullName(), prop.getName());
|
||||
logger.warning(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if we should ignore this field.
|
||||
* <p>
|
||||
* We want to ignore ebean internal fields and some others as well.
|
||||
* </p>
|
||||
*/
|
||||
private boolean ignoreFieldByName(String fieldName) {
|
||||
if (fieldName.startsWith("_ebean_")){
|
||||
// ignore Ebean internal fields
|
||||
return true;
|
||||
}
|
||||
if (fieldName.startsWith("ajc$instance$")) {
|
||||
// ignore AspectJ internal fields
|
||||
return true;
|
||||
}
|
||||
|
||||
// we are interested in this field
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* reflect the bean properties from Class. Some of these properties may not
|
||||
* map to database columns.
|
||||
*/
|
||||
private void createProperties(DeployBeanDescriptor<?> desc, Class<?> beanType, int level) {
|
||||
|
||||
boolean scalaObject = desc.isScalaObject();
|
||||
|
||||
try {
|
||||
Method[] declaredMethods = beanType.getDeclaredMethods();
|
||||
Field[] fields = beanType.getDeclaredFields();
|
||||
|
||||
for (int i = 0; i < fields.length; i++) {
|
||||
|
||||
Field field = fields[i];
|
||||
if (Modifier.isStatic(field.getModifiers())) {
|
||||
// not interested in static fields
|
||||
|
||||
} else if (Modifier.isTransient(field.getModifiers())) {
|
||||
// not interested in transient fields
|
||||
logger.finer("Skipping transient field "+field.getName()+" in "+beanType.getName());
|
||||
|
||||
} else if (ignoreFieldByName(field.getName())) {
|
||||
// not interested this field (ebean or aspectJ field)
|
||||
|
||||
} else {
|
||||
|
||||
String fieldName = getFieldName(field, beanType);
|
||||
String initFieldName = initCap(fieldName);
|
||||
|
||||
Method getter = findGetter(field, initFieldName, declaredMethods, scalaObject);
|
||||
Method setter = findSetter(field, initFieldName, declaredMethods, scalaObject);
|
||||
|
||||
DeployBeanProperty prop = createProp(level, desc, field, beanType, getter, setter);
|
||||
if (prop == null){
|
||||
// transient annotation on unsupported type
|
||||
|
||||
} else {
|
||||
// set a order that gives priority to inherited properties
|
||||
// push Id/EmbeddedId up and CreatedTimestamp/UpdatedTimestamp down
|
||||
int sortOverride = prop.getSortOverride();
|
||||
prop.setSortOrder((level*10000+100-i + sortOverride));
|
||||
|
||||
DeployBeanProperty replaced = desc.addBeanProperty(prop);
|
||||
if (replaced != null){
|
||||
if (replaced.isTransient()) {
|
||||
// expected for inheritance...
|
||||
} else {
|
||||
String msg = "Huh??? property "+prop.getFullBeanName()+" being defined twice";
|
||||
msg += " but replaced property was not transient? This is not expected?";
|
||||
logger.warning(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Class<?> superClass = beanType.getSuperclass();
|
||||
|
||||
if (!superClass.equals(Object.class)) {
|
||||
// recursively add any properties in the inheritance heirarchy
|
||||
// up to the Object.class level...
|
||||
createProperties(desc, superClass, level + 1);
|
||||
}
|
||||
|
||||
} catch (PersistenceException ex) {
|
||||
throw ex;
|
||||
|
||||
} catch (Exception ex) {
|
||||
throw new PersistenceException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the first letter of the string upper case.
|
||||
*/
|
||||
private String initCap(String str){
|
||||
if (str.length() > 1){
|
||||
return Character.toUpperCase(str.charAt(0))+str.substring(1);
|
||||
} else {
|
||||
// only a single char
|
||||
return str.toUpperCase();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the bean spec field name (trim of "is" from boolean types)
|
||||
*/
|
||||
private String getFieldName(Field field, Class<?> beanType){
|
||||
|
||||
String name = field.getName();
|
||||
|
||||
if ((Boolean.class.equals(field.getType()) || boolean.class.equals(field.getType()))
|
||||
&& name.startsWith("is") && name.length() > 2){
|
||||
|
||||
// it is a boolean type field starting with "is"
|
||||
char c = name.charAt(2);
|
||||
if (Character.isUpperCase(c)){
|
||||
String msg = "trimming off 'is' from boolean field name "+name+" in class "+beanType.getName();
|
||||
logger.log(Level.INFO, msg);
|
||||
|
||||
return name.substring(2);
|
||||
}
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a public non-static getter method that matches this field (according to bean-spec rules).
|
||||
*/
|
||||
private Method findGetter(Field field, String initFieldName, Method[] declaredMethods, boolean scalaObject){
|
||||
|
||||
String methGetName = "get"+initFieldName;
|
||||
String methIsName = "is"+initFieldName;
|
||||
String scalaGet = field.getName();
|
||||
|
||||
for (int i = 0; i < declaredMethods.length; i++) {
|
||||
Method m = declaredMethods[i];
|
||||
if ((scalaObject && m.getName().equals(scalaGet))
|
||||
|| m.getName().equals(methGetName) || m.getName().equals(methIsName)){
|
||||
|
||||
Class<?>[] params = m.getParameterTypes();
|
||||
if (params.length == 0){
|
||||
if (field.getType().equals(m.getReturnType())){
|
||||
int modifiers = m.getModifiers();
|
||||
if (Modifier.isPublic(modifiers) && !Modifier.isStatic(modifiers)) {
|
||||
// we find it...
|
||||
return m;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a public non-static setter method that matches this field (according to bean-spec rules).
|
||||
*/
|
||||
private Method findSetter(Field field, String initFieldName, Method[] declaredMethods, boolean scalaObject){
|
||||
|
||||
String methSetName = "set"+initFieldName;
|
||||
String scalaSetName = field.getName()+"_$eq";
|
||||
|
||||
for (int i = 0; i < declaredMethods.length; i++) {
|
||||
Method m = declaredMethods[i];
|
||||
|
||||
if ((scalaObject && m.getName().equals(scalaSetName))
|
||||
|| m.getName().equals(methSetName)){
|
||||
|
||||
Class<?>[] params = m.getParameterTypes();
|
||||
if (params.length == 1 && field.getType().equals(params[0])){
|
||||
if (void.class.equals(m.getReturnType())){
|
||||
int modifiers = m.getModifiers();
|
||||
if (Modifier.isPublic(modifiers) && !Modifier.isStatic(modifiers)) {
|
||||
return m;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
private DeployBeanProperty createManyType(DeployBeanDescriptor<?> desc, Class<?> targetType, ManyType manyType) {
|
||||
|
||||
ScalarType<?> scalarType = typeManager.getScalarType(targetType);
|
||||
if (scalarType != null) {
|
||||
return new DeployBeanPropertySimpleCollection(desc, targetType, scalarType, manyType);
|
||||
}
|
||||
//TODO: Handle Collection of CompoundType and Embedded Type
|
||||
return new DeployBeanPropertyAssocMany(desc, targetType, manyType);
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
private DeployBeanProperty createProp(DeployBeanDescriptor<?> desc, Field field) {
|
||||
|
||||
Class<?> propertyType = field.getType();
|
||||
Class<?> innerType = propertyType;
|
||||
ScalarTypeConverter<?, ?> typeConverter = null;
|
||||
|
||||
if (propertyType.equals(scalaOptionClass)){
|
||||
innerType = determineTargetType(field);
|
||||
typeConverter = scalaOptionTypeConverter;
|
||||
}
|
||||
|
||||
// check for Collection type (list, set or map)
|
||||
ManyType manyType = determineManyType.getManyType(propertyType);
|
||||
|
||||
if (manyType != null) {
|
||||
// List, Set or Map based object
|
||||
Class<?> targetType = determineTargetType(field);
|
||||
if (targetType == null){
|
||||
Transient transAnnotation = field.getAnnotation(Transient.class);
|
||||
if (transAnnotation != null) {
|
||||
// not supporting this field (generic type used)
|
||||
return null;
|
||||
}
|
||||
logger.warning("Could not find parameter type (via reflection) on "+desc.getFullName()+" "+field.getName());
|
||||
}
|
||||
return createManyType(desc, targetType, manyType);
|
||||
}
|
||||
|
||||
if (innerType.isEnum() || innerType.isPrimitive()){
|
||||
return new DeployBeanProperty(desc, propertyType, null, typeConverter);
|
||||
}
|
||||
|
||||
ScalarType<?> scalarType = typeManager.getScalarType(innerType);
|
||||
if (scalarType != null) {
|
||||
return new DeployBeanProperty(desc, propertyType, scalarType, typeConverter);
|
||||
}
|
||||
|
||||
CtCompoundType<?> compoundType = typeManager.getCompoundType(innerType);
|
||||
if (compoundType != null) {
|
||||
return new DeployBeanPropertyCompound(desc, propertyType, compoundType, typeConverter);
|
||||
}
|
||||
|
||||
if (!isTransientField(field)){
|
||||
try {
|
||||
CheckImmutableResponse checkImmutable = typeManager.checkImmutable(innerType);
|
||||
if (checkImmutable.isImmutable()){
|
||||
if (checkImmutable.isCompoundType()){
|
||||
// use reflection to support compound immutable value objects
|
||||
typeManager.recursiveCreateScalarDataReader(innerType);
|
||||
compoundType = typeManager.getCompoundType(innerType);
|
||||
if (compoundType != null) {
|
||||
return new DeployBeanPropertyCompound(desc, propertyType, compoundType, typeConverter);
|
||||
}
|
||||
|
||||
} else {
|
||||
// use reflection to support simple immutable value objects
|
||||
scalarType = typeManager.recursiveCreateScalarTypes(innerType);
|
||||
return new DeployBeanProperty(desc, propertyType, scalarType, typeConverter);
|
||||
}
|
||||
}
|
||||
} catch (Exception e){
|
||||
logger.log(Level.SEVERE, "Error with "+desc+" field:"+field.getName(), e);
|
||||
}
|
||||
}
|
||||
|
||||
return new DeployBeanPropertyAssocOne(desc, propertyType);
|
||||
}
|
||||
|
||||
private boolean isTransientField(Field field) {
|
||||
|
||||
Transient t = field.getAnnotation(Transient.class);
|
||||
return (t != null);
|
||||
}
|
||||
|
||||
private DeployBeanProperty createProp(int level, DeployBeanDescriptor<?> desc, Field field, Class<?> beanType, Method getter, Method setter) {
|
||||
|
||||
DeployBeanProperty prop = createProp(desc, field);
|
||||
if (prop == null){
|
||||
// transient annotation on unsupported type
|
||||
return null;
|
||||
} else {
|
||||
prop.setOwningType(beanType);
|
||||
prop.setName(field.getName());
|
||||
|
||||
// the getter or setter could be null if we are using
|
||||
// javaagent type enhancement. If we are using subclass
|
||||
// generation then we do need to find the getter and setter
|
||||
prop.setReadMethod(getter);
|
||||
prop.setWriteMethod(setter);
|
||||
prop.setField(field);
|
||||
return prop;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the type of the List,Set or Map. Not been set explicitly so
|
||||
* determine this from ParameterizedType.
|
||||
*/
|
||||
private Class<?> determineTargetType(Field field) {
|
||||
|
||||
Type genType = field.getGenericType();
|
||||
if (genType instanceof ParameterizedType) {
|
||||
ParameterizedType ptype = (ParameterizedType) genType;
|
||||
|
||||
Type[] typeArgs = ptype.getActualTypeArguments();
|
||||
if (typeArgs.length == 1) {
|
||||
// probably a Set or List
|
||||
if (typeArgs[0] instanceof Class<?>){
|
||||
return (Class<?>) typeArgs[0];
|
||||
}
|
||||
throw new RuntimeException("Unexpected Parameterised Type? "+typeArgs[0]);
|
||||
}
|
||||
if (typeArgs.length == 2) {
|
||||
// this is probably a Map
|
||||
if (typeArgs[1] instanceof ParameterizedType) {
|
||||
// not supporting ParameterizedType on Map.
|
||||
return null;
|
||||
}
|
||||
return (Class<?>) typeArgs[1];
|
||||
}
|
||||
}
|
||||
// if targetType is null, then must be set in annotations
|
||||
return null;
|
||||
}
|
||||
}
|
||||
package com.avaje.ebeaninternal.server.deploy.parse;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Iterator;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
import javax.persistence.Transient;
|
||||
|
||||
import com.avaje.ebean.config.ScalarTypeConverter;
|
||||
import com.avaje.ebeaninternal.server.core.Message;
|
||||
import com.avaje.ebeaninternal.server.deploy.DetermineManyType;
|
||||
import com.avaje.ebeaninternal.server.deploy.ManyType;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanDescriptor;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocMany;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocOne;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyCompound;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertySimpleCollection;
|
||||
import com.avaje.ebeaninternal.server.type.CtCompoundType;
|
||||
import com.avaje.ebeaninternal.server.type.ScalaOptionTypeConverter;
|
||||
import com.avaje.ebeaninternal.server.type.ScalarType;
|
||||
import com.avaje.ebeaninternal.server.type.TypeManager;
|
||||
import com.avaje.ebeaninternal.server.type.reflect.CheckImmutableResponse;
|
||||
|
||||
/**
|
||||
* Create the properties for a bean.
|
||||
* <p>
|
||||
* This also needs to determine if the property is a associated many, associated
|
||||
* one or normal scalar property.
|
||||
* </p>
|
||||
*/
|
||||
public class DeployCreateProperties {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(DeployCreateProperties.class.getName());
|
||||
|
||||
private final Class<?> scalaOptionClass;
|
||||
/**
|
||||
* Use to wrap and unwrap Scala Option.
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
private final ScalarTypeConverter scalaOptionTypeConverter;
|
||||
|
||||
private final DetermineManyType determineManyType;
|
||||
|
||||
private final TypeManager typeManager;
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
public DeployCreateProperties(TypeManager typeManager) {
|
||||
this.typeManager = typeManager;
|
||||
|
||||
Class<?> tmpOptionClass = DetectScala.getScalaOptionClass();
|
||||
|
||||
if (tmpOptionClass == null){
|
||||
scalaOptionClass = null;
|
||||
scalaOptionTypeConverter = null;
|
||||
} else {
|
||||
scalaOptionClass = tmpOptionClass;
|
||||
scalaOptionTypeConverter = new ScalaOptionTypeConverter();
|
||||
}
|
||||
|
||||
this.determineManyType = new DetermineManyType(tmpOptionClass != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the appropriate properties for a bean.
|
||||
*/
|
||||
public void createProperties(DeployBeanDescriptor<?> desc) {
|
||||
|
||||
createProperties(desc, desc.getBeanType(), 0);
|
||||
desc.sortProperties();
|
||||
|
||||
// check the transient properties...
|
||||
Iterator<DeployBeanProperty> it = desc.propertiesAll();
|
||||
|
||||
while (it.hasNext()) {
|
||||
DeployBeanProperty prop = it.next();
|
||||
if (prop.isTransient()){
|
||||
if (prop.getWriteMethod() == null || prop.getReadMethod() == null){
|
||||
// Typically a helper method ... this is expected
|
||||
logger.finest("... transient: "+prop.getFullBeanName());
|
||||
} else {
|
||||
// dubious, possible error...
|
||||
String msg = Message.msg("deploy.property.nofield", desc.getFullName(), prop.getName());
|
||||
logger.warning(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if we should ignore this field.
|
||||
* <p>
|
||||
* We want to ignore ebean internal fields and some others as well.
|
||||
* </p>
|
||||
*/
|
||||
private boolean ignoreFieldByName(String fieldName) {
|
||||
if (fieldName.startsWith("_ebean_")){
|
||||
// ignore Ebean internal fields
|
||||
return true;
|
||||
}
|
||||
if (fieldName.startsWith("ajc$instance$")) {
|
||||
// ignore AspectJ internal fields
|
||||
return true;
|
||||
}
|
||||
|
||||
// we are interested in this field
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* reflect the bean properties from Class. Some of these properties may not
|
||||
* map to database columns.
|
||||
*/
|
||||
private void createProperties(DeployBeanDescriptor<?> desc, Class<?> beanType, int level) {
|
||||
|
||||
boolean scalaObject = desc.isScalaObject();
|
||||
|
||||
try {
|
||||
Method[] declaredMethods = beanType.getDeclaredMethods();
|
||||
Field[] fields = beanType.getDeclaredFields();
|
||||
|
||||
for (int i = 0; i < fields.length; i++) {
|
||||
|
||||
Field field = fields[i];
|
||||
if (Modifier.isStatic(field.getModifiers())) {
|
||||
// not interested in static fields
|
||||
|
||||
} else if (Modifier.isTransient(field.getModifiers())) {
|
||||
// not interested in transient fields
|
||||
logger.finer("Skipping transient field "+field.getName()+" in "+beanType.getName());
|
||||
|
||||
} else if (ignoreFieldByName(field.getName())) {
|
||||
// not interested this field (ebean or aspectJ field)
|
||||
|
||||
} else {
|
||||
|
||||
String fieldName = getFieldName(field, beanType);
|
||||
String initFieldName = initCap(fieldName);
|
||||
|
||||
Method getter = findGetter(field, initFieldName, declaredMethods, scalaObject);
|
||||
Method setter = findSetter(field, initFieldName, declaredMethods, scalaObject);
|
||||
|
||||
DeployBeanProperty prop = createProp(level, desc, field, beanType, getter, setter);
|
||||
if (prop == null){
|
||||
// transient annotation on unsupported type
|
||||
|
||||
} else {
|
||||
// set a order that gives priority to inherited properties
|
||||
// push Id/EmbeddedId up and CreatedTimestamp/UpdatedTimestamp down
|
||||
int sortOverride = prop.getSortOverride();
|
||||
prop.setSortOrder((level*10000+100-i + sortOverride));
|
||||
|
||||
DeployBeanProperty replaced = desc.addBeanProperty(prop);
|
||||
if (replaced != null){
|
||||
if (replaced.isTransient()) {
|
||||
// expected for inheritance...
|
||||
} else {
|
||||
String msg = "Huh??? property "+prop.getFullBeanName()+" being defined twice";
|
||||
msg += " but replaced property was not transient? This is not expected?";
|
||||
logger.warning(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Class<?> superClass = beanType.getSuperclass();
|
||||
|
||||
if (!superClass.equals(Object.class)) {
|
||||
// recursively add any properties in the inheritance heirarchy
|
||||
// up to the Object.class level...
|
||||
createProperties(desc, superClass, level + 1);
|
||||
}
|
||||
|
||||
} catch (PersistenceException ex) {
|
||||
throw ex;
|
||||
|
||||
} catch (Exception ex) {
|
||||
throw new PersistenceException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the first letter of the string upper case.
|
||||
*/
|
||||
private String initCap(String str){
|
||||
if (str.length() > 1){
|
||||
return Character.toUpperCase(str.charAt(0))+str.substring(1);
|
||||
} else {
|
||||
// only a single char
|
||||
return str.toUpperCase();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the bean spec field name (trim of "is" from boolean types)
|
||||
*/
|
||||
private String getFieldName(Field field, Class<?> beanType){
|
||||
|
||||
String name = field.getName();
|
||||
|
||||
if ((Boolean.class.equals(field.getType()) || boolean.class.equals(field.getType()))
|
||||
&& name.startsWith("is") && name.length() > 2){
|
||||
|
||||
// it is a boolean type field starting with "is"
|
||||
char c = name.charAt(2);
|
||||
if (Character.isUpperCase(c)){
|
||||
String msg = "trimming off 'is' from boolean field name "+name+" in class "+beanType.getName();
|
||||
logger.log(Level.INFO, msg);
|
||||
|
||||
return name.substring(2);
|
||||
}
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a public non-static getter method that matches this field (according to bean-spec rules).
|
||||
*/
|
||||
private Method findGetter(Field field, String initFieldName, Method[] declaredMethods, boolean scalaObject){
|
||||
|
||||
String methGetName = "get"+initFieldName;
|
||||
String methIsName = "is"+initFieldName;
|
||||
String scalaGet = field.getName();
|
||||
|
||||
for (int i = 0; i < declaredMethods.length; i++) {
|
||||
Method m = declaredMethods[i];
|
||||
if ((scalaObject && m.getName().equals(scalaGet))
|
||||
|| m.getName().equals(methGetName) || m.getName().equals(methIsName)){
|
||||
|
||||
Class<?>[] params = m.getParameterTypes();
|
||||
if (params.length == 0){
|
||||
if (field.getType().equals(m.getReturnType())){
|
||||
int modifiers = m.getModifiers();
|
||||
if (Modifier.isPublic(modifiers) && !Modifier.isStatic(modifiers)) {
|
||||
// we find it...
|
||||
return m;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a public non-static setter method that matches this field (according to bean-spec rules).
|
||||
*/
|
||||
private Method findSetter(Field field, String initFieldName, Method[] declaredMethods, boolean scalaObject){
|
||||
|
||||
String methSetName = "set"+initFieldName;
|
||||
String scalaSetName = field.getName()+"_$eq";
|
||||
|
||||
for (int i = 0; i < declaredMethods.length; i++) {
|
||||
Method m = declaredMethods[i];
|
||||
|
||||
if ((scalaObject && m.getName().equals(scalaSetName))
|
||||
|| m.getName().equals(methSetName)){
|
||||
|
||||
Class<?>[] params = m.getParameterTypes();
|
||||
if (params.length == 1 && field.getType().equals(params[0])){
|
||||
if (void.class.equals(m.getReturnType())){
|
||||
int modifiers = m.getModifiers();
|
||||
if (Modifier.isPublic(modifiers) && !Modifier.isStatic(modifiers)) {
|
||||
return m;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
private DeployBeanProperty createManyType(DeployBeanDescriptor<?> desc, Class<?> targetType, ManyType manyType) {
|
||||
|
||||
ScalarType<?> scalarType = typeManager.getScalarType(targetType);
|
||||
if (scalarType != null) {
|
||||
return new DeployBeanPropertySimpleCollection(desc, targetType, scalarType, manyType);
|
||||
}
|
||||
//TODO: Handle Collection of CompoundType and Embedded Type
|
||||
return new DeployBeanPropertyAssocMany(desc, targetType, manyType);
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
private DeployBeanProperty createProp(DeployBeanDescriptor<?> desc, Field field) {
|
||||
|
||||
Class<?> propertyType = field.getType();
|
||||
Class<?> innerType = propertyType;
|
||||
ScalarTypeConverter<?, ?> typeConverter = null;
|
||||
|
||||
if (propertyType.equals(scalaOptionClass)){
|
||||
innerType = determineTargetType(field);
|
||||
typeConverter = scalaOptionTypeConverter;
|
||||
}
|
||||
|
||||
// check for Collection type (list, set or map)
|
||||
ManyType manyType = determineManyType.getManyType(propertyType);
|
||||
|
||||
if (manyType != null) {
|
||||
// List, Set or Map based object
|
||||
Class<?> targetType = determineTargetType(field);
|
||||
if (targetType == null){
|
||||
Transient transAnnotation = field.getAnnotation(Transient.class);
|
||||
if (transAnnotation != null) {
|
||||
// not supporting this field (generic type used)
|
||||
return null;
|
||||
}
|
||||
logger.warning("Could not find parameter type (via reflection) on "+desc.getFullName()+" "+field.getName());
|
||||
}
|
||||
return createManyType(desc, targetType, manyType);
|
||||
}
|
||||
|
||||
if (innerType.isEnum() || innerType.isPrimitive()){
|
||||
return new DeployBeanProperty(desc, propertyType, null, typeConverter);
|
||||
}
|
||||
|
||||
ScalarType<?> scalarType = typeManager.getScalarType(innerType);
|
||||
if (scalarType != null) {
|
||||
return new DeployBeanProperty(desc, propertyType, scalarType, typeConverter);
|
||||
}
|
||||
|
||||
CtCompoundType<?> compoundType = typeManager.getCompoundType(innerType);
|
||||
if (compoundType != null) {
|
||||
return new DeployBeanPropertyCompound(desc, propertyType, compoundType, typeConverter);
|
||||
}
|
||||
|
||||
if (!isTransientField(field)){
|
||||
try {
|
||||
CheckImmutableResponse checkImmutable = typeManager.checkImmutable(innerType);
|
||||
if (checkImmutable.isImmutable()){
|
||||
if (checkImmutable.isCompoundType()){
|
||||
// use reflection to support compound immutable value objects
|
||||
typeManager.recursiveCreateScalarDataReader(innerType);
|
||||
compoundType = typeManager.getCompoundType(innerType);
|
||||
if (compoundType != null) {
|
||||
return new DeployBeanPropertyCompound(desc, propertyType, compoundType, typeConverter);
|
||||
}
|
||||
|
||||
} else {
|
||||
// use reflection to support simple immutable value objects
|
||||
scalarType = typeManager.recursiveCreateScalarTypes(innerType);
|
||||
return new DeployBeanProperty(desc, propertyType, scalarType, typeConverter);
|
||||
}
|
||||
}
|
||||
} catch (Exception e){
|
||||
logger.log(Level.SEVERE, "Error with "+desc+" field:"+field.getName(), e);
|
||||
}
|
||||
}
|
||||
|
||||
return new DeployBeanPropertyAssocOne(desc, propertyType);
|
||||
}
|
||||
|
||||
private boolean isTransientField(Field field) {
|
||||
|
||||
Transient t = field.getAnnotation(Transient.class);
|
||||
return (t != null);
|
||||
}
|
||||
|
||||
private DeployBeanProperty createProp(int level, DeployBeanDescriptor<?> desc, Field field, Class<?> beanType, Method getter, Method setter) {
|
||||
|
||||
DeployBeanProperty prop = createProp(desc, field);
|
||||
if (prop == null){
|
||||
// transient annotation on unsupported type
|
||||
return null;
|
||||
} else {
|
||||
prop.setOwningType(beanType);
|
||||
prop.setName(field.getName());
|
||||
|
||||
// the getter or setter could be null if we are using
|
||||
// javaagent type enhancement. If we are using subclass
|
||||
// generation then we do need to find the getter and setter
|
||||
prop.setReadMethod(getter);
|
||||
prop.setWriteMethod(setter);
|
||||
prop.setField(field);
|
||||
return prop;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the type of the List,Set or Map. Not been set explicitly so
|
||||
* determine this from ParameterizedType.
|
||||
*/
|
||||
private Class<?> determineTargetType(Field field) {
|
||||
|
||||
Type genType = field.getGenericType();
|
||||
if (genType instanceof ParameterizedType) {
|
||||
ParameterizedType ptype = (ParameterizedType) genType;
|
||||
|
||||
Type[] typeArgs = ptype.getActualTypeArguments();
|
||||
if (typeArgs.length == 1) {
|
||||
// probably a Set or List
|
||||
if (typeArgs[0] instanceof Class<?>){
|
||||
return (Class<?>) typeArgs[0];
|
||||
}
|
||||
throw new RuntimeException("Unexpected Parameterised Type? "+typeArgs[0]);
|
||||
}
|
||||
if (typeArgs.length == 2) {
|
||||
// this is probably a Map
|
||||
if (typeArgs[1] instanceof ParameterizedType) {
|
||||
// not supporting ParameterizedType on Map.
|
||||
return null;
|
||||
}
|
||||
return (Class<?>) typeArgs[1];
|
||||
}
|
||||
}
|
||||
// if targetType is null, then must be set in annotations
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,196 +1,177 @@
|
||||
/**
|
||||
* Copyright (C) 2006 Robin Bygrave
|
||||
*
|
||||
* This file is part of Ebean.
|
||||
*
|
||||
* Ebean is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Ebean 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package com.avaje.ebeaninternal.server.deploy.parse;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.sql.Types;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.persistence.DiscriminatorColumn;
|
||||
import javax.persistence.DiscriminatorType;
|
||||
import javax.persistence.DiscriminatorValue;
|
||||
import javax.persistence.Inheritance;
|
||||
|
||||
import com.avaje.ebeaninternal.server.core.BootupClasses;
|
||||
import com.avaje.ebeaninternal.server.deploy.InheritInfo;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanDescriptor;
|
||||
|
||||
/**
|
||||
* Builds the InheritInfo deployment information.
|
||||
*/
|
||||
public class DeployInherit {
|
||||
|
||||
private final Map<Class<?>, DeployInheritInfo> deployMap = new LinkedHashMap<Class<?>, DeployInheritInfo>();
|
||||
|
||||
private final Map<Class<?>, InheritInfo> finalMap = new LinkedHashMap<Class<?>, InheritInfo>();
|
||||
|
||||
private final BootupClasses bootupClasses;
|
||||
|
||||
/**
|
||||
* Create the InheritInfoDeploy.
|
||||
*/
|
||||
public DeployInherit(BootupClasses bootupClasses) {
|
||||
this.bootupClasses = bootupClasses;
|
||||
initialise();
|
||||
}
|
||||
|
||||
public void process(DeployBeanDescriptor<?> desc) {
|
||||
InheritInfo inheritInfo = finalMap.get(desc.getBeanType());
|
||||
desc.setInheritInfo(inheritInfo);
|
||||
}
|
||||
|
||||
private void initialise() {
|
||||
List<Class<?>> entityList = bootupClasses.getEntities();
|
||||
|
||||
findInheritClasses(entityList);
|
||||
buildDeployTree();
|
||||
buildFinalTree();
|
||||
}
|
||||
|
||||
private void findInheritClasses(List<Class<?>> entityList) {
|
||||
|
||||
// go through each class and initialise the info object...
|
||||
Iterator<Class<?>> it = entityList.iterator();
|
||||
while (it.hasNext()) {
|
||||
Class<?> cls = (Class<?>) it.next();
|
||||
if (isInheritanceClass(cls)) {
|
||||
DeployInheritInfo info = createInfo(cls);
|
||||
deployMap.put(cls, info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void buildDeployTree() {
|
||||
Iterator<DeployInheritInfo> it = deployMap.values().iterator();
|
||||
while (it.hasNext()) {
|
||||
DeployInheritInfo info = it.next();
|
||||
if (!info.isRoot()) {
|
||||
DeployInheritInfo parent = getInfo(info.getParent());
|
||||
parent.addChild(info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void buildFinalTree() {
|
||||
|
||||
Iterator<DeployInheritInfo> it = deployMap.values().iterator();
|
||||
while (it.hasNext()) {
|
||||
DeployInheritInfo deploy = it.next();
|
||||
if (deploy.isRoot()) {
|
||||
// build tree top down...
|
||||
createFinalInfo(null, null, deploy);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private InheritInfo createFinalInfo(InheritInfo root, InheritInfo parent,
|
||||
DeployInheritInfo deploy) {
|
||||
|
||||
InheritInfo node = new InheritInfo(root, parent, deploy);
|
||||
if (parent != null) {
|
||||
parent.addChild(node);
|
||||
}
|
||||
finalMap.put(node.getType(), node);
|
||||
|
||||
if (root == null) {
|
||||
root = node;
|
||||
}
|
||||
|
||||
// buildFinalChildren(root, child, deploy);
|
||||
|
||||
Iterator<DeployInheritInfo> it = deploy.children();
|
||||
|
||||
while (it.hasNext()) {
|
||||
DeployInheritInfo childDeploy = it.next();
|
||||
|
||||
createFinalInfo(root, node, childDeploy);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the InheritInfo for a given class.
|
||||
*/
|
||||
private DeployInheritInfo getInfo(Class<?> cls) {
|
||||
return deployMap.get(cls);
|
||||
}
|
||||
|
||||
private DeployInheritInfo createInfo(Class<?> cls) {
|
||||
|
||||
DeployInheritInfo info = new DeployInheritInfo(cls);
|
||||
|
||||
Class<?> parent = findParent(cls);
|
||||
if (parent != null) {
|
||||
info.setParent(parent);
|
||||
} else {
|
||||
// its the root of inheritance tree...
|
||||
}
|
||||
|
||||
Inheritance ia = (Inheritance) cls.getAnnotation(Inheritance.class);
|
||||
if (ia != null) {
|
||||
ia.strategy();
|
||||
}
|
||||
DiscriminatorColumn da = (DiscriminatorColumn) cls.getAnnotation(DiscriminatorColumn.class);
|
||||
if (da != null) {
|
||||
info.setDiscriminatorColumn(da.name());
|
||||
DiscriminatorType discriminatorType = da.discriminatorType();
|
||||
if (discriminatorType.equals(DiscriminatorType.INTEGER)){
|
||||
info.setDiscriminatorType(Types.INTEGER);
|
||||
} else {
|
||||
info.setDiscriminatorType(Types.VARCHAR);
|
||||
}
|
||||
info.setDiscriminatorLength(da.length());
|
||||
}
|
||||
|
||||
DiscriminatorValue dv = (DiscriminatorValue) cls.getAnnotation(DiscriminatorValue.class);
|
||||
if (dv != null) {
|
||||
info.setDiscriminatorValue(dv.value());
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
private Class<?> findParent(Class<?> cls) {
|
||||
Class<?> superCls = cls.getSuperclass();
|
||||
if (isInheritanceClass(superCls)) {
|
||||
return superCls;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isInheritanceClass(Class<?> cls) {
|
||||
if (cls.equals(Object.class)) {
|
||||
return false;
|
||||
}
|
||||
Annotation a = cls.getAnnotation(Inheritance.class);
|
||||
if (a != null) {
|
||||
return true;
|
||||
}
|
||||
// search up the inheritance heirarchy
|
||||
return isInheritanceClass(cls.getSuperclass());
|
||||
}
|
||||
|
||||
}
|
||||
package com.avaje.ebeaninternal.server.deploy.parse;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.sql.Types;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.persistence.DiscriminatorColumn;
|
||||
import javax.persistence.DiscriminatorType;
|
||||
import javax.persistence.DiscriminatorValue;
|
||||
import javax.persistence.Inheritance;
|
||||
|
||||
import com.avaje.ebeaninternal.server.core.BootupClasses;
|
||||
import com.avaje.ebeaninternal.server.deploy.InheritInfo;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanDescriptor;
|
||||
|
||||
/**
|
||||
* Builds the InheritInfo deployment information.
|
||||
*/
|
||||
public class DeployInherit {
|
||||
|
||||
private final Map<Class<?>, DeployInheritInfo> deployMap = new LinkedHashMap<Class<?>, DeployInheritInfo>();
|
||||
|
||||
private final Map<Class<?>, InheritInfo> finalMap = new LinkedHashMap<Class<?>, InheritInfo>();
|
||||
|
||||
private final BootupClasses bootupClasses;
|
||||
|
||||
/**
|
||||
* Create the InheritInfoDeploy.
|
||||
*/
|
||||
public DeployInherit(BootupClasses bootupClasses) {
|
||||
this.bootupClasses = bootupClasses;
|
||||
initialise();
|
||||
}
|
||||
|
||||
public void process(DeployBeanDescriptor<?> desc) {
|
||||
InheritInfo inheritInfo = finalMap.get(desc.getBeanType());
|
||||
desc.setInheritInfo(inheritInfo);
|
||||
}
|
||||
|
||||
private void initialise() {
|
||||
List<Class<?>> entityList = bootupClasses.getEntities();
|
||||
|
||||
findInheritClasses(entityList);
|
||||
buildDeployTree();
|
||||
buildFinalTree();
|
||||
}
|
||||
|
||||
private void findInheritClasses(List<Class<?>> entityList) {
|
||||
|
||||
// go through each class and initialise the info object...
|
||||
Iterator<Class<?>> it = entityList.iterator();
|
||||
while (it.hasNext()) {
|
||||
Class<?> cls = (Class<?>) it.next();
|
||||
if (isInheritanceClass(cls)) {
|
||||
DeployInheritInfo info = createInfo(cls);
|
||||
deployMap.put(cls, info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void buildDeployTree() {
|
||||
Iterator<DeployInheritInfo> it = deployMap.values().iterator();
|
||||
while (it.hasNext()) {
|
||||
DeployInheritInfo info = it.next();
|
||||
if (!info.isRoot()) {
|
||||
DeployInheritInfo parent = getInfo(info.getParent());
|
||||
parent.addChild(info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void buildFinalTree() {
|
||||
|
||||
Iterator<DeployInheritInfo> it = deployMap.values().iterator();
|
||||
while (it.hasNext()) {
|
||||
DeployInheritInfo deploy = it.next();
|
||||
if (deploy.isRoot()) {
|
||||
// build tree top down...
|
||||
createFinalInfo(null, null, deploy);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private InheritInfo createFinalInfo(InheritInfo root, InheritInfo parent,
|
||||
DeployInheritInfo deploy) {
|
||||
|
||||
InheritInfo node = new InheritInfo(root, parent, deploy);
|
||||
if (parent != null) {
|
||||
parent.addChild(node);
|
||||
}
|
||||
finalMap.put(node.getType(), node);
|
||||
|
||||
if (root == null) {
|
||||
root = node;
|
||||
}
|
||||
|
||||
// buildFinalChildren(root, child, deploy);
|
||||
|
||||
Iterator<DeployInheritInfo> it = deploy.children();
|
||||
|
||||
while (it.hasNext()) {
|
||||
DeployInheritInfo childDeploy = it.next();
|
||||
|
||||
createFinalInfo(root, node, childDeploy);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the InheritInfo for a given class.
|
||||
*/
|
||||
private DeployInheritInfo getInfo(Class<?> cls) {
|
||||
return deployMap.get(cls);
|
||||
}
|
||||
|
||||
private DeployInheritInfo createInfo(Class<?> cls) {
|
||||
|
||||
DeployInheritInfo info = new DeployInheritInfo(cls);
|
||||
|
||||
Class<?> parent = findParent(cls);
|
||||
if (parent != null) {
|
||||
info.setParent(parent);
|
||||
} else {
|
||||
// its the root of inheritance tree...
|
||||
}
|
||||
|
||||
Inheritance ia = (Inheritance) cls.getAnnotation(Inheritance.class);
|
||||
if (ia != null) {
|
||||
ia.strategy();
|
||||
}
|
||||
DiscriminatorColumn da = (DiscriminatorColumn) cls.getAnnotation(DiscriminatorColumn.class);
|
||||
if (da != null) {
|
||||
info.setDiscriminatorColumn(da.name());
|
||||
DiscriminatorType discriminatorType = da.discriminatorType();
|
||||
if (discriminatorType.equals(DiscriminatorType.INTEGER)){
|
||||
info.setDiscriminatorType(Types.INTEGER);
|
||||
} else {
|
||||
info.setDiscriminatorType(Types.VARCHAR);
|
||||
}
|
||||
info.setDiscriminatorLength(da.length());
|
||||
}
|
||||
|
||||
DiscriminatorValue dv = (DiscriminatorValue) cls.getAnnotation(DiscriminatorValue.class);
|
||||
if (dv != null) {
|
||||
info.setDiscriminatorValue(dv.value());
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
private Class<?> findParent(Class<?> cls) {
|
||||
Class<?> superCls = cls.getSuperclass();
|
||||
if (isInheritanceClass(superCls)) {
|
||||
return superCls;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isInheritanceClass(Class<?> cls) {
|
||||
if (cls.equals(Object.class)) {
|
||||
return false;
|
||||
}
|
||||
Annotation a = cls.getAnnotation(Inheritance.class);
|
||||
if (a != null) {
|
||||
return true;
|
||||
}
|
||||
// search up the inheritance heirarchy
|
||||
return isInheritanceClass(cls.getSuperclass());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+264
-283
@@ -1,283 +1,264 @@
|
||||
/**
|
||||
* Copyright (C) 2006 Robin Bygrave
|
||||
*
|
||||
* This file is part of Ebean.
|
||||
*
|
||||
* Ebean is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Ebean 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package com.avaje.ebeaninternal.server.deploy.parse;
|
||||
|
||||
import java.sql.Types;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import com.avaje.ebeaninternal.server.deploy.InheritInfo;
|
||||
|
||||
/**
|
||||
* Represents a node in the Inheritance tree.
|
||||
* Holds information regarding Super Subclass support.
|
||||
*/
|
||||
public class DeployInheritInfo {
|
||||
|
||||
/**
|
||||
* the default discriminator column according to the JPA 1.0 spec.
|
||||
*/
|
||||
private static final String JPA_DEFAULT_DISCRIM_COLUMN = "dtype";
|
||||
|
||||
private int discriminatorLength;
|
||||
|
||||
private int discriminatorType;
|
||||
|
||||
private String discriminatorStringValue;
|
||||
private Object discriminatorObjectValue;
|
||||
|
||||
private String discriminatorColumn;
|
||||
|
||||
private String discriminatorWhere;
|
||||
|
||||
private Class<?> type;
|
||||
|
||||
private Class<?> parent;
|
||||
|
||||
private ArrayList<DeployInheritInfo> children = new ArrayList<DeployInheritInfo>();
|
||||
|
||||
/**
|
||||
* Create for a given type.
|
||||
*/
|
||||
public DeployInheritInfo(Class<?> type){
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* return the type.
|
||||
*/
|
||||
public Class<?> getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the type of the root object.
|
||||
*/
|
||||
public Class<?> getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the type of the root object.
|
||||
*/
|
||||
public void setParent(Class<?> parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this is abstract node.
|
||||
*/
|
||||
public boolean isAbstract() {
|
||||
return (discriminatorObjectValue == null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this is the root node.
|
||||
*/
|
||||
public boolean isRoot(){
|
||||
return parent == null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the child nodes.
|
||||
*/
|
||||
public Iterator<DeployInheritInfo> children() {
|
||||
return children.iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a child node.
|
||||
*/
|
||||
public void addChild(DeployInheritInfo childInfo){
|
||||
children.add(childInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the derived where for the discriminator.
|
||||
*/
|
||||
public String getDiscriminatorWhere() {
|
||||
return discriminatorWhere;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the derived where for the discriminator.
|
||||
*/
|
||||
public void setDiscriminatorWhere(String discriminatorWhere) {
|
||||
this.discriminatorWhere = discriminatorWhere;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the column name of the discriminator.
|
||||
*/
|
||||
public String getDiscriminatorColumn(InheritInfo parent) {
|
||||
if (discriminatorColumn == null){
|
||||
if (parent == null){
|
||||
discriminatorColumn = JPA_DEFAULT_DISCRIM_COLUMN;
|
||||
} else {
|
||||
discriminatorColumn = parent.getDiscriminatorColumn();
|
||||
}
|
||||
}
|
||||
return discriminatorColumn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the column name of the discriminator.
|
||||
*/
|
||||
public void setDiscriminatorColumn(String discriminatorColumn) {
|
||||
this.discriminatorColumn = discriminatorColumn;
|
||||
}
|
||||
|
||||
public int getDiscriminatorLength(InheritInfo parent) {
|
||||
if (discriminatorLength == 0){
|
||||
if (parent == null){
|
||||
discriminatorLength = 10;
|
||||
} else {
|
||||
discriminatorLength = parent.getDiscriminatorLength();
|
||||
}
|
||||
}
|
||||
return discriminatorLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the sql type of the discriminator value.
|
||||
*/
|
||||
public int getDiscriminatorType(InheritInfo parent) {
|
||||
if (discriminatorType == 0){
|
||||
if (parent == null){
|
||||
discriminatorType = Types.VARCHAR;
|
||||
} else {
|
||||
discriminatorType = parent.getDiscriminatorType();
|
||||
}
|
||||
}
|
||||
return discriminatorType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the sql type of the discriminator.
|
||||
*/
|
||||
public void setDiscriminatorType(int discriminatorType) {
|
||||
this.discriminatorType = discriminatorType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the length of the discriminator column.
|
||||
*/
|
||||
public int getDiscriminatorLength() {
|
||||
return discriminatorLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the length of the discriminator column.
|
||||
*/
|
||||
public void setDiscriminatorLength(int discriminatorLength) {
|
||||
this.discriminatorLength = discriminatorLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the discriminator value for this node.
|
||||
*/
|
||||
public Object getDiscriminatorObjectValue() {
|
||||
return discriminatorObjectValue;
|
||||
}
|
||||
|
||||
public String getDiscriminatorStringValue() {
|
||||
return discriminatorStringValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the discriminator value for this node.
|
||||
*/
|
||||
public void setDiscriminatorValue(String value) {
|
||||
if (value != null){
|
||||
value = value.trim();
|
||||
if (value.length() == 0){
|
||||
value = null;
|
||||
} else {
|
||||
discriminatorStringValue = value;
|
||||
// convert the value if desired
|
||||
if (discriminatorType == Types.INTEGER){
|
||||
this.discriminatorObjectValue = Integer.valueOf(value.toString());
|
||||
} else {
|
||||
this.discriminatorObjectValue = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String getWhere() {
|
||||
|
||||
List<Object> discList = new ArrayList<Object>();
|
||||
|
||||
appendDiscriminator(discList);
|
||||
|
||||
return buildWhereLiteral(discList);
|
||||
}
|
||||
|
||||
private void appendDiscriminator(List<Object> list) {
|
||||
if (discriminatorObjectValue != null){
|
||||
list.add(discriminatorObjectValue);
|
||||
}
|
||||
for (DeployInheritInfo child : children) {
|
||||
child.appendDiscriminator(list);
|
||||
}
|
||||
}
|
||||
|
||||
private String buildWhereLiteral(List<Object> discList) {
|
||||
int size = discList.size();
|
||||
if (size == 0){
|
||||
return "";
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(discriminatorColumn);
|
||||
if (size == 1){
|
||||
sb.append(" = ");
|
||||
} else {
|
||||
sb.append(" in (");
|
||||
}
|
||||
for (int i = 0; i < discList.size(); i++) {
|
||||
appendSqlLiteralValue(i, discList.get(i), sb);
|
||||
}
|
||||
if (size > 1){
|
||||
sb.append(")");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private void appendSqlLiteralValue(int count, Object value, StringBuilder sb) {
|
||||
if (count > 0){
|
||||
sb.append(",");
|
||||
}
|
||||
if (value instanceof String){
|
||||
sb.append("'").append(value).append("'");
|
||||
} else {
|
||||
sb.append(value);
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("InheritInfo[").append(type.getName()).append("]");
|
||||
sb.append(" root[").append(parent.getName()).append("]");
|
||||
sb.append(" disValue[").append(discriminatorStringValue).append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
||||
package com.avaje.ebeaninternal.server.deploy.parse;
|
||||
|
||||
import java.sql.Types;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import com.avaje.ebeaninternal.server.deploy.InheritInfo;
|
||||
|
||||
/**
|
||||
* Represents a node in the Inheritance tree.
|
||||
* Holds information regarding Super Subclass support.
|
||||
*/
|
||||
public class DeployInheritInfo {
|
||||
|
||||
/**
|
||||
* the default discriminator column according to the JPA 1.0 spec.
|
||||
*/
|
||||
private static final String JPA_DEFAULT_DISCRIM_COLUMN = "dtype";
|
||||
|
||||
private int discriminatorLength;
|
||||
|
||||
private int discriminatorType;
|
||||
|
||||
private String discriminatorStringValue;
|
||||
private Object discriminatorObjectValue;
|
||||
|
||||
private String discriminatorColumn;
|
||||
|
||||
private String discriminatorWhere;
|
||||
|
||||
private Class<?> type;
|
||||
|
||||
private Class<?> parent;
|
||||
|
||||
private ArrayList<DeployInheritInfo> children = new ArrayList<DeployInheritInfo>();
|
||||
|
||||
/**
|
||||
* Create for a given type.
|
||||
*/
|
||||
public DeployInheritInfo(Class<?> type){
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* return the type.
|
||||
*/
|
||||
public Class<?> getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the type of the root object.
|
||||
*/
|
||||
public Class<?> getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the type of the root object.
|
||||
*/
|
||||
public void setParent(Class<?> parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this is abstract node.
|
||||
*/
|
||||
public boolean isAbstract() {
|
||||
return (discriminatorObjectValue == null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this is the root node.
|
||||
*/
|
||||
public boolean isRoot(){
|
||||
return parent == null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the child nodes.
|
||||
*/
|
||||
public Iterator<DeployInheritInfo> children() {
|
||||
return children.iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a child node.
|
||||
*/
|
||||
public void addChild(DeployInheritInfo childInfo){
|
||||
children.add(childInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the derived where for the discriminator.
|
||||
*/
|
||||
public String getDiscriminatorWhere() {
|
||||
return discriminatorWhere;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the derived where for the discriminator.
|
||||
*/
|
||||
public void setDiscriminatorWhere(String discriminatorWhere) {
|
||||
this.discriminatorWhere = discriminatorWhere;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the column name of the discriminator.
|
||||
*/
|
||||
public String getDiscriminatorColumn(InheritInfo parent) {
|
||||
if (discriminatorColumn == null){
|
||||
if (parent == null){
|
||||
discriminatorColumn = JPA_DEFAULT_DISCRIM_COLUMN;
|
||||
} else {
|
||||
discriminatorColumn = parent.getDiscriminatorColumn();
|
||||
}
|
||||
}
|
||||
return discriminatorColumn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the column name of the discriminator.
|
||||
*/
|
||||
public void setDiscriminatorColumn(String discriminatorColumn) {
|
||||
this.discriminatorColumn = discriminatorColumn;
|
||||
}
|
||||
|
||||
public int getDiscriminatorLength(InheritInfo parent) {
|
||||
if (discriminatorLength == 0){
|
||||
if (parent == null){
|
||||
discriminatorLength = 10;
|
||||
} else {
|
||||
discriminatorLength = parent.getDiscriminatorLength();
|
||||
}
|
||||
}
|
||||
return discriminatorLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the sql type of the discriminator value.
|
||||
*/
|
||||
public int getDiscriminatorType(InheritInfo parent) {
|
||||
if (discriminatorType == 0){
|
||||
if (parent == null){
|
||||
discriminatorType = Types.VARCHAR;
|
||||
} else {
|
||||
discriminatorType = parent.getDiscriminatorType();
|
||||
}
|
||||
}
|
||||
return discriminatorType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the sql type of the discriminator.
|
||||
*/
|
||||
public void setDiscriminatorType(int discriminatorType) {
|
||||
this.discriminatorType = discriminatorType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the length of the discriminator column.
|
||||
*/
|
||||
public int getDiscriminatorLength() {
|
||||
return discriminatorLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the length of the discriminator column.
|
||||
*/
|
||||
public void setDiscriminatorLength(int discriminatorLength) {
|
||||
this.discriminatorLength = discriminatorLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the discriminator value for this node.
|
||||
*/
|
||||
public Object getDiscriminatorObjectValue() {
|
||||
return discriminatorObjectValue;
|
||||
}
|
||||
|
||||
public String getDiscriminatorStringValue() {
|
||||
return discriminatorStringValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the discriminator value for this node.
|
||||
*/
|
||||
public void setDiscriminatorValue(String value) {
|
||||
if (value != null){
|
||||
value = value.trim();
|
||||
if (value.length() == 0){
|
||||
value = null;
|
||||
} else {
|
||||
discriminatorStringValue = value;
|
||||
// convert the value if desired
|
||||
if (discriminatorType == Types.INTEGER){
|
||||
this.discriminatorObjectValue = Integer.valueOf(value.toString());
|
||||
} else {
|
||||
this.discriminatorObjectValue = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String getWhere() {
|
||||
|
||||
List<Object> discList = new ArrayList<Object>();
|
||||
|
||||
appendDiscriminator(discList);
|
||||
|
||||
return buildWhereLiteral(discList);
|
||||
}
|
||||
|
||||
private void appendDiscriminator(List<Object> list) {
|
||||
if (discriminatorObjectValue != null){
|
||||
list.add(discriminatorObjectValue);
|
||||
}
|
||||
for (DeployInheritInfo child : children) {
|
||||
child.appendDiscriminator(list);
|
||||
}
|
||||
}
|
||||
|
||||
private String buildWhereLiteral(List<Object> discList) {
|
||||
int size = discList.size();
|
||||
if (size == 0){
|
||||
return "";
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(discriminatorColumn);
|
||||
if (size == 1){
|
||||
sb.append(" = ");
|
||||
} else {
|
||||
sb.append(" in (");
|
||||
}
|
||||
for (int i = 0; i < discList.size(); i++) {
|
||||
appendSqlLiteralValue(i, discList.get(i), sb);
|
||||
}
|
||||
if (size > 1){
|
||||
sb.append(")");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private void appendSqlLiteralValue(int count, Object value, StringBuilder sb) {
|
||||
if (count > 0){
|
||||
sb.append(",");
|
||||
}
|
||||
if (value instanceof String){
|
||||
sb.append("'").append(value).append("'");
|
||||
} else {
|
||||
sb.append(value);
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("InheritInfo[").append(type.getName()).append("]");
|
||||
sb.append(" root[").append(parent.getName()).append("]");
|
||||
sb.append(" disValue[").append(discriminatorStringValue).append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,266 +1,247 @@
|
||||
/**
|
||||
* Copyright (C) 2006 Robin Bygrave
|
||||
*
|
||||
* This file is part of Ebean.
|
||||
*
|
||||
* Ebean is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Ebean 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package com.avaje.ebeaninternal.server.deploy.parse;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.sql.Types;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.persistence.EnumType;
|
||||
import javax.persistence.Enumerated;
|
||||
import javax.persistence.PersistenceException;
|
||||
|
||||
import com.avaje.ebean.config.EncryptDeploy;
|
||||
import com.avaje.ebean.config.EncryptDeployManager;
|
||||
import com.avaje.ebean.config.EncryptKeyManager;
|
||||
import com.avaje.ebean.config.Encryptor;
|
||||
import com.avaje.ebean.config.NamingConvention;
|
||||
import com.avaje.ebean.config.ServerConfig;
|
||||
import com.avaje.ebean.config.TableName;
|
||||
import com.avaje.ebean.config.dbplatform.DatabasePlatform;
|
||||
import com.avaje.ebean.validation.factory.Validator;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyCompound;
|
||||
import com.avaje.ebeaninternal.server.type.DataEncryptSupport;
|
||||
import com.avaje.ebeaninternal.server.type.ScalarType;
|
||||
import com.avaje.ebeaninternal.server.type.ScalarTypeEnumStandard;
|
||||
import com.avaje.ebeaninternal.server.type.SimpleAesEncryptor;
|
||||
import com.avaje.ebeaninternal.server.type.TypeManager;
|
||||
|
||||
/**
|
||||
* Utility object to help processing deployment information.
|
||||
*/
|
||||
public class DeployUtil {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(DeployUtil.class.getName());
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Assumes CLOB rather than LONGVARCHAR.
|
||||
*/
|
||||
private static final int dbCLOBType = Types.CLOB;
|
||||
|
||||
/**
|
||||
* Assumes BLOB rather than LONGVARBINARY. This should probably be
|
||||
* configurable.
|
||||
*/
|
||||
private static final int dbBLOBType = Types.BLOB;
|
||||
|
||||
private final NamingConvention namingConvention;
|
||||
|
||||
private final TypeManager typeManager;
|
||||
|
||||
private final ValidatorFactoryManager validatorFactoryManager;
|
||||
|
||||
private final String manyToManyAlias;
|
||||
|
||||
private final DatabasePlatform dbPlatform;
|
||||
|
||||
private final EncryptDeployManager encryptDeployManager;
|
||||
|
||||
private final EncryptKeyManager encryptKeyManager;
|
||||
|
||||
private final Encryptor bytesEncryptor;
|
||||
|
||||
public DeployUtil(TypeManager typeMgr, ServerConfig serverConfig) {
|
||||
|
||||
this.typeManager = typeMgr;
|
||||
this.namingConvention = serverConfig.getNamingConvention();
|
||||
this.dbPlatform = serverConfig.getDatabasePlatform();
|
||||
this.encryptDeployManager = serverConfig.getEncryptDeployManager();
|
||||
this.encryptKeyManager = serverConfig.getEncryptKeyManager();
|
||||
|
||||
Encryptor be = serverConfig.getEncryptor();
|
||||
this.bytesEncryptor = be != null ? be : new SimpleAesEncryptor();
|
||||
|
||||
// this alias is used for ManyToMany lazy loading queries
|
||||
this.manyToManyAlias = "zzzzzz";
|
||||
|
||||
this.validatorFactoryManager = new ValidatorFactoryManager();
|
||||
}
|
||||
|
||||
public TypeManager getTypeManager() {
|
||||
return typeManager;
|
||||
}
|
||||
|
||||
public DatabasePlatform getDbPlatform() {
|
||||
return dbPlatform;
|
||||
}
|
||||
|
||||
public NamingConvention getNamingConvention() {
|
||||
return namingConvention;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the EncryptKeyManager has been defined.
|
||||
*/
|
||||
public void checkEncryptKeyManagerDefined(String fullPropName) {
|
||||
if (encryptKeyManager == null){
|
||||
String msg = "Using encryption on "+fullPropName+" but no EncryptKeyManager defined!";
|
||||
throw new PersistenceException(msg);
|
||||
}
|
||||
}
|
||||
|
||||
public EncryptDeploy getEncryptDeploy(TableName table, String column) {
|
||||
if (encryptDeployManager == null){
|
||||
return EncryptDeploy.ANNOTATION;
|
||||
}
|
||||
return encryptDeployManager.getEncryptDeploy(table, column);
|
||||
}
|
||||
|
||||
public DataEncryptSupport createDataEncryptSupport(String table, String column) {
|
||||
return new DataEncryptSupport(encryptKeyManager, bytesEncryptor, table, column);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the table alias used for ManyToMany joins.
|
||||
*/
|
||||
public String getManyToManyAlias() {
|
||||
return manyToManyAlias;
|
||||
}
|
||||
|
||||
public void createValidator(DeployBeanProperty prop, Annotation ann) {
|
||||
try {
|
||||
Validator validator = validatorFactoryManager.create(ann, prop.getPropertyType());
|
||||
if (validator != null){
|
||||
prop.addValidator(validator);
|
||||
}
|
||||
} catch (Exception e){
|
||||
String msg = "Error creating a validator on "+prop.getFullBeanName();
|
||||
logger.log(Level.SEVERE, msg, e);
|
||||
}
|
||||
}
|
||||
|
||||
public ScalarType<?> setEnumScalarType(Enumerated enumerated, DeployBeanProperty prop) {
|
||||
|
||||
Class<?> enumType = prop.getPropertyType();
|
||||
if (!enumType.isEnum()) {
|
||||
throw new IllegalArgumentException("Class ["+enumType+"] is Not a Enum?");
|
||||
}
|
||||
ScalarType<?> scalarType = typeManager.getScalarType(enumType);
|
||||
if (scalarType == null) {
|
||||
// see if it has a Mapping in avaje.properties
|
||||
scalarType = typeManager.createEnumScalarType(enumType);
|
||||
if (scalarType == null){
|
||||
// use JPA normal Enum type (without mapping)
|
||||
EnumType type = enumerated != null? enumerated.value(): null;
|
||||
scalarType = createEnumScalarTypePerSpec(enumType, type, prop.getDbType());
|
||||
}
|
||||
|
||||
typeManager.add(scalarType);
|
||||
}
|
||||
prop.setScalarType(scalarType);
|
||||
prop.setDbType(scalarType.getJdbcType());
|
||||
return scalarType;
|
||||
}
|
||||
|
||||
private ScalarType<?> createEnumScalarTypePerSpec(Class<?> enumType, EnumType type, int dbType) {
|
||||
|
||||
if (type == null) {
|
||||
// default as per spec is ORDINAL
|
||||
return new ScalarTypeEnumStandard.OrdinalEnum(enumType);
|
||||
|
||||
} else if (type == EnumType.ORDINAL) {
|
||||
return new ScalarTypeEnumStandard.OrdinalEnum(enumType);
|
||||
|
||||
} else {
|
||||
return new ScalarTypeEnumStandard.StringEnum(enumType);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the ScalarType for this property.
|
||||
* <p>
|
||||
* This determines if there is a conversion required from the logical (bean)
|
||||
* type to a DB (jdbc) type. This is the case for java.util.Date etc.
|
||||
* </p>
|
||||
*/
|
||||
public void setScalarType(DeployBeanProperty property) {
|
||||
|
||||
if (property.getScalarType() != null){
|
||||
// already has a ScalarType assigned.
|
||||
// this will be an Enum type...
|
||||
return;
|
||||
}
|
||||
if (property instanceof DeployBeanPropertyCompound){
|
||||
// compound properties have a CvoInternalType instead
|
||||
return;
|
||||
}
|
||||
|
||||
ScalarType<?> scalarType = getScalarType(property);
|
||||
if (scalarType != null){
|
||||
// set the jdbc type this maps to
|
||||
|
||||
property.setDbType(scalarType.getJdbcType());
|
||||
property.setScalarType(scalarType);
|
||||
}
|
||||
}
|
||||
|
||||
private ScalarType<?> getScalarType(DeployBeanProperty property) {
|
||||
|
||||
// Note that Temporal types already have dbType
|
||||
// set via annotations
|
||||
Class<?> propType = property.getPropertyType();
|
||||
ScalarType<?> scalarType = typeManager.getScalarType(propType, property.getDbType());
|
||||
if (scalarType != null) {
|
||||
return scalarType;
|
||||
}
|
||||
|
||||
String msg = property.getFullBeanName()+" has no ScalarType - type[" + propType.getName() + "]";
|
||||
if (!property.isTransient()){
|
||||
throw new PersistenceException(msg);
|
||||
|
||||
} else {
|
||||
// this is ok...
|
||||
logger.finest("... transient property "+msg);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This property is marked as a Lob object.
|
||||
*/
|
||||
public void setLobType(DeployBeanProperty prop) {
|
||||
|
||||
// is String or byte[] ? used to determine if its a CLOB or BLOB
|
||||
Class<?> type = prop.getPropertyType();
|
||||
|
||||
// this also sets the lob flag on DeployBeanProperty
|
||||
int lobType = isClobType(type) ? dbCLOBType : dbBLOBType;
|
||||
|
||||
ScalarType<?> scalarType = typeManager.getScalarType(type, lobType);
|
||||
if (scalarType == null) {
|
||||
// this should never occur actually
|
||||
throw new RuntimeException("No ScalarType for LOB type ["+type+"] ["+lobType+"]");
|
||||
}
|
||||
prop.setDbType(lobType);
|
||||
prop.setScalarType(scalarType);
|
||||
}
|
||||
|
||||
public boolean isClobType(Class<?> type){
|
||||
if (type.equals(String.class)){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
package com.avaje.ebeaninternal.server.deploy.parse;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.sql.Types;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.persistence.EnumType;
|
||||
import javax.persistence.Enumerated;
|
||||
import javax.persistence.PersistenceException;
|
||||
|
||||
import com.avaje.ebean.config.EncryptDeploy;
|
||||
import com.avaje.ebean.config.EncryptDeployManager;
|
||||
import com.avaje.ebean.config.EncryptKeyManager;
|
||||
import com.avaje.ebean.config.Encryptor;
|
||||
import com.avaje.ebean.config.NamingConvention;
|
||||
import com.avaje.ebean.config.ServerConfig;
|
||||
import com.avaje.ebean.config.TableName;
|
||||
import com.avaje.ebean.config.dbplatform.DatabasePlatform;
|
||||
import com.avaje.ebean.validation.factory.Validator;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyCompound;
|
||||
import com.avaje.ebeaninternal.server.type.DataEncryptSupport;
|
||||
import com.avaje.ebeaninternal.server.type.ScalarType;
|
||||
import com.avaje.ebeaninternal.server.type.ScalarTypeEnumStandard;
|
||||
import com.avaje.ebeaninternal.server.type.SimpleAesEncryptor;
|
||||
import com.avaje.ebeaninternal.server.type.TypeManager;
|
||||
|
||||
/**
|
||||
* Utility object to help processing deployment information.
|
||||
*/
|
||||
public class DeployUtil {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(DeployUtil.class.getName());
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Assumes CLOB rather than LONGVARCHAR.
|
||||
*/
|
||||
private static final int dbCLOBType = Types.CLOB;
|
||||
|
||||
/**
|
||||
* Assumes BLOB rather than LONGVARBINARY. This should probably be
|
||||
* configurable.
|
||||
*/
|
||||
private static final int dbBLOBType = Types.BLOB;
|
||||
|
||||
private final NamingConvention namingConvention;
|
||||
|
||||
private final TypeManager typeManager;
|
||||
|
||||
private final ValidatorFactoryManager validatorFactoryManager;
|
||||
|
||||
private final String manyToManyAlias;
|
||||
|
||||
private final DatabasePlatform dbPlatform;
|
||||
|
||||
private final EncryptDeployManager encryptDeployManager;
|
||||
|
||||
private final EncryptKeyManager encryptKeyManager;
|
||||
|
||||
private final Encryptor bytesEncryptor;
|
||||
|
||||
public DeployUtil(TypeManager typeMgr, ServerConfig serverConfig) {
|
||||
|
||||
this.typeManager = typeMgr;
|
||||
this.namingConvention = serverConfig.getNamingConvention();
|
||||
this.dbPlatform = serverConfig.getDatabasePlatform();
|
||||
this.encryptDeployManager = serverConfig.getEncryptDeployManager();
|
||||
this.encryptKeyManager = serverConfig.getEncryptKeyManager();
|
||||
|
||||
Encryptor be = serverConfig.getEncryptor();
|
||||
this.bytesEncryptor = be != null ? be : new SimpleAesEncryptor();
|
||||
|
||||
// this alias is used for ManyToMany lazy loading queries
|
||||
this.manyToManyAlias = "zzzzzz";
|
||||
|
||||
this.validatorFactoryManager = new ValidatorFactoryManager();
|
||||
}
|
||||
|
||||
public TypeManager getTypeManager() {
|
||||
return typeManager;
|
||||
}
|
||||
|
||||
public DatabasePlatform getDbPlatform() {
|
||||
return dbPlatform;
|
||||
}
|
||||
|
||||
public NamingConvention getNamingConvention() {
|
||||
return namingConvention;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the EncryptKeyManager has been defined.
|
||||
*/
|
||||
public void checkEncryptKeyManagerDefined(String fullPropName) {
|
||||
if (encryptKeyManager == null){
|
||||
String msg = "Using encryption on "+fullPropName+" but no EncryptKeyManager defined!";
|
||||
throw new PersistenceException(msg);
|
||||
}
|
||||
}
|
||||
|
||||
public EncryptDeploy getEncryptDeploy(TableName table, String column) {
|
||||
if (encryptDeployManager == null){
|
||||
return EncryptDeploy.ANNOTATION;
|
||||
}
|
||||
return encryptDeployManager.getEncryptDeploy(table, column);
|
||||
}
|
||||
|
||||
public DataEncryptSupport createDataEncryptSupport(String table, String column) {
|
||||
return new DataEncryptSupport(encryptKeyManager, bytesEncryptor, table, column);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the table alias used for ManyToMany joins.
|
||||
*/
|
||||
public String getManyToManyAlias() {
|
||||
return manyToManyAlias;
|
||||
}
|
||||
|
||||
public void createValidator(DeployBeanProperty prop, Annotation ann) {
|
||||
try {
|
||||
Validator validator = validatorFactoryManager.create(ann, prop.getPropertyType());
|
||||
if (validator != null){
|
||||
prop.addValidator(validator);
|
||||
}
|
||||
} catch (Exception e){
|
||||
String msg = "Error creating a validator on "+prop.getFullBeanName();
|
||||
logger.log(Level.SEVERE, msg, e);
|
||||
}
|
||||
}
|
||||
|
||||
public ScalarType<?> setEnumScalarType(Enumerated enumerated, DeployBeanProperty prop) {
|
||||
|
||||
Class<?> enumType = prop.getPropertyType();
|
||||
if (!enumType.isEnum()) {
|
||||
throw new IllegalArgumentException("Class ["+enumType+"] is Not a Enum?");
|
||||
}
|
||||
ScalarType<?> scalarType = typeManager.getScalarType(enumType);
|
||||
if (scalarType == null) {
|
||||
// see if it has a Mapping in avaje.properties
|
||||
scalarType = typeManager.createEnumScalarType(enumType);
|
||||
if (scalarType == null){
|
||||
// use JPA normal Enum type (without mapping)
|
||||
EnumType type = enumerated != null? enumerated.value(): null;
|
||||
scalarType = createEnumScalarTypePerSpec(enumType, type, prop.getDbType());
|
||||
}
|
||||
|
||||
typeManager.add(scalarType);
|
||||
}
|
||||
prop.setScalarType(scalarType);
|
||||
prop.setDbType(scalarType.getJdbcType());
|
||||
return scalarType;
|
||||
}
|
||||
|
||||
private ScalarType<?> createEnumScalarTypePerSpec(Class<?> enumType, EnumType type, int dbType) {
|
||||
|
||||
if (type == null) {
|
||||
// default as per spec is ORDINAL
|
||||
return new ScalarTypeEnumStandard.OrdinalEnum(enumType);
|
||||
|
||||
} else if (type == EnumType.ORDINAL) {
|
||||
return new ScalarTypeEnumStandard.OrdinalEnum(enumType);
|
||||
|
||||
} else {
|
||||
return new ScalarTypeEnumStandard.StringEnum(enumType);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the ScalarType for this property.
|
||||
* <p>
|
||||
* This determines if there is a conversion required from the logical (bean)
|
||||
* type to a DB (jdbc) type. This is the case for java.util.Date etc.
|
||||
* </p>
|
||||
*/
|
||||
public void setScalarType(DeployBeanProperty property) {
|
||||
|
||||
if (property.getScalarType() != null){
|
||||
// already has a ScalarType assigned.
|
||||
// this will be an Enum type...
|
||||
return;
|
||||
}
|
||||
if (property instanceof DeployBeanPropertyCompound){
|
||||
// compound properties have a CvoInternalType instead
|
||||
return;
|
||||
}
|
||||
|
||||
ScalarType<?> scalarType = getScalarType(property);
|
||||
if (scalarType != null){
|
||||
// set the jdbc type this maps to
|
||||
|
||||
property.setDbType(scalarType.getJdbcType());
|
||||
property.setScalarType(scalarType);
|
||||
}
|
||||
}
|
||||
|
||||
private ScalarType<?> getScalarType(DeployBeanProperty property) {
|
||||
|
||||
// Note that Temporal types already have dbType
|
||||
// set via annotations
|
||||
Class<?> propType = property.getPropertyType();
|
||||
ScalarType<?> scalarType = typeManager.getScalarType(propType, property.getDbType());
|
||||
if (scalarType != null) {
|
||||
return scalarType;
|
||||
}
|
||||
|
||||
String msg = property.getFullBeanName()+" has no ScalarType - type[" + propType.getName() + "]";
|
||||
if (!property.isTransient()){
|
||||
throw new PersistenceException(msg);
|
||||
|
||||
} else {
|
||||
// this is ok...
|
||||
logger.finest("... transient property "+msg);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This property is marked as a Lob object.
|
||||
*/
|
||||
public void setLobType(DeployBeanProperty prop) {
|
||||
|
||||
// is String or byte[] ? used to determine if its a CLOB or BLOB
|
||||
Class<?> type = prop.getPropertyType();
|
||||
|
||||
// this also sets the lob flag on DeployBeanProperty
|
||||
int lobType = isClobType(type) ? dbCLOBType : dbBLOBType;
|
||||
|
||||
ScalarType<?> scalarType = typeManager.getScalarType(type, lobType);
|
||||
if (scalarType == null) {
|
||||
// this should never occur actually
|
||||
throw new RuntimeException("No ScalarType for LOB type ["+type+"] ["+lobType+"]");
|
||||
}
|
||||
prop.setDbType(lobType);
|
||||
prop.setScalarType(scalarType);
|
||||
}
|
||||
|
||||
public boolean isClobType(Class<?> type){
|
||||
if (type.equals(String.class)){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,62 +1,43 @@
|
||||
/**
|
||||
* Copyright (C) 2009 Authors
|
||||
*
|
||||
* This file is part of Ebean.
|
||||
*
|
||||
* Ebean is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Ebean 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package com.avaje.ebeaninternal.server.deploy.parse;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.avaje.ebeaninternal.api.ClassUtil;
|
||||
|
||||
/**
|
||||
* Used to detected if Scala support is required.
|
||||
*
|
||||
* @author rbygrave
|
||||
*/
|
||||
public class DetectScala {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(DetectScala.class.getName());
|
||||
|
||||
private static Class<?> scalaOptionClass = initScalaOptionClass();
|
||||
|
||||
private static boolean hasScalaSupport = scalaOptionClass != null;
|
||||
|
||||
private static Class<?> initScalaOptionClass() {
|
||||
try {
|
||||
return ClassUtil.forName("scala.Option");
|
||||
} catch (ClassNotFoundException e) {
|
||||
// scala not in the classpath...
|
||||
logger.fine("Scala type 'scala.Option' not found. Scala Support disabled.");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if scala is in the classpath.
|
||||
*/
|
||||
public static boolean hasScalaSupport() {
|
||||
return hasScalaSupport;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the scala.Option class or null if scala is not in the classpath.
|
||||
*/
|
||||
public static Class<?> getScalaOptionClass() {
|
||||
return scalaOptionClass;
|
||||
}
|
||||
}
|
||||
package com.avaje.ebeaninternal.server.deploy.parse;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.avaje.ebeaninternal.api.ClassUtil;
|
||||
|
||||
/**
|
||||
* Used to detected if Scala support is required.
|
||||
*
|
||||
* @author rbygrave
|
||||
*/
|
||||
public class DetectScala {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(DetectScala.class.getName());
|
||||
|
||||
private static Class<?> scalaOptionClass = initScalaOptionClass();
|
||||
|
||||
private static boolean hasScalaSupport = scalaOptionClass != null;
|
||||
|
||||
private static Class<?> initScalaOptionClass() {
|
||||
try {
|
||||
return ClassUtil.forName("scala.Option");
|
||||
} catch (ClassNotFoundException e) {
|
||||
// scala not in the classpath...
|
||||
logger.fine("Scala type 'scala.Option' not found. Scala Support disabled.");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if scala is in the classpath.
|
||||
*/
|
||||
public static boolean hasScalaSupport() {
|
||||
return hasScalaSupport;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the scala.Option class or null if scala is not in the classpath.
|
||||
*/
|
||||
public static Class<?> getScalaOptionClass() {
|
||||
return scalaOptionClass;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,77 +1,58 @@
|
||||
/**
|
||||
* Copyright (C) 2006 Robin Bygrave
|
||||
*
|
||||
* This file is part of Ebean.
|
||||
*
|
||||
* Ebean is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Ebean 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package com.avaje.ebeaninternal.server.deploy.parse;
|
||||
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptorManager;
|
||||
|
||||
|
||||
/**
|
||||
* Read the deployment annotations for the bean.
|
||||
*/
|
||||
public class ReadAnnotations {
|
||||
|
||||
/**
|
||||
* Read the initial non-relationship annotations included Id and EmbeddedId.
|
||||
* <p>
|
||||
* We then have enough to create BeanTables which are used in readAssociations
|
||||
* to resolve the relationships etc.
|
||||
* </p>
|
||||
*/
|
||||
public void readInitial(DeployBeanInfo<?> info){
|
||||
|
||||
try {
|
||||
new AnnotationClass(info).parse();
|
||||
new AnnotationFields(info).parse();
|
||||
|
||||
} catch (RuntimeException e){
|
||||
String msg = "Error reading annotations for "+info;
|
||||
throw new RuntimeException(msg, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Read and process the associated relationship annotations.
|
||||
* <p>
|
||||
* These can only be processed after the BeanTables have been created
|
||||
* </p>
|
||||
* <p>
|
||||
* This uses the factory as a call back to get the BeanTable for a given
|
||||
* associated bean.
|
||||
* </p>
|
||||
*/
|
||||
public void readAssociations(DeployBeanInfo<?> info, BeanDescriptorManager factory){
|
||||
|
||||
try {
|
||||
|
||||
new AnnotationAssocOnes(info, factory).parse();
|
||||
new AnnotationAssocManys(info, factory).parse();
|
||||
|
||||
// read the Sql annotations last because they may be
|
||||
// dependent on field level annotations
|
||||
new AnnotationSql(info).parse();
|
||||
|
||||
} catch (RuntimeException e){
|
||||
String msg = "Error reading annotations for "+info;
|
||||
throw new RuntimeException(msg, e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
package com.avaje.ebeaninternal.server.deploy.parse;
|
||||
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptorManager;
|
||||
|
||||
|
||||
/**
|
||||
* Read the deployment annotations for the bean.
|
||||
*/
|
||||
public class ReadAnnotations {
|
||||
|
||||
/**
|
||||
* Read the initial non-relationship annotations included Id and EmbeddedId.
|
||||
* <p>
|
||||
* We then have enough to create BeanTables which are used in readAssociations
|
||||
* to resolve the relationships etc.
|
||||
* </p>
|
||||
*/
|
||||
public void readInitial(DeployBeanInfo<?> info){
|
||||
|
||||
try {
|
||||
new AnnotationClass(info).parse();
|
||||
new AnnotationFields(info).parse();
|
||||
|
||||
} catch (RuntimeException e){
|
||||
String msg = "Error reading annotations for "+info;
|
||||
throw new RuntimeException(msg, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Read and process the associated relationship annotations.
|
||||
* <p>
|
||||
* These can only be processed after the BeanTables have been created
|
||||
* </p>
|
||||
* <p>
|
||||
* This uses the factory as a call back to get the BeanTable for a given
|
||||
* associated bean.
|
||||
* </p>
|
||||
*/
|
||||
public void readAssociations(DeployBeanInfo<?> info, BeanDescriptorManager factory){
|
||||
|
||||
try {
|
||||
|
||||
new AnnotationAssocOnes(info, factory).parse();
|
||||
new AnnotationAssocManys(info, factory).parse();
|
||||
|
||||
// read the Sql annotations last because they may be
|
||||
// dependent on field level annotations
|
||||
new AnnotationSql(info).parse();
|
||||
|
||||
} catch (RuntimeException e){
|
||||
String msg = "Error reading annotations for "+info;
|
||||
throw new RuntimeException(msg, e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+51
-70
@@ -1,70 +1,51 @@
|
||||
/**
|
||||
* Copyright (C) 2006 Robin Bygrave
|
||||
*
|
||||
* This file is part of Ebean.
|
||||
*
|
||||
* Ebean is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Ebean 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package com.avaje.ebeaninternal.server.deploy.parse;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanDescriptor;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocMany;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocOne;
|
||||
|
||||
/**
|
||||
* Mark transient properties.
|
||||
*/
|
||||
public class TransientProperties {
|
||||
|
||||
public TransientProperties() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark any additional properties as transient.
|
||||
*/
|
||||
public void process(DeployBeanDescriptor<?> desc) {
|
||||
|
||||
List<DeployBeanProperty> props = desc.propertiesBase();
|
||||
for (int i = 0; i < props.size(); i++) {
|
||||
DeployBeanProperty prop = props.get(i);
|
||||
if (!prop.isDbRead() && !prop.isDbInsertable() && !prop.isDbUpdateable()) {
|
||||
// non-transient...
|
||||
prop.setTransient(true);
|
||||
}
|
||||
}
|
||||
|
||||
List<DeployBeanPropertyAssocOne<?>> ones = desc.propertiesAssocOne();
|
||||
for (int i = 0; i < ones.size(); i++) {
|
||||
DeployBeanPropertyAssocOne<?> prop = ones.get(i);
|
||||
if (prop.getBeanTable() == null) {
|
||||
if (!prop.isEmbedded()) {
|
||||
prop.setTransient(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<DeployBeanPropertyAssocMany<?>> manys = desc.propertiesAssocMany();
|
||||
for (int i = 0; i < manys.size(); i++) {
|
||||
DeployBeanPropertyAssocMany<?> prop = manys.get(i);
|
||||
if (prop.getBeanTable() == null) {
|
||||
prop.setTransient(true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
package com.avaje.ebeaninternal.server.deploy.parse;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanDescriptor;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocMany;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocOne;
|
||||
|
||||
/**
|
||||
* Mark transient properties.
|
||||
*/
|
||||
public class TransientProperties {
|
||||
|
||||
public TransientProperties() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark any additional properties as transient.
|
||||
*/
|
||||
public void process(DeployBeanDescriptor<?> desc) {
|
||||
|
||||
List<DeployBeanProperty> props = desc.propertiesBase();
|
||||
for (int i = 0; i < props.size(); i++) {
|
||||
DeployBeanProperty prop = props.get(i);
|
||||
if (!prop.isDbRead() && !prop.isDbInsertable() && !prop.isDbUpdateable()) {
|
||||
// non-transient...
|
||||
prop.setTransient(true);
|
||||
}
|
||||
}
|
||||
|
||||
List<DeployBeanPropertyAssocOne<?>> ones = desc.propertiesAssocOne();
|
||||
for (int i = 0; i < ones.size(); i++) {
|
||||
DeployBeanPropertyAssocOne<?> prop = ones.get(i);
|
||||
if (prop.getBeanTable() == null) {
|
||||
if (!prop.isEmbedded()) {
|
||||
prop.setTransient(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<DeployBeanPropertyAssocMany<?>> manys = desc.propertiesAssocMany();
|
||||
for (int i = 0; i < manys.size(); i++) {
|
||||
DeployBeanPropertyAssocMany<?> prop = manys.get(i);
|
||||
if (prop.getBeanTable() == null) {
|
||||
prop.setTransient(true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user