No effective change - change newline char

This commit is contained in:
rbygrave
2015-05-09 01:08:33 +12:00
parent dfb69e3cde
commit 89db75e8c5
81 changed files with 17950 additions and 17950 deletions
@@ -1,319 +1,319 @@
package com.avaje.ebeaninternal.server.deploy.parse;
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.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.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;
import com.avaje.ebeaninternal.server.query.SqlJoinType;
/**
* 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() {
for (DeployBeanProperty prop : descriptor.propertiesAll()) {
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);
}
}
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(SqlJoinType.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(SqlJoinType.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(SqlJoinType.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(SqlJoinType.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 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.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.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;
import com.avaje.ebeaninternal.server.query.SqlJoinType;
/**
* 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() {
for (DeployBeanProperty prop : descriptor.propertiesAll()) {
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);
}
}
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(SqlJoinType.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(SqlJoinType.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(SqlJoinType.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(SqlJoinType.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();
}
}
@@ -1,213 +1,213 @@
package com.avaje.ebeaninternal.server.deploy.parse;
import java.util.Map;
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 javax.validation.constraints.NotNull;
import com.avaje.ebean.annotation.EmbeddedColumns;
import com.avaje.ebean.annotation.Where;
import com.avaje.ebean.config.NamingConvention;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptorManager;
import com.avaje.ebeaninternal.server.deploy.BeanTable;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocOne;
import com.avaje.ebeaninternal.server.lib.util.StringHelper;
import com.avaje.ebeaninternal.server.query.SqlJoinType;
/**
* 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() {
for (DeployBeanProperty prop : descriptor.propertiesAll()) {
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());
}
if (validationAnnotations) {
NotNull notNull = get(prop, NotNull.class);
if (notNull != null) {
prop.setNullable(false);
// overrides optional attribute of ManyToOne etc
prop.getTableJoin().setType(SqlJoinType.INNER);
}
}
// 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);
}
if (!joinColumn.nullable()) {
prop.setNullable(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);
}
readEmbeddedAttributeOverrides(prop);
}
}
package com.avaje.ebeaninternal.server.deploy.parse;
import java.util.Map;
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 javax.validation.constraints.NotNull;
import com.avaje.ebean.annotation.EmbeddedColumns;
import com.avaje.ebean.annotation.Where;
import com.avaje.ebean.config.NamingConvention;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptorManager;
import com.avaje.ebeaninternal.server.deploy.BeanTable;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocOne;
import com.avaje.ebeaninternal.server.lib.util.StringHelper;
import com.avaje.ebeaninternal.server.query.SqlJoinType;
/**
* 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() {
for (DeployBeanProperty prop : descriptor.propertiesAll()) {
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());
}
if (validationAnnotations) {
NotNull notNull = get(prop, NotNull.class);
if (notNull != null) {
prop.setNullable(false);
// overrides optional attribute of ManyToOne etc
prop.getTableJoin().setType(SqlJoinType.INNER);
}
}
// 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);
}
if (!joinColumn.nullable()) {
prop.setNullable(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);
}
readEmbeddedAttributeOverrides(prop);
}
}
@@ -1,31 +1,31 @@
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,169 +1,169 @@
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 com.avaje.ebean.annotation.CacheStrategy;
import com.avaje.ebean.annotation.CacheTuning;
import com.avaje.ebean.annotation.EntityConcurrencyMode;
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 void read(Class<?> cls) {
Entity entity = cls.getAnnotation(Entity.class);
if (entity != null) {
if (entity.name().equals("")) {
descriptor.setName(cls.getSimpleName());
} else {
descriptor.setName(entity.name());
}
}
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);
CacheTuning cacheTuning = cls.getAnnotation(CacheTuning.class);
if (cacheStrategy != null || cacheTuning != null) {
readCacheStrategy(cacheStrategy, cacheTuning);
}
EntityConcurrencyMode entityConcurrencyMode = cls.getAnnotation(EntityConcurrencyMode.class);
if (entityConcurrencyMode != null) {
descriptor.setConcurrencyMode(entityConcurrencyMode.value());
}
}
private void readCacheStrategy(CacheStrategy cacheStrategy, CacheTuning cacheTuning) {
CacheOptions cacheOptions = descriptor.getCacheOptions();
if (cacheTuning != null) {
cacheOptions.setMaxSecsToLive(cacheTuning.maxSecsToLive());
cacheOptions.setMaxIdleSecs(cacheTuning.maxIdleSecs());
}
if (cacheStrategy != null) {
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);
}
}
}
}
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);
}
}
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 com.avaje.ebean.annotation.CacheStrategy;
import com.avaje.ebean.annotation.CacheTuning;
import com.avaje.ebean.annotation.EntityConcurrencyMode;
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 void read(Class<?> cls) {
Entity entity = cls.getAnnotation(Entity.class);
if (entity != null) {
if (entity.name().equals("")) {
descriptor.setName(cls.getSimpleName());
} else {
descriptor.setName(entity.name());
}
}
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);
CacheTuning cacheTuning = cls.getAnnotation(CacheTuning.class);
if (cacheStrategy != null || cacheTuning != null) {
readCacheStrategy(cacheStrategy, cacheTuning);
}
EntityConcurrencyMode entityConcurrencyMode = cls.getAnnotation(EntityConcurrencyMode.class);
if (entityConcurrencyMode != null) {
descriptor.setConcurrencyMode(entityConcurrencyMode.value());
}
}
private void readCacheStrategy(CacheStrategy cacheStrategy, CacheTuning cacheTuning) {
CacheOptions cacheOptions = descriptor.getCacheOptions();
if (cacheTuning != null) {
cacheOptions.setMaxSecsToLive(cacheTuning.maxSecsToLive());
cacheOptions.setMaxIdleSecs(cacheTuning.maxIdleSecs());
}
if (cacheStrategy != null) {
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);
}
}
}
}
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);
}
}
@@ -1,427 +1,427 @@
package com.avaje.ebeaninternal.server.deploy.parse;
import com.avaje.ebean.annotation.*;
import com.avaje.ebean.config.EncryptDeploy;
import com.avaje.ebean.config.EncryptDeploy.Mode;
import com.avaje.ebean.config.dbplatform.DbEncrypt;
import com.avaje.ebean.config.dbplatform.DbEncryptFunction;
import com.avaje.ebean.config.dbplatform.IdType;
import com.avaje.ebeaninternal.server.deploy.generatedproperty.GeneratedPropertyFactory;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssoc;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocOne;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyCompound;
import com.avaje.ebeaninternal.server.idgen.UuidIdGenerator;
import com.avaje.ebeaninternal.server.lib.util.StringHelper;
import com.avaje.ebeaninternal.server.type.*;
import javax.persistence.*;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.sql.Types;
import java.util.Map;
import java.util.UUID;
/**
* Read the field level deployment annotations.
*/
public class AnnotationFields extends AnnotationParser {
/**
* By default we lazy load Lob properties.
*/
private FetchType defaultLobFetchType = FetchType.LAZY;
private GeneratedPropertyFactory generatedPropFactory = new GeneratedPropertyFactory();
public AnnotationFields(DeployBeanInfo<?> info, boolean eagerFetchLobs) {
super(info);
if (eagerFetchLobs) {
defaultLobFetchType = FetchType.EAGER;
}
}
/**
* Read the field level deployment annotations.
*/
public void parse() {
for (DeployBeanProperty prop : descriptor.propertiesAll()) {
if (prop instanceof DeployBeanPropertyAssoc<?>) {
readAssocOne(prop);
} else {
readField(prop);
}
}
}
/**
* Read the Id marker annotations on EmbeddedId properties.
*/
private void readAssocOne(DeployBeanProperty prop) {
Id id = get(prop, Id.class);
if (id != null) {
prop.setId(true);
prop.setNullable(false);
}
EmbeddedId embeddedId = get(prop, EmbeddedId.class);
if (embeddedId != null) {
prop.setId(true);
prop.setNullable(false);
prop.setEmbedded(true);
}
if (prop instanceof DeployBeanPropertyAssocOne<?>) {
if (prop.isId() && !prop.isEmbedded()) {
prop.setEmbedded(true);
}
readEmbeddedAttributeOverrides((DeployBeanPropertyAssocOne<?>) prop);
}
}
private void readField(DeployBeanProperty prop) {
// all Enums will have a ScalarType assigned...
boolean isEnum = prop.getPropertyType().isEnum();
Enumerated enumerated = get(prop, Enumerated.class);
if (isEnum || enumerated != null) {
util.setEnumScalarType(enumerated, prop);
}
// its persistent and assumed to be on the base table
// rather than on a secondary table
prop.setDbRead(true);
prop.setDbInsertable(true);
prop.setDbUpdateable(true);
Column column = get(prop, Column.class);
if (column != null) {
readColumn(column, prop);
}
Expose expose = get(prop, Expose.class);
if (expose != null) {
prop.setExposeSerialize(expose.serialize());
prop.setExposeDeserialize(expose.deserialize());
}
if (prop.getDbColumn() == null) {
// No @Column annotation or @Column.name() not set
// Use the NamingConvention to set the DB column name
String dbColumn = namingConvention.getColumnFromProperty(beanType, prop.getName());
prop.setDbColumn(dbColumn);
}
GeneratedValue gen = get(prop, GeneratedValue.class);
if (gen != null) {
readGenValue(gen, prop);
}
Id id = (Id) get(prop, Id.class);
if (id != null) {
readId(id, prop);
}
// determine the JDBC type using Lob/Temporal
// otherwise based on the property Class
Lob lob = get(prop, Lob.class);
Temporal temporal = get(prop, Temporal.class);
if (temporal != null) {
readTemporal(temporal, prop);
} else if (lob != null) {
util.setLobType(prop);
}
Formula formula = get(prop, Formula.class);
if (formula != null) {
prop.setSqlFormula(formula.select(), formula.join());
}
Version version = get(prop, Version.class);
if (version != null) {
// explicitly specify a version column
prop.setVersionColumn(true);
generatedPropFactory.setVersion(prop);
}
Basic basic = get(prop, Basic.class);
if (basic != null) {
prop.setFetchType(basic.fetch());
if (!basic.optional()) {
prop.setNullable(false);
}
} else if (prop.isLob()) {
// use the default Lob fetchType
prop.setFetchType(defaultLobFetchType);
}
CreatedTimestamp ct = get(prop, CreatedTimestamp.class);
if (ct != null) {
generatedPropFactory.setInsertTimestamp(prop);
}
UpdatedTimestamp ut = get(prop, UpdatedTimestamp.class);
if (ut != null) {
generatedPropFactory.setUpdateTimestamp(prop);
}
if (validationAnnotations) {
NotNull notNull = get(prop, NotNull.class);
if (notNull != null && isNotNullOnAllValidationGroups(notNull.groups())) {
// Not null on all validation groups so enable
// DDL generation of Not Null Constraint
prop.setNullable(false);
}
Size size = get(prop, Size.class);
if (size != null) {
if (size.max() < Integer.MAX_VALUE) {
// explicitly specify a version column
prop.setDbLength(size.max());
}
}
}
EmbeddedColumns columns = get(prop, EmbeddedColumns.class);
if (columns != null) {
if (prop instanceof DeployBeanPropertyCompound) {
DeployBeanPropertyCompound p = (DeployBeanPropertyCompound) prop;
// convert into a Map
String propColumns = columns.columns();
Map<String, String> propMap = StringHelper.delimitedToMap(propColumns, ",", "=");
p.getDeployEmbedded().putAll(propMap);
CtCompoundType<?> compoundType = p.getCompoundType();
if (compoundType == null) {
throw new RuntimeException("No registered CtCompoundType for " + p.getPropertyType());
}
} else {
throw new RuntimeException("Can't use EmbeddedColumns on ScalarType "
+ prop.getFullBeanName());
}
}
// Want to process last so we can use with @Formula
Transient t = get(prop, Transient.class);
if (t != null) {
// it is not a persistent property.
prop.setDbRead(false);
prop.setDbInsertable(false);
prop.setDbUpdateable(false);
prop.setTransient(true);
}
if (!prop.isTransient()) {
EncryptDeploy encryptDeploy = util.getEncryptDeploy(info.getDescriptor().getBaseTableFull(),
prop.getDbColumn());
if (encryptDeploy == null || encryptDeploy.getMode().equals(Mode.MODE_ANNOTATION)) {
Encrypted encrypted = get(prop, Encrypted.class);
if (encrypted != null) {
setEncryption(prop, encrypted.dbEncryption(), encrypted.dbLength());
}
} else if (Mode.MODE_ENCRYPT.equals(encryptDeploy.getMode())) {
setEncryption(prop, encryptDeploy.isDbEncrypt(), encryptDeploy.getDbLength());
}
}
Index index = get(prop, Index.class);
if (index != null) {
if(hasRelationshipItem(prop)) {
throw new RuntimeException("Can't use Index on foreign key relationships.");
}
prop.setIndexed(true);
prop.setIndexName(index.value());
}
}
private boolean hasRelationshipItem(DeployBeanProperty prop) {
return get(prop, OneToMany.class) != null ||
get(prop, ManyToOne.class) != null ||
get(prop, OneToOne.class) != null;
}
/**
* Return true if the validation is on all validation groups and hence
* can be applied to DDL generation.
*/
private boolean isNotNullOnAllValidationGroups(Class<?>[] groups) {
if (groups.length == 0) {
return true;
}
if (groups.length == 1 && javax.validation.groups.Default.class.isAssignableFrom(groups[0])) {
return true;
}
return false;
}
private void setEncryption(DeployBeanProperty prop, boolean dbEncString, int dbLen) {
util.checkEncryptKeyManagerDefined(prop.getFullBeanName());
ScalarType<?> st = prop.getScalarType();
if (byte[].class.equals(st.getType())) {
// Always using Java client encryption rather than DB for encryption
// of binary data (partially as this is not supported on all db's etc)
// This could be reviewed at a later stage.
ScalarTypeBytesBase baseType = (ScalarTypeBytesBase) st;
DataEncryptSupport support = createDataEncryptSupport(prop);
ScalarTypeBytesEncrypted encryptedScalarType = new ScalarTypeBytesEncrypted(baseType, support);
prop.setScalarType(encryptedScalarType);
prop.setLocalEncrypted(true);
return;
}
if (dbEncString) {
DbEncrypt dbEncrypt = util.getDbPlatform().getDbEncrypt();
if (dbEncrypt != null) {
// check if we have a DB encryption function for this type
int jdbcType = prop.getScalarType().getJdbcType();
DbEncryptFunction dbEncryptFunction = dbEncrypt.getDbEncryptFunction(jdbcType);
if (dbEncryptFunction != null) {
// Use DB functions to encrypt and decrypt
prop.setDbEncryptFunction(dbEncryptFunction, dbEncrypt, dbLen);
return;
}
}
}
prop.setScalarType(createScalarType(prop, st));
prop.setLocalEncrypted(true);
if (dbLen > 0) {
prop.setDbLength(dbLen);
}
}
@SuppressWarnings({"unchecked", "rawtypes"})
private ScalarTypeEncryptedWrapper<?> createScalarType(DeployBeanProperty prop, ScalarType<?> st) {
// Use Java Encryptor wrapping the logical scalar type
DataEncryptSupport support = createDataEncryptSupport(prop);
ScalarTypeBytesBase byteType = getDbEncryptType(prop);
return new ScalarTypeEncryptedWrapper(st, byteType, support);
}
private ScalarTypeBytesBase getDbEncryptType(DeployBeanProperty prop) {
int dbType = prop.isLob() ? Types.BLOB : Types.VARBINARY;
return (ScalarTypeBytesBase) util.getTypeManager().getScalarType(dbType);
}
private DataEncryptSupport createDataEncryptSupport(DeployBeanProperty prop) {
String table = info.getDescriptor().getBaseTable();
String column = prop.getDbColumn();
return util.createDataEncryptSupport(table, column);
}
private void readId(Id id, DeployBeanProperty prop) {
prop.setId(true);
prop.setNullable(false);
if (prop.getPropertyType().equals(UUID.class)) {
// An Id of type UUID
if (descriptor.getIdGeneratorName() == null) {
// Without a generator explicitly specified
// so will use the default one AUTO_UUID
descriptor.setIdGeneratorName(UuidIdGenerator.AUTO_UUID);
descriptor.setIdType(IdType.GENERATOR);
}
}
}
private void readGenValue(GeneratedValue gen, DeployBeanProperty prop) {
String genName = gen.generator();
SequenceGenerator sequenceGenerator = find(prop, SequenceGenerator.class);
if (sequenceGenerator != null) {
if (sequenceGenerator.name().equals(genName)) {
genName = sequenceGenerator.sequenceName();
}
descriptor.setSequenceInitialValue(sequenceGenerator.initialValue());
descriptor.setSequenceAllocationSize(sequenceGenerator.allocationSize());
}
GenerationType strategy = gen.strategy();
if (strategy == GenerationType.IDENTITY) {
descriptor.setIdType(IdType.IDENTITY);
} else if (strategy == GenerationType.SEQUENCE) {
descriptor.setIdType(IdType.SEQUENCE);
if (genName != null && genName.length() > 0) {
descriptor.setIdGeneratorName(genName);
}
} else if (strategy == GenerationType.AUTO) {
if (prop.getPropertyType().equals(UUID.class)) {
descriptor.setIdGeneratorName(UuidIdGenerator.AUTO_UUID);
descriptor.setIdType(IdType.GENERATOR);
} else {
// use DatabasePlatform defaults
}
}
}
private void readTemporal(Temporal temporal, DeployBeanProperty prop) {
TemporalType type = temporal.value();
if (type.equals(TemporalType.DATE)) {
prop.setDbType(Types.DATE);
} else if (type.equals(TemporalType.TIMESTAMP)) {
prop.setDbType(Types.TIMESTAMP);
} else if (type.equals(TemporalType.TIME)) {
prop.setDbType(Types.TIME);
} else {
throw new PersistenceException("Unhandled type " + type);
}
}
private void readColumn(Column columnAnn, DeployBeanProperty prop) {
if (!isEmpty(columnAnn.name())) {
String dbColumn = databasePlatform.convertQuotedIdentifiers(columnAnn.name());
prop.setDbColumn(dbColumn);
}
prop.setDbInsertable(columnAnn.insertable());
prop.setDbUpdateable(columnAnn.updatable());
prop.setNullable(columnAnn.nullable());
prop.setUnique(columnAnn.unique());
if (columnAnn.precision() > 0) {
prop.setDbLength(columnAnn.precision());
} else if (columnAnn.length() != 255) {
// set default 255 on DbTypeMap
prop.setDbLength(columnAnn.length());
}
prop.setDbScale(columnAnn.scale());
prop.setDbColumnDefn(columnAnn.columnDefinition());
String baseTable = descriptor.getBaseTable();
String tableName = columnAnn.table();
if (tableName.equals("") || tableName.equalsIgnoreCase(baseTable)) {
// its a base table property...
} else {
// its on a secondary table...
prop.setSecondaryTable(tableName);
// DeployTableJoin tableJoin = info.getTableJoin(tableName);
// tableJoin.addProperty(prop);
}
}
}
package com.avaje.ebeaninternal.server.deploy.parse;
import com.avaje.ebean.annotation.*;
import com.avaje.ebean.config.EncryptDeploy;
import com.avaje.ebean.config.EncryptDeploy.Mode;
import com.avaje.ebean.config.dbplatform.DbEncrypt;
import com.avaje.ebean.config.dbplatform.DbEncryptFunction;
import com.avaje.ebean.config.dbplatform.IdType;
import com.avaje.ebeaninternal.server.deploy.generatedproperty.GeneratedPropertyFactory;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssoc;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocOne;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyCompound;
import com.avaje.ebeaninternal.server.idgen.UuidIdGenerator;
import com.avaje.ebeaninternal.server.lib.util.StringHelper;
import com.avaje.ebeaninternal.server.type.*;
import javax.persistence.*;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.sql.Types;
import java.util.Map;
import java.util.UUID;
/**
* Read the field level deployment annotations.
*/
public class AnnotationFields extends AnnotationParser {
/**
* By default we lazy load Lob properties.
*/
private FetchType defaultLobFetchType = FetchType.LAZY;
private GeneratedPropertyFactory generatedPropFactory = new GeneratedPropertyFactory();
public AnnotationFields(DeployBeanInfo<?> info, boolean eagerFetchLobs) {
super(info);
if (eagerFetchLobs) {
defaultLobFetchType = FetchType.EAGER;
}
}
/**
* Read the field level deployment annotations.
*/
public void parse() {
for (DeployBeanProperty prop : descriptor.propertiesAll()) {
if (prop instanceof DeployBeanPropertyAssoc<?>) {
readAssocOne(prop);
} else {
readField(prop);
}
}
}
/**
* Read the Id marker annotations on EmbeddedId properties.
*/
private void readAssocOne(DeployBeanProperty prop) {
Id id = get(prop, Id.class);
if (id != null) {
prop.setId(true);
prop.setNullable(false);
}
EmbeddedId embeddedId = get(prop, EmbeddedId.class);
if (embeddedId != null) {
prop.setId(true);
prop.setNullable(false);
prop.setEmbedded(true);
}
if (prop instanceof DeployBeanPropertyAssocOne<?>) {
if (prop.isId() && !prop.isEmbedded()) {
prop.setEmbedded(true);
}
readEmbeddedAttributeOverrides((DeployBeanPropertyAssocOne<?>) prop);
}
}
private void readField(DeployBeanProperty prop) {
// all Enums will have a ScalarType assigned...
boolean isEnum = prop.getPropertyType().isEnum();
Enumerated enumerated = get(prop, Enumerated.class);
if (isEnum || enumerated != null) {
util.setEnumScalarType(enumerated, prop);
}
// its persistent and assumed to be on the base table
// rather than on a secondary table
prop.setDbRead(true);
prop.setDbInsertable(true);
prop.setDbUpdateable(true);
Column column = get(prop, Column.class);
if (column != null) {
readColumn(column, prop);
}
Expose expose = get(prop, Expose.class);
if (expose != null) {
prop.setExposeSerialize(expose.serialize());
prop.setExposeDeserialize(expose.deserialize());
}
if (prop.getDbColumn() == null) {
// No @Column annotation or @Column.name() not set
// Use the NamingConvention to set the DB column name
String dbColumn = namingConvention.getColumnFromProperty(beanType, prop.getName());
prop.setDbColumn(dbColumn);
}
GeneratedValue gen = get(prop, GeneratedValue.class);
if (gen != null) {
readGenValue(gen, prop);
}
Id id = (Id) get(prop, Id.class);
if (id != null) {
readId(id, prop);
}
// determine the JDBC type using Lob/Temporal
// otherwise based on the property Class
Lob lob = get(prop, Lob.class);
Temporal temporal = get(prop, Temporal.class);
if (temporal != null) {
readTemporal(temporal, prop);
} else if (lob != null) {
util.setLobType(prop);
}
Formula formula = get(prop, Formula.class);
if (formula != null) {
prop.setSqlFormula(formula.select(), formula.join());
}
Version version = get(prop, Version.class);
if (version != null) {
// explicitly specify a version column
prop.setVersionColumn(true);
generatedPropFactory.setVersion(prop);
}
Basic basic = get(prop, Basic.class);
if (basic != null) {
prop.setFetchType(basic.fetch());
if (!basic.optional()) {
prop.setNullable(false);
}
} else if (prop.isLob()) {
// use the default Lob fetchType
prop.setFetchType(defaultLobFetchType);
}
CreatedTimestamp ct = get(prop, CreatedTimestamp.class);
if (ct != null) {
generatedPropFactory.setInsertTimestamp(prop);
}
UpdatedTimestamp ut = get(prop, UpdatedTimestamp.class);
if (ut != null) {
generatedPropFactory.setUpdateTimestamp(prop);
}
if (validationAnnotations) {
NotNull notNull = get(prop, NotNull.class);
if (notNull != null && isNotNullOnAllValidationGroups(notNull.groups())) {
// Not null on all validation groups so enable
// DDL generation of Not Null Constraint
prop.setNullable(false);
}
Size size = get(prop, Size.class);
if (size != null) {
if (size.max() < Integer.MAX_VALUE) {
// explicitly specify a version column
prop.setDbLength(size.max());
}
}
}
EmbeddedColumns columns = get(prop, EmbeddedColumns.class);
if (columns != null) {
if (prop instanceof DeployBeanPropertyCompound) {
DeployBeanPropertyCompound p = (DeployBeanPropertyCompound) prop;
// convert into a Map
String propColumns = columns.columns();
Map<String, String> propMap = StringHelper.delimitedToMap(propColumns, ",", "=");
p.getDeployEmbedded().putAll(propMap);
CtCompoundType<?> compoundType = p.getCompoundType();
if (compoundType == null) {
throw new RuntimeException("No registered CtCompoundType for " + p.getPropertyType());
}
} else {
throw new RuntimeException("Can't use EmbeddedColumns on ScalarType "
+ prop.getFullBeanName());
}
}
// Want to process last so we can use with @Formula
Transient t = get(prop, Transient.class);
if (t != null) {
// it is not a persistent property.
prop.setDbRead(false);
prop.setDbInsertable(false);
prop.setDbUpdateable(false);
prop.setTransient(true);
}
if (!prop.isTransient()) {
EncryptDeploy encryptDeploy = util.getEncryptDeploy(info.getDescriptor().getBaseTableFull(),
prop.getDbColumn());
if (encryptDeploy == null || encryptDeploy.getMode().equals(Mode.MODE_ANNOTATION)) {
Encrypted encrypted = get(prop, Encrypted.class);
if (encrypted != null) {
setEncryption(prop, encrypted.dbEncryption(), encrypted.dbLength());
}
} else if (Mode.MODE_ENCRYPT.equals(encryptDeploy.getMode())) {
setEncryption(prop, encryptDeploy.isDbEncrypt(), encryptDeploy.getDbLength());
}
}
Index index = get(prop, Index.class);
if (index != null) {
if(hasRelationshipItem(prop)) {
throw new RuntimeException("Can't use Index on foreign key relationships.");
}
prop.setIndexed(true);
prop.setIndexName(index.value());
}
}
private boolean hasRelationshipItem(DeployBeanProperty prop) {
return get(prop, OneToMany.class) != null ||
get(prop, ManyToOne.class) != null ||
get(prop, OneToOne.class) != null;
}
/**
* Return true if the validation is on all validation groups and hence
* can be applied to DDL generation.
*/
private boolean isNotNullOnAllValidationGroups(Class<?>[] groups) {
if (groups.length == 0) {
return true;
}
if (groups.length == 1 && javax.validation.groups.Default.class.isAssignableFrom(groups[0])) {
return true;
}
return false;
}
private void setEncryption(DeployBeanProperty prop, boolean dbEncString, int dbLen) {
util.checkEncryptKeyManagerDefined(prop.getFullBeanName());
ScalarType<?> st = prop.getScalarType();
if (byte[].class.equals(st.getType())) {
// Always using Java client encryption rather than DB for encryption
// of binary data (partially as this is not supported on all db's etc)
// This could be reviewed at a later stage.
ScalarTypeBytesBase baseType = (ScalarTypeBytesBase) st;
DataEncryptSupport support = createDataEncryptSupport(prop);
ScalarTypeBytesEncrypted encryptedScalarType = new ScalarTypeBytesEncrypted(baseType, support);
prop.setScalarType(encryptedScalarType);
prop.setLocalEncrypted(true);
return;
}
if (dbEncString) {
DbEncrypt dbEncrypt = util.getDbPlatform().getDbEncrypt();
if (dbEncrypt != null) {
// check if we have a DB encryption function for this type
int jdbcType = prop.getScalarType().getJdbcType();
DbEncryptFunction dbEncryptFunction = dbEncrypt.getDbEncryptFunction(jdbcType);
if (dbEncryptFunction != null) {
// Use DB functions to encrypt and decrypt
prop.setDbEncryptFunction(dbEncryptFunction, dbEncrypt, dbLen);
return;
}
}
}
prop.setScalarType(createScalarType(prop, st));
prop.setLocalEncrypted(true);
if (dbLen > 0) {
prop.setDbLength(dbLen);
}
}
@SuppressWarnings({"unchecked", "rawtypes"})
private ScalarTypeEncryptedWrapper<?> createScalarType(DeployBeanProperty prop, ScalarType<?> st) {
// Use Java Encryptor wrapping the logical scalar type
DataEncryptSupport support = createDataEncryptSupport(prop);
ScalarTypeBytesBase byteType = getDbEncryptType(prop);
return new ScalarTypeEncryptedWrapper(st, byteType, support);
}
private ScalarTypeBytesBase getDbEncryptType(DeployBeanProperty prop) {
int dbType = prop.isLob() ? Types.BLOB : Types.VARBINARY;
return (ScalarTypeBytesBase) util.getTypeManager().getScalarType(dbType);
}
private DataEncryptSupport createDataEncryptSupport(DeployBeanProperty prop) {
String table = info.getDescriptor().getBaseTable();
String column = prop.getDbColumn();
return util.createDataEncryptSupport(table, column);
}
private void readId(Id id, DeployBeanProperty prop) {
prop.setId(true);
prop.setNullable(false);
if (prop.getPropertyType().equals(UUID.class)) {
// An Id of type UUID
if (descriptor.getIdGeneratorName() == null) {
// Without a generator explicitly specified
// so will use the default one AUTO_UUID
descriptor.setIdGeneratorName(UuidIdGenerator.AUTO_UUID);
descriptor.setIdType(IdType.GENERATOR);
}
}
}
private void readGenValue(GeneratedValue gen, DeployBeanProperty prop) {
String genName = gen.generator();
SequenceGenerator sequenceGenerator = find(prop, SequenceGenerator.class);
if (sequenceGenerator != null) {
if (sequenceGenerator.name().equals(genName)) {
genName = sequenceGenerator.sequenceName();
}
descriptor.setSequenceInitialValue(sequenceGenerator.initialValue());
descriptor.setSequenceAllocationSize(sequenceGenerator.allocationSize());
}
GenerationType strategy = gen.strategy();
if (strategy == GenerationType.IDENTITY) {
descriptor.setIdType(IdType.IDENTITY);
} else if (strategy == GenerationType.SEQUENCE) {
descriptor.setIdType(IdType.SEQUENCE);
if (genName != null && genName.length() > 0) {
descriptor.setIdGeneratorName(genName);
}
} else if (strategy == GenerationType.AUTO) {
if (prop.getPropertyType().equals(UUID.class)) {
descriptor.setIdGeneratorName(UuidIdGenerator.AUTO_UUID);
descriptor.setIdType(IdType.GENERATOR);
} else {
// use DatabasePlatform defaults
}
}
}
private void readTemporal(Temporal temporal, DeployBeanProperty prop) {
TemporalType type = temporal.value();
if (type.equals(TemporalType.DATE)) {
prop.setDbType(Types.DATE);
} else if (type.equals(TemporalType.TIMESTAMP)) {
prop.setDbType(Types.TIMESTAMP);
} else if (type.equals(TemporalType.TIME)) {
prop.setDbType(Types.TIME);
} else {
throw new PersistenceException("Unhandled type " + type);
}
}
private void readColumn(Column columnAnn, DeployBeanProperty prop) {
if (!isEmpty(columnAnn.name())) {
String dbColumn = databasePlatform.convertQuotedIdentifiers(columnAnn.name());
prop.setDbColumn(dbColumn);
}
prop.setDbInsertable(columnAnn.insertable());
prop.setDbUpdateable(columnAnn.updatable());
prop.setNullable(columnAnn.nullable());
prop.setUnique(columnAnn.unique());
if (columnAnn.precision() > 0) {
prop.setDbLength(columnAnn.precision());
} else if (columnAnn.length() != 255) {
// set default 255 on DbTypeMap
prop.setDbLength(columnAnn.length());
}
prop.setDbScale(columnAnn.scale());
prop.setDbColumnDefn(columnAnn.columnDefinition());
String baseTable = descriptor.getBaseTable();
String tableName = columnAnn.table();
if (tableName.equals("") || tableName.equalsIgnoreCase(baseTable)) {
// its a base table property...
} else {
// its on a secondary table...
prop.setSecondaryTable(tableName);
// DeployTableJoin tableJoin = info.getTableJoin(tableName);
// tableJoin.addProperty(prop);
}
}
}
@@ -1,77 +1,77 @@
package com.avaje.ebeaninternal.server.deploy.parse;
import java.util.HashMap;
import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.CascadeType;
import com.avaje.ebeaninternal.server.deploy.BeanCascadeInfo;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanDescriptor;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocOne;
/**
* Base class for reading deployment annotations.
*/
public abstract class AnnotationParser extends AnnotationBase {
protected final DeployBeanInfo<?> info;
protected final DeployBeanDescriptor<?> descriptor;
protected final Class<?> beanType;
protected boolean validationAnnotations;
public AnnotationParser(DeployBeanInfo<?> info) {
super(info.getUtil());
this.info = info;
this.beanType = info.getDescriptor().getBeanType();
this.descriptor = info.getDescriptor();
try {
Class.forName("javax.validation.constraints.NotNull");
validationAnnotations = true;
} catch (ClassNotFoundException e) {
// javax.validation not in the classpath so don't
// check for NotNull and Size
validationAnnotations = false;
}
}
/**
* 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);
}
}
/**
* Read an AttributeOverrides if they exist for this embedded bean.
*/
protected void readEmbeddedAttributeOverrides(DeployBeanPropertyAssocOne<?> prop) {
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 javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.CascadeType;
import com.avaje.ebeaninternal.server.deploy.BeanCascadeInfo;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanDescriptor;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocOne;
/**
* Base class for reading deployment annotations.
*/
public abstract class AnnotationParser extends AnnotationBase {
protected final DeployBeanInfo<?> info;
protected final DeployBeanDescriptor<?> descriptor;
protected final Class<?> beanType;
protected boolean validationAnnotations;
public AnnotationParser(DeployBeanInfo<?> info) {
super(info.getUtil());
this.info = info;
this.beanType = info.getDescriptor().getBeanType();
this.descriptor = info.getDescriptor();
try {
Class.forName("javax.validation.constraints.NotNull");
validationAnnotations = true;
} catch (ClassNotFoundException e) {
// javax.validation not in the classpath so don't
// check for NotNull and Size
validationAnnotations = false;
}
}
/**
* 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);
}
}
/**
* Read an AttributeOverrides if they exist for this embedded bean.
*/
protected void readEmbeddedAttributeOverrides(DeployBeanPropertyAssocOne<?> prop) {
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);
}
}
}
@@ -1,41 +1,41 @@
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,78 +1,78 @@
package com.avaje.ebeaninternal.server.deploy.parse;
import java.util.HashMap;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanDescriptor;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocOne;
import com.avaje.ebeaninternal.server.deploy.meta.DeployTableJoin;
import com.avaje.ebeaninternal.server.query.SqlJoinType;
/**
* 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(SqlJoinType.INNER);
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) {
DeployTableJoin tableJoin = beanProp.getTableJoin();
tableJoin.setType(outerJoin ? SqlJoinType.OUTER : SqlJoinType.INNER);
}
}
package com.avaje.ebeaninternal.server.deploy.parse;
import java.util.HashMap;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanDescriptor;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocOne;
import com.avaje.ebeaninternal.server.deploy.meta.DeployTableJoin;
import com.avaje.ebeaninternal.server.query.SqlJoinType;
/**
* 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(SqlJoinType.INNER);
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) {
DeployTableJoin tableJoin = beanProp.getTableJoin();
tableJoin.setType(outerJoin ? SqlJoinType.OUTER : SqlJoinType.INNER);
}
}
@@ -1,427 +1,427 @@
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 javax.persistence.ManyToOne;
import javax.persistence.PersistenceException;
import javax.persistence.Transient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.avaje.ebean.annotation.ColumnHstore;
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.ScalarType;
import com.avaje.ebeaninternal.server.type.ScalarTypePostgresHstore;
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 = LoggerFactory.getLogger(DeployCreateProperties.class);
private final DetermineManyType determineManyType;
private final TypeManager typeManager;
public DeployCreateProperties(TypeManager typeManager) {
this.typeManager = typeManager;
this.determineManyType = new DetermineManyType();
}
/**
* Create the appropriate properties for a bean.
*/
public void createProperties(DeployBeanDescriptor<?> desc) {
createProperties(desc, desc.getBeanType(), 0);
desc.sortProperties();
// check the transient properties...
for (DeployBeanProperty prop : desc.propertiesAll()) {
if (prop.isTransient()) {
if (prop.getWriteMethod() == null || prop.getReadMethod() == null) {
// Typically a helper method ... this is expected
logger.trace("... transient: " + prop.getFullBeanName());
} else {
// dubious, possible error...
String msg = Message.msg("deploy.property.nofield", desc.getFullName(), prop.getName());
logger.warn(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;
}
/**
* properties 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.trace("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(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.warn(msg);
}
}
}
}
}
Class<?> superClass = beanType.getSuperclass();
if (!superClass.equals(Object.class)) {
// recursively add any properties in the inheritance hierarchy
// 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.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) {
try {
ScalarType<?> scalarType = typeManager.getScalarType(targetType);
if (scalarType != null) {
return new DeployBeanPropertySimpleCollection(desc, targetType, manyType);
}
} catch (NullPointerException e) {
logger.debug("expected non-scalar type" + e.getMessage());
}
// 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();
ManyToOne manyToOne = field.getAnnotation(ManyToOne.class);
if (manyToOne != null){
Class<?> tt = manyToOne.targetEntity();
if (tt != null && !tt.equals(void.class)){
propertyType = tt;
logger.debug("target type" + tt);
}
}
Class<?> innerType = propertyType;
String specialTypeKey = getSpecialScalarType(field);
if (specialTypeKey != null) {
ScalarType<?> scalarType = typeManager.getScalarTypeFromKey(specialTypeKey);
if (scalarType == null) {
logger.error("Could not find ScalarType to match key ["+specialTypeKey+"]");
} else {
return new DeployBeanProperty(desc, propertyType, scalarType, null);
}
}
// 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.warn("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, null);
}
ScalarType<?> scalarType = typeManager.getScalarType(innerType);
if (scalarType != null) {
return new DeployBeanProperty(desc, propertyType, scalarType, null);
}
CtCompoundType<?> compoundType = typeManager.getCompoundType(innerType);
if (compoundType != null) {
return new DeployBeanPropertyCompound(desc, propertyType, compoundType, null);
}
if (isTransientField(field)) {
return null;
}
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, null);
}
} else {
// use reflection to support simple immutable value objects
scalarType = typeManager.recursiveCreateScalarTypes(innerType);
return new DeployBeanProperty(desc, propertyType, scalarType, null);
}
}
return new DeployBeanPropertyAssocOne(desc, propertyType);
} catch (Exception e) {
logger.error("Error with " + desc + " field:" + field.getName(), e);
return null;
}
}
private String getSpecialScalarType(Field field) {
if (field.getAnnotation(ColumnHstore.class) != null) {
return ScalarTypePostgresHstore.KEY;
}
return null;
}
private boolean isTransientField(Field field) {
Transient t = field.getAnnotation(Transient.class);
return (t != null);
}
private DeployBeanProperty createProp(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]);
return null;
}
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 javax.persistence.ManyToOne;
import javax.persistence.PersistenceException;
import javax.persistence.Transient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.avaje.ebean.annotation.ColumnHstore;
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.ScalarType;
import com.avaje.ebeaninternal.server.type.ScalarTypePostgresHstore;
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 = LoggerFactory.getLogger(DeployCreateProperties.class);
private final DetermineManyType determineManyType;
private final TypeManager typeManager;
public DeployCreateProperties(TypeManager typeManager) {
this.typeManager = typeManager;
this.determineManyType = new DetermineManyType();
}
/**
* Create the appropriate properties for a bean.
*/
public void createProperties(DeployBeanDescriptor<?> desc) {
createProperties(desc, desc.getBeanType(), 0);
desc.sortProperties();
// check the transient properties...
for (DeployBeanProperty prop : desc.propertiesAll()) {
if (prop.isTransient()) {
if (prop.getWriteMethod() == null || prop.getReadMethod() == null) {
// Typically a helper method ... this is expected
logger.trace("... transient: " + prop.getFullBeanName());
} else {
// dubious, possible error...
String msg = Message.msg("deploy.property.nofield", desc.getFullName(), prop.getName());
logger.warn(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;
}
/**
* properties 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.trace("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(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.warn(msg);
}
}
}
}
}
Class<?> superClass = beanType.getSuperclass();
if (!superClass.equals(Object.class)) {
// recursively add any properties in the inheritance hierarchy
// 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.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) {
try {
ScalarType<?> scalarType = typeManager.getScalarType(targetType);
if (scalarType != null) {
return new DeployBeanPropertySimpleCollection(desc, targetType, manyType);
}
} catch (NullPointerException e) {
logger.debug("expected non-scalar type" + e.getMessage());
}
// 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();
ManyToOne manyToOne = field.getAnnotation(ManyToOne.class);
if (manyToOne != null){
Class<?> tt = manyToOne.targetEntity();
if (tt != null && !tt.equals(void.class)){
propertyType = tt;
logger.debug("target type" + tt);
}
}
Class<?> innerType = propertyType;
String specialTypeKey = getSpecialScalarType(field);
if (specialTypeKey != null) {
ScalarType<?> scalarType = typeManager.getScalarTypeFromKey(specialTypeKey);
if (scalarType == null) {
logger.error("Could not find ScalarType to match key ["+specialTypeKey+"]");
} else {
return new DeployBeanProperty(desc, propertyType, scalarType, null);
}
}
// 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.warn("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, null);
}
ScalarType<?> scalarType = typeManager.getScalarType(innerType);
if (scalarType != null) {
return new DeployBeanProperty(desc, propertyType, scalarType, null);
}
CtCompoundType<?> compoundType = typeManager.getCompoundType(innerType);
if (compoundType != null) {
return new DeployBeanPropertyCompound(desc, propertyType, compoundType, null);
}
if (isTransientField(field)) {
return null;
}
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, null);
}
} else {
// use reflection to support simple immutable value objects
scalarType = typeManager.recursiveCreateScalarTypes(innerType);
return new DeployBeanProperty(desc, propertyType, scalarType, null);
}
}
return new DeployBeanPropertyAssocOne(desc, propertyType);
} catch (Exception e) {
logger.error("Error with " + desc + " field:" + field.getName(), e);
return null;
}
}
private String getSpecialScalarType(Field field) {
if (field.getAnnotation(ColumnHstore.class) != null) {
return ScalarTypePostgresHstore.KEY;
}
return null;
}
private boolean isTransientField(Field field) {
Transient t = field.getAnnotation(Transient.class);
return (t != null);
}
private DeployBeanProperty createProp(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]);
return null;
}
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,165 +1,165 @@
package com.avaje.ebeaninternal.server.deploy.parse;
import java.lang.annotation.Annotation;
import java.sql.Types;
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...
for (Class<?> cls : entityList) {
if (isInheritanceClass(cls)) {
DeployInheritInfo info = createInfo(cls);
deployMap.put(cls, info);
}
}
}
private void buildDeployTree() {
for (DeployInheritInfo info : deployMap.values()) {
if (!info.isRoot()) {
DeployInheritInfo parent = getInfo(info.getParent());
parent.addChild(info);
}
}
}
private void buildFinalTree() {
for (DeployInheritInfo deploy : deployMap.values()) {
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);
for (DeployInheritInfo childDeploy : deploy.children()) {
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) {
// lowercase the discriminator column for RawSql and JSON
info.setDiscriminatorColumn(da.name().toLowerCase());
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.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...
for (Class<?> cls : entityList) {
if (isInheritanceClass(cls)) {
DeployInheritInfo info = createInfo(cls);
deployMap.put(cls, info);
}
}
}
private void buildDeployTree() {
for (DeployInheritInfo info : deployMap.values()) {
if (!info.isRoot()) {
DeployInheritInfo parent = getInfo(info.getParent());
parent.addChild(info);
}
}
}
private void buildFinalTree() {
for (DeployInheritInfo deploy : deployMap.values()) {
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);
for (DeployInheritInfo childDeploy : deploy.children()) {
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) {
// lowercase the discriminator column for RawSql and JSON
info.setDiscriminatorColumn(da.name().toLowerCase());
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());
}
}
@@ -1,263 +1,263 @@
package com.avaje.ebeaninternal.server.deploy.parse;
import java.sql.Types;
import java.util.ArrayList;
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 List<DeployInheritInfo> children() {
return children;
}
/**
* 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.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 List<DeployInheritInfo> children() {
return children;
}
/**
* 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,228 +1,228 @@
package com.avaje.ebeaninternal.server.deploy.parse;
import java.sql.Types;
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.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;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Utility object to help processing deployment information.
*/
public class DeployUtil {
private static final Logger logger = LoggerFactory.getLogger(DeployUtil.class);
/**
* 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 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";
}
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 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.trace("... 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.sql.Types;
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.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;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Utility object to help processing deployment information.
*/
public class DeployUtil {
private static final Logger logger = LoggerFactory.getLogger(DeployUtil.class);
/**
* 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 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";
}
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 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.trace("... 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,58 +1,58 @@
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, boolean eagerFetchLobs){
try {
new AnnotationClass(info).parse();
new AnnotationFields(info, eagerFetchLobs).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, boolean eagerFetchLobs){
try {
new AnnotationClass(info).parse();
new AnnotationFields(info, eagerFetchLobs).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);
}
}
}
@@ -1,51 +1,51 @@
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);
}
}
}
}