Change license to Apache2 and reformat

This commit is contained in:
rbygrave
2012-09-15 00:00:08 +12:00
parent 96ce4c0ddf
commit 7aae897def
560 changed files with 73292 additions and 85907 deletions
@@ -1,141 +1,122 @@
/**
* Copyright (C) 2006 Robin Bygrave
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy;
import javax.persistence.CascadeType;
/**
* Persist info for determining if save or delete should be performed.
* <p>
* This is set to associated Beans, Table joins and List.
* </p>
*/
public class BeanCascadeInfo {
/**
* should delete cascade.
*/
boolean delete;
/**
* Should save cascade.
*/
boolean save;
/**
* Should validate cascade.
*/
boolean validate;
/**
* Set the raw deployment attribute.
*/
public void setAttribute(String attr) {
if (attr == null){
return;
}
attr = attr.toLowerCase();
delete = (attr.indexOf("delete")>-1);
if (!delete){
// same as EJB3 remove
delete = (attr.indexOf("remove")>-1);
}
save = (attr.indexOf("save")>-1);
if (!save){
// same as EJB3 persist
save = (attr.indexOf("persist")>-1);
}
if (attr.indexOf("validate")>-1){
validate = true;
}
if (attr.indexOf("all")>-1){
delete = true;
save = true;
validate = true;
}
}
public void setTypes(CascadeType[] types) {
for (int i = 0; i < types.length; i++) {
setType(types[i]);
}
}
private void setType(CascadeType type) {
if (type.equals(CascadeType.ALL)){
save = true;
delete = true;
}
if (type.equals(CascadeType.REMOVE)){
delete = true;
}
if (type.equals(CascadeType.PERSIST)){
save = true;
}
if (type.equals(CascadeType.MERGE)){
save = true;
}
if (save || delete){
validate = true;
}
}
/**
* Return true if delete should cascade.
*/
public boolean isDelete() {
return delete;
}
/**
* Set to true if delete should cascade.
*/
public void setDelete(boolean isDelete) {
this.delete = isDelete;
}
/**
* Return true if save should cascade.
*/
public boolean isSave() {
return save;
}
/**
* Set to true if save should cascade.
*/
public void setSave(boolean isUpdate) {
this.save = isUpdate;
}
/**
* Return true if validate should be cascaded.
*/
public boolean isValidate() {
return validate;
}
/**
* Set validate to cascade or not.
*/
public void setValidate(boolean isValidate) {
this.validate = isValidate;
}
}
package com.avaje.ebeaninternal.server.deploy;
import javax.persistence.CascadeType;
/**
* Persist info for determining if save or delete should be performed.
* <p>
* This is set to associated Beans, Table joins and List.
* </p>
*/
public class BeanCascadeInfo {
/**
* should delete cascade.
*/
boolean delete;
/**
* Should save cascade.
*/
boolean save;
/**
* Should validate cascade.
*/
boolean validate;
/**
* Set the raw deployment attribute.
*/
public void setAttribute(String attr) {
if (attr == null){
return;
}
attr = attr.toLowerCase();
delete = (attr.indexOf("delete")>-1);
if (!delete){
// same as EJB3 remove
delete = (attr.indexOf("remove")>-1);
}
save = (attr.indexOf("save")>-1);
if (!save){
// same as EJB3 persist
save = (attr.indexOf("persist")>-1);
}
if (attr.indexOf("validate")>-1){
validate = true;
}
if (attr.indexOf("all")>-1){
delete = true;
save = true;
validate = true;
}
}
public void setTypes(CascadeType[] types) {
for (int i = 0; i < types.length; i++) {
setType(types[i]);
}
}
private void setType(CascadeType type) {
if (type.equals(CascadeType.ALL)){
save = true;
delete = true;
}
if (type.equals(CascadeType.REMOVE)){
delete = true;
}
if (type.equals(CascadeType.PERSIST)){
save = true;
}
if (type.equals(CascadeType.MERGE)){
save = true;
}
if (save || delete){
validate = true;
}
}
/**
* Return true if delete should cascade.
*/
public boolean isDelete() {
return delete;
}
/**
* Set to true if delete should cascade.
*/
public void setDelete(boolean isDelete) {
this.delete = isDelete;
}
/**
* Return true if save should cascade.
*/
public boolean isSave() {
return save;
}
/**
* Set to true if save should cascade.
*/
public void setSave(boolean isUpdate) {
this.save = isUpdate;
}
/**
* Return true if validate should be cascaded.
*/
public boolean isValidate() {
return validate;
}
/**
* Set validate to cascade or not.
*/
public void setValidate(boolean isValidate) {
this.validate = isValidate;
}
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -1,56 +1,37 @@
/**
* Copyright (C) 2006 Robin Bygrave
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy;
import com.avaje.ebean.cache.ServerCacheManager;
import com.avaje.ebean.config.EncryptKey;
import com.avaje.ebeaninternal.server.deploy.id.IdBinder;
/**
* Provides a method to find a BeanDescriptor.
* <p>
* Used during deployment of to resolve relationships between beans.
* </p>
*/
public interface BeanDescriptorMap {
/**
* Return the name of the server/database.
*/
public String getServerName();
/**
* Return the Cache Manager.
*/
public ServerCacheManager getCacheManager();
/**
* Return the BeanDescriptor for a given class.
*/
public <T> BeanDescriptor<T> getBeanDescriptor(Class<T> entityType);
/**
* Return the Encrypt key given the table and column name.
*/
public EncryptKey getEncryptKey(String tableName, String columnName);
public IdBinder createIdBinder(BeanProperty[] uids);
}
package com.avaje.ebeaninternal.server.deploy;
import com.avaje.ebean.cache.ServerCacheManager;
import com.avaje.ebean.config.EncryptKey;
import com.avaje.ebeaninternal.server.deploy.id.IdBinder;
/**
* Provides a method to find a BeanDescriptor.
* <p>
* Used during deployment of to resolve relationships between beans.
* </p>
*/
public interface BeanDescriptorMap {
/**
* Return the name of the server/database.
*/
public String getServerName();
/**
* Return the Cache Manager.
*/
public ServerCacheManager getCacheManager();
/**
* Return the BeanDescriptor for a given class.
*/
public <T> BeanDescriptor<T> getBeanDescriptor(Class<T> entityType);
/**
* Return the Encrypt key given the table and column name.
*/
public EncryptKey getEncryptKey(String tableName, String columnName);
public IdBinder createIdBinder(BeanProperty[] uids);
}
@@ -1,50 +1,31 @@
/**
* Copyright (C) 2006 Robin Bygrave
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy;
public class BeanEmbeddedMeta {
final BeanProperty[] properties;
public BeanEmbeddedMeta(BeanProperty[] properties) {
this.properties = properties;
}
/**
* Return the properties with over ridden mapping information.
*/
public BeanProperty[] getProperties() {
return properties;
}
/**
* Return true if at least one property is a version property.
*/
public boolean isEmbeddedVersion() {
for (int i = 0; i < properties.length; i++) {
if (properties[i].isVersion()){
return true;
}
}
return false;
}
}
package com.avaje.ebeaninternal.server.deploy;
public class BeanEmbeddedMeta {
final BeanProperty[] properties;
public BeanEmbeddedMeta(BeanProperty[] properties) {
this.properties = properties;
}
/**
* Return the properties with over ridden mapping information.
*/
public BeanProperty[] getProperties() {
return properties;
}
/**
* Return true if at least one property is a version property.
*/
public boolean isEmbeddedVersion() {
for (int i = 0; i < properties.length; i++) {
if (properties[i].isVersion()){
return true;
}
}
return false;
}
}
@@ -1,72 +1,53 @@
/**
* Copyright (C) 2006 Robin Bygrave
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy;
import java.util.Map;
import javax.persistence.PersistenceException;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocOne;
/**
* Creates BeanProperties for Embedded beans that have deployment information
* such as the actual DB column name and table alias.
*/
public class BeanEmbeddedMetaFactory {
/**
* Create BeanProperties for embedded beans using the deployment specific DB column name and table alias.
*/
public static BeanEmbeddedMeta create(BeanDescriptorMap owner, DeployBeanPropertyAssocOne<?> prop,
BeanDescriptor<?> descriptor) {
// we can get a BeanDescriptor for an Embedded bean
// and know that it is NOT recursive, as Embedded beans are
// only allow to hold simple scalar types...
BeanDescriptor<?> targetDesc = owner.getBeanDescriptor(prop.getTargetType());
if (targetDesc == null){
String msg = "Could not find BeanDescriptor for "+prop.getTargetType()
+". Perhaps the EmbeddedId class is not registered?";
throw new PersistenceException(msg);
}
// deployment override information (column names)
Map<String, String> propColMap = prop.getDeployEmbedded().getPropertyColumnMap();
BeanProperty[] sourceProperties = targetDesc.propertiesBaseScalar();
BeanProperty[] embeddedProperties = new BeanProperty[sourceProperties.length];
for (int i = 0; i < sourceProperties.length; i++) {
String propertyName = sourceProperties[i].getName();
String dbColumn = propColMap.get(propertyName);
if (dbColumn == null) {
// dbColumn not overridden so take original
dbColumn = sourceProperties[i].getDbColumn();
}
BeanPropertyOverride overrides = new BeanPropertyOverride(dbColumn);
embeddedProperties[i] = new BeanProperty(sourceProperties[i], overrides);
}
return new BeanEmbeddedMeta(embeddedProperties);
}
}
package com.avaje.ebeaninternal.server.deploy;
import java.util.Map;
import javax.persistence.PersistenceException;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocOne;
/**
* Creates BeanProperties for Embedded beans that have deployment information
* such as the actual DB column name and table alias.
*/
public class BeanEmbeddedMetaFactory {
/**
* Create BeanProperties for embedded beans using the deployment specific DB column name and table alias.
*/
public static BeanEmbeddedMeta create(BeanDescriptorMap owner, DeployBeanPropertyAssocOne<?> prop,
BeanDescriptor<?> descriptor) {
// we can get a BeanDescriptor for an Embedded bean
// and know that it is NOT recursive, as Embedded beans are
// only allow to hold simple scalar types...
BeanDescriptor<?> targetDesc = owner.getBeanDescriptor(prop.getTargetType());
if (targetDesc == null){
String msg = "Could not find BeanDescriptor for "+prop.getTargetType()
+". Perhaps the EmbeddedId class is not registered?";
throw new PersistenceException(msg);
}
// deployment override information (column names)
Map<String, String> propColMap = prop.getDeployEmbedded().getPropertyColumnMap();
BeanProperty[] sourceProperties = targetDesc.propertiesBaseScalar();
BeanProperty[] embeddedProperties = new BeanProperty[sourceProperties.length];
for (int i = 0; i < sourceProperties.length; i++) {
String propertyName = sourceProperties[i].getName();
String dbColumn = propColMap.get(propertyName);
if (dbColumn == null) {
// dbColumn not overridden so take original
dbColumn = sourceProperties[i].getDbColumn();
}
BeanPropertyOverride overrides = new BeanPropertyOverride(dbColumn);
embeddedProperties[i] = new BeanProperty(sourceProperties[i], overrides);
}
return new BeanEmbeddedMeta(embeddedProperties);
}
}
@@ -1,45 +1,26 @@
/**
* Copyright (C) 2006 Robin Bygrave
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy;
import java.util.List;
import com.avaje.ebean.event.BeanFinder;
/**
* Factory for controlling the construction of BeanFinders.
*/
public interface BeanFinderManager {
/**
* Return the number of beans with a registered finder.
*/
public int getRegisterCount();
/**
* Create the appropriate BeanController.
*/
public int createBeanFinders(List<Class<?>> finderClassList);
/**
* Return the BeanController for a given entity type.
*/
public <T> BeanFinder<T> getBeanFinder(Class<T> entityType);
}
package com.avaje.ebeaninternal.server.deploy;
import java.util.List;
import com.avaje.ebean.event.BeanFinder;
/**
* Factory for controlling the construction of BeanFinders.
*/
public interface BeanFinderManager {
/**
* Return the number of beans with a registered finder.
*/
public int getRegisterCount();
/**
* Create the appropriate BeanController.
*/
public int createBeanFinders(List<Class<?>> finderClassList);
/**
* Return the BeanController for a given entity type.
*/
public <T> BeanFinder<T> getBeanFinder(Class<T> entityType);
}
@@ -1,75 +1,56 @@
/**
* Copyright (C) 2006 Robin Bygrave
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy;
import com.avaje.ebeaninternal.server.core.InternString;
/**
* Represents a database foreign key which can map to an object relationship.
*/
public class BeanForeignKey {
private final String dbColumn;
private final int dbType;
/**
* Construct the BeanForeignKey.
*/
public BeanForeignKey(String dbColumn, int dbType) {
this.dbColumn = InternString.intern(dbColumn);
this.dbType = dbType;
}
/**
* Return the database column.
*/
public String getDbColumn() {
return dbColumn;
}
/**
* Return the JDBC datatype of the database column.
*/
public int getDbType() {
return dbType;
}
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (obj instanceof BeanForeignKey) {
return obj.hashCode() == hashCode();
}
return false;
}
public int hashCode() {
int hc = getClass().hashCode();
hc = hc * 31 + (dbColumn != null ? dbColumn.hashCode() : 0);
return hc;
}
public String toString() {
return dbColumn;
}
}
package com.avaje.ebeaninternal.server.deploy;
import com.avaje.ebeaninternal.server.core.InternString;
/**
* Represents a database foreign key which can map to an object relationship.
*/
public class BeanForeignKey {
private final String dbColumn;
private final int dbType;
/**
* Construct the BeanForeignKey.
*/
public BeanForeignKey(String dbColumn, int dbType) {
this.dbColumn = InternString.intern(dbColumn);
this.dbType = dbType;
}
/**
* Return the database column.
*/
public String getDbColumn() {
return dbColumn;
}
/**
* Return the JDBC datatype of the database column.
*/
public int getDbType() {
return dbType;
}
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (obj instanceof BeanForeignKey) {
return obj.hashCode() == hashCode();
}
return false;
}
public int hashCode() {
int hc = getClass().hashCode();
hc = hc * 31 + (dbColumn != null ? dbColumn.hashCode() : 0);
return hc;
}
public String toString() {
return dbColumn;
}
}
@@ -1,59 +1,40 @@
/**
* Copyright (C) 2006 Robin Bygrave
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy;
import com.avaje.ebeaninternal.server.persist.BeanPersister;
/**
* Holds the BeanDescriptor and its associated BeanPersister.
*/
public class BeanManager<T> {
private final BeanPersister persister;
private final BeanDescriptor<T> descriptor;
public BeanManager(BeanDescriptor<T> descriptor, BeanPersister persister) {
this.descriptor = descriptor;
this.persister = persister;
}
/**
* Return the associated BeanPersister.
*/
public BeanPersister getBeanPersister() {
return persister;
}
/**
* Return the BeanDescriptor.
*/
public BeanDescriptor<T> getBeanDescriptor() {
return descriptor;
}
/**
* Return true if this bean type is an LDAP entity type.
*/
public boolean isLdapEntityType() {
return descriptor.isLdapEntityType();
}
}
package com.avaje.ebeaninternal.server.deploy;
import com.avaje.ebeaninternal.server.persist.BeanPersister;
/**
* Holds the BeanDescriptor and its associated BeanPersister.
*/
public class BeanManager<T> {
private final BeanPersister persister;
private final BeanDescriptor<T> descriptor;
public BeanManager(BeanDescriptor<T> descriptor, BeanPersister persister) {
this.descriptor = descriptor;
this.persister = persister;
}
/**
* Return the associated BeanPersister.
*/
public BeanPersister getBeanPersister() {
return persister;
}
/**
* Return the BeanDescriptor.
*/
public BeanDescriptor<T> getBeanDescriptor() {
return descriptor;
}
/**
* Return true if this bean type is an LDAP entity type.
*/
public boolean isLdapEntityType() {
return descriptor.isLdapEntityType();
}
}
@@ -1,46 +1,27 @@
/**
* Copyright (C) 2006 Robin Bygrave
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy;
import com.avaje.ebean.config.ServerConfig;
import com.avaje.ebean.config.dbplatform.DatabasePlatform;
import com.avaje.ebeaninternal.server.persist.BeanPersister;
import com.avaje.ebeaninternal.server.persist.BeanPersisterFactory;
import com.avaje.ebeaninternal.server.persist.dml.DmlBeanPersisterFactory;
/**
* Creates BeanManagers.
*/
public class BeanManagerFactory {
final BeanPersisterFactory peristerFactory;
public BeanManagerFactory(ServerConfig config, DatabasePlatform dbPlatform) {
peristerFactory = new DmlBeanPersisterFactory(dbPlatform);
}
public <T> BeanManager<T> create(BeanDescriptor<T> desc) {
BeanPersister persister = peristerFactory.create(desc);
return new BeanManager<T>(desc, persister);
}
}
package com.avaje.ebeaninternal.server.deploy;
import com.avaje.ebean.config.ServerConfig;
import com.avaje.ebean.config.dbplatform.DatabasePlatform;
import com.avaje.ebeaninternal.server.persist.BeanPersister;
import com.avaje.ebeaninternal.server.persist.BeanPersisterFactory;
import com.avaje.ebeaninternal.server.persist.dml.DmlBeanPersisterFactory;
/**
* Creates BeanManagers.
*/
public class BeanManagerFactory {
final BeanPersisterFactory peristerFactory;
public BeanManagerFactory(ServerConfig config, DatabasePlatform dbPlatform) {
peristerFactory = new DmlBeanPersisterFactory(dbPlatform);
}
public <T> BeanManager<T> create(BeanDescriptor<T> desc) {
BeanPersister persister = peristerFactory.create(desc);
return new BeanManager<T>(desc, persister);
}
}
File diff suppressed because it is too large Load Diff
@@ -1,402 +1,383 @@
/**
* Copyright (C) 2006 Robin Bygrave
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.persistence.PersistenceException;
import com.avaje.ebean.bean.EntityBean;
import com.avaje.ebeaninternal.server.core.InternString;
import com.avaje.ebeaninternal.server.deploy.id.IdBinder;
import com.avaje.ebeaninternal.server.deploy.id.ImportedId;
import com.avaje.ebeaninternal.server.deploy.id.ImportedIdEmbedded;
import com.avaje.ebeaninternal.server.deploy.id.ImportedIdMultiple;
import com.avaje.ebeaninternal.server.deploy.id.ImportedIdSimple;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssoc;
import com.avaje.ebeaninternal.server.el.ElPropertyChainBuilder;
import com.avaje.ebeaninternal.server.el.ElPropertyValue;
/**
* Abstract base for properties mapped to an associated bean, list, set or map.
*/
public abstract class BeanPropertyAssoc<T> extends BeanProperty {
private static final Logger logger = Logger.getLogger(BeanPropertyAssoc.class.getName());
/**
* The descriptor of the target. This MUST be initialised after construction
* so as to avoid a dependency loop between BeanDescriptors.
*/
BeanDescriptor<T> targetDescriptor;
IdBinder targetIdBinder;
InheritInfo targetInheritInfo;
String targetIdProperty;
/**
* Persist settings.
*/
final BeanCascadeInfo cascadeInfo;
/**
* Join between the beans.
*/
final TableJoin tableJoin;
/**
* The type of the joined bean.
*/
final Class<T> targetType;
/**
* The join table information.
*/
final BeanTable beanTable;
final String mappedBy;
/**
* Whether the associated join type should be an outer join.
*/
final boolean isOuterJoin;
String extraWhere;
boolean saveRecurseSkippable;
boolean deleteRecurseSkippable;
/**
* Construct the property.
*/
public BeanPropertyAssoc(BeanDescriptorMap owner, BeanDescriptor<?> descriptor, DeployBeanPropertyAssoc<T> deploy) {
super(owner, descriptor, deploy);
this.extraWhere = InternString.intern(deploy.getExtraWhere());
this.isOuterJoin = deploy.isOuterJoin();
this.beanTable = deploy.getBeanTable();
this.mappedBy = InternString.intern(deploy.getMappedBy());
this.tableJoin = new TableJoin(deploy.getTableJoin(), null);
this.targetType = deploy.getTargetType();
this.cascadeInfo = deploy.getCascadeInfo();
}
/**
* Initialise post construction.
*/
@Override
public void initialise() {
// this *MUST* execute after the BeanDescriptor is
// put into the map to stop infinite recursion
if (!isTransient){
targetDescriptor = descriptor.getBeanDescriptor(targetType);
targetIdBinder = targetDescriptor.getIdBinder();
targetInheritInfo = targetDescriptor.getInheritInfo();
saveRecurseSkippable = targetDescriptor.isSaveRecurseSkippable();
deleteRecurseSkippable = targetDescriptor.isDeleteRecurseSkippable();
cascadeValidate = cascadeInfo.isValidate();
if (!targetIdBinder.isComplexId()){
targetIdProperty = targetIdBinder.getIdProperty();
}
}
}
/**
* Create a ElPropertyValue for a *ToOne or *ToMany.
*/
protected ElPropertyValue createElPropertyValue(String propName, String remainder, ElPropertyChainBuilder chain, boolean propertyDeploy) {
// associated or embedded bean
BeanDescriptor<?> embDesc = getTargetDescriptor();
if (chain == null) {
chain = new ElPropertyChainBuilder(isEmbedded(), propName);
}
chain.add(this);
if (containsMany()) {
chain.setContainsMany(true);
}
return embDesc.buildElGetValue(remainder, chain, propertyDeploy);
}
/**
* Add table join with table alias based on prefix.
*/
public boolean addJoin(boolean forceOuterJoin, String prefix, DbSqlContext ctx) {
return tableJoin.addJoin(forceOuterJoin, prefix, ctx);
}
/**
* Add table join with explicit table alias.
*/
public boolean addJoin(boolean forceOuterJoin, String a1, String a2, DbSqlContext ctx) {
return tableJoin.addJoin(forceOuterJoin, a1, a2, ctx);
}
/**
* Add table join with explicit table alias.
*/
public void addInnerJoin(String a1, String a2, DbSqlContext ctx) {
tableJoin.addInnerJoin(a1, a2, ctx);
}
/**
* Return false.
*/
public boolean isScalar() {
return false;
}
/**
* Return the mappedBy property.
* This will be null on the owning side.
*/
public String getMappedBy() {
return mappedBy;
}
/**
* Return the Id property of the target entity type.
* <p>
* This will return null for multiple Id properties.
* </p>
*/
public String getTargetIdProperty() {
return targetIdProperty;
}
/**
* Return the BeanDescriptor of the target.
*/
public BeanDescriptor<T> getTargetDescriptor() {
return targetDescriptor;
}
public boolean isSaveRecurseSkippable(Object bean) {
if (!saveRecurseSkippable){
// we have to saveRecurse even if the bean is not dirty
// as this bean has cascade save on some of its properties
return false;
}
if (bean instanceof EntityBean){
return !((EntityBean)bean)._ebean_getIntercept().isNewOrDirty();
} else {
// we don't know so we say no
return false;
}
}
/**
* Return true if save can be skipped for unmodified bean(s) of this
* property.
* <p>
* That is, if a bean of this property is unmodified we don't need to
* saveRecurse because none of its associated beans have cascade save set to
* true.
* </p>
*/
public boolean isSaveRecurseSkippable() {
return saveRecurseSkippable;
}
/**
* Similar to isSaveRecurseSkippable but in terms of delete.
*/
public boolean isDeleteRecurseSkippable() {
return deleteRecurseSkippable;
}
/**
* Return true if the unique id properties are all not null for this bean.
*/
public boolean hasId(Object bean) {
BeanDescriptor<?> targetDesc = getTargetDescriptor();
BeanProperty[] uids = targetDesc.propertiesId();
for (int i = 0; i < uids.length; i++) {
Object value = uids[i].getValue(bean);
if (value == null) {
return false;
}
}
// all the unique properties are non-null
return true;
}
/**
* Return the type of the target.
* <p>
* This is the class of the associated bean, or beans contained in a list,
* set or map.
* </p>
*/
public Class<?> getTargetType() {
return targetType;
}
/**
* Return an extra clause to add to the query for loading or joining
* to this bean type.
*/
public String getExtraWhere() {
return extraWhere;
}
/**
* Return if this association should use an Outer join.
*/
public boolean isOuterJoin() {
return isOuterJoin;
}
/**
* Return true if this association is updateable.
*/
public boolean isUpdateable() {
if (tableJoin.columns().length > 0) {
return tableJoin.columns()[0].isUpdateable();
}
return true;
}
/**
* Return true if this association is insertable.
*/
public boolean isInsertable() {
if (tableJoin.columns().length > 0) {
return tableJoin.columns()[0].isInsertable();
}
return true;
}
/**
* return the join to use for the bean.
*/
public TableJoin getTableJoin() {
return tableJoin;
}
/**
* Return the BeanTable for this association.
* <p>
* This has the table name which is used to determine the relationship for
* this association.
* </p>
*/
public BeanTable getBeanTable() {
return beanTable;
}
/**
* Get the persist info.
*/
public BeanCascadeInfo getCascadeInfo() {
return cascadeInfo;
}
/**
* Build the list of imported property. Matches BeanProperty from the target
* descriptor back to local database columns in the TableJoin.
*/
protected ImportedId createImportedId(BeanPropertyAssoc<?> owner, BeanDescriptor<?> target, TableJoin join) {
BeanProperty[] props = target.propertiesId();
BeanProperty[] others = target.propertiesBaseScalar();
if (descriptor.isSqlSelectBased()){
String dbColumn = owner.getDbColumn();
return new ImportedIdSimple(owner, dbColumn, props[0], 0);
}
TableJoinColumn[] cols = join.columns();
if (props.length == 1) {
if (!props[0].isEmbedded()) {
// simple single scalar id
if (cols.length != 1){
String msg = "No Imported Id column for ["+props[0]+"] in table ["+join.getTable()+"]";
logger.log(Level.SEVERE, msg);
return null;
} else {
return createImportedScalar(owner, cols[0], props, others);
}
} else {
// embedded id
BeanPropertyAssocOne<?> embProp = (BeanPropertyAssocOne<?>)props[0];
BeanProperty[] embBaseProps = embProp.getTargetDescriptor().propertiesBaseScalar();
ImportedIdSimple[] scalars = createImportedList(owner, cols, embBaseProps, others);
return new ImportedIdEmbedded(owner, embProp, scalars);
}
} else {
// Concatenated key that is not embedded
ImportedIdSimple[] scalars = createImportedList(owner, cols, props, others);
return new ImportedIdMultiple(owner, scalars);
}
}
private ImportedIdSimple[] createImportedList(BeanPropertyAssoc<?> owner, TableJoinColumn[] cols, BeanProperty[] props, BeanProperty[] others) {
ArrayList<ImportedIdSimple> list = new ArrayList<ImportedIdSimple>();
for (int i = 0; i < cols.length; i++) {
list.add(createImportedScalar(owner, cols[i], props, others));
}
return ImportedIdSimple.sort(list);
}
private ImportedIdSimple createImportedScalar(BeanPropertyAssoc<?> owner, TableJoinColumn col, BeanProperty[] props, BeanProperty[] others) {
String matchColumn = col.getForeignDbColumn();
String localColumn = col.getLocalDbColumn();
for (int j = 0; j < props.length; j++) {
if (props[j].getDbColumn().equalsIgnoreCase(matchColumn)) {
return new ImportedIdSimple(owner, localColumn, props[j], j);
}
}
for (int j = 0; j < others.length; j++) {
if (others[j].getDbColumn().equalsIgnoreCase(matchColumn)) {
return new ImportedIdSimple(owner, localColumn, others[j], j+props.length);
}
}
String msg = "Error with the Join on ["+getFullBeanName()
+"]. Could not find the local match for ["+matchColumn+"] "//in table["+searchTable+"]?"
+" Perhaps an error in a @JoinColumn";
throw new PersistenceException(msg);
}
}
package com.avaje.ebeaninternal.server.deploy;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.persistence.PersistenceException;
import com.avaje.ebean.bean.EntityBean;
import com.avaje.ebeaninternal.server.core.InternString;
import com.avaje.ebeaninternal.server.deploy.id.IdBinder;
import com.avaje.ebeaninternal.server.deploy.id.ImportedId;
import com.avaje.ebeaninternal.server.deploy.id.ImportedIdEmbedded;
import com.avaje.ebeaninternal.server.deploy.id.ImportedIdMultiple;
import com.avaje.ebeaninternal.server.deploy.id.ImportedIdSimple;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssoc;
import com.avaje.ebeaninternal.server.el.ElPropertyChainBuilder;
import com.avaje.ebeaninternal.server.el.ElPropertyValue;
/**
* Abstract base for properties mapped to an associated bean, list, set or map.
*/
public abstract class BeanPropertyAssoc<T> extends BeanProperty {
private static final Logger logger = Logger.getLogger(BeanPropertyAssoc.class.getName());
/**
* The descriptor of the target. This MUST be initialised after construction
* so as to avoid a dependency loop between BeanDescriptors.
*/
BeanDescriptor<T> targetDescriptor;
IdBinder targetIdBinder;
InheritInfo targetInheritInfo;
String targetIdProperty;
/**
* Persist settings.
*/
final BeanCascadeInfo cascadeInfo;
/**
* Join between the beans.
*/
final TableJoin tableJoin;
/**
* The type of the joined bean.
*/
final Class<T> targetType;
/**
* The join table information.
*/
final BeanTable beanTable;
final String mappedBy;
/**
* Whether the associated join type should be an outer join.
*/
final boolean isOuterJoin;
String extraWhere;
boolean saveRecurseSkippable;
boolean deleteRecurseSkippable;
/**
* Construct the property.
*/
public BeanPropertyAssoc(BeanDescriptorMap owner, BeanDescriptor<?> descriptor, DeployBeanPropertyAssoc<T> deploy) {
super(owner, descriptor, deploy);
this.extraWhere = InternString.intern(deploy.getExtraWhere());
this.isOuterJoin = deploy.isOuterJoin();
this.beanTable = deploy.getBeanTable();
this.mappedBy = InternString.intern(deploy.getMappedBy());
this.tableJoin = new TableJoin(deploy.getTableJoin(), null);
this.targetType = deploy.getTargetType();
this.cascadeInfo = deploy.getCascadeInfo();
}
/**
* Initialise post construction.
*/
@Override
public void initialise() {
// this *MUST* execute after the BeanDescriptor is
// put into the map to stop infinite recursion
if (!isTransient){
targetDescriptor = descriptor.getBeanDescriptor(targetType);
targetIdBinder = targetDescriptor.getIdBinder();
targetInheritInfo = targetDescriptor.getInheritInfo();
saveRecurseSkippable = targetDescriptor.isSaveRecurseSkippable();
deleteRecurseSkippable = targetDescriptor.isDeleteRecurseSkippable();
cascadeValidate = cascadeInfo.isValidate();
if (!targetIdBinder.isComplexId()){
targetIdProperty = targetIdBinder.getIdProperty();
}
}
}
/**
* Create a ElPropertyValue for a *ToOne or *ToMany.
*/
protected ElPropertyValue createElPropertyValue(String propName, String remainder, ElPropertyChainBuilder chain, boolean propertyDeploy) {
// associated or embedded bean
BeanDescriptor<?> embDesc = getTargetDescriptor();
if (chain == null) {
chain = new ElPropertyChainBuilder(isEmbedded(), propName);
}
chain.add(this);
if (containsMany()) {
chain.setContainsMany(true);
}
return embDesc.buildElGetValue(remainder, chain, propertyDeploy);
}
/**
* Add table join with table alias based on prefix.
*/
public boolean addJoin(boolean forceOuterJoin, String prefix, DbSqlContext ctx) {
return tableJoin.addJoin(forceOuterJoin, prefix, ctx);
}
/**
* Add table join with explicit table alias.
*/
public boolean addJoin(boolean forceOuterJoin, String a1, String a2, DbSqlContext ctx) {
return tableJoin.addJoin(forceOuterJoin, a1, a2, ctx);
}
/**
* Add table join with explicit table alias.
*/
public void addInnerJoin(String a1, String a2, DbSqlContext ctx) {
tableJoin.addInnerJoin(a1, a2, ctx);
}
/**
* Return false.
*/
public boolean isScalar() {
return false;
}
/**
* Return the mappedBy property.
* This will be null on the owning side.
*/
public String getMappedBy() {
return mappedBy;
}
/**
* Return the Id property of the target entity type.
* <p>
* This will return null for multiple Id properties.
* </p>
*/
public String getTargetIdProperty() {
return targetIdProperty;
}
/**
* Return the BeanDescriptor of the target.
*/
public BeanDescriptor<T> getTargetDescriptor() {
return targetDescriptor;
}
public boolean isSaveRecurseSkippable(Object bean) {
if (!saveRecurseSkippable){
// we have to saveRecurse even if the bean is not dirty
// as this bean has cascade save on some of its properties
return false;
}
if (bean instanceof EntityBean){
return !((EntityBean)bean)._ebean_getIntercept().isNewOrDirty();
} else {
// we don't know so we say no
return false;
}
}
/**
* Return true if save can be skipped for unmodified bean(s) of this
* property.
* <p>
* That is, if a bean of this property is unmodified we don't need to
* saveRecurse because none of its associated beans have cascade save set to
* true.
* </p>
*/
public boolean isSaveRecurseSkippable() {
return saveRecurseSkippable;
}
/**
* Similar to isSaveRecurseSkippable but in terms of delete.
*/
public boolean isDeleteRecurseSkippable() {
return deleteRecurseSkippable;
}
/**
* Return true if the unique id properties are all not null for this bean.
*/
public boolean hasId(Object bean) {
BeanDescriptor<?> targetDesc = getTargetDescriptor();
BeanProperty[] uids = targetDesc.propertiesId();
for (int i = 0; i < uids.length; i++) {
Object value = uids[i].getValue(bean);
if (value == null) {
return false;
}
}
// all the unique properties are non-null
return true;
}
/**
* Return the type of the target.
* <p>
* This is the class of the associated bean, or beans contained in a list,
* set or map.
* </p>
*/
public Class<?> getTargetType() {
return targetType;
}
/**
* Return an extra clause to add to the query for loading or joining
* to this bean type.
*/
public String getExtraWhere() {
return extraWhere;
}
/**
* Return if this association should use an Outer join.
*/
public boolean isOuterJoin() {
return isOuterJoin;
}
/**
* Return true if this association is updateable.
*/
public boolean isUpdateable() {
if (tableJoin.columns().length > 0) {
return tableJoin.columns()[0].isUpdateable();
}
return true;
}
/**
* Return true if this association is insertable.
*/
public boolean isInsertable() {
if (tableJoin.columns().length > 0) {
return tableJoin.columns()[0].isInsertable();
}
return true;
}
/**
* return the join to use for the bean.
*/
public TableJoin getTableJoin() {
return tableJoin;
}
/**
* Return the BeanTable for this association.
* <p>
* This has the table name which is used to determine the relationship for
* this association.
* </p>
*/
public BeanTable getBeanTable() {
return beanTable;
}
/**
* Get the persist info.
*/
public BeanCascadeInfo getCascadeInfo() {
return cascadeInfo;
}
/**
* Build the list of imported property. Matches BeanProperty from the target
* descriptor back to local database columns in the TableJoin.
*/
protected ImportedId createImportedId(BeanPropertyAssoc<?> owner, BeanDescriptor<?> target, TableJoin join) {
BeanProperty[] props = target.propertiesId();
BeanProperty[] others = target.propertiesBaseScalar();
if (descriptor.isSqlSelectBased()){
String dbColumn = owner.getDbColumn();
return new ImportedIdSimple(owner, dbColumn, props[0], 0);
}
TableJoinColumn[] cols = join.columns();
if (props.length == 1) {
if (!props[0].isEmbedded()) {
// simple single scalar id
if (cols.length != 1){
String msg = "No Imported Id column for ["+props[0]+"] in table ["+join.getTable()+"]";
logger.log(Level.SEVERE, msg);
return null;
} else {
return createImportedScalar(owner, cols[0], props, others);
}
} else {
// embedded id
BeanPropertyAssocOne<?> embProp = (BeanPropertyAssocOne<?>)props[0];
BeanProperty[] embBaseProps = embProp.getTargetDescriptor().propertiesBaseScalar();
ImportedIdSimple[] scalars = createImportedList(owner, cols, embBaseProps, others);
return new ImportedIdEmbedded(owner, embProp, scalars);
}
} else {
// Concatenated key that is not embedded
ImportedIdSimple[] scalars = createImportedList(owner, cols, props, others);
return new ImportedIdMultiple(owner, scalars);
}
}
private ImportedIdSimple[] createImportedList(BeanPropertyAssoc<?> owner, TableJoinColumn[] cols, BeanProperty[] props, BeanProperty[] others) {
ArrayList<ImportedIdSimple> list = new ArrayList<ImportedIdSimple>();
for (int i = 0; i < cols.length; i++) {
list.add(createImportedScalar(owner, cols[i], props, others));
}
return ImportedIdSimple.sort(list);
}
private ImportedIdSimple createImportedScalar(BeanPropertyAssoc<?> owner, TableJoinColumn col, BeanProperty[] props, BeanProperty[] others) {
String matchColumn = col.getForeignDbColumn();
String localColumn = col.getLocalDbColumn();
for (int j = 0; j < props.length; j++) {
if (props[j].getDbColumn().equalsIgnoreCase(matchColumn)) {
return new ImportedIdSimple(owner, localColumn, props[j], j);
}
}
for (int j = 0; j < others.length; j++) {
if (others[j].getDbColumn().equalsIgnoreCase(matchColumn)) {
return new ImportedIdSimple(owner, localColumn, others[j], j+props.length);
}
}
String msg = "Error with the Join on ["+getFullBeanName()
+"]. Could not find the local match for ["+matchColumn+"] "//in table["+searchTable+"]?"
+" Perhaps an error in a @JoinColumn";
throw new PersistenceException(msg);
}
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -1,229 +1,210 @@
/**
* Copyright (C) 2009 Robin Bygrave
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy;
import com.avaje.ebean.config.ScalarTypeConverter;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyCompound;
import com.avaje.ebeaninternal.server.el.ElPropertyChainBuilder;
import com.avaje.ebeaninternal.server.el.ElPropertyValue;
import com.avaje.ebeaninternal.server.query.SqlBeanLoad;
import com.avaje.ebeaninternal.server.text.json.ReadJsonContext;
import com.avaje.ebeaninternal.server.text.json.WriteJsonContext;
import com.avaje.ebeaninternal.server.type.CtCompoundProperty;
import com.avaje.ebeaninternal.server.type.CtCompoundPropertyElAdapter;
import com.avaje.ebeaninternal.server.type.CtCompoundType;
import java.sql.SQLException;
import java.util.LinkedHashMap;
import java.util.List;
/**
* Property mapped to an Immutable Compound Value Object.
* <p>
* An Immutable Compound Value Object is similar to an Embedded bean but it
* doesn't require enhancement and MUST be treated as an Immutable type.
* </p>
*/
public class BeanPropertyCompound extends BeanProperty {
private final CtCompoundType<?> compoundType;
/**
* Type Converter for scala.Option and similar type wrapping.
*/
@SuppressWarnings("rawtypes")
private final ScalarTypeConverter typeConverter;
private final BeanProperty[] scalarProperties;
private final LinkedHashMap<String, BeanProperty> propertyMap = new LinkedHashMap<String, BeanProperty>();
private final LinkedHashMap<String, CtCompoundPropertyElAdapter> nonScalarMap = new LinkedHashMap<String, CtCompoundPropertyElAdapter>();
private final BeanPropertyCompoundRoot root;
/**
* Create the property.
*/
public BeanPropertyCompound(BeanDescriptorMap owner, BeanDescriptor<?> descriptor, DeployBeanPropertyCompound deploy) {
super(owner, descriptor, deploy);
this.compoundType = deploy.getCompoundType();
this.typeConverter = deploy.getTypeConverter();
this.root = deploy.getFlatProperties(owner, descriptor);
this.scalarProperties = root.getScalarProperties();
for (int i = 0; i < scalarProperties.length; i++) {
propertyMap.put(scalarProperties[i].getName(), scalarProperties[i]);
}
List<CtCompoundProperty> nonScalarPropsList = root.getNonScalarProperties();
for (int i = 0; i < nonScalarPropsList.size(); i++) {
CtCompoundProperty ctProp = nonScalarPropsList.get(i);
CtCompoundPropertyElAdapter adapter = new CtCompoundPropertyElAdapter(ctProp);
nonScalarMap.put(ctProp.getRelativeName(), adapter);
}
}
@Override
public void initialise() {
// do nothing for normal BeanProperty
if (!isTransient && compoundType == null) {
String msg = "No cvoInternalType assigned to " + descriptor.getFullName() + "." + getName();
throw new RuntimeException(msg);
}
}
@Override
public void setDeployOrder(int deployOrder) {
this.deployOrder = deployOrder;
for (CtCompoundPropertyElAdapter adapter : nonScalarMap.values()) {
adapter.setDeployOrder(deployOrder);
}
}
/**
* Get the underlying compound type.
*/
@SuppressWarnings("unchecked")
public Object getValueUnderlying(Object bean) {
Object value = getValue(bean);
if (typeConverter != null){
value = typeConverter.unwrapValue(value);
}
return value;
}
@Override
public Object getValue(Object bean) {
return super.getValue(bean);
}
@Override
public Object getValueIntercept(Object bean) {
return super.getValueIntercept(bean);
}
@Override
public void setValue(Object bean, Object value) {
super.setValue(bean, value);
}
@Override
public void setValueIntercept(Object bean, Object value) {
super.setValueIntercept(bean, value);
}
public ElPropertyValue buildElPropertyValue(String propName, String remainder, ElPropertyChainBuilder chain, boolean propertyDeploy) {
if (chain == null) {
chain = new ElPropertyChainBuilder(true, propName);
}
// first add this property
chain.add(this);
// handle all the rest of the chain handled by the
// BeanProperty (all depth for nested compound type)
BeanProperty p = propertyMap.get(remainder);
if (p != null) {
return chain.add(p).build();
}
CtCompoundPropertyElAdapter elAdapter = nonScalarMap.get(remainder);
if (elAdapter == null) {
throw new RuntimeException("property [" + remainder + "] not found in " + getFullBeanName());
}
return chain.add(elAdapter).build();
}
@Override
public void appendSelect(DbSqlContext ctx, boolean subQuery) {
if (!isTransient) {
for (int i = 0; i < scalarProperties.length; i++) {
scalarProperties[i].appendSelect(ctx, subQuery);
}
}
}
public BeanProperty[] getScalarProperties() {
return scalarProperties;
}
@Override
public Object readSet(DbReadContext ctx, Object bean, Class<?> type) throws SQLException {
boolean assignable = (type == null || owningType.isAssignableFrom(type));
Object v = compoundType.read(ctx.getDataReader());
if (assignable) {
setValue(bean, v);
}
return v;
}
/**
* Read the data from the resultSet effectively ignoring it and returning
* null.
*/
@SuppressWarnings("unchecked")
@Override
public Object read(DbReadContext ctx) throws SQLException {
Object v = compoundType.read(ctx.getDataReader());
if (typeConverter != null){
v = typeConverter.wrapValue(v);
}
return v;
}
@Override
public void loadIgnore(DbReadContext ctx) {
compoundType.loadIgnore(ctx.getDataReader());
}
@Override
public void load(SqlBeanLoad sqlBeanLoad) throws SQLException {
sqlBeanLoad.load(this);
}
@Override
public Object elGetReference(Object bean) {
return bean;
}
public void jsonWrite(WriteJsonContext ctx, Object bean) {
Object valueObject = getValueIntercept(bean);
compoundType.jsonWrite(ctx, valueObject, name);
}
public void jsonRead(ReadJsonContext ctx, Object bean){
Object objValue = compoundType.jsonRead(ctx);
setValue(bean, objValue);
}
}
package com.avaje.ebeaninternal.server.deploy;
import com.avaje.ebean.config.ScalarTypeConverter;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyCompound;
import com.avaje.ebeaninternal.server.el.ElPropertyChainBuilder;
import com.avaje.ebeaninternal.server.el.ElPropertyValue;
import com.avaje.ebeaninternal.server.query.SqlBeanLoad;
import com.avaje.ebeaninternal.server.text.json.ReadJsonContext;
import com.avaje.ebeaninternal.server.text.json.WriteJsonContext;
import com.avaje.ebeaninternal.server.type.CtCompoundProperty;
import com.avaje.ebeaninternal.server.type.CtCompoundPropertyElAdapter;
import com.avaje.ebeaninternal.server.type.CtCompoundType;
import java.sql.SQLException;
import java.util.LinkedHashMap;
import java.util.List;
/**
* Property mapped to an Immutable Compound Value Object.
* <p>
* An Immutable Compound Value Object is similar to an Embedded bean but it
* doesn't require enhancement and MUST be treated as an Immutable type.
* </p>
*/
public class BeanPropertyCompound extends BeanProperty {
private final CtCompoundType<?> compoundType;
/**
* Type Converter for scala.Option and similar type wrapping.
*/
@SuppressWarnings("rawtypes")
private final ScalarTypeConverter typeConverter;
private final BeanProperty[] scalarProperties;
private final LinkedHashMap<String, BeanProperty> propertyMap = new LinkedHashMap<String, BeanProperty>();
private final LinkedHashMap<String, CtCompoundPropertyElAdapter> nonScalarMap = new LinkedHashMap<String, CtCompoundPropertyElAdapter>();
private final BeanPropertyCompoundRoot root;
/**
* Create the property.
*/
public BeanPropertyCompound(BeanDescriptorMap owner, BeanDescriptor<?> descriptor, DeployBeanPropertyCompound deploy) {
super(owner, descriptor, deploy);
this.compoundType = deploy.getCompoundType();
this.typeConverter = deploy.getTypeConverter();
this.root = deploy.getFlatProperties(owner, descriptor);
this.scalarProperties = root.getScalarProperties();
for (int i = 0; i < scalarProperties.length; i++) {
propertyMap.put(scalarProperties[i].getName(), scalarProperties[i]);
}
List<CtCompoundProperty> nonScalarPropsList = root.getNonScalarProperties();
for (int i = 0; i < nonScalarPropsList.size(); i++) {
CtCompoundProperty ctProp = nonScalarPropsList.get(i);
CtCompoundPropertyElAdapter adapter = new CtCompoundPropertyElAdapter(ctProp);
nonScalarMap.put(ctProp.getRelativeName(), adapter);
}
}
@Override
public void initialise() {
// do nothing for normal BeanProperty
if (!isTransient && compoundType == null) {
String msg = "No cvoInternalType assigned to " + descriptor.getFullName() + "." + getName();
throw new RuntimeException(msg);
}
}
@Override
public void setDeployOrder(int deployOrder) {
this.deployOrder = deployOrder;
for (CtCompoundPropertyElAdapter adapter : nonScalarMap.values()) {
adapter.setDeployOrder(deployOrder);
}
}
/**
* Get the underlying compound type.
*/
@SuppressWarnings("unchecked")
public Object getValueUnderlying(Object bean) {
Object value = getValue(bean);
if (typeConverter != null){
value = typeConverter.unwrapValue(value);
}
return value;
}
@Override
public Object getValue(Object bean) {
return super.getValue(bean);
}
@Override
public Object getValueIntercept(Object bean) {
return super.getValueIntercept(bean);
}
@Override
public void setValue(Object bean, Object value) {
super.setValue(bean, value);
}
@Override
public void setValueIntercept(Object bean, Object value) {
super.setValueIntercept(bean, value);
}
public ElPropertyValue buildElPropertyValue(String propName, String remainder, ElPropertyChainBuilder chain, boolean propertyDeploy) {
if (chain == null) {
chain = new ElPropertyChainBuilder(true, propName);
}
// first add this property
chain.add(this);
// handle all the rest of the chain handled by the
// BeanProperty (all depth for nested compound type)
BeanProperty p = propertyMap.get(remainder);
if (p != null) {
return chain.add(p).build();
}
CtCompoundPropertyElAdapter elAdapter = nonScalarMap.get(remainder);
if (elAdapter == null) {
throw new RuntimeException("property [" + remainder + "] not found in " + getFullBeanName());
}
return chain.add(elAdapter).build();
}
@Override
public void appendSelect(DbSqlContext ctx, boolean subQuery) {
if (!isTransient) {
for (int i = 0; i < scalarProperties.length; i++) {
scalarProperties[i].appendSelect(ctx, subQuery);
}
}
}
public BeanProperty[] getScalarProperties() {
return scalarProperties;
}
@Override
public Object readSet(DbReadContext ctx, Object bean, Class<?> type) throws SQLException {
boolean assignable = (type == null || owningType.isAssignableFrom(type));
Object v = compoundType.read(ctx.getDataReader());
if (assignable) {
setValue(bean, v);
}
return v;
}
/**
* Read the data from the resultSet effectively ignoring it and returning
* null.
*/
@SuppressWarnings("unchecked")
@Override
public Object read(DbReadContext ctx) throws SQLException {
Object v = compoundType.read(ctx.getDataReader());
if (typeConverter != null){
v = typeConverter.wrapValue(v);
}
return v;
}
@Override
public void loadIgnore(DbReadContext ctx) {
compoundType.loadIgnore(ctx.getDataReader());
}
@Override
public void load(SqlBeanLoad sqlBeanLoad) throws SQLException {
sqlBeanLoad.load(this);
}
@Override
public Object elGetReference(Object bean) {
return bean;
}
public void jsonWrite(WriteJsonContext ctx, Object bean) {
Object valueObject = getValueIntercept(bean);
compoundType.jsonWrite(ctx, valueObject, name);
}
public void jsonRead(ReadJsonContext ctx, Object bean){
Object objValue = compoundType.jsonRead(ctx);
setValue(bean, objValue);
}
}
@@ -1,129 +1,110 @@
/**
* Copyright (C) 2009 Authors
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import com.avaje.ebean.bean.EntityBean;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
import com.avaje.ebeaninternal.server.reflect.BeanReflectSetter;
import com.avaje.ebeaninternal.server.type.CtCompoundProperty;
/**
* Represents the root BeanProperty for properties of a compound type.
* <p>
* Holds all the scalar and non-scalar properties of the compound type. The
* scalar properties match to DB columns and the non-scalar ones are here solely
* to support EL expression language for nested compound types.
* </p>
*
* @author rbygrave
*/
public class BeanPropertyCompoundRoot {
private final BeanReflectSetter setter;
/**
* The method used to write the property.
*/
private final Method writeMethod;
private final String name;
private final String fullBeanName;
private final LinkedHashMap<String, BeanPropertyCompoundScalar> propMap;
private final ArrayList<BeanPropertyCompoundScalar> propList;
private List<CtCompoundProperty> nonScalarProperties;
public BeanPropertyCompoundRoot(DeployBeanProperty deploy) {
this.fullBeanName = deploy.getFullBeanName();
this.name = deploy.getName();
this.setter = deploy.getSetter();
this.writeMethod = deploy.getWriteMethod();
this.propList = new ArrayList<BeanPropertyCompoundScalar>();
this.propMap = new LinkedHashMap<String, BeanPropertyCompoundScalar>();
}
public BeanProperty[] getScalarProperties() {
return propList.toArray(new BeanProperty[propList.size()]);
}
public void register(BeanPropertyCompoundScalar prop) {
propList.add(prop);
propMap.put(prop.getName(), prop);
}
public BeanPropertyCompoundScalar getCompoundScalarProperty(String propName) {
return propMap.get(propName);
}
public List<CtCompoundProperty> getNonScalarProperties() {
return nonScalarProperties;
}
public void setNonScalarProperties(List<CtCompoundProperty> nonScalarProperties) {
this.nonScalarProperties = nonScalarProperties;
}
/**
* Set the value of the property without interception or
* PropertyChangeSupport.
*/
public void setRootValue(Object bean, Object value) {
try {
if (bean instanceof EntityBean) {
setter.set(bean, value);
} else {
Object[] args = new Object[1];
args[0] = value;
writeMethod.invoke(bean, args);
}
} catch (Exception ex) {
String beanType = bean == null ? "null" : bean.getClass().getName();
String msg = "set " + name + " with arg[" + value + "] on ["+fullBeanName+"] with type[" + beanType + "] threw error";
throw new RuntimeException(msg, ex);
}
}
/**
* Set the value of the property.
*/
public void setRootValueIntercept(Object bean, Object value) {
try {
if (bean instanceof EntityBean) {
setter.setIntercept(bean, value);
} else {
Object[] args = new Object[1];
args[0] = value;
writeMethod.invoke(bean, args);
}
} catch (Exception ex) {
String beanType = bean == null ? "null" : bean.getClass().getName();
String msg = "setIntercept " + name + " arg[" + value + "] on ["+fullBeanName+"] with type[" + beanType + "] threw error";
throw new RuntimeException(msg, ex);
}
}
}
package com.avaje.ebeaninternal.server.deploy;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import com.avaje.ebean.bean.EntityBean;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
import com.avaje.ebeaninternal.server.reflect.BeanReflectSetter;
import com.avaje.ebeaninternal.server.type.CtCompoundProperty;
/**
* Represents the root BeanProperty for properties of a compound type.
* <p>
* Holds all the scalar and non-scalar properties of the compound type. The
* scalar properties match to DB columns and the non-scalar ones are here solely
* to support EL expression language for nested compound types.
* </p>
*
* @author rbygrave
*/
public class BeanPropertyCompoundRoot {
private final BeanReflectSetter setter;
/**
* The method used to write the property.
*/
private final Method writeMethod;
private final String name;
private final String fullBeanName;
private final LinkedHashMap<String, BeanPropertyCompoundScalar> propMap;
private final ArrayList<BeanPropertyCompoundScalar> propList;
private List<CtCompoundProperty> nonScalarProperties;
public BeanPropertyCompoundRoot(DeployBeanProperty deploy) {
this.fullBeanName = deploy.getFullBeanName();
this.name = deploy.getName();
this.setter = deploy.getSetter();
this.writeMethod = deploy.getWriteMethod();
this.propList = new ArrayList<BeanPropertyCompoundScalar>();
this.propMap = new LinkedHashMap<String, BeanPropertyCompoundScalar>();
}
public BeanProperty[] getScalarProperties() {
return propList.toArray(new BeanProperty[propList.size()]);
}
public void register(BeanPropertyCompoundScalar prop) {
propList.add(prop);
propMap.put(prop.getName(), prop);
}
public BeanPropertyCompoundScalar getCompoundScalarProperty(String propName) {
return propMap.get(propName);
}
public List<CtCompoundProperty> getNonScalarProperties() {
return nonScalarProperties;
}
public void setNonScalarProperties(List<CtCompoundProperty> nonScalarProperties) {
this.nonScalarProperties = nonScalarProperties;
}
/**
* Set the value of the property without interception or
* PropertyChangeSupport.
*/
public void setRootValue(Object bean, Object value) {
try {
if (bean instanceof EntityBean) {
setter.set(bean, value);
} else {
Object[] args = new Object[1];
args[0] = value;
writeMethod.invoke(bean, args);
}
} catch (Exception ex) {
String beanType = bean == null ? "null" : bean.getClass().getName();
String msg = "set " + name + " with arg[" + value + "] on ["+fullBeanName+"] with type[" + beanType + "] threw error";
throw new RuntimeException(msg, ex);
}
}
/**
* Set the value of the property.
*/
public void setRootValueIntercept(Object bean, Object value) {
try {
if (bean instanceof EntityBean) {
setter.setIntercept(bean, value);
} else {
Object[] args = new Object[1];
args[0] = value;
writeMethod.invoke(bean, args);
}
} catch (Exception ex) {
String beanType = bean == null ? "null" : bean.getClass().getName();
String msg = "setIntercept " + name + " arg[" + value + "] on ["+fullBeanName+"] with type[" + beanType + "] threw error";
throw new RuntimeException(msg, ex);
}
}
}
@@ -1,120 +1,101 @@
/**
* Copyright (C) 2009 Authors
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy;
import com.avaje.ebean.config.ScalarTypeConverter;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
import com.avaje.ebeaninternal.server.type.CtCompoundProperty;
/**
* A BeanProperty owned by a Compound value object that maps to
* a real scalar type.
*
* @author rbygrave
*/
public class BeanPropertyCompoundScalar extends BeanProperty {
private final BeanPropertyCompoundRoot rootProperty;
private final CtCompoundProperty ctProperty;
@SuppressWarnings("rawtypes")
private final ScalarTypeConverter typeConverter;
public BeanPropertyCompoundScalar(BeanPropertyCompoundRoot rootProperty, DeployBeanProperty scalarDeploy,
CtCompoundProperty ctProperty, ScalarTypeConverter<?, ?> typeConverter) {
super(scalarDeploy);
this.rootProperty = rootProperty;
this.ctProperty = ctProperty;
this.typeConverter = typeConverter;
}
@SuppressWarnings("unchecked")
@Override
public Object getValue(Object valueObject) {
if (typeConverter != null){
valueObject = typeConverter.unwrapValue(valueObject);
}
return ctProperty.getValue(valueObject);
}
@Override
public void setValue(Object bean, Object value) {
setValueInCompound(bean, value, false);
}
@SuppressWarnings("unchecked")
public void setValueInCompound(Object bean, Object value, boolean intercept) {
Object compoundValue = ctProperty.setValue(bean, value);
if (compoundValue != null){
if (typeConverter != null){
compoundValue = typeConverter.wrapValue(compoundValue);
}
// we are at the top level and we have a compound value
// that we can set using the root property
if (intercept){
rootProperty.setRootValueIntercept(bean, compoundValue);
} else {
rootProperty.setRootValue(bean, compoundValue);
}
}
}
/**
* No interception on embedded scalar values inside a CVO.
*/
@Override
public void setValueIntercept(Object bean, Object value) {
setValueInCompound(bean, value, true);
}
/**
* No interception on embedded scalar values inside a CVO.
*/
@Override
public Object getValueIntercept(Object bean) {
return getValue(bean);
}
@Override
public Object elGetReference(Object bean) {
return getValue(bean);
}
@Override
public Object elGetValue(Object bean) {
return getValue(bean);
}
@Override
public void elSetReference(Object bean) {
super.elSetReference(bean);
}
@Override
public void elSetValue(Object bean, Object value, boolean populate, boolean reference) {
super.elSetValue(bean, value, populate, reference);
}
}
package com.avaje.ebeaninternal.server.deploy;
import com.avaje.ebean.config.ScalarTypeConverter;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
import com.avaje.ebeaninternal.server.type.CtCompoundProperty;
/**
* A BeanProperty owned by a Compound value object that maps to
* a real scalar type.
*
* @author rbygrave
*/
public class BeanPropertyCompoundScalar extends BeanProperty {
private final BeanPropertyCompoundRoot rootProperty;
private final CtCompoundProperty ctProperty;
@SuppressWarnings("rawtypes")
private final ScalarTypeConverter typeConverter;
public BeanPropertyCompoundScalar(BeanPropertyCompoundRoot rootProperty, DeployBeanProperty scalarDeploy,
CtCompoundProperty ctProperty, ScalarTypeConverter<?, ?> typeConverter) {
super(scalarDeploy);
this.rootProperty = rootProperty;
this.ctProperty = ctProperty;
this.typeConverter = typeConverter;
}
@SuppressWarnings("unchecked")
@Override
public Object getValue(Object valueObject) {
if (typeConverter != null){
valueObject = typeConverter.unwrapValue(valueObject);
}
return ctProperty.getValue(valueObject);
}
@Override
public void setValue(Object bean, Object value) {
setValueInCompound(bean, value, false);
}
@SuppressWarnings("unchecked")
public void setValueInCompound(Object bean, Object value, boolean intercept) {
Object compoundValue = ctProperty.setValue(bean, value);
if (compoundValue != null){
if (typeConverter != null){
compoundValue = typeConverter.wrapValue(compoundValue);
}
// we are at the top level and we have a compound value
// that we can set using the root property
if (intercept){
rootProperty.setRootValueIntercept(bean, compoundValue);
} else {
rootProperty.setRootValue(bean, compoundValue);
}
}
}
/**
* No interception on embedded scalar values inside a CVO.
*/
@Override
public void setValueIntercept(Object bean, Object value) {
setValueInCompound(bean, value, true);
}
/**
* No interception on embedded scalar values inside a CVO.
*/
@Override
public Object getValueIntercept(Object bean) {
return getValue(bean);
}
@Override
public Object elGetReference(Object bean) {
return getValue(bean);
}
@Override
public Object elGetValue(Object bean) {
return getValue(bean);
}
@Override
public void elSetReference(Object bean) {
super.elSetReference(bean);
}
@Override
public void elSetValue(Object bean, Object value, boolean populate, boolean reference) {
super.elSetValue(bean, value, populate, reference);
}
}
@@ -1,64 +1,45 @@
/**
* Copyright (C) 2006 Robin Bygrave
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy;
import com.avaje.ebeaninternal.server.core.InternString;
import com.avaje.ebeaninternal.server.lib.util.StringHelper;
/**
* Used hold meta data when a bean property is overridden.
* <p>
* Typically this is for Embedded Beans.
* </p>
*/
public class BeanPropertyOverride {
private final String dbColumn;
private final String sqlFormulaSelect;
private final String sqlFormulaJoin;
public BeanPropertyOverride(String dbColumn) {
this(dbColumn, null, null);
}
public BeanPropertyOverride(String dbColumn, String sqlFormulaSelect, String sqlFormulaJoin) {
this.dbColumn = InternString.intern(dbColumn);
this.sqlFormulaSelect = InternString.intern(sqlFormulaSelect);
this.sqlFormulaJoin = InternString.intern(sqlFormulaJoin);
}
public String getDbColumn() {
return dbColumn;
}
public String getSqlFormulaSelect() {
return sqlFormulaSelect;
}
public String getSqlFormulaJoin() {
return sqlFormulaJoin;
}
public String replace(String src, String srcDbColumn){
return StringHelper.replaceString(src, srcDbColumn, dbColumn);
}
}
package com.avaje.ebeaninternal.server.deploy;
import com.avaje.ebeaninternal.server.core.InternString;
import com.avaje.ebeaninternal.server.lib.util.StringHelper;
/**
* Used hold meta data when a bean property is overridden.
* <p>
* Typically this is for Embedded Beans.
* </p>
*/
public class BeanPropertyOverride {
private final String dbColumn;
private final String sqlFormulaSelect;
private final String sqlFormulaJoin;
public BeanPropertyOverride(String dbColumn) {
this(dbColumn, null, null);
}
public BeanPropertyOverride(String dbColumn, String sqlFormulaSelect, String sqlFormulaJoin) {
this.dbColumn = InternString.intern(dbColumn);
this.sqlFormulaSelect = InternString.intern(sqlFormulaSelect);
this.sqlFormulaJoin = InternString.intern(sqlFormulaJoin);
}
public String getDbColumn() {
return dbColumn;
}
public String getSqlFormulaSelect() {
return sqlFormulaSelect;
}
public String getSqlFormulaJoin() {
return sqlFormulaJoin;
}
public String replace(String src, String srcDbColumn){
return StringHelper.replaceString(src, srcDbColumn, dbColumn);
}
}
@@ -1,99 +1,80 @@
/**
* Copyright (C) 2009 Authors
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy;
import java.util.Iterator;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.BasicAttribute;
import com.avaje.ebean.bean.BeanCollectionAdd;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertySimpleCollection;
import com.avaje.ebeaninternal.server.ldap.LdapPersistenceException;
import com.avaje.ebeaninternal.server.type.ScalarType;
public class BeanPropertySimpleCollection<T> extends BeanPropertyAssocMany<T> {
private final ScalarType<T> collectionScalarType;
public BeanPropertySimpleCollection(BeanDescriptorMap owner, BeanDescriptor<?> descriptor, DeployBeanPropertySimpleCollection<T> deploy) {
super(owner, descriptor, deploy);
this.collectionScalarType = deploy.getCollectionScalarType();
}
public void initialise() {
super.initialise();
}
@Override
public Attribute createAttribute(Object bean) {
Object v = getValue(bean);
if (v == null){
return null;
}
if (ldapAttributeAdapter != null){
return ldapAttributeAdapter.createAttribute(v);
}
BasicAttribute attrs = new BasicAttribute(getDbColumn());
Iterator<?> it = help.getIterator(v);
if (it != null){
while (it.hasNext()) {
Object beanValue = it.next();
Object attrValue = collectionScalarType.toJdbcType(beanValue);
attrs.add(attrValue);
}
}
return attrs;
}
@Override
public void setAttributeValue(Object bean, Attribute attr) {
try {
if (attr != null){
Object beanValue;
if (ldapAttributeAdapter != null){
beanValue = ldapAttributeAdapter.readAttribute(attr);
} else {
boolean vanilla = true;
beanValue = help.createEmpty(vanilla);
BeanCollectionAdd collAdd = help.getBeanCollectionAdd(beanValue, mapKey);
NamingEnumeration<?> en = attr.getAll();
while (en.hasMoreElements()) {
Object attrValue = (Object) en.nextElement();
Object collValue = collectionScalarType.toBeanType(attrValue);
collAdd.addBean(collValue);
}
}
setValue(bean, beanValue);
}
} catch (NamingException e) {
throw new LdapPersistenceException(e);
}
}
}
package com.avaje.ebeaninternal.server.deploy;
import java.util.Iterator;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.BasicAttribute;
import com.avaje.ebean.bean.BeanCollectionAdd;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertySimpleCollection;
import com.avaje.ebeaninternal.server.ldap.LdapPersistenceException;
import com.avaje.ebeaninternal.server.type.ScalarType;
public class BeanPropertySimpleCollection<T> extends BeanPropertyAssocMany<T> {
private final ScalarType<T> collectionScalarType;
public BeanPropertySimpleCollection(BeanDescriptorMap owner, BeanDescriptor<?> descriptor, DeployBeanPropertySimpleCollection<T> deploy) {
super(owner, descriptor, deploy);
this.collectionScalarType = deploy.getCollectionScalarType();
}
public void initialise() {
super.initialise();
}
@Override
public Attribute createAttribute(Object bean) {
Object v = getValue(bean);
if (v == null){
return null;
}
if (ldapAttributeAdapter != null){
return ldapAttributeAdapter.createAttribute(v);
}
BasicAttribute attrs = new BasicAttribute(getDbColumn());
Iterator<?> it = help.getIterator(v);
if (it != null){
while (it.hasNext()) {
Object beanValue = it.next();
Object attrValue = collectionScalarType.toJdbcType(beanValue);
attrs.add(attrValue);
}
}
return attrs;
}
@Override
public void setAttributeValue(Object bean, Attribute attr) {
try {
if (attr != null){
Object beanValue;
if (ldapAttributeAdapter != null){
beanValue = ldapAttributeAdapter.readAttribute(attr);
} else {
boolean vanilla = true;
beanValue = help.createEmpty(vanilla);
BeanCollectionAdd collAdd = help.getBeanCollectionAdd(beanValue, mapKey);
NamingEnumeration<?> en = attr.getAll();
while (en.hasMoreElements()) {
Object attrValue = (Object) en.nextElement();
Object collValue = collectionScalarType.toBeanType(attrValue);
collAdd.addBean(collValue);
}
}
setValue(bean, beanValue);
}
} catch (NamingException e) {
throw new LdapPersistenceException(e);
}
}
}
@@ -1,61 +1,42 @@
/**
* Copyright (C) 2009 Robin Bygrave
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy;
import java.util.List;
import java.util.logging.Logger;
import com.avaje.ebean.event.BeanQueryAdapter;
import com.avaje.ebeaninternal.server.core.BootupClasses;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanDescriptor;
/**
* Default implementation for creating BeanControllers.
*/
public class BeanQueryAdapterManager {
private static final Logger logger = Logger.getLogger(BeanQueryAdapterManager.class.getName());
private final List<BeanQueryAdapter> list;
public BeanQueryAdapterManager(BootupClasses bootupClasses){
list = bootupClasses.getBeanQueryAdapters();
}
public int getRegisterCount() {
return list.size();
}
/**
* Return the BeanPersistController for a given entity type.
*/
public void addQueryAdapter(DeployBeanDescriptor<?> deployDesc){
for (int i = 0; i < list.size(); i++) {
BeanQueryAdapter c = list.get(i);
if (c.isRegisterFor(deployDesc.getBeanType())){
logger.fine("BeanQueryAdapter on[" + deployDesc.getFullName() + "] " + c.getClass().getName());
deployDesc.addQueryAdapter(c);
}
}
}
}
package com.avaje.ebeaninternal.server.deploy;
import java.util.List;
import java.util.logging.Logger;
import com.avaje.ebean.event.BeanQueryAdapter;
import com.avaje.ebeaninternal.server.core.BootupClasses;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanDescriptor;
/**
* Default implementation for creating BeanControllers.
*/
public class BeanQueryAdapterManager {
private static final Logger logger = Logger.getLogger(BeanQueryAdapterManager.class.getName());
private final List<BeanQueryAdapter> list;
public BeanQueryAdapterManager(BootupClasses bootupClasses){
list = bootupClasses.getBeanQueryAdapters();
}
public int getRegisterCount() {
return list.size();
}
/**
* Return the BeanPersistController for a given entity type.
*/
public void addQueryAdapter(DeployBeanDescriptor<?> deployDesc){
for (int i = 0; i < list.size(); i++) {
BeanQueryAdapter c = list.get(i);
if (c.isRegisterFor(deployDesc.getBeanType())){
logger.fine("BeanQueryAdapter on[" + deployDesc.getFullName() + "] " + c.getClass().getName());
deployDesc.addQueryAdapter(c);
}
}
}
}
@@ -1,142 +1,123 @@
/**
* Copyright (C) 2006 Robin Bygrave
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.avaje.ebean.config.GlobalProperties;
import com.avaje.ebeaninternal.server.core.InternString;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanTable;
import com.avaje.ebeaninternal.server.deploy.meta.DeployTableJoin;
import com.avaje.ebeaninternal.server.deploy.meta.DeployTableJoinColumn;
/**
* Used for associated beans in place of a BeanDescriptor. This is done to avoid
* recursion issues due to the potentially bi-directional and circular
* relationships between beans.
* <p>
* It holds the main deployment information and not all the detail that is held
* in a BeanDescriptor.
* </p>
*/
public class BeanTable {
private static final Logger logger = Logger.getLogger(BeanTable.class.getName());
private final Class<?> beanType;
/**
* The base table.
*/
private final String baseTable;
private final BeanProperty[] idProperties;
/**
* Create the BeanTable.
*/
public BeanTable(DeployBeanTable mutable, BeanDescriptorMap owner) {
this.beanType = mutable.getBeanType();
this.baseTable = InternString.intern(mutable.getBaseTable());
this.idProperties = mutable.createIdProperties(owner);
}
public String toString(){
return baseTable;
}
/**
* Return the base table for this BeanTable.
* This is used to determine the join information
* for associations.
*/
public String getBaseTable() {
return baseTable;
}
/**
* Gets the unqualified base table.
*
* @return the unqualified base table
*/
public String getUnqualifiedBaseTable(){
final String[] chunks = baseTable.split("\\.");
return chunks.length == 2 ? chunks[1] :chunks[0];
}
/**
* Return the Id properties.
*/
public BeanProperty[] getIdProperties() {
return idProperties;
}
/**
* Return the class for this beanTable.
*/
public Class<?> getBeanType() {
return beanType;
}
public void createJoinColumn(String foreignKeyPrefix, DeployTableJoin join, boolean reverse) {
boolean complexKey = false;
BeanProperty[] props = idProperties;
if (idProperties.length == 1){
if (idProperties[0] instanceof BeanPropertyAssocOne<?>) {
BeanPropertyAssocOne<?> assocOne = (BeanPropertyAssocOne<?>)idProperties[0];
props = assocOne.getProperties();
complexKey = true;
}
}
for (int i = 0; i < props.length; i++) {
String lc = props[i].getDbColumn();
String fk = lc;
if (foreignKeyPrefix != null){
fk = foreignKeyPrefix+"_"+fk;
}
if (complexKey){
// check to see if we want prefixes by default with complex keys
boolean usePrefixOnComplex = GlobalProperties.getBoolean("ebean.prefixComplexKeys", false);
if (!usePrefixOnComplex){
// just to copy the column name rather than prefix with the foreignKeyPrefix.
// I think that with complex keys this is the more common approach.
String msg = "On table["+baseTable+"] foreign key column ["+lc+"]";
logger.log(Level.FINE, msg);
fk = lc;
}
}
DeployTableJoinColumn joinCol = new DeployTableJoinColumn(lc, fk);
if (reverse){
joinCol = joinCol.reverse();
}
join.addJoinColumn(joinCol);
}
}
}
package com.avaje.ebeaninternal.server.deploy;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.avaje.ebean.config.GlobalProperties;
import com.avaje.ebeaninternal.server.core.InternString;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanTable;
import com.avaje.ebeaninternal.server.deploy.meta.DeployTableJoin;
import com.avaje.ebeaninternal.server.deploy.meta.DeployTableJoinColumn;
/**
* Used for associated beans in place of a BeanDescriptor. This is done to avoid
* recursion issues due to the potentially bi-directional and circular
* relationships between beans.
* <p>
* It holds the main deployment information and not all the detail that is held
* in a BeanDescriptor.
* </p>
*/
public class BeanTable {
private static final Logger logger = Logger.getLogger(BeanTable.class.getName());
private final Class<?> beanType;
/**
* The base table.
*/
private final String baseTable;
private final BeanProperty[] idProperties;
/**
* Create the BeanTable.
*/
public BeanTable(DeployBeanTable mutable, BeanDescriptorMap owner) {
this.beanType = mutable.getBeanType();
this.baseTable = InternString.intern(mutable.getBaseTable());
this.idProperties = mutable.createIdProperties(owner);
}
public String toString(){
return baseTable;
}
/**
* Return the base table for this BeanTable.
* This is used to determine the join information
* for associations.
*/
public String getBaseTable() {
return baseTable;
}
/**
* Gets the unqualified base table.
*
* @return the unqualified base table
*/
public String getUnqualifiedBaseTable(){
final String[] chunks = baseTable.split("\\.");
return chunks.length == 2 ? chunks[1] :chunks[0];
}
/**
* Return the Id properties.
*/
public BeanProperty[] getIdProperties() {
return idProperties;
}
/**
* Return the class for this beanTable.
*/
public Class<?> getBeanType() {
return beanType;
}
public void createJoinColumn(String foreignKeyPrefix, DeployTableJoin join, boolean reverse) {
boolean complexKey = false;
BeanProperty[] props = idProperties;
if (idProperties.length == 1){
if (idProperties[0] instanceof BeanPropertyAssocOne<?>) {
BeanPropertyAssocOne<?> assocOne = (BeanPropertyAssocOne<?>)idProperties[0];
props = assocOne.getProperties();
complexKey = true;
}
}
for (int i = 0; i < props.length; i++) {
String lc = props[i].getDbColumn();
String fk = lc;
if (foreignKeyPrefix != null){
fk = foreignKeyPrefix+"_"+fk;
}
if (complexKey){
// check to see if we want prefixes by default with complex keys
boolean usePrefixOnComplex = GlobalProperties.getBoolean("ebean.prefixComplexKeys", false);
if (!usePrefixOnComplex){
// just to copy the column name rather than prefix with the foreignKeyPrefix.
// I think that with complex keys this is the more common approach.
String msg = "On table["+baseTable+"] foreign key column ["+lc+"]";
logger.log(Level.FINE, msg);
fk = lc;
}
}
DeployTableJoinColumn joinCol = new DeployTableJoinColumn(lc, fk);
if (reverse){
joinCol = joinCol.reverse();
}
join.addJoinColumn(joinCol);
}
}
}
@@ -1,43 +1,24 @@
/**
* Copyright (C) 2009 Authors
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy;
/**
* Used to convert between collection types.
* <P>
* This typically means wrap and unwrap mutable scala collection types of Buffer, Set and Map.
* </p>
*
* @author rbygrave
*
*/
public interface CollectionTypeConverter {
/**
* Convert the wrapped type to the underlying Java List, Set or Map.
*/
public Object toUnderlying(Object wrapped);
/**
* Wrap the underlying Java List, Set or Map into the final collection type.
*/
public Object toWrapped(Object wrapped);
}
package com.avaje.ebeaninternal.server.deploy;
/**
* Used to convert between collection types.
* <P>
* This typically means wrap and unwrap mutable scala collection types of Buffer, Set and Map.
* </p>
*
* @author rbygrave
*
*/
public interface CollectionTypeConverter {
/**
* Convert the wrapped type to the underlying Java List, Set or Map.
*/
public Object toUnderlying(Object wrapped);
/**
* Wrap the underlying Java List, Set or Map into the final collection type.
*/
public Object toWrapped(Object wrapped);
}
@@ -1,40 +1,21 @@
/**
* Copyright (C) 2009 Authors
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy;
/**
* Holds multiple column unique constraints defined for an entity.
*/
public class CompoundUniqueContraint {
private final String[] columns;
public CompoundUniqueContraint(String[] columns) {
this.columns = columns;
}
/**
* Return the columns that make up this unique constraint.
*/
public String[] getColumns() {
return columns;
}
}
package com.avaje.ebeaninternal.server.deploy;
/**
* Holds multiple column unique constraints defined for an entity.
*/
public class CompoundUniqueContraint {
private final String[] columns;
public CompoundUniqueContraint(String[] columns) {
this.columns = columns;
}
/**
* Return the columns that make up this unique constraint.
*/
public String[] getColumns() {
return columns;
}
}
@@ -1,83 +1,64 @@
/**
* Copyright (C) 2009 Authors
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy;
import com.avaje.ebean.bean.PersistenceContext;
import com.avaje.ebeaninternal.server.transaction.DefaultPersistenceContext;
/**
* Provides context when performing a bean copy.
*
* @author rbygrave
*/
public class CopyContext {
private final boolean vanillaMode;
private final boolean sharing;
private final PersistenceContext pc;
public CopyContext(boolean vanillaMode, boolean sharing) {
this.vanillaMode = vanillaMode;
this.sharing = sharing;
this.pc = new DefaultPersistenceContext();
}
public CopyContext(boolean vanillaMode) {
this(vanillaMode, false);
}
/**
* Return true if the copy should be a vanilla bean.
*/
public boolean isVanillaMode() {
return vanillaMode;
}
/**
* Return true if the copy should be safe for sharing.
*/
public boolean isSharing() {
return sharing;
}
/**
* Return the persistence context used during the copy.
*/
public PersistenceContext getPersistenceContext() {
return pc;
}
/**
* Put the bean if absent into the persistence context.
*/
public Object putIfAbsent(Object id, Object bean){
return pc.putIfAbsent(id, bean);
}
/**
* Return the bean for the given type and id from the persistence context.
*/
public Object get(Class<?> beanType, Object beanId){
return pc.get(beanType, beanId);
}
}
package com.avaje.ebeaninternal.server.deploy;
import com.avaje.ebean.bean.PersistenceContext;
import com.avaje.ebeaninternal.server.transaction.DefaultPersistenceContext;
/**
* Provides context when performing a bean copy.
*
* @author rbygrave
*/
public class CopyContext {
private final boolean vanillaMode;
private final boolean sharing;
private final PersistenceContext pc;
public CopyContext(boolean vanillaMode, boolean sharing) {
this.vanillaMode = vanillaMode;
this.sharing = sharing;
this.pc = new DefaultPersistenceContext();
}
public CopyContext(boolean vanillaMode) {
this(vanillaMode, false);
}
/**
* Return true if the copy should be a vanilla bean.
*/
public boolean isVanillaMode() {
return vanillaMode;
}
/**
* Return true if the copy should be safe for sharing.
*/
public boolean isSharing() {
return sharing;
}
/**
* Return the persistence context used during the copy.
*/
public PersistenceContext getPersistenceContext() {
return pc;
}
/**
* Put the bean if absent into the persistence context.
*/
public Object putIfAbsent(Object id, Object bean){
return pc.putIfAbsent(id, bean);
}
/**
* Return the bean for the given type and id from the persistence context.
*/
public Object get(Class<?> beanType, Object beanId){
return pc.get(beanType, beanId);
}
}
@@ -1,42 +1,39 @@
/**
*
*/
package com.avaje.ebeaninternal.server.deploy;
public class DRawSqlColumnInfo {
final String name;
final String label;
final String propertyName;
final boolean scalarProperty;
public DRawSqlColumnInfo(String name, String label, String propertyName, boolean scalarProperty) {
this.name = name;
this.label = label;
this.propertyName = propertyName;
this.scalarProperty = scalarProperty;
}
public String getName() {
return name;
}
public String getLabel() {
return label;
}
public String getPropertyName() {
return propertyName;
}
public boolean isScalarProperty() {
return scalarProperty;
}
public String toString() {
return "name:" + name + " label:" + label + " prop:" + propertyName;
}
package com.avaje.ebeaninternal.server.deploy;
public class DRawSqlColumnInfo {
final String name;
final String label;
final String propertyName;
final boolean scalarProperty;
public DRawSqlColumnInfo(String name, String label, String propertyName, boolean scalarProperty) {
this.name = name;
this.label = label;
this.propertyName = propertyName;
this.scalarProperty = scalarProperty;
}
public String getName() {
return name;
}
public String getLabel() {
return label;
}
public String getPropertyName() {
return propertyName;
}
public boolean isScalarProperty() {
return scalarProperty;
}
public String toString() {
return "name:" + name + " label:" + label + " prop:" + propertyName;
}
}
@@ -1,80 +1,61 @@
/**
* Copyright (C) 2006 Robin Bygrave
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy;
import java.util.HashMap;
import java.util.List;
import javax.persistence.PersistenceException;
import com.avaje.ebean.event.BeanFinder;
/**
* Default implementation for BeanFinderFactory.
*/
public class DefaultBeanFinderManager implements BeanFinderManager {
HashMap<Class<?>, BeanFinder<?>> registerFor = new HashMap<Class<?>, BeanFinder<?>>();
public int createBeanFinders(List<Class<?>> finderClassList) {
for (Class<?> cls : finderClassList) {
Class<?> entityType = getEntityClass(cls);
try {
BeanFinder<?> beanFinder = (BeanFinder<?>) cls.newInstance();
registerFor.put(entityType, beanFinder);
} catch (Exception ex) {
throw new PersistenceException(ex);
}
}
return registerFor.size();
}
public int getRegisterCount() {
return registerFor.size();
}
/**
* Return the BeanFinder for a given entity type.
*/
@SuppressWarnings("unchecked")
public <T> BeanFinder<T> getBeanFinder(Class<T> entityType) {
return (BeanFinder<T>)registerFor.get(entityType);
}
/**
* Find the entity class given the controller class.
* <p>
* This uses reflection to find the generics parameter type.
* </p>
*/
private Class<?> getEntityClass(Class<?> controller){
Class<?> cls = ParamTypeUtil.findParamType(controller, BeanFinder.class);
if (cls == null){
String msg = "Could not determine the entity class (generics parameter type) from "+controller+" using reflection.";
throw new PersistenceException(msg);
}
return cls;
}
}
package com.avaje.ebeaninternal.server.deploy;
import java.util.HashMap;
import java.util.List;
import javax.persistence.PersistenceException;
import com.avaje.ebean.event.BeanFinder;
/**
* Default implementation for BeanFinderFactory.
*/
public class DefaultBeanFinderManager implements BeanFinderManager {
HashMap<Class<?>, BeanFinder<?>> registerFor = new HashMap<Class<?>, BeanFinder<?>>();
public int createBeanFinders(List<Class<?>> finderClassList) {
for (Class<?> cls : finderClassList) {
Class<?> entityType = getEntityClass(cls);
try {
BeanFinder<?> beanFinder = (BeanFinder<?>) cls.newInstance();
registerFor.put(entityType, beanFinder);
} catch (Exception ex) {
throw new PersistenceException(ex);
}
}
return registerFor.size();
}
public int getRegisterCount() {
return registerFor.size();
}
/**
* Return the BeanFinder for a given entity type.
*/
@SuppressWarnings("unchecked")
public <T> BeanFinder<T> getBeanFinder(Class<T> entityType) {
return (BeanFinder<T>)registerFor.get(entityType);
}
/**
* Find the entity class given the controller class.
* <p>
* This uses reflection to find the generics parameter type.
* </p>
*/
private Class<?> getEntityClass(Class<?> controller){
Class<?> cls = ParamTypeUtil.findParamType(controller, BeanFinder.class);
if (cls == null){
String msg = "Could not determine the entity class (generics parameter type) from "+controller+" using reflection.";
throw new PersistenceException(msg);
}
return cls;
}
}
@@ -1,191 +1,172 @@
/**
* Copyright (C) 2006 Robin Bygrave
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.avaje.ebeaninternal.server.lib.resource.ResourceContent;
import com.avaje.ebeaninternal.server.lib.resource.ResourceSource;
import com.avaje.ebeaninternal.server.lib.util.Dnode;
import com.avaje.ebeaninternal.server.lib.util.DnodeReader;
/**
* Controls the creation and caching of BeanManager's, BeanDescriptors,
* BeanTable etc for both beans and tables(MapBeans).
* <p>
* Also supports some other deployment features such as type conversion.
* </p>
*/
public class DeployOrmXml {
private static final Logger logger = Logger.getLogger(DeployOrmXml.class.getName());
private final HashMap<String, DNativeQuery> nativeQueryCache;
private final ArrayList<Dnode> ormXmlList;
private final ResourceSource resSource;
public DeployOrmXml(ResourceSource resSource) {
this.resSource = resSource;
this.nativeQueryCache = new HashMap<String, DNativeQuery>();
this.ormXmlList = findAllOrmXml();
initialiseNativeQueries();
}
/**
* Register all the native queries in ALL orm xml deployment.
*/
private void initialiseNativeQueries() {
for (Dnode ormXml : ormXmlList) {
initialiseNativeQueries(ormXml);
}
}
/**
* Register the native queries in this particular orm xml deployment.
*/
private void initialiseNativeQueries(Dnode ormXml) {
Dnode entityMappings = ormXml.find("entity-mappings");
if (entityMappings != null) {
List<Dnode> nq = entityMappings.findAll("named-native-query", 1);
for (int i = 0; i < nq.size(); i++) {
Dnode nqNode = nq.get(i);
Dnode nqQueryNode = nqNode.find("query");
if (nqQueryNode != null) {
String queryContent = nqQueryNode.getNodeContent();
String queryName = (String) nqNode.getAttribute("name");
if (queryName != null && queryContent != null) {
DNativeQuery query = new DNativeQuery(queryContent);
nativeQueryCache.put(queryName, query);
}
}
}
}
}
/**
* Return a native named query.
* <p>
* These are loaded from the orm.xml deployment file.
* </p>
*/
public DNativeQuery getNativeQuery(String name) {
return nativeQueryCache.get(name);
}
private ArrayList<Dnode> findAllOrmXml() {
ArrayList<Dnode> ormXmlList = new ArrayList<Dnode>();
String defaultFile = "orm.xml";
readOrmXml(defaultFile, ormXmlList);
if (!ormXmlList.isEmpty()) {
StringBuilder sb = new StringBuilder();
for (Dnode ox : ormXmlList) {
sb.append(", ").append(ox.getAttribute("ebean.filename"));
}
String loadedFiles = sb.toString().substring(2);
logger.info("Deployment xml [" + loadedFiles + "] loaded.");
}
return ormXmlList;
}
private boolean readOrmXml(String ormXmlName, ArrayList<Dnode> ormXmlList) {
try {
Dnode ormXml = null;
ResourceContent content = resSource.getContent(ormXmlName);
if (content != null) {
// servlet resource or file system...
ormXml = readOrmXml(content.getInputStream());
} else {
// try the classpath...
ormXml = readOrmXmlFromClasspath(ormXmlName);
}
if (ormXml != null) {
ormXml.setAttribute("ebean.filename", ormXmlName);
ormXmlList.add(ormXml);
return true;
} else {
return false;
}
} catch (IOException e) {
logger.log(Level.SEVERE, "error reading orm xml deployment " + ormXmlName, e);
return false;
}
}
private Dnode readOrmXmlFromClasspath(String ormXmlName) throws IOException {
InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(ormXmlName);
if (is == null) {
return null;
} else {
return readOrmXml(is);
}
}
private Dnode readOrmXml(InputStream in) throws IOException {
DnodeReader reader = new DnodeReader();
Dnode ormXml = reader.parseXml(in);
in.close();
return ormXml;
}
/**
* Find the deployment xml for a given entity. This will return null if no
* matching deployment xml is found for this entity.
* <p>
* This searches all the ormXml files and returns the first match.
* </p>
*/
public Dnode findEntityDeploymentXml(String className) {
for (Dnode ormXml : ormXmlList) {
Dnode entityMappings = ormXml.find("entity-mappings");
List<Dnode> entities = entityMappings.findAll("entity", "class", className, 1);
if (entities.size() == 1) {
return entities.get(0);
}
}
return null;
}
}
package com.avaje.ebeaninternal.server.deploy;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.avaje.ebeaninternal.server.lib.resource.ResourceContent;
import com.avaje.ebeaninternal.server.lib.resource.ResourceSource;
import com.avaje.ebeaninternal.server.lib.util.Dnode;
import com.avaje.ebeaninternal.server.lib.util.DnodeReader;
/**
* Controls the creation and caching of BeanManager's, BeanDescriptors,
* BeanTable etc for both beans and tables(MapBeans).
* <p>
* Also supports some other deployment features such as type conversion.
* </p>
*/
public class DeployOrmXml {
private static final Logger logger = Logger.getLogger(DeployOrmXml.class.getName());
private final HashMap<String, DNativeQuery> nativeQueryCache;
private final ArrayList<Dnode> ormXmlList;
private final ResourceSource resSource;
public DeployOrmXml(ResourceSource resSource) {
this.resSource = resSource;
this.nativeQueryCache = new HashMap<String, DNativeQuery>();
this.ormXmlList = findAllOrmXml();
initialiseNativeQueries();
}
/**
* Register all the native queries in ALL orm xml deployment.
*/
private void initialiseNativeQueries() {
for (Dnode ormXml : ormXmlList) {
initialiseNativeQueries(ormXml);
}
}
/**
* Register the native queries in this particular orm xml deployment.
*/
private void initialiseNativeQueries(Dnode ormXml) {
Dnode entityMappings = ormXml.find("entity-mappings");
if (entityMappings != null) {
List<Dnode> nq = entityMappings.findAll("named-native-query", 1);
for (int i = 0; i < nq.size(); i++) {
Dnode nqNode = nq.get(i);
Dnode nqQueryNode = nqNode.find("query");
if (nqQueryNode != null) {
String queryContent = nqQueryNode.getNodeContent();
String queryName = (String) nqNode.getAttribute("name");
if (queryName != null && queryContent != null) {
DNativeQuery query = new DNativeQuery(queryContent);
nativeQueryCache.put(queryName, query);
}
}
}
}
}
/**
* Return a native named query.
* <p>
* These are loaded from the orm.xml deployment file.
* </p>
*/
public DNativeQuery getNativeQuery(String name) {
return nativeQueryCache.get(name);
}
private ArrayList<Dnode> findAllOrmXml() {
ArrayList<Dnode> ormXmlList = new ArrayList<Dnode>();
String defaultFile = "orm.xml";
readOrmXml(defaultFile, ormXmlList);
if (!ormXmlList.isEmpty()) {
StringBuilder sb = new StringBuilder();
for (Dnode ox : ormXmlList) {
sb.append(", ").append(ox.getAttribute("ebean.filename"));
}
String loadedFiles = sb.toString().substring(2);
logger.info("Deployment xml [" + loadedFiles + "] loaded.");
}
return ormXmlList;
}
private boolean readOrmXml(String ormXmlName, ArrayList<Dnode> ormXmlList) {
try {
Dnode ormXml = null;
ResourceContent content = resSource.getContent(ormXmlName);
if (content != null) {
// servlet resource or file system...
ormXml = readOrmXml(content.getInputStream());
} else {
// try the classpath...
ormXml = readOrmXmlFromClasspath(ormXmlName);
}
if (ormXml != null) {
ormXml.setAttribute("ebean.filename", ormXmlName);
ormXmlList.add(ormXml);
return true;
} else {
return false;
}
} catch (IOException e) {
logger.log(Level.SEVERE, "error reading orm xml deployment " + ormXmlName, e);
return false;
}
}
private Dnode readOrmXmlFromClasspath(String ormXmlName) throws IOException {
InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(ormXmlName);
if (is == null) {
return null;
} else {
return readOrmXml(is);
}
}
private Dnode readOrmXml(InputStream in) throws IOException {
DnodeReader reader = new DnodeReader();
Dnode ormXml = reader.parseXml(in);
in.close();
return ormXml;
}
/**
* Find the deployment xml for a given entity. This will return null if no
* matching deployment xml is found for this entity.
* <p>
* This searches all the ormXml files and returns the first match.
* </p>
*/
public Dnode findEntityDeploymentXml(String className) {
for (Dnode ormXml : ormXmlList) {
Dnode entityMappings = ormXml.find("entity-mappings");
List<Dnode> entities = entityMappings.findAll("entity", "class", className, 1);
if (entities.size() == 1) {
return entities.get(0);
}
}
return null;
}
}
@@ -1,71 +1,52 @@
/**
* Copyright (C) 2006 Robin Bygrave
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy;
import com.avaje.ebeaninternal.server.core.InternString;
/**
* The Exported foreign key and property.
* <p>
* Used to for Assoc Manys to create references etc.
* </p>
*/
public class ExportedProperty {
private final String foreignDbColumn;
private final BeanProperty property;
private final boolean embedded;
public ExportedProperty(boolean embedded, String foreignDbColumn, BeanProperty property) {
this.embedded = embedded;
this.foreignDbColumn = InternString.intern(foreignDbColumn);
this.property = property;
}
/**
* Return true if this is part of an embedded concatinated key.
*/
public boolean isEmbedded() {
return embedded;
}
/**
* Return the property value from the bean.
*/
public Object getValue(Object bean){
return property.getValue(bean);
}
/**
* Return the foreign database column matching this property.
* <p>
* We use this foreign database column in the query predicates
* in preference to a parentProperty.idProperty = value.
* Just using the foreign database column avoids triggering
* a join to the 'parent' table.
* </p>
*/
public String getForeignDbColumn() {
return foreignDbColumn;
}
}
package com.avaje.ebeaninternal.server.deploy;
import com.avaje.ebeaninternal.server.core.InternString;
/**
* The Exported foreign key and property.
* <p>
* Used to for Assoc Manys to create references etc.
* </p>
*/
public class ExportedProperty {
private final String foreignDbColumn;
private final BeanProperty property;
private final boolean embedded;
public ExportedProperty(boolean embedded, String foreignDbColumn, BeanProperty property) {
this.embedded = embedded;
this.foreignDbColumn = InternString.intern(foreignDbColumn);
this.property = property;
}
/**
* Return true if this is part of an embedded concatinated key.
*/
public boolean isEmbedded() {
return embedded;
}
/**
* Return the property value from the bean.
*/
public Object getValue(Object bean){
return property.getValue(bean);
}
/**
* Return the foreign database column matching this property.
* <p>
* We use this foreign database column in the query predicates
* in preference to a parentProperty.idProperty = value.
* Just using the foreign database column avoids triggering
* a join to the 'parent' table.
* </p>
*/
public String getForeignDbColumn() {
return foreignDbColumn;
}
}
@@ -1,371 +1,352 @@
/**
* Copyright (C) 2006 Robin Bygrave
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import javax.persistence.PersistenceException;
import com.avaje.ebeaninternal.server.core.InternString;
import com.avaje.ebeaninternal.server.deploy.id.IdBinder;
import com.avaje.ebeaninternal.server.deploy.parse.DeployInheritInfo;
import com.avaje.ebeaninternal.server.query.SqlTreeProperties;
import com.avaje.ebeaninternal.server.subclass.SubClassUtil;
/**
* Represents a node in the Inheritance tree. Holds information regarding Super
* Subclass support.
*/
public class InheritInfo {
private final String discriminatorStringValue;
private final Object discriminatorValue;
private final String discriminatorColumn;
private final int discriminatorType;
private final int discriminatorLength;
private final String where;
private final Class<?> type;
private final ArrayList<InheritInfo> children = new ArrayList<InheritInfo>();
/**
* Map of discriminator values to InheritInfo.
*/
private final HashMap<String, InheritInfo> discMap;
/**
* Map of class types to InheritInfo (taking into account subclass proxy classes).
*/
private final HashMap<String, InheritInfo> typeMap;
private final InheritInfo parent;
private final InheritInfo root;
private BeanDescriptor<?> descriptor;
public InheritInfo(InheritInfo r, InheritInfo parent, DeployInheritInfo deploy) {
this.parent = parent;
this.type = deploy.getType();
this.discriminatorColumn = InternString.intern(deploy.getDiscriminatorColumn(parent));
this.discriminatorValue = deploy.getDiscriminatorObjectValue();
this.discriminatorStringValue = deploy.getDiscriminatorStringValue();
this.discriminatorType = deploy.getDiscriminatorType(parent);
this.discriminatorLength = deploy.getDiscriminatorLength(parent);
this.where = InternString.intern(deploy.getWhere());
if (r == null) {
// this is a root node
root = this;
discMap = new HashMap<String, InheritInfo>();
typeMap = new HashMap<String, InheritInfo>();
registerWithRoot(this);
} else {
this.root = r;
// register with the root node...
discMap = null;
typeMap = null;
root.registerWithRoot(this);
}
}
/**
* Visit all the children in the inheritance tree.
*/
public void visitChildren(InheritInfoVisitor visitor) {
for (int i = 0; i < children.size(); i++) {
InheritInfo child = children.get(i);
visitor.visit(child);
child.visitChildren(visitor);
}
}
/**
* return true if anything in the inheritance hierarchy has a relationship
* with a save cascade on it.
*/
public boolean isSaveRecurseSkippable() {
return root.isNodeSaveRecurseSkippable();
}
private boolean isNodeSaveRecurseSkippable() {
if (!descriptor.isSaveRecurseSkippable()){
return false;
}
for (int i = 0; i < children.size(); i++) {
InheritInfo child = children.get(i);
if (!child.isNodeSaveRecurseSkippable()){
return false;
}
}
return true;
}
/**
* return true if anything in the inheritance hierarchy has a relationship
* with a delete cascade on it.
*/
public boolean isDeleteRecurseSkippable() {
return root.isNodeDeleteRecurseSkippable();
}
private boolean isNodeDeleteRecurseSkippable() {
if (!descriptor.isDeleteRecurseSkippable()) {
return false;
}
for (int i = 0; i < children.size(); i++) {
InheritInfo child = children.get(i);
if (!child.isNodeDeleteRecurseSkippable()) {
return false;
}
}
return true;
}
/**
* Set the descriptor for this node.
*/
public void setDescriptor(BeanDescriptor<?> descriptor) {
this.descriptor = descriptor;
}
/**
* Return the associated BeanDescriptor for this node.
*/
public BeanDescriptor<?> getBeanDescriptor() {
return descriptor;
}
/**
* Get the bean property additionally looking in the sub types.
*/
public BeanProperty findSubTypeProperty(String propertyName) {
BeanProperty prop = null;
for (int i = 0, x=children.size(); i < x; i++) {
InheritInfo childInfo = children.get(i);
// recursively search this child bean descriptor
prop = childInfo.getBeanDescriptor().findBeanProperty(propertyName);
if (prop != null){
return prop;
}
}
return null;
}
/**
* Add the local properties for each sub class below this one.
*/
public void addChildrenProperties(SqlTreeProperties selectProps) {
for (int i = 0, x=children.size(); i < x; i++) {
InheritInfo childInfo = children.get(i);
selectProps.add(childInfo.descriptor.propertiesLocal());
childInfo.addChildrenProperties(selectProps);
}
}
/**
* Return the associated InheritInfo for this DB row read.
*/
public InheritInfo readType(DbReadContext ctx) throws SQLException {
String discValue = ctx.getDataReader().getString();
return readType(discValue);
}
/**
* Return the associated InheritInfo for this discriminator value.
*/
public InheritInfo readType(String discValue) {
if (discValue == null) {
return null;
}
InheritInfo typeInfo = root.getType(discValue);
if (typeInfo == null) {
String m = "Inheritance type for discriminator value [" + discValue + "] was not found?";
throw new PersistenceException(m);
}
return typeInfo;
}
/**
* Return the associated InheritInfo for this bean type.
*/
public InheritInfo readType(Class<?> beanType) {
InheritInfo typeInfo = root.getTypeByClass(beanType);
if (typeInfo == null) {
String m = "Inheritance type for bean type [" + beanType.getName() + "] was not found?";
throw new PersistenceException(m);
}
return typeInfo;
}
/**
* Create an EntityBean for this type.
*/
public Object createBean(boolean vanillaMode) {
return descriptor.createBean(vanillaMode);
}
/**
* Return the IdBinder for this type.
*/
public IdBinder getIdBinder() {
return descriptor.getIdBinder();
}
/**
* return the type.
*/
public Class<?> getType() {
return type;
}
/**
* Return the root node of the tree.
* <p>
* The root has a map of discriminator values to types.
* </p>
*/
public InheritInfo getRoot() {
return root;
}
/**
* Return the parent node.
*/
public InheritInfo getParent() {
return parent;
}
/**
* Return true if this is abstract node.
*/
public boolean isAbstract() {
return (discriminatorValue == null);
}
/**
* Return true if this is the root node.
*/
public boolean isRoot() {
return parent == null;
}
/**
* For a discriminator get the inheritance information for this tree.
*/
public InheritInfo getType(String discValue) {
return discMap.get(discValue);
}
/**
* Return the InheritInfo for the given bean type.
*/
private InheritInfo getTypeByClass(Class<?> beanType) {
String clsName = SubClassUtil.getSuperClassName(beanType.getName());
return typeMap.get(clsName);
}
private void registerWithRoot(InheritInfo info) {
if (info.getDiscriminatorStringValue() != null) {
String stringDiscValue = info.getDiscriminatorStringValue();
discMap.put(stringDiscValue, info);
}
String clsName = SubClassUtil.getSuperClassName(info.getType().getName());
typeMap.put(clsName, info);
}
/**
* Add a child node.
*/
public void addChild(InheritInfo childInfo) {
children.add(childInfo);
}
/**
* Return the derived where for the discriminator.
*/
public String getWhere() {
return where;
}
/**
* Return the column name of the discriminator.
*/
public String getDiscriminatorColumn() {
return discriminatorColumn;
}
/**
* Return the sql type of the discriminator value.
*/
public int getDiscriminatorType() {
return discriminatorType;
}
/**
* Return the length of the discriminator column.
*/
public int getDiscriminatorLength() {
return discriminatorLength;
}
/**
* Return the discriminator value for this node.
*/
public String getDiscriminatorStringValue() {
return discriminatorStringValue;
}
public Object getDiscriminatorValue() {
return discriminatorValue;
}
public String toString() {
return "InheritInfo[" + type.getName() + "] disc[" + discriminatorStringValue + "]";
}
}
package com.avaje.ebeaninternal.server.deploy;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import javax.persistence.PersistenceException;
import com.avaje.ebeaninternal.server.core.InternString;
import com.avaje.ebeaninternal.server.deploy.id.IdBinder;
import com.avaje.ebeaninternal.server.deploy.parse.DeployInheritInfo;
import com.avaje.ebeaninternal.server.query.SqlTreeProperties;
import com.avaje.ebeaninternal.server.subclass.SubClassUtil;
/**
* Represents a node in the Inheritance tree. Holds information regarding Super
* Subclass support.
*/
public class InheritInfo {
private final String discriminatorStringValue;
private final Object discriminatorValue;
private final String discriminatorColumn;
private final int discriminatorType;
private final int discriminatorLength;
private final String where;
private final Class<?> type;
private final ArrayList<InheritInfo> children = new ArrayList<InheritInfo>();
/**
* Map of discriminator values to InheritInfo.
*/
private final HashMap<String, InheritInfo> discMap;
/**
* Map of class types to InheritInfo (taking into account subclass proxy classes).
*/
private final HashMap<String, InheritInfo> typeMap;
private final InheritInfo parent;
private final InheritInfo root;
private BeanDescriptor<?> descriptor;
public InheritInfo(InheritInfo r, InheritInfo parent, DeployInheritInfo deploy) {
this.parent = parent;
this.type = deploy.getType();
this.discriminatorColumn = InternString.intern(deploy.getDiscriminatorColumn(parent));
this.discriminatorValue = deploy.getDiscriminatorObjectValue();
this.discriminatorStringValue = deploy.getDiscriminatorStringValue();
this.discriminatorType = deploy.getDiscriminatorType(parent);
this.discriminatorLength = deploy.getDiscriminatorLength(parent);
this.where = InternString.intern(deploy.getWhere());
if (r == null) {
// this is a root node
root = this;
discMap = new HashMap<String, InheritInfo>();
typeMap = new HashMap<String, InheritInfo>();
registerWithRoot(this);
} else {
this.root = r;
// register with the root node...
discMap = null;
typeMap = null;
root.registerWithRoot(this);
}
}
/**
* Visit all the children in the inheritance tree.
*/
public void visitChildren(InheritInfoVisitor visitor) {
for (int i = 0; i < children.size(); i++) {
InheritInfo child = children.get(i);
visitor.visit(child);
child.visitChildren(visitor);
}
}
/**
* return true if anything in the inheritance hierarchy has a relationship
* with a save cascade on it.
*/
public boolean isSaveRecurseSkippable() {
return root.isNodeSaveRecurseSkippable();
}
private boolean isNodeSaveRecurseSkippable() {
if (!descriptor.isSaveRecurseSkippable()){
return false;
}
for (int i = 0; i < children.size(); i++) {
InheritInfo child = children.get(i);
if (!child.isNodeSaveRecurseSkippable()){
return false;
}
}
return true;
}
/**
* return true if anything in the inheritance hierarchy has a relationship
* with a delete cascade on it.
*/
public boolean isDeleteRecurseSkippable() {
return root.isNodeDeleteRecurseSkippable();
}
private boolean isNodeDeleteRecurseSkippable() {
if (!descriptor.isDeleteRecurseSkippable()) {
return false;
}
for (int i = 0; i < children.size(); i++) {
InheritInfo child = children.get(i);
if (!child.isNodeDeleteRecurseSkippable()) {
return false;
}
}
return true;
}
/**
* Set the descriptor for this node.
*/
public void setDescriptor(BeanDescriptor<?> descriptor) {
this.descriptor = descriptor;
}
/**
* Return the associated BeanDescriptor for this node.
*/
public BeanDescriptor<?> getBeanDescriptor() {
return descriptor;
}
/**
* Get the bean property additionally looking in the sub types.
*/
public BeanProperty findSubTypeProperty(String propertyName) {
BeanProperty prop = null;
for (int i = 0, x=children.size(); i < x; i++) {
InheritInfo childInfo = children.get(i);
// recursively search this child bean descriptor
prop = childInfo.getBeanDescriptor().findBeanProperty(propertyName);
if (prop != null){
return prop;
}
}
return null;
}
/**
* Add the local properties for each sub class below this one.
*/
public void addChildrenProperties(SqlTreeProperties selectProps) {
for (int i = 0, x=children.size(); i < x; i++) {
InheritInfo childInfo = children.get(i);
selectProps.add(childInfo.descriptor.propertiesLocal());
childInfo.addChildrenProperties(selectProps);
}
}
/**
* Return the associated InheritInfo for this DB row read.
*/
public InheritInfo readType(DbReadContext ctx) throws SQLException {
String discValue = ctx.getDataReader().getString();
return readType(discValue);
}
/**
* Return the associated InheritInfo for this discriminator value.
*/
public InheritInfo readType(String discValue) {
if (discValue == null) {
return null;
}
InheritInfo typeInfo = root.getType(discValue);
if (typeInfo == null) {
String m = "Inheritance type for discriminator value [" + discValue + "] was not found?";
throw new PersistenceException(m);
}
return typeInfo;
}
/**
* Return the associated InheritInfo for this bean type.
*/
public InheritInfo readType(Class<?> beanType) {
InheritInfo typeInfo = root.getTypeByClass(beanType);
if (typeInfo == null) {
String m = "Inheritance type for bean type [" + beanType.getName() + "] was not found?";
throw new PersistenceException(m);
}
return typeInfo;
}
/**
* Create an EntityBean for this type.
*/
public Object createBean(boolean vanillaMode) {
return descriptor.createBean(vanillaMode);
}
/**
* Return the IdBinder for this type.
*/
public IdBinder getIdBinder() {
return descriptor.getIdBinder();
}
/**
* return the type.
*/
public Class<?> getType() {
return type;
}
/**
* Return the root node of the tree.
* <p>
* The root has a map of discriminator values to types.
* </p>
*/
public InheritInfo getRoot() {
return root;
}
/**
* Return the parent node.
*/
public InheritInfo getParent() {
return parent;
}
/**
* Return true if this is abstract node.
*/
public boolean isAbstract() {
return (discriminatorValue == null);
}
/**
* Return true if this is the root node.
*/
public boolean isRoot() {
return parent == null;
}
/**
* For a discriminator get the inheritance information for this tree.
*/
public InheritInfo getType(String discValue) {
return discMap.get(discValue);
}
/**
* Return the InheritInfo for the given bean type.
*/
private InheritInfo getTypeByClass(Class<?> beanType) {
String clsName = SubClassUtil.getSuperClassName(beanType.getName());
return typeMap.get(clsName);
}
private void registerWithRoot(InheritInfo info) {
if (info.getDiscriminatorStringValue() != null) {
String stringDiscValue = info.getDiscriminatorStringValue();
discMap.put(stringDiscValue, info);
}
String clsName = SubClassUtil.getSuperClassName(info.getType().getName());
typeMap.put(clsName, info);
}
/**
* Add a child node.
*/
public void addChild(InheritInfo childInfo) {
children.add(childInfo);
}
/**
* Return the derived where for the discriminator.
*/
public String getWhere() {
return where;
}
/**
* Return the column name of the discriminator.
*/
public String getDiscriminatorColumn() {
return discriminatorColumn;
}
/**
* Return the sql type of the discriminator value.
*/
public int getDiscriminatorType() {
return discriminatorType;
}
/**
* Return the length of the discriminator column.
*/
public int getDiscriminatorLength() {
return discriminatorLength;
}
/**
* Return the discriminator value for this node.
*/
public String getDiscriminatorStringValue() {
return discriminatorStringValue;
}
public Object getDiscriminatorValue() {
return discriminatorValue;
}
public String toString() {
return "InheritInfo[" + type.getName() + "] disc[" + discriminatorStringValue + "]";
}
}
@@ -1,87 +1,68 @@
/**
* Copyright (C) 2009 Authors
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy;
import com.avaje.ebeaninternal.api.SpiQuery;
/**
* Represents the type of a OneToMany or ManyToMany property.
*/
public class ManyType {
public static final ManyType JAVA_LIST = new ManyType(Underlying.LIST);
public static final ManyType JAVA_SET = new ManyType(Underlying.SET);
public static final ManyType JAVA_MAP = new ManyType(Underlying.MAP);
public enum Underlying {
LIST,
SET,
MAP
}
private final SpiQuery.Type queryType;
private final Underlying underlying;
private final CollectionTypeConverter typeConverter;
private ManyType(Underlying underlying) {
this(underlying, null);
}
public ManyType(Underlying underlying, CollectionTypeConverter typeConverter) {
this.underlying = underlying;
this.typeConverter = typeConverter;
switch (underlying) {
case LIST:
queryType = SpiQuery.Type.LIST;
break;
case SET:
queryType = SpiQuery.Type.SET;
break;
default:
queryType = SpiQuery.Type.MAP;
break;
}
}
/**
* Return the matching Query type.
*/
public SpiQuery.Type getQueryType() {
return queryType;
}
/**
* Return the underlying type.
*/
public Underlying getUnderlying() {
return underlying;
}
/**
* Return the type converter if there is one.
*/
public CollectionTypeConverter getTypeConverter() {
return typeConverter;
}
}
package com.avaje.ebeaninternal.server.deploy;
import com.avaje.ebeaninternal.api.SpiQuery;
/**
* Represents the type of a OneToMany or ManyToMany property.
*/
public class ManyType {
public static final ManyType JAVA_LIST = new ManyType(Underlying.LIST);
public static final ManyType JAVA_SET = new ManyType(Underlying.SET);
public static final ManyType JAVA_MAP = new ManyType(Underlying.MAP);
public enum Underlying {
LIST,
SET,
MAP
}
private final SpiQuery.Type queryType;
private final Underlying underlying;
private final CollectionTypeConverter typeConverter;
private ManyType(Underlying underlying) {
this(underlying, null);
}
public ManyType(Underlying underlying, CollectionTypeConverter typeConverter) {
this.underlying = underlying;
this.typeConverter = typeConverter;
switch (underlying) {
case LIST:
queryType = SpiQuery.Type.LIST;
break;
case SET:
queryType = SpiQuery.Type.SET;
break;
default:
queryType = SpiQuery.Type.MAP;
break;
}
}
/**
* Return the matching Query type.
*/
public SpiQuery.Type getQueryType() {
return queryType;
}
/**
* Return the underlying type.
*/
public Underlying getUnderlying() {
return underlying;
}
/**
* Return the type converter if there is one.
*/
public CollectionTypeConverter getTypeConverter() {
return typeConverter;
}
}
@@ -1,61 +1,42 @@
/**
* Copyright (C) 2006 Robin Bygrave
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy;
import java.util.List;
import java.util.logging.Logger;
import com.avaje.ebean.event.BeanPersistController;
import com.avaje.ebeaninternal.server.core.BootupClasses;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanDescriptor;
/**
* Default implementation for creating BeanControllers.
*/
public class PersistControllerManager {
private static final Logger logger = Logger.getLogger(PersistControllerManager.class.getName());
private final List<BeanPersistController> list;
public PersistControllerManager(BootupClasses bootupClasses){
list = bootupClasses.getBeanPersistControllers();
}
public int getRegisterCount() {
return list.size();
}
/**
* Return the BeanPersistController for a given entity type.
*/
public void addPersistControllers(DeployBeanDescriptor<?> deployDesc){
for (int i = 0; i < list.size(); i++) {
BeanPersistController c = list.get(i);
if (c.isRegisterFor(deployDesc.getBeanType())){
logger.fine("BeanPersistController on[" + deployDesc.getFullName() + "] " + c.getClass().getName());
deployDesc.addPersistController(c);
}
}
}
}
package com.avaje.ebeaninternal.server.deploy;
import java.util.List;
import java.util.logging.Logger;
import com.avaje.ebean.event.BeanPersistController;
import com.avaje.ebeaninternal.server.core.BootupClasses;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanDescriptor;
/**
* Default implementation for creating BeanControllers.
*/
public class PersistControllerManager {
private static final Logger logger = Logger.getLogger(PersistControllerManager.class.getName());
private final List<BeanPersistController> list;
public PersistControllerManager(BootupClasses bootupClasses){
list = bootupClasses.getBeanPersistControllers();
}
public int getRegisterCount() {
return list.size();
}
/**
* Return the BeanPersistController for a given entity type.
*/
public void addPersistControllers(DeployBeanDescriptor<?> deployDesc){
for (int i = 0; i < list.size(); i++) {
BeanPersistController c = list.get(i);
if (c.isRegisterFor(deployDesc.getBeanType())){
logger.fine("BeanPersistController on[" + deployDesc.getFullName() + "] " + c.getClass().getName());
deployDesc.addPersistController(c);
}
}
}
}
@@ -1,85 +1,66 @@
/**
* Copyright (C) 2006 Robin Bygrave
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy;
import java.util.List;
import java.util.logging.Logger;
import javax.persistence.PersistenceException;
import com.avaje.ebean.event.BeanPersistListener;
import com.avaje.ebeaninternal.server.core.BootupClasses;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanDescriptor;
/**
* Manages the assignment/registration of BeanPersistListener with their
* respective DeployBeanDescriptor's.
*/
public class PersistListenerManager {
private static final Logger logger = Logger.getLogger(PersistListenerManager.class.getName());
private final List<BeanPersistListener<?>> list;
public PersistListenerManager(BootupClasses bootupClasses) {
list = bootupClasses.getBeanPersistListeners();
}
public int getRegisterCount() {
return list.size();
}
/**
* Return the BeanPersistController for a given entity type.
*/
@SuppressWarnings("unchecked")
public <T> void addPersistListeners(DeployBeanDescriptor<T> deployDesc) {
for (int i = 0; i < list.size(); i++) {
BeanPersistListener<?> c = list.get(i);
if (isRegisterFor(deployDesc.getBeanType(), c)) {
logger.fine("BeanPersistListener on[" + deployDesc.getFullName() + "] " + c.getClass().getName());
deployDesc.addPersistListener((BeanPersistListener<T>) c);
}
}
}
public static boolean isRegisterFor(Class<?> beanType, BeanPersistListener<?> c) {
Class<?> listenerEntity = getEntityClass(c.getClass());
return beanType.equals(listenerEntity);
}
/**
* Find the entity class given the controller class.
* <p>
* This uses reflection to find the generics parameter type.
* </p>
*/
private static Class<?> getEntityClass(Class<?> controller) {
Class<?> cls = ParamTypeUtil.findParamType(controller, BeanPersistListener.class);
if (cls == null) {
String msg = "Could not determine the entity class (generics parameter type) from " + controller
+ " using reflection.";
throw new PersistenceException(msg);
}
return cls;
}
}
package com.avaje.ebeaninternal.server.deploy;
import java.util.List;
import java.util.logging.Logger;
import javax.persistence.PersistenceException;
import com.avaje.ebean.event.BeanPersistListener;
import com.avaje.ebeaninternal.server.core.BootupClasses;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanDescriptor;
/**
* Manages the assignment/registration of BeanPersistListener with their
* respective DeployBeanDescriptor's.
*/
public class PersistListenerManager {
private static final Logger logger = Logger.getLogger(PersistListenerManager.class.getName());
private final List<BeanPersistListener<?>> list;
public PersistListenerManager(BootupClasses bootupClasses) {
list = bootupClasses.getBeanPersistListeners();
}
public int getRegisterCount() {
return list.size();
}
/**
* Return the BeanPersistController for a given entity type.
*/
@SuppressWarnings("unchecked")
public <T> void addPersistListeners(DeployBeanDescriptor<T> deployDesc) {
for (int i = 0; i < list.size(); i++) {
BeanPersistListener<?> c = list.get(i);
if (isRegisterFor(deployDesc.getBeanType(), c)) {
logger.fine("BeanPersistListener on[" + deployDesc.getFullName() + "] " + c.getClass().getName());
deployDesc.addPersistListener((BeanPersistListener<T>) c);
}
}
}
public static boolean isRegisterFor(Class<?> beanType, BeanPersistListener<?> c) {
Class<?> listenerEntity = getEntityClass(c.getClass());
return beanType.equals(listenerEntity);
}
/**
* Find the entity class given the controller class.
* <p>
* This uses reflection to find the generics parameter type.
* </p>
*/
private static Class<?> getEntityClass(Class<?> controller) {
Class<?> cls = ParamTypeUtil.findParamType(controller, BeanPersistListener.class);
if (cls == null) {
String msg = "Could not determine the entity class (generics parameter type) from " + controller
+ " using reflection.";
throw new PersistenceException(msg);
}
return cls;
}
}
@@ -1,104 +1,85 @@
/**
* Copyright (C) 2009 Authors
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy;
import java.lang.reflect.Method;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
import com.avaje.ebeaninternal.server.reflect.BeanReflectGetter;
/**
* For abstract classes that hold the id property we need to
* use reflection to get the id values some times.
* <p>
* This provides the BeanReflectGetter objects to do that.
* </p>
* @author rbygrave
*/
public class ReflectGetter {
/**
* Create a reflection based BeanReflectGetter for getting the
* id from abstract inheritance hierarchy object.
*/
public static BeanReflectGetter create(DeployBeanProperty prop) {
if (!prop.isId()){
// not expecting this to ever be used/called
return new NonIdGetter(prop.getFullBeanName());
} else {
String property = prop.getFullBeanName();
Method readMethod = prop.getReadMethod();
if (readMethod == null){
String m = "Abstract class with no readMethod for "+property;
throw new RuntimeException(m);
}
return new IdGetter(property, readMethod);
}
}
public static class IdGetter implements BeanReflectGetter {
public static final Object[] NO_ARGS = new Object[0];
private final Method readMethod;
private final String property;
public IdGetter(String property, Method readMethod) {
this.property = property;
this.readMethod = readMethod;
}
public Object get(Object bean) {
try {
return readMethod.invoke(bean, NO_ARGS);
} catch (Exception e) {
String m = "Error on ["+property+"] using readMethod "+readMethod;
throw new RuntimeException(m, e);
}
}
public Object getIntercept(Object bean) {
return get(bean);
}
}
public static class NonIdGetter implements BeanReflectGetter {
private final String property;
public NonIdGetter(String property) {
this.property = property;
}
public Object get(Object bean) {
String m = "Not expecting this method to be called on ["+property
+"] as it is a NON ID property on an abstract class";
throw new RuntimeException(m);
}
public Object getIntercept(Object bean) {
return get(bean);
}
}
}
package com.avaje.ebeaninternal.server.deploy;
import java.lang.reflect.Method;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
import com.avaje.ebeaninternal.server.reflect.BeanReflectGetter;
/**
* For abstract classes that hold the id property we need to
* use reflection to get the id values some times.
* <p>
* This provides the BeanReflectGetter objects to do that.
* </p>
* @author rbygrave
*/
public class ReflectGetter {
/**
* Create a reflection based BeanReflectGetter for getting the
* id from abstract inheritance hierarchy object.
*/
public static BeanReflectGetter create(DeployBeanProperty prop) {
if (!prop.isId()){
// not expecting this to ever be used/called
return new NonIdGetter(prop.getFullBeanName());
} else {
String property = prop.getFullBeanName();
Method readMethod = prop.getReadMethod();
if (readMethod == null){
String m = "Abstract class with no readMethod for "+property;
throw new RuntimeException(m);
}
return new IdGetter(property, readMethod);
}
}
public static class IdGetter implements BeanReflectGetter {
public static final Object[] NO_ARGS = new Object[0];
private final Method readMethod;
private final String property;
public IdGetter(String property, Method readMethod) {
this.property = property;
this.readMethod = readMethod;
}
public Object get(Object bean) {
try {
return readMethod.invoke(bean, NO_ARGS);
} catch (Exception e) {
String m = "Error on ["+property+"] using readMethod "+readMethod;
throw new RuntimeException(m, e);
}
}
public Object getIntercept(Object bean) {
return get(bean);
}
}
public static class NonIdGetter implements BeanReflectGetter {
private final String property;
public NonIdGetter(String property) {
this.property = property;
}
public Object get(Object bean) {
String m = "Not expecting this method to be called on ["+property
+"] as it is a NON ID property on an abstract class";
throw new RuntimeException(m);
}
public Object getIntercept(Object bean) {
return get(bean);
}
}
}
@@ -1,72 +1,53 @@
/**
* Copyright (C) 2009 Authors
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy;
import java.lang.reflect.Method;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
import com.avaje.ebeaninternal.server.reflect.BeanReflectSetter;
/**
* A place holder for BeanReflectSetter that should never be called.
* <p>
* This is for properties of classes that are abstract and at the root
* of an inheritance hierarchy.
* </p>
* @author rbygrave
*/
public class ReflectSetter {
/**
* Creates place holder objects that should never be called.
*/
public static BeanReflectSetter create(DeployBeanProperty prop) {
String fullName = prop.getFullBeanName();
Method writeMethod = prop.getWriteMethod();
return new RefCalled(fullName, writeMethod);
}
static class RefCalled implements BeanReflectSetter {
final String fullName;
final Method writeMethod;
RefCalled(String fullName, Method writeMethod) {
this.fullName = fullName;
this.writeMethod = writeMethod;
}
public void set(Object bean, Object value) {
Object[] a = new Object[1];
a[0] = value;
try {
writeMethod.invoke(bean, a);
} catch (Exception e) {
String beanType = bean == null ? "null" : bean.getClass().toString();
String msg = "Error setting value on "+fullName+" value["+value+"] on type["+beanType+"]";
throw new RuntimeException(msg, e);
}
}
public void setIntercept(Object bean, Object value) {
String msg = "Not expecting setIntercept to be called. Refer Bug 368";
throw new RuntimeException(msg);
}
}
}
package com.avaje.ebeaninternal.server.deploy;
import java.lang.reflect.Method;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
import com.avaje.ebeaninternal.server.reflect.BeanReflectSetter;
/**
* A place holder for BeanReflectSetter that should never be called.
* <p>
* This is for properties of classes that are abstract and at the root
* of an inheritance hierarchy.
* </p>
* @author rbygrave
*/
public class ReflectSetter {
/**
* Creates place holder objects that should never be called.
*/
public static BeanReflectSetter create(DeployBeanProperty prop) {
String fullName = prop.getFullBeanName();
Method writeMethod = prop.getWriteMethod();
return new RefCalled(fullName, writeMethod);
}
static class RefCalled implements BeanReflectSetter {
final String fullName;
final Method writeMethod;
RefCalled(String fullName, Method writeMethod) {
this.fullName = fullName;
this.writeMethod = writeMethod;
}
public void set(Object bean, Object value) {
Object[] a = new Object[1];
a[0] = value;
try {
writeMethod.invoke(bean, a);
} catch (Exception e) {
String beanType = bean == null ? "null" : bean.getClass().toString();
String msg = "Error setting value on "+fullName+" value["+value+"] on type["+beanType+"]";
throw new RuntimeException(msg, e);
}
}
public void setIntercept(Object bean, Object value) {
String msg = "Not expecting setIntercept to be called. Refer Bug 368";
throw new RuntimeException(msg);
}
}
}
@@ -1,48 +1,29 @@
/**
* Copyright (C) 2009 Authors
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy;
import scala.collection.JavaConversions;
/**
* Converts between Java List and Scala mutable Buffer.
*
* @author rbygrave
*/
public class ScalaBufferConverter implements CollectionTypeConverter {
// @SuppressWarnings({ "rawtypes" })
public Object toUnderlying(Object wrapped) {
throw new IllegalArgumentException("Scala types not supported in this build");
// if (wrapped instanceof JavaConversions.JListWrapper){
// return ((JavaConversions.JListWrapper)wrapped).underlying();
// }
// return null;
}
public Object toWrapped(Object wrapped) {
throw new IllegalArgumentException("Scala types not supported in this build");
// if (wrapped instanceof java.util.List<?>){
// return JavaConversions.asScalaBuffer((java.util.List<?>)wrapped);
// }
// return wrapped;
}
}
package com.avaje.ebeaninternal.server.deploy;
import scala.collection.JavaConversions;
/**
* Converts between Java List and Scala mutable Buffer.
*
* @author rbygrave
*/
public class ScalaBufferConverter implements CollectionTypeConverter {
// @SuppressWarnings({ "rawtypes" })
public Object toUnderlying(Object wrapped) {
throw new IllegalArgumentException("Scala types not supported in this build");
// if (wrapped instanceof JavaConversions.JListWrapper){
// return ((JavaConversions.JListWrapper)wrapped).underlying();
// }
// return null;
}
public Object toWrapped(Object wrapped) {
throw new IllegalArgumentException("Scala types not supported in this build");
// if (wrapped instanceof java.util.List<?>){
// return JavaConversions.asScalaBuffer((java.util.List<?>)wrapped);
// }
// return wrapped;
}
}
@@ -1,48 +1,29 @@
/**
* Copyright (C) 2009 Authors
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy;
import scala.collection.JavaConversions;
/**
* Converts between Java Map and Scala mutable Map.
*
* @author rbygrave
*/
public class ScalaMapConverter implements CollectionTypeConverter {
// @SuppressWarnings({ "rawtypes" })
public Object toUnderlying(Object wrapped) {
throw new IllegalArgumentException("Scala types not supported in this build");
// if (wrapped instanceof JavaConversions.JMapWrapper){
// return ((JavaConversions.JMapWrapper)wrapped).underlying();
// }
// return null;
}
public Object toWrapped(Object wrapped) {
throw new IllegalArgumentException("Scala types not supported in this build");
// if (wrapped instanceof java.util.Map<?,?>){
// return JavaConversions.mapAsScalaMap((java.util.Map<?,?>)wrapped);
// }
// return wrapped;
}
}
package com.avaje.ebeaninternal.server.deploy;
import scala.collection.JavaConversions;
/**
* Converts between Java Map and Scala mutable Map.
*
* @author rbygrave
*/
public class ScalaMapConverter implements CollectionTypeConverter {
// @SuppressWarnings({ "rawtypes" })
public Object toUnderlying(Object wrapped) {
throw new IllegalArgumentException("Scala types not supported in this build");
// if (wrapped instanceof JavaConversions.JMapWrapper){
// return ((JavaConversions.JMapWrapper)wrapped).underlying();
// }
// return null;
}
public Object toWrapped(Object wrapped) {
throw new IllegalArgumentException("Scala types not supported in this build");
// if (wrapped instanceof java.util.Map<?,?>){
// return JavaConversions.mapAsScalaMap((java.util.Map<?,?>)wrapped);
// }
// return wrapped;
}
}
@@ -1,49 +1,30 @@
/**
* Copyright (C) 2009 Authors
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy;
import scala.collection.JavaConversions;
import scala.collection.convert.DecorateAsScala;
/**
* Converts between Java Set and Scala mutable Set.
*
* @author rbygrave
*/
public class ScalaSetConverter implements CollectionTypeConverter {
// @SuppressWarnings({ "rawtypes" })
public Object toUnderlying(Object wrapped) {
throw new IllegalArgumentException("Scala types not supported in this build");
// if (wrapped instanceof JavaConversions.JSetWrapper){
// return ((JavaConversions.JSetWrapper)wrapped).underlying();
// }
// return null;
}
public Object toWrapped(Object wrapped) {
throw new IllegalArgumentException("Scala types not supported in this build");
// if (wrapped instanceof java.util.Set<?>){
// return JavaConversions.asScalaSet((java.util.Set<?>)wrapped);
// }
// return wrapped;
}
}
package com.avaje.ebeaninternal.server.deploy;
import scala.collection.JavaConversions;
import scala.collection.convert.DecorateAsScala;
/**
* Converts between Java Set and Scala mutable Set.
*
* @author rbygrave
*/
public class ScalaSetConverter implements CollectionTypeConverter {
// @SuppressWarnings({ "rawtypes" })
public Object toUnderlying(Object wrapped) {
throw new IllegalArgumentException("Scala types not supported in this build");
// if (wrapped instanceof JavaConversions.JSetWrapper){
// return ((JavaConversions.JSetWrapper)wrapped).underlying();
// }
// return null;
}
public Object toWrapped(Object wrapped) {
throw new IllegalArgumentException("Scala types not supported in this build");
// if (wrapped instanceof java.util.Set<?>){
// return JavaConversions.asScalaSet((java.util.Set<?>)wrapped);
// }
// return wrapped;
}
}
@@ -1,227 +1,208 @@
/**
* Copyright (C) 2006 Robin Bygrave
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy;
import com.avaje.ebeaninternal.server.core.InternString;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
import com.avaje.ebeaninternal.server.deploy.meta.DeployTableJoin;
import com.avaje.ebeaninternal.server.deploy.meta.DeployTableJoinColumn;
import com.avaje.ebeaninternal.server.query.SplitName;
import com.avaje.ebeaninternal.server.query.SqlBeanLoad;
import java.sql.SQLException;
import java.util.LinkedHashMap;
/**
* Represents a join to another table.
*/
public final class TableJoin {
public static final String NEW_LINE = "\n";
public static final String LEFT_OUTER = "left outer join";
public static final String JOIN = "join";
/**
* Flag set when the imported key maps to the primary key.
* This occurs for intersection tables (ManyToMany).
*/
private final boolean importedPrimaryKey;
/**
* The joined table.
*/
private final String table;
/**
* The type of join. LEFT OUTER etc.
*/
private final String type;
/**
* The persist cascade info.
*/
private final BeanCascadeInfo cascadeInfo;
/**
* Properties as an array.
*/
private final BeanProperty[] properties;
/**
* Columns as an array.
*/
private final TableJoinColumn[] columns;
/**
* Create a TableJoin.
*/
public TableJoin(DeployTableJoin deploy, LinkedHashMap<String,BeanProperty> propMap) {
this.importedPrimaryKey = deploy.isImportedPrimaryKey();
this.table = InternString.intern(deploy.getTable());
this.type = InternString.intern(deploy.getType());
this.cascadeInfo = deploy.getCascadeInfo();
DeployTableJoinColumn[] deployCols = deploy.columns();
this.columns = new TableJoinColumn[deployCols.length];
for (int i = 0; i < deployCols.length; i++) {
this.columns[i] = new TableJoinColumn(deployCols[i]);
}
DeployBeanProperty[] deployProps = deploy.properties();
if (deployProps.length > 0 && propMap == null){
throw new NullPointerException("propMap is null?");
}
this.properties = new BeanProperty[deployProps.length];
for (int i = 0; i < deployProps.length; i++) {
BeanProperty prop = propMap.get(deployProps[i].getName());
this.properties[i] = prop;
}
}
/**
* Create a tableJoin based on this object but with different alias.
*/
public TableJoin createWithAlias(String localAlias, String foreignAlias) {
return new TableJoin(this, localAlias, foreignAlias);
}
/**
* Construct a copy but with different table alias'.
*/
private TableJoin(TableJoin join, String localAlias, String foreignAlias){
// copy the immutable fields
this.importedPrimaryKey = join.importedPrimaryKey;
this.table = join.table;
this.type = join.type;
this.cascadeInfo = join.cascadeInfo;
this.properties = join.properties;
this.columns = join.columns;
}
public String toString() {
StringBuilder sb = new StringBuilder(30);
sb.append(type).append(" ").append(table).append(" ");
for (int i = 0; i < columns.length; i++) {
sb.append(columns[i]).append(" ");
}
return sb.toString();
}
public void appendSelect(DbSqlContext ctx, boolean subQuery) {
for (int i = 0, x = properties.length; i < x; i++) {
properties[i].appendSelect(ctx, subQuery);
}
}
public void load(SqlBeanLoad sqlBeanLoad) throws SQLException {
for (int i = 0, x = properties.length; i < x; i++) {
properties[i].load(sqlBeanLoad);
}
}
public Object readSet(DbReadContext ctx, Object bean, Class<?> type) throws SQLException {
for (int i = 0, x = properties.length; i < x; i++) {
properties[i].readSet(ctx, bean, type);
}
return null;
}
/**
* Return true if the imported foreign key maps to the primary key.
*/
public boolean isImportedPrimaryKey() {
return importedPrimaryKey;
}
/**
* Return the persist info.
*/
public BeanCascadeInfo getCascadeInfo() {
return cascadeInfo;
}
/**
* Return the join columns.
*/
public TableJoinColumn[] columns() {
return columns;
}
/**
* For secondary table joins returns the properties mapped to that table.
*/
public BeanProperty[] properties() {
return properties;
}
/**
* Return the joined table name.
*/
public String getTable() {
return table;
}
/**
* Return the type of join. LEFT OUTER JOIN etc.
*/
public String getType() {
return type;
}
/**
* Return true if this join is a left outer join.
*/
public boolean isOuterJoin() {
return type.equals(LEFT_OUTER);
}
public boolean addJoin(boolean forceOuterJoin, String prefix, DbSqlContext ctx) {
String[] names = SplitName.split(prefix);
String a1 = ctx.getTableAlias(names[0]);
String a2 = ctx.getTableAlias(prefix);
return addJoin(forceOuterJoin, a1, a2, ctx);
}
public boolean addJoin(boolean forceOuterJoin, String a1, String a2, DbSqlContext ctx) {
ctx.addJoin(forceOuterJoin?LEFT_OUTER:type, table, columns(), a1, a2);
return forceOuterJoin || LEFT_OUTER.equals(type);
}
/**
* Explicitly add a (non-outer) join.
*/
public void addInnerJoin(String a1, String a2, DbSqlContext ctx) {
ctx.addJoin(JOIN, table, columns(), a1, a2);
}
}
package com.avaje.ebeaninternal.server.deploy;
import com.avaje.ebeaninternal.server.core.InternString;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
import com.avaje.ebeaninternal.server.deploy.meta.DeployTableJoin;
import com.avaje.ebeaninternal.server.deploy.meta.DeployTableJoinColumn;
import com.avaje.ebeaninternal.server.query.SplitName;
import com.avaje.ebeaninternal.server.query.SqlBeanLoad;
import java.sql.SQLException;
import java.util.LinkedHashMap;
/**
* Represents a join to another table.
*/
public final class TableJoin {
public static final String NEW_LINE = "\n";
public static final String LEFT_OUTER = "left outer join";
public static final String JOIN = "join";
/**
* Flag set when the imported key maps to the primary key.
* This occurs for intersection tables (ManyToMany).
*/
private final boolean importedPrimaryKey;
/**
* The joined table.
*/
private final String table;
/**
* The type of join. LEFT OUTER etc.
*/
private final String type;
/**
* The persist cascade info.
*/
private final BeanCascadeInfo cascadeInfo;
/**
* Properties as an array.
*/
private final BeanProperty[] properties;
/**
* Columns as an array.
*/
private final TableJoinColumn[] columns;
/**
* Create a TableJoin.
*/
public TableJoin(DeployTableJoin deploy, LinkedHashMap<String,BeanProperty> propMap) {
this.importedPrimaryKey = deploy.isImportedPrimaryKey();
this.table = InternString.intern(deploy.getTable());
this.type = InternString.intern(deploy.getType());
this.cascadeInfo = deploy.getCascadeInfo();
DeployTableJoinColumn[] deployCols = deploy.columns();
this.columns = new TableJoinColumn[deployCols.length];
for (int i = 0; i < deployCols.length; i++) {
this.columns[i] = new TableJoinColumn(deployCols[i]);
}
DeployBeanProperty[] deployProps = deploy.properties();
if (deployProps.length > 0 && propMap == null){
throw new NullPointerException("propMap is null?");
}
this.properties = new BeanProperty[deployProps.length];
for (int i = 0; i < deployProps.length; i++) {
BeanProperty prop = propMap.get(deployProps[i].getName());
this.properties[i] = prop;
}
}
/**
* Create a tableJoin based on this object but with different alias.
*/
public TableJoin createWithAlias(String localAlias, String foreignAlias) {
return new TableJoin(this, localAlias, foreignAlias);
}
/**
* Construct a copy but with different table alias'.
*/
private TableJoin(TableJoin join, String localAlias, String foreignAlias){
// copy the immutable fields
this.importedPrimaryKey = join.importedPrimaryKey;
this.table = join.table;
this.type = join.type;
this.cascadeInfo = join.cascadeInfo;
this.properties = join.properties;
this.columns = join.columns;
}
public String toString() {
StringBuilder sb = new StringBuilder(30);
sb.append(type).append(" ").append(table).append(" ");
for (int i = 0; i < columns.length; i++) {
sb.append(columns[i]).append(" ");
}
return sb.toString();
}
public void appendSelect(DbSqlContext ctx, boolean subQuery) {
for (int i = 0, x = properties.length; i < x; i++) {
properties[i].appendSelect(ctx, subQuery);
}
}
public void load(SqlBeanLoad sqlBeanLoad) throws SQLException {
for (int i = 0, x = properties.length; i < x; i++) {
properties[i].load(sqlBeanLoad);
}
}
public Object readSet(DbReadContext ctx, Object bean, Class<?> type) throws SQLException {
for (int i = 0, x = properties.length; i < x; i++) {
properties[i].readSet(ctx, bean, type);
}
return null;
}
/**
* Return true if the imported foreign key maps to the primary key.
*/
public boolean isImportedPrimaryKey() {
return importedPrimaryKey;
}
/**
* Return the persist info.
*/
public BeanCascadeInfo getCascadeInfo() {
return cascadeInfo;
}
/**
* Return the join columns.
*/
public TableJoinColumn[] columns() {
return columns;
}
/**
* For secondary table joins returns the properties mapped to that table.
*/
public BeanProperty[] properties() {
return properties;
}
/**
* Return the joined table name.
*/
public String getTable() {
return table;
}
/**
* Return the type of join. LEFT OUTER JOIN etc.
*/
public String getType() {
return type;
}
/**
* Return true if this join is a left outer join.
*/
public boolean isOuterJoin() {
return type.equals(LEFT_OUTER);
}
public boolean addJoin(boolean forceOuterJoin, String prefix, DbSqlContext ctx) {
String[] names = SplitName.split(prefix);
String a1 = ctx.getTableAlias(names[0]);
String a2 = ctx.getTableAlias(prefix);
return addJoin(forceOuterJoin, a1, a2, ctx);
}
public boolean addJoin(boolean forceOuterJoin, String a1, String a2, DbSqlContext ctx) {
ctx.addJoin(forceOuterJoin?LEFT_OUTER:type, table, columns(), a1, a2);
return forceOuterJoin || LEFT_OUTER.equals(type);
}
/**
* Explicitly add a (non-outer) join.
*/
public void addInnerJoin(String a1, String a2, DbSqlContext ctx) {
ctx.addJoin(JOIN, table, columns(), a1, a2);
}
}
@@ -1,86 +1,67 @@
/**
* Copyright (C) 2006 Robin Bygrave
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy;
import com.avaje.ebeaninternal.server.core.InternString;
import com.avaje.ebeaninternal.server.deploy.meta.DeployTableJoinColumn;
/**
* A join pair of local and foreign properties.
*/
public class TableJoinColumn {
/**
* The local database column name.
*/
private final String localDbColumn;
/**
* The foreign database column name.
*/
private final String foreignDbColumn;
private final boolean insertable;
private final boolean updateable;
/**
* Create the pair.
*/
public TableJoinColumn(DeployTableJoinColumn deploy) {
this.localDbColumn = InternString.intern(deploy.getLocalDbColumn());
this.foreignDbColumn = InternString.intern(deploy.getForeignDbColumn());
this.insertable = deploy.isInsertable();
this.updateable = deploy.isUpdateable();
}
public String toString() {
return localDbColumn+" = "+foreignDbColumn;
}
/**
* Return the foreign database column name.
*/
public String getForeignDbColumn() {
return foreignDbColumn;
}
/**
* Return the local database column name.
*/
public String getLocalDbColumn() {
return localDbColumn;
}
/**
* Return true if this column should be insertable.
*/
public boolean isInsertable() {
return insertable;
}
/**
* Return true if this column should be updateable.
*/
public boolean isUpdateable() {
return updateable;
}
}
package com.avaje.ebeaninternal.server.deploy;
import com.avaje.ebeaninternal.server.core.InternString;
import com.avaje.ebeaninternal.server.deploy.meta.DeployTableJoinColumn;
/**
* A join pair of local and foreign properties.
*/
public class TableJoinColumn {
/**
* The local database column name.
*/
private final String localDbColumn;
/**
* The foreign database column name.
*/
private final String foreignDbColumn;
private final boolean insertable;
private final boolean updateable;
/**
* Create the pair.
*/
public TableJoinColumn(DeployTableJoinColumn deploy) {
this.localDbColumn = InternString.intern(deploy.getLocalDbColumn());
this.foreignDbColumn = InternString.intern(deploy.getForeignDbColumn());
this.insertable = deploy.isInsertable();
this.updateable = deploy.isUpdateable();
}
public String toString() {
return localDbColumn+" = "+foreignDbColumn;
}
/**
* Return the foreign database column name.
*/
public String getForeignDbColumn() {
return foreignDbColumn;
}
/**
* Return the local database column name.
*/
public String getLocalDbColumn() {
return localDbColumn;
}
/**
* Return true if this column should be insertable.
*/
public boolean isInsertable() {
return insertable;
}
/**
* Return true if this column should be updateable.
*/
public boolean isUpdateable() {
return updateable;
}
}
@@ -1,83 +1,64 @@
/**
* Copyright (C) 2006 Robin Bygrave
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy.generatedproperty;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Types;
import javax.persistence.PersistenceException;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
/**
* Creates "Counter" GeneratedProperty for various types of number.
* <p>
* Aka, Integer, Long, Short etc.
* </p>
*/
public class CounterFactory {
final GeneratedCounterInteger integerCounter = new GeneratedCounterInteger();
final GeneratedCounterLong longCounter = new GeneratedCounterLong();
public void setCounter(DeployBeanProperty property) {
property.setGeneratedProperty(createCounter(property));
}
/**
* Create the GeneratedProperty based on the property type.
*/
private GeneratedProperty createCounter(DeployBeanProperty property) {
Class<?> propType = property.getPropertyType();
if (propType.equals(Integer.class) || propType.equals(int.class)) {
return integerCounter;
}
if (propType.equals(Long.class) || propType.equals(long.class)) {
return longCounter;
}
int type = getType(propType);
return new GeneratedCounter(type);
}
private int getType(Class<?> propType){
if (propType.equals(Short.class) || propType.equals(short.class)){
return Types.TINYINT;
}
if (propType.equals(BigDecimal.class)){
return Types.DECIMAL;
}
if (propType.equals(Double.class) || propType.equals(double.class)){
return Types.DOUBLE;
}
if (propType.equals(Float.class) || propType.equals(float.class)){
return Types.REAL;
}
if (propType.equals(BigInteger.class)){
return Types.BIGINT;
}
String msg = "Can not support Counter for type "+propType.getName();
throw new PersistenceException(msg);
}
}
package com.avaje.ebeaninternal.server.deploy.generatedproperty;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Types;
import javax.persistence.PersistenceException;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
/**
* Creates "Counter" GeneratedProperty for various types of number.
* <p>
* Aka, Integer, Long, Short etc.
* </p>
*/
public class CounterFactory {
final GeneratedCounterInteger integerCounter = new GeneratedCounterInteger();
final GeneratedCounterLong longCounter = new GeneratedCounterLong();
public void setCounter(DeployBeanProperty property) {
property.setGeneratedProperty(createCounter(property));
}
/**
* Create the GeneratedProperty based on the property type.
*/
private GeneratedProperty createCounter(DeployBeanProperty property) {
Class<?> propType = property.getPropertyType();
if (propType.equals(Integer.class) || propType.equals(int.class)) {
return integerCounter;
}
if (propType.equals(Long.class) || propType.equals(long.class)) {
return longCounter;
}
int type = getType(propType);
return new GeneratedCounter(type);
}
private int getType(Class<?> propType){
if (propType.equals(Short.class) || propType.equals(short.class)){
return Types.TINYINT;
}
if (propType.equals(BigDecimal.class)){
return Types.DECIMAL;
}
if (propType.equals(Double.class) || propType.equals(double.class)){
return Types.DOUBLE;
}
if (propType.equals(Float.class) || propType.equals(float.class)){
return Types.REAL;
}
if (propType.equals(BigInteger.class)){
return Types.BIGINT;
}
String msg = "Can not support Counter for type "+propType.getName();
throw new PersistenceException(msg);
}
}
@@ -1,71 +1,52 @@
/**
* Copyright (C) 2006 Robin Bygrave
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy.generatedproperty;
import com.avaje.ebeaninternal.server.core.BasicTypeConverter;
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
/**
* A general number counter for various number types.
*/
public class GeneratedCounter implements GeneratedProperty {
final int numberType;
public GeneratedCounter(int numberType) {
this.numberType = numberType;
}
/**
* Always returns a 1.
*/
public Object getInsertValue(BeanProperty prop, Object bean) {
Integer i = Integer.valueOf(1);
return BasicTypeConverter.convert(i, numberType);
}
/**
* Increments the current value by one.
*/
public Object getUpdateValue(BeanProperty prop, Object bean) {
Number currVal = (Number) prop.getValue(bean);
Integer nextVal = Integer.valueOf(currVal.intValue() + 1);
return BasicTypeConverter.convert(nextVal, numberType);
}
/**
* Include this in every update.
*/
public boolean includeInUpdate() {
return true;
}
/**
* Include this in every insert setting initial counter value to 1.
*/
public boolean includeInInsert() {
return true;
}
public boolean isDDLNotNullable() {
return true;
}
}
package com.avaje.ebeaninternal.server.deploy.generatedproperty;
import com.avaje.ebeaninternal.server.core.BasicTypeConverter;
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
/**
* A general number counter for various number types.
*/
public class GeneratedCounter implements GeneratedProperty {
final int numberType;
public GeneratedCounter(int numberType) {
this.numberType = numberType;
}
/**
* Always returns a 1.
*/
public Object getInsertValue(BeanProperty prop, Object bean) {
Integer i = Integer.valueOf(1);
return BasicTypeConverter.convert(i, numberType);
}
/**
* Increments the current value by one.
*/
public Object getUpdateValue(BeanProperty prop, Object bean) {
Number currVal = (Number) prop.getValue(bean);
Integer nextVal = Integer.valueOf(currVal.intValue() + 1);
return BasicTypeConverter.convert(nextVal, numberType);
}
/**
* Include this in every update.
*/
public boolean includeInUpdate() {
return true;
}
/**
* Include this in every insert setting initial counter value to 1.
*/
public boolean includeInInsert() {
return true;
}
public boolean isDDLNotNullable() {
return true;
}
}
@@ -1,66 +1,47 @@
/**
* Copyright (C) 2006 Robin Bygrave
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy.generatedproperty;
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
/**
* Used to create a counter version column for Integer.
*/
public class GeneratedCounterInteger implements GeneratedProperty {
public GeneratedCounterInteger() {
}
/**
* Always returns a 1.
*/
public Object getInsertValue(BeanProperty prop, Object bean) {
return Integer.valueOf(1);
}
/**
* Increments the current value by one.
*/
public Object getUpdateValue(BeanProperty prop, Object bean) {
Integer i = (Integer) prop.getValue(bean);
return Integer.valueOf(i.intValue() + 1);
}
/**
* Include this in every update.
*/
public boolean includeInUpdate() {
return true;
}
/**
* Include this in every insert setting initial counter value to 1.
*/
public boolean includeInInsert() {
return true;
}
public boolean isDDLNotNullable() {
return true;
}
}
package com.avaje.ebeaninternal.server.deploy.generatedproperty;
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
/**
* Used to create a counter version column for Integer.
*/
public class GeneratedCounterInteger implements GeneratedProperty {
public GeneratedCounterInteger() {
}
/**
* Always returns a 1.
*/
public Object getInsertValue(BeanProperty prop, Object bean) {
return Integer.valueOf(1);
}
/**
* Increments the current value by one.
*/
public Object getUpdateValue(BeanProperty prop, Object bean) {
Integer i = (Integer) prop.getValue(bean);
return Integer.valueOf(i.intValue() + 1);
}
/**
* Include this in every update.
*/
public boolean includeInUpdate() {
return true;
}
/**
* Include this in every insert setting initial counter value to 1.
*/
public boolean includeInInsert() {
return true;
}
public boolean isDDLNotNullable() {
return true;
}
}
@@ -1,66 +1,47 @@
/**
* Copyright (C) 2006 Robin Bygrave
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy.generatedproperty;
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
/**
* Used to create a counter version column for Long.
*/
public class GeneratedCounterLong implements GeneratedProperty {
public GeneratedCounterLong() {
}
/**
* Always returns a 1.
*/
public Object getInsertValue(BeanProperty prop, Object bean) {
return Long.valueOf(1);
}
/**
* Increments the current value by one.
*/
public Object getUpdateValue(BeanProperty prop, Object bean) {
Long i = (Long) prop.getValue(bean);
return Long.valueOf(i.longValue() + 1);
}
/**
* Include this in every update.
*/
public boolean includeInUpdate() {
return true;
}
/**
* Include this in every insert setting initial counter value to 1.
*/
public boolean includeInInsert() {
return true;
}
public boolean isDDLNotNullable() {
return true;
}
}
package com.avaje.ebeaninternal.server.deploy.generatedproperty;
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
/**
* Used to create a counter version column for Long.
*/
public class GeneratedCounterLong implements GeneratedProperty {
public GeneratedCounterLong() {
}
/**
* Always returns a 1.
*/
public Object getInsertValue(BeanProperty prop, Object bean) {
return Long.valueOf(1);
}
/**
* Increments the current value by one.
*/
public Object getUpdateValue(BeanProperty prop, Object bean) {
Long i = (Long) prop.getValue(bean);
return Long.valueOf(i.longValue() + 1);
}
/**
* Include this in every update.
*/
public boolean includeInUpdate() {
return true;
}
/**
* Include this in every insert setting initial counter value to 1.
*/
public boolean includeInInsert() {
return true;
}
public boolean isDDLNotNullable() {
return true;
}
}
@@ -1,63 +1,44 @@
/**
* Copyright (C) 2006 Robin Bygrave
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy.generatedproperty;
import java.util.Date;
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
/**
* Used to generate a (java.util.Date) timestamp when a bean is inserted.
*/
public class GeneratedInsertDate implements GeneratedProperty {
/**
* Return the current time as a Timestamp.
*/
public Object getInsertValue(BeanProperty prop, Object bean) {
return new Date(System.currentTimeMillis());
}
/**
* Just returns the beans original insert timestamp value.
*/
public Object getUpdateValue(BeanProperty prop, Object bean) {
return prop.getValue(bean);
}
/**
* Return false.
*/
public boolean includeInUpdate() {
return false;
}
/**
* Return true.
*/
public boolean includeInInsert() {
return true;
}
public boolean isDDLNotNullable() {
return true;
}
}
package com.avaje.ebeaninternal.server.deploy.generatedproperty;
import java.util.Date;
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
/**
* Used to generate a (java.util.Date) timestamp when a bean is inserted.
*/
public class GeneratedInsertDate implements GeneratedProperty {
/**
* Return the current time as a Timestamp.
*/
public Object getInsertValue(BeanProperty prop, Object bean) {
return new Date(System.currentTimeMillis());
}
/**
* Just returns the beans original insert timestamp value.
*/
public Object getUpdateValue(BeanProperty prop, Object bean) {
return prop.getValue(bean);
}
/**
* Return false.
*/
public boolean includeInUpdate() {
return false;
}
/**
* Return true.
*/
public boolean includeInInsert() {
return true;
}
public boolean isDDLNotNullable() {
return true;
}
}
@@ -1,61 +1,42 @@
/**
* Copyright (C) 2006 Robin Bygrave
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy.generatedproperty;
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
/**
* Used to generate a (Long) timestamp when a bean is inserted.
*/
public class GeneratedInsertLong implements GeneratedProperty {
/**
* Return the current time as a Timestamp.
*/
public Object getInsertValue(BeanProperty prop, Object bean) {
return Long.valueOf(System.currentTimeMillis());
}
/**
* Just returns the beans original insert timestamp value.
*/
public Object getUpdateValue(BeanProperty prop, Object bean) {
return prop.getValue(bean);
}
/**
* Return false.
*/
public boolean includeInUpdate() {
return false;
}
/**
* Return true.
*/
public boolean includeInInsert() {
return true;
}
public boolean isDDLNotNullable() {
return true;
}
}
package com.avaje.ebeaninternal.server.deploy.generatedproperty;
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
/**
* Used to generate a (Long) timestamp when a bean is inserted.
*/
public class GeneratedInsertLong implements GeneratedProperty {
/**
* Return the current time as a Timestamp.
*/
public Object getInsertValue(BeanProperty prop, Object bean) {
return Long.valueOf(System.currentTimeMillis());
}
/**
* Just returns the beans original insert timestamp value.
*/
public Object getUpdateValue(BeanProperty prop, Object bean) {
return prop.getValue(bean);
}
/**
* Return false.
*/
public boolean includeInUpdate() {
return false;
}
/**
* Return true.
*/
public boolean includeInInsert() {
return true;
}
public boolean isDDLNotNullable() {
return true;
}
}
@@ -1,63 +1,44 @@
/**
* Copyright (C) 2006 Robin Bygrave
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy.generatedproperty;
import java.sql.Timestamp;
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
/**
* Used to generate a timestamp when a bean is inserted.
*/
public class GeneratedInsertTimestamp implements GeneratedProperty {
/**
* Return the current time as a Timestamp.
*/
public Object getInsertValue(BeanProperty prop, Object bean) {
return new Timestamp(System.currentTimeMillis());
}
/**
* Just returns the beans original insert timestamp value.
*/
public Object getUpdateValue(BeanProperty prop, Object bean) {
return prop.getValue(bean);
}
/**
* Return false.
*/
public boolean includeInUpdate() {
return false;
}
/**
* Return true.
*/
public boolean includeInInsert() {
return true;
}
public boolean isDDLNotNullable() {
return true;
}
}
package com.avaje.ebeaninternal.server.deploy.generatedproperty;
import java.sql.Timestamp;
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
/**
* Used to generate a timestamp when a bean is inserted.
*/
public class GeneratedInsertTimestamp implements GeneratedProperty {
/**
* Return the current time as a Timestamp.
*/
public Object getInsertValue(BeanProperty prop, Object bean) {
return new Timestamp(System.currentTimeMillis());
}
/**
* Just returns the beans original insert timestamp value.
*/
public Object getUpdateValue(BeanProperty prop, Object bean) {
return prop.getValue(bean);
}
/**
* Return false.
*/
public boolean includeInUpdate() {
return false;
}
/**
* Return true.
*/
public boolean includeInInsert() {
return true;
}
public boolean isDDLNotNullable() {
return true;
}
}
@@ -1,59 +1,40 @@
/**
* Copyright (C) 2006 Robin Bygrave
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy.generatedproperty;
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
/**
* Used to generate values for a property rather than have then set by the user.
* For example generate the update timestamp when a bean is updated.
*/
public interface GeneratedProperty {
/**
* Get the generated insert value for a specific property of a bean.
*/
public Object getInsertValue(BeanProperty prop, Object bean);
/**
* Get the generated update value for a specific property of a bean.
*/
public Object getUpdateValue(BeanProperty prop, Object bean);
/**
* Return true if this should always be includes in an update statement.
* <p>
* Used to include GeneratedUpdateTimestamp in dynamic table updates.
* </p>
*/
public boolean includeInUpdate();
/**
* Return true if this should be included in insert statements.
*/
public boolean includeInInsert();
/**
* Return true if the GeneratedProperty implies the DDL to create the DB
* column should have a not null constraint.
*/
public boolean isDDLNotNullable();
}
package com.avaje.ebeaninternal.server.deploy.generatedproperty;
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
/**
* Used to generate values for a property rather than have then set by the user.
* For example generate the update timestamp when a bean is updated.
*/
public interface GeneratedProperty {
/**
* Get the generated insert value for a specific property of a bean.
*/
public Object getInsertValue(BeanProperty prop, Object bean);
/**
* Get the generated update value for a specific property of a bean.
*/
public Object getUpdateValue(BeanProperty prop, Object bean);
/**
* Return true if this should always be includes in an update statement.
* <p>
* Used to include GeneratedUpdateTimestamp in dynamic table updates.
* </p>
*/
public boolean includeInUpdate();
/**
* Return true if this should be included in insert statements.
*/
public boolean includeInInsert();
/**
* Return true if the GeneratedProperty implies the DDL to create the DB
* column should have a not null constraint.
*/
public boolean isDDLNotNullable();
}
@@ -1,84 +1,65 @@
/**
* Copyright (C) 2006 Robin Bygrave
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy.generatedproperty;
import java.math.BigDecimal;
import java.util.HashSet;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
/**
* Default implementation of GeneratedPropertyFactory.
*/
public class GeneratedPropertyFactory {
CounterFactory counterFactory;
InsertTimestampFactory insertFactory;
UpdateTimestampFactory updateFactory;
HashSet<String> numberTypes = new HashSet<String>();
public GeneratedPropertyFactory() {
counterFactory = new CounterFactory();
insertFactory = new InsertTimestampFactory();
updateFactory = new UpdateTimestampFactory();
numberTypes.add(Integer.class.getName());
numberTypes.add(int.class.getName());
numberTypes.add(Long.class.getName());
numberTypes.add(long.class.getName());
numberTypes.add(Short.class.getName());
numberTypes.add(short.class.getName());
numberTypes.add(Double.class.getName());
numberTypes.add(double.class.getName());
numberTypes.add(BigDecimal.class.getName());
}
private boolean isNumberType(String typeClassName) {
return numberTypes.contains(typeClassName);
}
public void setVersion(DeployBeanProperty property) {
if (isNumberType(property.getPropertyType().getName())) {
setCounter(property);
} else {
setUpdateTimestamp(property);
}
}
public void setCounter(DeployBeanProperty property) {
counterFactory.setCounter(property);
}
public void setInsertTimestamp(DeployBeanProperty property) {
insertFactory.setInsertTimestamp(property);
}
public void setUpdateTimestamp(DeployBeanProperty property) {
updateFactory.setUpdateTimestamp(property);
}
}
package com.avaje.ebeaninternal.server.deploy.generatedproperty;
import java.math.BigDecimal;
import java.util.HashSet;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
/**
* Default implementation of GeneratedPropertyFactory.
*/
public class GeneratedPropertyFactory {
CounterFactory counterFactory;
InsertTimestampFactory insertFactory;
UpdateTimestampFactory updateFactory;
HashSet<String> numberTypes = new HashSet<String>();
public GeneratedPropertyFactory() {
counterFactory = new CounterFactory();
insertFactory = new InsertTimestampFactory();
updateFactory = new UpdateTimestampFactory();
numberTypes.add(Integer.class.getName());
numberTypes.add(int.class.getName());
numberTypes.add(Long.class.getName());
numberTypes.add(long.class.getName());
numberTypes.add(Short.class.getName());
numberTypes.add(short.class.getName());
numberTypes.add(Double.class.getName());
numberTypes.add(double.class.getName());
numberTypes.add(BigDecimal.class.getName());
}
private boolean isNumberType(String typeClassName) {
return numberTypes.contains(typeClassName);
}
public void setVersion(DeployBeanProperty property) {
if (isNumberType(property.getPropertyType().getName())) {
setCounter(property);
} else {
setUpdateTimestamp(property);
}
}
public void setCounter(DeployBeanProperty property) {
counterFactory.setCounter(property);
}
public void setInsertTimestamp(DeployBeanProperty property) {
insertFactory.setInsertTimestamp(property);
}
public void setUpdateTimestamp(DeployBeanProperty property) {
updateFactory.setUpdateTimestamp(property);
}
}
@@ -1,64 +1,45 @@
/**
* Copyright (C) 2006 Robin Bygrave
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy.generatedproperty;
import java.util.Date;
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
/**
* Generate a (java.util.Date) Timestamp whenever the bean is inserted or
* updated.
*/
public class GeneratedUpdateDate implements GeneratedProperty {
/**
* Return now as a Timestamp.
*/
public Object getInsertValue(BeanProperty prop, Object bean) {
return new Date(System.currentTimeMillis());
}
/**
* Return now as a Timestamp.
*/
public Object getUpdateValue(BeanProperty prop, Object bean) {
return new Date(System.currentTimeMillis());
}
/**
* For dynamic table updates make sure this is included.
*/
public boolean includeInUpdate() {
return true;
}
/**
* Include this in every insert.
*/
public boolean includeInInsert() {
return true;
}
public boolean isDDLNotNullable() {
return true;
}
}
package com.avaje.ebeaninternal.server.deploy.generatedproperty;
import java.util.Date;
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
/**
* Generate a (java.util.Date) Timestamp whenever the bean is inserted or
* updated.
*/
public class GeneratedUpdateDate implements GeneratedProperty {
/**
* Return now as a Timestamp.
*/
public Object getInsertValue(BeanProperty prop, Object bean) {
return new Date(System.currentTimeMillis());
}
/**
* Return now as a Timestamp.
*/
public Object getUpdateValue(BeanProperty prop, Object bean) {
return new Date(System.currentTimeMillis());
}
/**
* For dynamic table updates make sure this is included.
*/
public boolean includeInUpdate() {
return true;
}
/**
* Include this in every insert.
*/
public boolean includeInInsert() {
return true;
}
public boolean isDDLNotNullable() {
return true;
}
}
@@ -1,61 +1,42 @@
/**
* Copyright (C) 2006 Robin Bygrave
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy.generatedproperty;
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
/**
* Generate a (Long) Timestamp whenever the bean is inserted or updated.
*/
public class GeneratedUpdateLong implements GeneratedProperty {
/**
* Return now as a Timestamp.
*/
public Object getInsertValue(BeanProperty prop, Object bean) {
return Long.valueOf(System.currentTimeMillis());
}
/**
* Return now as a Timestamp.
*/
public Object getUpdateValue(BeanProperty prop, Object bean) {
return Long.valueOf(System.currentTimeMillis());
}
/**
* For dynamic table updates make sure this is included.
*/
public boolean includeInUpdate() {
return true;
}
/**
* Include this in every insert.
*/
public boolean includeInInsert() {
return true;
}
public boolean isDDLNotNullable() {
return true;
}
}
package com.avaje.ebeaninternal.server.deploy.generatedproperty;
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
/**
* Generate a (Long) Timestamp whenever the bean is inserted or updated.
*/
public class GeneratedUpdateLong implements GeneratedProperty {
/**
* Return now as a Timestamp.
*/
public Object getInsertValue(BeanProperty prop, Object bean) {
return Long.valueOf(System.currentTimeMillis());
}
/**
* Return now as a Timestamp.
*/
public Object getUpdateValue(BeanProperty prop, Object bean) {
return Long.valueOf(System.currentTimeMillis());
}
/**
* For dynamic table updates make sure this is included.
*/
public boolean includeInUpdate() {
return true;
}
/**
* Include this in every insert.
*/
public boolean includeInInsert() {
return true;
}
public boolean isDDLNotNullable() {
return true;
}
}
@@ -1,63 +1,44 @@
/**
* Copyright (C) 2006 Robin Bygrave
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy.generatedproperty;
import java.sql.Timestamp;
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
/**
* Generate a Timestamp whenever the bean is inserted or updated.
*/
public class GeneratedUpdateTimestamp implements GeneratedProperty {
/**
* Return now as a Timestamp.
*/
public Object getInsertValue(BeanProperty prop, Object bean) {
return new Timestamp(System.currentTimeMillis());
}
/**
* Return now as a Timestamp.
*/
public Object getUpdateValue(BeanProperty prop, Object bean) {
return new Timestamp(System.currentTimeMillis());
}
/**
* For dynamic table updates make sure this is included.
*/
public boolean includeInUpdate() {
return true;
}
/**
* Include this in every insert.
*/
public boolean includeInInsert() {
return true;
}
public boolean isDDLNotNullable() {
return true;
}
}
package com.avaje.ebeaninternal.server.deploy.generatedproperty;
import java.sql.Timestamp;
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
/**
* Generate a Timestamp whenever the bean is inserted or updated.
*/
public class GeneratedUpdateTimestamp implements GeneratedProperty {
/**
* Return now as a Timestamp.
*/
public Object getInsertValue(BeanProperty prop, Object bean) {
return new Timestamp(System.currentTimeMillis());
}
/**
* Return now as a Timestamp.
*/
public Object getUpdateValue(BeanProperty prop, Object bean) {
return new Timestamp(System.currentTimeMillis());
}
/**
* For dynamic table updates make sure this is included.
*/
public boolean includeInUpdate() {
return true;
}
/**
* Include this in every insert.
*/
public boolean includeInInsert() {
return true;
}
public boolean isDDLNotNullable() {
return true;
}
}
@@ -1,66 +1,47 @@
/**
* Copyright (C) 2006 Robin Bygrave
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy.generatedproperty;
import java.sql.Timestamp;
import javax.persistence.PersistenceException;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
/**
* Helper for creating Insert timestamp GeneratedProperty objects.
*/
public class InsertTimestampFactory {
final GeneratedInsertTimestamp timestamp = new GeneratedInsertTimestamp();
final GeneratedInsertDate utilDate = new GeneratedInsertDate();
final GeneratedInsertLong longTime = new GeneratedInsertLong();
public void setInsertTimestamp(DeployBeanProperty property) {
property.setGeneratedProperty(createInsertTimestamp(property));
}
/**
* Create the insert GeneratedProperty depending on the property type.
*/
public GeneratedProperty createInsertTimestamp(DeployBeanProperty property) {
Class<?> propType = property.getPropertyType();
if (propType.equals(Timestamp.class)) {
return timestamp;
}
if (propType.equals(java.util.Date.class)) {
return utilDate;
}
if (propType.equals(Long.class) || propType.equals(long.class)) {
return longTime;
}
//TODO: Support JODA Time objects ... perhaps others?
String msg = "Generated Insert Timestamp not supported on "+propType.getName();
throw new PersistenceException(msg);
}
}
package com.avaje.ebeaninternal.server.deploy.generatedproperty;
import java.sql.Timestamp;
import javax.persistence.PersistenceException;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
/**
* Helper for creating Insert timestamp GeneratedProperty objects.
*/
public class InsertTimestampFactory {
final GeneratedInsertTimestamp timestamp = new GeneratedInsertTimestamp();
final GeneratedInsertDate utilDate = new GeneratedInsertDate();
final GeneratedInsertLong longTime = new GeneratedInsertLong();
public void setInsertTimestamp(DeployBeanProperty property) {
property.setGeneratedProperty(createInsertTimestamp(property));
}
/**
* Create the insert GeneratedProperty depending on the property type.
*/
public GeneratedProperty createInsertTimestamp(DeployBeanProperty property) {
Class<?> propType = property.getPropertyType();
if (propType.equals(Timestamp.class)) {
return timestamp;
}
if (propType.equals(java.util.Date.class)) {
return utilDate;
}
if (propType.equals(Long.class) || propType.equals(long.class)) {
return longTime;
}
//TODO: Support JODA Time objects ... perhaps others?
String msg = "Generated Insert Timestamp not supported on "+propType.getName();
throw new PersistenceException(msg);
}
}
@@ -1,66 +1,47 @@
/**
* Copyright (C) 2006 Robin Bygrave
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy.generatedproperty;
import java.sql.Timestamp;
import javax.persistence.PersistenceException;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
/**
* Helper for creating Update timestamp GeneratedProperty objects.
*/
public class UpdateTimestampFactory {
final GeneratedUpdateTimestamp timestamp = new GeneratedUpdateTimestamp();
final GeneratedUpdateDate utilDate = new GeneratedUpdateDate();
final GeneratedUpdateLong longTime = new GeneratedUpdateLong();
public void setUpdateTimestamp(DeployBeanProperty property) {
property.setGeneratedProperty(createUpdateTimestamp(property));
}
/**
* Create the update GeneratedProperty depending on the property type.
*/
private GeneratedProperty createUpdateTimestamp(DeployBeanProperty property) {
Class<?> propType = property.getPropertyType();
if (propType.equals(Timestamp.class)) {
return timestamp;
}
if (propType.equals(java.util.Date.class)) {
return utilDate;
}
if (propType.equals(Long.class) || propType.equals(long.class)) {
return longTime;
}
//TODO: Support JODA Time objects ... perhaps others?
String msg = "Generated update Timestamp not supported on "+propType.getName();
throw new PersistenceException(msg);
}
}
package com.avaje.ebeaninternal.server.deploy.generatedproperty;
import java.sql.Timestamp;
import javax.persistence.PersistenceException;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
/**
* Helper for creating Update timestamp GeneratedProperty objects.
*/
public class UpdateTimestampFactory {
final GeneratedUpdateTimestamp timestamp = new GeneratedUpdateTimestamp();
final GeneratedUpdateDate utilDate = new GeneratedUpdateDate();
final GeneratedUpdateLong longTime = new GeneratedUpdateLong();
public void setUpdateTimestamp(DeployBeanProperty property) {
property.setGeneratedProperty(createUpdateTimestamp(property));
}
/**
* Create the update GeneratedProperty depending on the property type.
*/
private GeneratedProperty createUpdateTimestamp(DeployBeanProperty property) {
Class<?> propType = property.getPropertyType();
if (propType.equals(Timestamp.class)) {
return timestamp;
}
if (propType.equals(java.util.Date.class)) {
return utilDate;
}
if (propType.equals(Long.class) || propType.equals(long.class)) {
return longTime;
}
//TODO: Support JODA Time objects ... perhaps others?
String msg = "Generated update Timestamp not supported on "+propType.getName();
throw new PersistenceException(msg);
}
}
@@ -1,59 +1,40 @@
/**
* Copyright (C) 2006 Robin Bygrave
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy.id;
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocOne;
/**
* Creates the appropriate IdConvertSet depending on the type of Id property(s).
*/
public class IdBinderFactory {
private static final IdBinderEmpty EMPTY = new IdBinderEmpty();
private final boolean idInExpandedForm;
public IdBinderFactory(boolean idInExpandedForm) {
this.idInExpandedForm = idInExpandedForm;
}
/**
* Create the IdConvertSet for the given type of Id properties.
*/
public IdBinder createIdBinder(BeanProperty[] uids) {
if (uids.length == 0){
// for report type beans that don't need an id
return EMPTY;
} else if (uids.length == 1){
if (uids[0].isEmbedded()){
return new IdBinderEmbedded(idInExpandedForm, (BeanPropertyAssocOne<?>)uids[0]);
} else {
return new IdBinderSimple(uids[0]);
}
} else {
return new IdBinderMultiple(uids);
}
}
}
package com.avaje.ebeaninternal.server.deploy.id;
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocOne;
/**
* Creates the appropriate IdConvertSet depending on the type of Id property(s).
*/
public class IdBinderFactory {
private static final IdBinderEmpty EMPTY = new IdBinderEmpty();
private final boolean idInExpandedForm;
public IdBinderFactory(boolean idInExpandedForm) {
this.idInExpandedForm = idInExpandedForm;
}
/**
* Create the IdConvertSet for the given type of Id properties.
*/
public IdBinder createIdBinder(BeanProperty[] uids) {
if (uids.length == 0){
// for report type beans that don't need an id
return EMPTY;
} else if (uids.length == 1){
if (uids[0].isEmbedded()){
return new IdBinderEmbedded(idInExpandedForm, (BeanPropertyAssocOne<?>)uids[0]);
} else {
return new IdBinderSimple(uids[0]);
}
} else {
return new IdBinderMultiple(uids);
}
}
}
File diff suppressed because it is too large Load Diff
@@ -1,61 +1,42 @@
/**
* Copyright (C) 2006 Robin Bygrave
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy.meta;
import java.util.HashMap;
import java.util.Map;
/**
* Collects Deployment information on Embedded beans.
* <p>
* Typically collects the overridden column names mapped
* to the Embedded bean.
* </p>
*/
public class DeployBeanEmbedded {
/**
* A map of property names to dbColumns.
*/
Map<String,String> propMap = new HashMap<String, String>();
/**
* Set a property name to use a specific dbColumn.
*/
public void put(String propertyName, String dbCoumn){
propMap.put(propertyName, dbCoumn);
}
/**
* Set a Map of property names to dbColumns.
*/
public void putAll(Map<String,String> propertyColumnMap){
propMap.putAll(propertyColumnMap);
}
/**
* Return a map of property names to dbColumns.
*/
public Map<String, String> getPropertyColumnMap() {
return propMap;
}
}
package com.avaje.ebeaninternal.server.deploy.meta;
import java.util.HashMap;
import java.util.Map;
/**
* Collects Deployment information on Embedded beans.
* <p>
* Typically collects the overridden column names mapped
* to the Embedded bean.
* </p>
*/
public class DeployBeanEmbedded {
/**
* A map of property names to dbColumns.
*/
Map<String,String> propMap = new HashMap<String, String>();
/**
* Set a property name to use a specific dbColumn.
*/
public void put(String propertyName, String dbCoumn){
propMap.put(propertyName, dbCoumn);
}
/**
* Set a Map of property names to dbColumns.
*/
public void putAll(Map<String,String> propertyColumnMap){
propMap.putAll(propertyColumnMap);
}
/**
* Return a map of property names to dbColumns.
*/
public Map<String, String> getPropertyColumnMap() {
return propMap;
}
}
File diff suppressed because it is too large Load Diff
@@ -1,175 +1,156 @@
/**
* Copyright (C) 2006 Robin Bygrave
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy.meta;
import com.avaje.ebeaninternal.server.deploy.BeanCascadeInfo;
import com.avaje.ebeaninternal.server.deploy.BeanTable;
/**
* Abstract base for properties mapped to an associated bean, list, set or map.
*/
public abstract class DeployBeanPropertyAssoc<T> extends DeployBeanProperty {
/**
* The type of the joined bean.
*/
Class<T> targetType;
/**
* Persist settings.
*/
BeanCascadeInfo cascadeInfo = new BeanCascadeInfo();
/**
* The join table information.
*/
BeanTable beanTable;
/**
* Join between the beans.
*/
DeployTableJoin tableJoin = new DeployTableJoin();
/**
* Whether the associated join type should be an outer join.
*/
boolean isOuterJoin = false;
/**
* Literal added to where clause of lazy loading query.
*/
String extraWhere;
/**
* From the deployment mappedBy attribute.
*/
String mappedBy;
/**
* Construct the property.
*/
public DeployBeanPropertyAssoc(DeployBeanDescriptor<?> desc, Class<T> targetType) {
super(desc, targetType, null, null);
this.targetType = targetType;
}
/**
* Return false.
*/
@Override
public boolean isScalar() {
return false;
}
/**
* Return the type of the target.
* <p>
* This is the class of the associated bean, or beans contained in a list,
* set or map.
* </p>
*/
public Class<T> getTargetType() {
return targetType;
}
/**
* Return if this association should use an Outer join.
*/
public boolean isOuterJoin() {
return isOuterJoin;
}
/**
* Specify that this bean should use an outer join.
*/
public void setOuterJoin(boolean isOuterJoin) {
this.isOuterJoin = isOuterJoin;
}
/**
* Return a literal expression that is added to the query that lazy loads
* the collection.
*/
public String getExtraWhere() {
return extraWhere;
}
/**
* Set a literal expression to add to the query that lazy loads the
* collection.
*/
public void setExtraWhere(String extraWhere) {
this.extraWhere = extraWhere;
}
/**
* return the join to use for the bean.
*/
public DeployTableJoin getTableJoin() {
return tableJoin;
}
/**
* Return the BeanTable for this association.
* <p>
* This has the table name which is used to determine the relationship for
* this association.
* </p>
*/
public BeanTable getBeanTable() {
return beanTable;
}
/**
* Set the bean table.
*/
public void setBeanTable(BeanTable beanTable) {
this.beanTable = beanTable;
getTableJoin().setTable(beanTable.getBaseTable());
}
/**
* Get the persist info.
*/
public BeanCascadeInfo getCascadeInfo() {
return cascadeInfo;
}
/**
* Return the mappedBy deployment attribute.
* <p>
* This is the name of the property in the 'detail' bean that maps back to
* this 'master' bean.
* </p>
*/
public String getMappedBy() {
return mappedBy;
}
/**
* Set mappedBy deployment attribute.
*/
public void setMappedBy(String mappedBy) {
if (!"".equals(mappedBy)) {
this.mappedBy = mappedBy;
}
}
}
package com.avaje.ebeaninternal.server.deploy.meta;
import com.avaje.ebeaninternal.server.deploy.BeanCascadeInfo;
import com.avaje.ebeaninternal.server.deploy.BeanTable;
/**
* Abstract base for properties mapped to an associated bean, list, set or map.
*/
public abstract class DeployBeanPropertyAssoc<T> extends DeployBeanProperty {
/**
* The type of the joined bean.
*/
Class<T> targetType;
/**
* Persist settings.
*/
BeanCascadeInfo cascadeInfo = new BeanCascadeInfo();
/**
* The join table information.
*/
BeanTable beanTable;
/**
* Join between the beans.
*/
DeployTableJoin tableJoin = new DeployTableJoin();
/**
* Whether the associated join type should be an outer join.
*/
boolean isOuterJoin = false;
/**
* Literal added to where clause of lazy loading query.
*/
String extraWhere;
/**
* From the deployment mappedBy attribute.
*/
String mappedBy;
/**
* Construct the property.
*/
public DeployBeanPropertyAssoc(DeployBeanDescriptor<?> desc, Class<T> targetType) {
super(desc, targetType, null, null);
this.targetType = targetType;
}
/**
* Return false.
*/
@Override
public boolean isScalar() {
return false;
}
/**
* Return the type of the target.
* <p>
* This is the class of the associated bean, or beans contained in a list,
* set or map.
* </p>
*/
public Class<T> getTargetType() {
return targetType;
}
/**
* Return if this association should use an Outer join.
*/
public boolean isOuterJoin() {
return isOuterJoin;
}
/**
* Specify that this bean should use an outer join.
*/
public void setOuterJoin(boolean isOuterJoin) {
this.isOuterJoin = isOuterJoin;
}
/**
* Return a literal expression that is added to the query that lazy loads
* the collection.
*/
public String getExtraWhere() {
return extraWhere;
}
/**
* Set a literal expression to add to the query that lazy loads the
* collection.
*/
public void setExtraWhere(String extraWhere) {
this.extraWhere = extraWhere;
}
/**
* return the join to use for the bean.
*/
public DeployTableJoin getTableJoin() {
return tableJoin;
}
/**
* Return the BeanTable for this association.
* <p>
* This has the table name which is used to determine the relationship for
* this association.
* </p>
*/
public BeanTable getBeanTable() {
return beanTable;
}
/**
* Set the bean table.
*/
public void setBeanTable(BeanTable beanTable) {
this.beanTable = beanTable;
getTableJoin().setTable(beanTable.getBaseTable());
}
/**
* Get the persist info.
*/
public BeanCascadeInfo getCascadeInfo() {
return cascadeInfo;
}
/**
* Return the mappedBy deployment attribute.
* <p>
* This is the name of the property in the 'detail' bean that maps back to
* this 'master' bean.
* </p>
*/
public String getMappedBy() {
return mappedBy;
}
/**
* Set mappedBy deployment attribute.
*/
public void setMappedBy(String mappedBy) {
if (!"".equals(mappedBy)) {
this.mappedBy = mappedBy;
}
}
}
@@ -1,213 +1,194 @@
/**
* Copyright (C) 2006 Robin Bygrave
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy.meta;
import com.avaje.ebean.bean.BeanCollection.ModifyListenMode;
import com.avaje.ebeaninternal.server.deploy.ManyType;
import com.avaje.ebeaninternal.server.deploy.TableJoin;
/**
* Property mapped to a List Set or Map.
*/
public class DeployBeanPropertyAssocMany<T> extends DeployBeanPropertyAssoc<T> {
ModifyListenMode modifyListenMode = ModifyListenMode.NONE;
/**
* Flag to indicate manyToMany relationship.
*/
boolean manyToMany;
/**
* Flag to indicate this is a unidirectional relationship.
*/
boolean unidirectional;
/**
* Join for manyToMany intersection table.
*/
DeployTableJoin intersectionJoin;
/**
* For ManyToMany this is the Inverse join used to build reference queries.
*/
DeployTableJoin inverseJoin;
String fetchOrderBy;
String mapKey;
/**
* The type of the many, set, list or map.
*/
ManyType manyType;
/**
* Create this property.
*/
public DeployBeanPropertyAssocMany(DeployBeanDescriptor<?> desc, Class<T> targetType, ManyType manyType) {
super(desc, targetType);
this.manyType = manyType;
}
/**
* When generics is not used for manyType you can specify via annotations.
* <p>
* Really only expect this for Scala due to a Scala compiler bug at the moment.
* Otherwise I'd probably not bother support this.
* </p>
*/
@SuppressWarnings("unchecked")
public void setTargetType(Class<?> cls){
this.targetType = (Class<T>)cls;
}
/**
* Return the many type.
*/
public ManyType getManyType() {
return manyType;
}
/**
* Return true if this is many to many.
*/
public boolean isManyToMany() {
return manyToMany;
}
/**
* Set to true if this is a many to many.
*/
public void setManyToMany(boolean isManyToMany) {
this.manyToMany = isManyToMany;
}
/**
* Return the mode for listening to changes to the List Set or Map.
*/
public ModifyListenMode getModifyListenMode() {
return modifyListenMode;
}
/**
* Set the mode for listening to changes to the List Set or Map.
*/
public void setModifyListenMode(ModifyListenMode modifyListenMode) {
this.modifyListenMode = modifyListenMode;
}
/**
* Return true if this is a unidirectional relationship.
*/
public boolean isUnidirectional() {
return unidirectional;
}
/**
* Set to true if this is a unidirectional relationship.
*/
public void setUnidirectional(boolean unidirectional) {
this.unidirectional = unidirectional;
}
/**
* Create the immutable version of the intersection join.
*/
public TableJoin createIntersectionTableJoin() {
if (intersectionJoin != null){
return new TableJoin(intersectionJoin, null);
} else {
return null;
}
}
/**
* Create the immutable version of the inverse join.
*/
public TableJoin createInverseTableJoin() {
if (inverseJoin != null){
return new TableJoin(inverseJoin, null);
} else {
return null;
}
}
/**
* ManyToMany only, join from local table to intersection table.
*/
public DeployTableJoin getIntersectionJoin() {
return intersectionJoin;
}
public DeployTableJoin getInverseJoin() {
return inverseJoin;
}
/**
* ManyToMany only, join from local table to intersection table.
*/
public void setIntersectionJoin(DeployTableJoin intersectionJoin) {
this.intersectionJoin = intersectionJoin;
}
/**
* ManyToMany only, join from foreign table to intersection table.
*/
public void setInverseJoin(DeployTableJoin inverseJoin) {
this.inverseJoin = inverseJoin;
}
/**
* Return the order by clause used to order the fetching of the data for
* this list, set or map.
*/
public String getFetchOrderBy() {
return fetchOrderBy;
}
/**
* Return the default mapKey when returning a Map.
*/
public String getMapKey() {
return mapKey;
}
/**
* Set the default mapKey to use when returning a Map.
*/
public void setMapKey(String mapKey) {
if (mapKey != null && mapKey.length() > 0) {
this.mapKey = mapKey;
}
}
/**
* Set the order by clause used to order the fetching or the data for this
* list, set or map.
*/
public void setFetchOrderBy(String orderBy) {
if (orderBy != null && orderBy.length() > 0) {
fetchOrderBy = orderBy;
}
}
}
package com.avaje.ebeaninternal.server.deploy.meta;
import com.avaje.ebean.bean.BeanCollection.ModifyListenMode;
import com.avaje.ebeaninternal.server.deploy.ManyType;
import com.avaje.ebeaninternal.server.deploy.TableJoin;
/**
* Property mapped to a List Set or Map.
*/
public class DeployBeanPropertyAssocMany<T> extends DeployBeanPropertyAssoc<T> {
ModifyListenMode modifyListenMode = ModifyListenMode.NONE;
/**
* Flag to indicate manyToMany relationship.
*/
boolean manyToMany;
/**
* Flag to indicate this is a unidirectional relationship.
*/
boolean unidirectional;
/**
* Join for manyToMany intersection table.
*/
DeployTableJoin intersectionJoin;
/**
* For ManyToMany this is the Inverse join used to build reference queries.
*/
DeployTableJoin inverseJoin;
String fetchOrderBy;
String mapKey;
/**
* The type of the many, set, list or map.
*/
ManyType manyType;
/**
* Create this property.
*/
public DeployBeanPropertyAssocMany(DeployBeanDescriptor<?> desc, Class<T> targetType, ManyType manyType) {
super(desc, targetType);
this.manyType = manyType;
}
/**
* When generics is not used for manyType you can specify via annotations.
* <p>
* Really only expect this for Scala due to a Scala compiler bug at the moment.
* Otherwise I'd probably not bother support this.
* </p>
*/
@SuppressWarnings("unchecked")
public void setTargetType(Class<?> cls){
this.targetType = (Class<T>)cls;
}
/**
* Return the many type.
*/
public ManyType getManyType() {
return manyType;
}
/**
* Return true if this is many to many.
*/
public boolean isManyToMany() {
return manyToMany;
}
/**
* Set to true if this is a many to many.
*/
public void setManyToMany(boolean isManyToMany) {
this.manyToMany = isManyToMany;
}
/**
* Return the mode for listening to changes to the List Set or Map.
*/
public ModifyListenMode getModifyListenMode() {
return modifyListenMode;
}
/**
* Set the mode for listening to changes to the List Set or Map.
*/
public void setModifyListenMode(ModifyListenMode modifyListenMode) {
this.modifyListenMode = modifyListenMode;
}
/**
* Return true if this is a unidirectional relationship.
*/
public boolean isUnidirectional() {
return unidirectional;
}
/**
* Set to true if this is a unidirectional relationship.
*/
public void setUnidirectional(boolean unidirectional) {
this.unidirectional = unidirectional;
}
/**
* Create the immutable version of the intersection join.
*/
public TableJoin createIntersectionTableJoin() {
if (intersectionJoin != null){
return new TableJoin(intersectionJoin, null);
} else {
return null;
}
}
/**
* Create the immutable version of the inverse join.
*/
public TableJoin createInverseTableJoin() {
if (inverseJoin != null){
return new TableJoin(inverseJoin, null);
} else {
return null;
}
}
/**
* ManyToMany only, join from local table to intersection table.
*/
public DeployTableJoin getIntersectionJoin() {
return intersectionJoin;
}
public DeployTableJoin getInverseJoin() {
return inverseJoin;
}
/**
* ManyToMany only, join from local table to intersection table.
*/
public void setIntersectionJoin(DeployTableJoin intersectionJoin) {
this.intersectionJoin = intersectionJoin;
}
/**
* ManyToMany only, join from foreign table to intersection table.
*/
public void setInverseJoin(DeployTableJoin inverseJoin) {
this.inverseJoin = inverseJoin;
}
/**
* Return the order by clause used to order the fetching of the data for
* this list, set or map.
*/
public String getFetchOrderBy() {
return fetchOrderBy;
}
/**
* Return the default mapKey when returning a Map.
*/
public String getMapKey() {
return mapKey;
}
/**
* Set the default mapKey to use when returning a Map.
*/
public void setMapKey(String mapKey) {
if (mapKey != null && mapKey.length() > 0) {
this.mapKey = mapKey;
}
}
/**
* Set the order by clause used to order the fetching or the data for this
* list, set or map.
*/
public void setFetchOrderBy(String orderBy) {
if (orderBy != null && orderBy.length() > 0) {
fetchOrderBy = orderBy;
}
}
}
@@ -1,114 +1,95 @@
/**
* Copyright (C) 2006 Robin Bygrave
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy.meta;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor.EntityType;
/**
* Property mapped to a joined bean.
*/
public class DeployBeanPropertyAssocOne<T> extends DeployBeanPropertyAssoc<T> {
boolean oneToOne;
boolean oneToOneExported;
boolean importedPrimaryKey;
DeployBeanEmbedded deployEmbedded;
/**
* Create the property.
*/
public DeployBeanPropertyAssocOne(DeployBeanDescriptor<?> desc, Class<T> targetType) {
super(desc, targetType);
}
/**
* Return the deploy information specifically for the deployment
* of Embedded beans.
*/
public DeployBeanEmbedded getDeployEmbedded() {
// deployment should be single threaded
if (deployEmbedded == null){
deployEmbedded = new DeployBeanEmbedded();
}
return deployEmbedded;
}
@Override
public String getDbColumn() {
DeployTableJoinColumn[] columns = tableJoin.columns();
if (columns.length == 1){
return columns[0].getLocalDbColumn();
}
return super.getDbColumn();
}
@Override
public String getElPlaceHolder(EntityType et) {
return super.getElPlaceHolder(et);
}
/**
* Return true if this a OneToOne property. Otherwise assumed ManyToOne.
*/
public boolean isOneToOne() {
return oneToOne;
}
/**
* Set to true if this is a OneToOne.
*/
public void setOneToOne(boolean oneToOne) {
this.oneToOne = oneToOne;
}
/**
* Return true if this is the exported side of a OneToOne.
*/
public boolean isOneToOneExported() {
return oneToOneExported;
}
/**
* Set to true if this is the exported side of a OneToOne. This means
* it doesn't 'own' the foreign key column. A OneToMany without the many.
*/
public void setOneToOneExported(boolean oneToOneExported) {
this.oneToOneExported = oneToOneExported;
}
/**
* If true this bean maps to the primary key.
*/
public boolean isImportedPrimaryKey() {
return importedPrimaryKey;
}
/**
* Set to true if the bean maps to the primary key.
*/
public void setImportedPrimaryKey(boolean importedPrimaryKey) {
this.importedPrimaryKey = importedPrimaryKey;
}
}
package com.avaje.ebeaninternal.server.deploy.meta;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor.EntityType;
/**
* Property mapped to a joined bean.
*/
public class DeployBeanPropertyAssocOne<T> extends DeployBeanPropertyAssoc<T> {
boolean oneToOne;
boolean oneToOneExported;
boolean importedPrimaryKey;
DeployBeanEmbedded deployEmbedded;
/**
* Create the property.
*/
public DeployBeanPropertyAssocOne(DeployBeanDescriptor<?> desc, Class<T> targetType) {
super(desc, targetType);
}
/**
* Return the deploy information specifically for the deployment
* of Embedded beans.
*/
public DeployBeanEmbedded getDeployEmbedded() {
// deployment should be single threaded
if (deployEmbedded == null){
deployEmbedded = new DeployBeanEmbedded();
}
return deployEmbedded;
}
@Override
public String getDbColumn() {
DeployTableJoinColumn[] columns = tableJoin.columns();
if (columns.length == 1){
return columns[0].getLocalDbColumn();
}
return super.getDbColumn();
}
@Override
public String getElPlaceHolder(EntityType et) {
return super.getElPlaceHolder(et);
}
/**
* Return true if this a OneToOne property. Otherwise assumed ManyToOne.
*/
public boolean isOneToOne() {
return oneToOne;
}
/**
* Set to true if this is a OneToOne.
*/
public void setOneToOne(boolean oneToOne) {
this.oneToOne = oneToOne;
}
/**
* Return true if this is the exported side of a OneToOne.
*/
public boolean isOneToOneExported() {
return oneToOneExported;
}
/**
* Set to true if this is the exported side of a OneToOne. This means
* it doesn't 'own' the foreign key column. A OneToMany without the many.
*/
public void setOneToOneExported(boolean oneToOneExported) {
this.oneToOneExported = oneToOneExported;
}
/**
* If true this bean maps to the primary key.
*/
public boolean isImportedPrimaryKey() {
return importedPrimaryKey;
}
/**
* Set to true if the bean maps to the primary key.
*/
public void setImportedPrimaryKey(boolean importedPrimaryKey) {
this.importedPrimaryKey = importedPrimaryKey;
}
}
@@ -1,138 +1,119 @@
/**
* Copyright (C) 2006 Robin Bygrave
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy.meta;
import java.util.ArrayList;
import java.util.List;
import java.util.Map.Entry;
import com.avaje.ebean.config.ScalarTypeConverter;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptorMap;
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
import com.avaje.ebeaninternal.server.deploy.BeanPropertyCompoundRoot;
import com.avaje.ebeaninternal.server.deploy.BeanPropertyCompoundScalar;
import com.avaje.ebeaninternal.server.type.CtCompoundProperty;
import com.avaje.ebeaninternal.server.type.CtCompoundType;
import com.avaje.ebeaninternal.server.type.CtCompoundTypeScalarList;
import com.avaje.ebeaninternal.server.type.ScalarType;
/**
* Property mapped to a joined bean.
*/
public class DeployBeanPropertyCompound extends DeployBeanProperty {
final CtCompoundType<?> compoundType;
final ScalarTypeConverter<?, ?> typeConverter;
DeployBeanEmbedded deployEmbedded;
/**
* Create the property.
*/
public DeployBeanPropertyCompound(DeployBeanDescriptor<?> desc, Class<?> targetType,
CtCompoundType<?> compoundType, ScalarTypeConverter<?, ?> typeConverter) {
super(desc, targetType, null, null);
this.compoundType = compoundType;
this.typeConverter = typeConverter;
}
public BeanPropertyCompoundRoot getFlatProperties(BeanDescriptorMap owner, BeanDescriptor<?> descriptor) {
// get a 'flat' list of all the scalar types, their relative property names
// and also set their matching dbColumn
// represents the root property
BeanPropertyCompoundRoot rootProperty = new BeanPropertyCompoundRoot(this);
// Walk the tree of a compound type collecting the
// scalar types and non-scalar properties
CtCompoundTypeScalarList ctMeta = new CtCompoundTypeScalarList();
compoundType.accumulateScalarTypes(null, ctMeta);
List<BeanProperty> beanPropertyList = new ArrayList<BeanProperty>();
// for each of the scalar types inside a compound value object
// build a BeanPropertyCompoundScalar with appropriate deployment
// information.
for (Entry<String, ScalarType<?>> entry : ctMeta.entries()) {
String relativePropertyName = entry.getKey();
ScalarType<?> scalarType = entry.getValue();
CtCompoundProperty ctProp = ctMeta.getCompoundType(relativePropertyName);
String dbColumn = relativePropertyName.replace(".", "_");
dbColumn = getDbColumn(relativePropertyName, dbColumn);
DeployBeanProperty deploy = new DeployBeanProperty(null, scalarType.getType(), scalarType, null);
deploy.setScalarType(scalarType);
deploy.setDbColumn(dbColumn);
deploy.setName(relativePropertyName);
deploy.setDbInsertable(true);
deploy.setDbUpdateable(true);
deploy.setDbRead(true);
BeanPropertyCompoundScalar bp = new BeanPropertyCompoundScalar(rootProperty, deploy, ctProp, typeConverter);
beanPropertyList.add(bp);
rootProperty.register(bp);
}
rootProperty.setNonScalarProperties(ctMeta.getNonScalarProperties());
return rootProperty;
}
private String getDbColumn(String propName, String defaultDbColumn){
if (deployEmbedded == null){
return defaultDbColumn;
}
String dbColumn = deployEmbedded.getPropertyColumnMap().get(propName);
return dbColumn == null ? defaultDbColumn : dbColumn;
}
/**
* Return the deploy information specifically for the deployment
* of Embedded beans.
*/
public DeployBeanEmbedded getDeployEmbedded() {
// deployment should be single threaded
if (deployEmbedded == null){
deployEmbedded = new DeployBeanEmbedded();
}
return deployEmbedded;
}
public ScalarTypeConverter<?, ?> getTypeConverter() {
return typeConverter;
}
public CtCompoundType<?> getCompoundType() {
return compoundType;
}
}
package com.avaje.ebeaninternal.server.deploy.meta;
import java.util.ArrayList;
import java.util.List;
import java.util.Map.Entry;
import com.avaje.ebean.config.ScalarTypeConverter;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptorMap;
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
import com.avaje.ebeaninternal.server.deploy.BeanPropertyCompoundRoot;
import com.avaje.ebeaninternal.server.deploy.BeanPropertyCompoundScalar;
import com.avaje.ebeaninternal.server.type.CtCompoundProperty;
import com.avaje.ebeaninternal.server.type.CtCompoundType;
import com.avaje.ebeaninternal.server.type.CtCompoundTypeScalarList;
import com.avaje.ebeaninternal.server.type.ScalarType;
/**
* Property mapped to a joined bean.
*/
public class DeployBeanPropertyCompound extends DeployBeanProperty {
final CtCompoundType<?> compoundType;
final ScalarTypeConverter<?, ?> typeConverter;
DeployBeanEmbedded deployEmbedded;
/**
* Create the property.
*/
public DeployBeanPropertyCompound(DeployBeanDescriptor<?> desc, Class<?> targetType,
CtCompoundType<?> compoundType, ScalarTypeConverter<?, ?> typeConverter) {
super(desc, targetType, null, null);
this.compoundType = compoundType;
this.typeConverter = typeConverter;
}
public BeanPropertyCompoundRoot getFlatProperties(BeanDescriptorMap owner, BeanDescriptor<?> descriptor) {
// get a 'flat' list of all the scalar types, their relative property names
// and also set their matching dbColumn
// represents the root property
BeanPropertyCompoundRoot rootProperty = new BeanPropertyCompoundRoot(this);
// Walk the tree of a compound type collecting the
// scalar types and non-scalar properties
CtCompoundTypeScalarList ctMeta = new CtCompoundTypeScalarList();
compoundType.accumulateScalarTypes(null, ctMeta);
List<BeanProperty> beanPropertyList = new ArrayList<BeanProperty>();
// for each of the scalar types inside a compound value object
// build a BeanPropertyCompoundScalar with appropriate deployment
// information.
for (Entry<String, ScalarType<?>> entry : ctMeta.entries()) {
String relativePropertyName = entry.getKey();
ScalarType<?> scalarType = entry.getValue();
CtCompoundProperty ctProp = ctMeta.getCompoundType(relativePropertyName);
String dbColumn = relativePropertyName.replace(".", "_");
dbColumn = getDbColumn(relativePropertyName, dbColumn);
DeployBeanProperty deploy = new DeployBeanProperty(null, scalarType.getType(), scalarType, null);
deploy.setScalarType(scalarType);
deploy.setDbColumn(dbColumn);
deploy.setName(relativePropertyName);
deploy.setDbInsertable(true);
deploy.setDbUpdateable(true);
deploy.setDbRead(true);
BeanPropertyCompoundScalar bp = new BeanPropertyCompoundScalar(rootProperty, deploy, ctProp, typeConverter);
beanPropertyList.add(bp);
rootProperty.register(bp);
}
rootProperty.setNonScalarProperties(ctMeta.getNonScalarProperties());
return rootProperty;
}
private String getDbColumn(String propName, String defaultDbColumn){
if (deployEmbedded == null){
return defaultDbColumn;
}
String dbColumn = deployEmbedded.getPropertyColumnMap().get(propName);
return dbColumn == null ? defaultDbColumn : dbColumn;
}
/**
* Return the deploy information specifically for the deployment
* of Embedded beans.
*/
public DeployBeanEmbedded getDeployEmbedded() {
// deployment should be single threaded
if (deployEmbedded == null){
deployEmbedded = new DeployBeanEmbedded();
}
return deployEmbedded;
}
public ScalarTypeConverter<?, ?> getTypeConverter() {
return typeConverter;
}
public CtCompoundType<?> getCompoundType() {
return compoundType;
}
}
@@ -1,403 +1,384 @@
/**
* Copyright (C) 2006 Robin Bygrave
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy.meta;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import com.avaje.ebean.bean.BeanCollection.ModifyListenMode;
import com.avaje.ebean.validation.factory.Validator;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptorMap;
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocMany;
import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocOne;
import com.avaje.ebeaninternal.server.deploy.BeanPropertyCompound;
import com.avaje.ebeaninternal.server.deploy.BeanPropertySimpleCollection;
import com.avaje.ebeaninternal.server.deploy.TableJoin;
/**
* Helper object to classify BeanProperties into appropriate lists.
*/
public class DeployBeanPropertyLists {
private BeanProperty derivedFirstVersionProp;
private final BeanDescriptor<?> desc;
private final LinkedHashMap<String, BeanProperty> propertyMap;
private final ArrayList<BeanProperty> ids = new ArrayList<BeanProperty>();
private final ArrayList<BeanProperty> version = new ArrayList<BeanProperty>();
private final ArrayList<BeanProperty> local = new ArrayList<BeanProperty>();
private final ArrayList<BeanProperty> manys = new ArrayList<BeanProperty>();
private final ArrayList<BeanProperty> nonManys = new ArrayList<BeanProperty>();
private final ArrayList<BeanProperty> ones = new ArrayList<BeanProperty>();
private final ArrayList<BeanProperty> onesExported = new ArrayList<BeanProperty>();
private final ArrayList<BeanProperty> onesImported = new ArrayList<BeanProperty>();
private final ArrayList<BeanProperty> embedded = new ArrayList<BeanProperty>();
private final ArrayList<BeanProperty> baseScalar = new ArrayList<BeanProperty>();
private final ArrayList<BeanPropertyCompound> baseCompound = new ArrayList<BeanPropertyCompound>();
private final ArrayList<BeanProperty> transients = new ArrayList<BeanProperty>();
private final ArrayList<BeanProperty> nonTransients = new ArrayList<BeanProperty>();
private final TableJoin[] tableJoins;
private final BeanPropertyAssocOne<?> unidirectional;
@SuppressWarnings({ "unchecked", "rawtypes" })
public DeployBeanPropertyLists(BeanDescriptorMap owner, BeanDescriptor<?> desc, DeployBeanDescriptor<?> deploy) {
this.desc = desc;
DeployBeanPropertyAssocOne<?> deployUnidirectional = deploy.getUnidirectional();
if (deployUnidirectional == null) {
unidirectional = null;
} else {
unidirectional = new BeanPropertyAssocOne(owner, desc, deployUnidirectional);
}
this.propertyMap = new LinkedHashMap<String, BeanProperty>();
Iterator<DeployBeanProperty> deployIt = deploy.propertiesAll();
while (deployIt.hasNext()) {
DeployBeanProperty deployProp = deployIt.next();
BeanProperty beanProp = createBeanProperty(owner, deployProp);
propertyMap.put(beanProp.getName(), beanProp);
}
Iterator<BeanProperty> it = propertyMap.values().iterator();
int order = 0;
while (it.hasNext()) {
BeanProperty prop = it.next();
prop.setDeployOrder(order++);
allocateToList(prop);
}
List<DeployTableJoin> deployTableJoins = deploy.getTableJoins();
tableJoins = new TableJoin[deployTableJoins.size()];
for (int i = 0; i < deployTableJoins.size(); i++) {
tableJoins[i] = new TableJoin(deployTableJoins.get(i), propertyMap);
}
}
/**
* Return the unidirectional.
*/
public BeanPropertyAssocOne<?> getUnidirectional() {
return unidirectional;
}
/**
* Allocate the property to a list.
*/
private void allocateToList(BeanProperty prop) {
if (prop.isTransient()) {
transients.add(prop);
return;
}
if (prop.isId()) {
ids.add(prop);
return;
} else {
nonTransients.add(prop);
}
if (desc.getInheritInfo() != null && prop.isLocal()) {
local.add(prop);
}
if (prop instanceof BeanPropertyAssocMany<?>) {
manys.add(prop);
} else {
nonManys.add(prop);
if (prop instanceof BeanPropertyAssocOne<?>) {
if (prop.isEmbedded()) {
embedded.add(prop);
} else {
ones.add(prop);
BeanPropertyAssocOne<?> assocOne = (BeanPropertyAssocOne<?>) prop;
if (assocOne.isOneToOneExported()) {
onesExported.add(prop);
} else {
onesImported.add(prop);
}
}
} else {
// its a "base" property...
if (prop.isVersion()) {
version.add(prop);
if (derivedFirstVersionProp == null) {
derivedFirstVersionProp = prop;
}
}
if (prop instanceof BeanPropertyCompound) {
baseCompound.add((BeanPropertyCompound) prop);
} else {
baseScalar.add(prop);
}
}
}
}
public BeanProperty getFirstVersion() {
return derivedFirstVersionProp;
}
public BeanProperty[] getPropertiesWithValidators(boolean recurse) {
ArrayList<BeanProperty> list = new ArrayList<BeanProperty>();
Iterator<BeanProperty> it = propertyMap.values().iterator();
while (it.hasNext()) {
BeanProperty property = (BeanProperty) it.next();
if (property.hasValidationRules(recurse)) {
list.add(property);
}
}
return list.toArray(new BeanProperty[list.size()]);
}
public Validator[] getBeanValidators() {
return new Validator[0];
}
public LinkedHashMap<String, BeanProperty> getPropertyMap() {
return propertyMap;
}
public TableJoin[] getTableJoin() {
return tableJoins;
}
/**
* Return the base scalar properties (excludes Id and secondary table
* properties).
*/
public BeanProperty[] getBaseScalar() {
return (BeanProperty[]) baseScalar.toArray(new BeanProperty[baseScalar.size()]);
}
public BeanPropertyCompound[] getBaseCompound() {
return (BeanPropertyCompound[]) baseCompound.toArray(new BeanPropertyCompound[baseCompound.size()]);
}
public BeanProperty getNaturalKey() {
String naturalKey = desc.getCacheOptions().getNaturalKey();
if (naturalKey != null){
return propertyMap.get(naturalKey);
}
return null;
}
public BeanProperty[] getId() {
return (BeanProperty[]) ids.toArray(new BeanProperty[ids.size()]);
}
public BeanProperty[] getNonTransients() {
return (BeanProperty[]) nonTransients.toArray(new BeanProperty[nonTransients.size()]);
}
public BeanProperty[] getTransients() {
return (BeanProperty[]) transients.toArray(new BeanProperty[transients.size()]);
}
public BeanProperty[] getVersion() {
return (BeanProperty[]) version.toArray(new BeanProperty[version.size()]);
}
public BeanProperty[] getLocal() {
return (BeanProperty[]) local.toArray(new BeanProperty[local.size()]);
}
public BeanPropertyAssocOne<?>[] getEmbedded() {
return (BeanPropertyAssocOne[]) embedded.toArray(new BeanPropertyAssocOne[embedded.size()]);
}
public BeanPropertyAssocOne<?>[] getOneExported() {
return (BeanPropertyAssocOne[]) onesExported.toArray(new BeanPropertyAssocOne[onesExported.size()]);
}
public BeanPropertyAssocOne<?>[] getOneImported() {
return (BeanPropertyAssocOne[]) onesImported.toArray(new BeanPropertyAssocOne[onesImported.size()]);
}
public BeanPropertyAssocOne<?>[] getOnes() {
return (BeanPropertyAssocOne[]) ones.toArray(new BeanPropertyAssocOne[ones.size()]);
}
public BeanPropertyAssocOne<?>[] getOneExportedSave() {
return getOne(false, Mode.Save);
}
public BeanPropertyAssocOne<?>[] getOneExportedDelete() {
return getOne(false, Mode.Delete);
}
public BeanPropertyAssocOne<?>[] getOneImportedSave() {
return getOne(true, Mode.Save);
}
public BeanPropertyAssocOne<?>[] getOneImportedDelete() {
return getOne(true, Mode.Delete);
}
public BeanProperty[] getNonMany() {
return (BeanProperty[]) nonManys.toArray(new BeanProperty[nonManys.size()]);
}
public BeanPropertyAssocMany<?>[] getMany() {
return (BeanPropertyAssocMany[]) manys.toArray(new BeanPropertyAssocMany[manys.size()]);
}
public BeanPropertyAssocMany<?>[] getManySave() {
return getMany(Mode.Save);
}
public BeanPropertyAssocMany<?>[] getManyDelete() {
return getMany(Mode.Delete);
}
public BeanPropertyAssocMany<?>[] getManyToMany() {
return getMany2Many();
}
/**
* Mode used to determine which BeanPropertyAssoc to include.
*/
private enum Mode {
Save, Delete, Validate;
}
private BeanPropertyAssocOne<?>[] getOne(boolean imported, Mode mode) {
ArrayList<BeanPropertyAssocOne<?>> list = new ArrayList<BeanPropertyAssocOne<?>>();
for (int i = 0; i < ones.size(); i++) {
BeanPropertyAssocOne<?> prop = (BeanPropertyAssocOne<?>) ones.get(i);
if (imported != prop.isOneToOneExported()) {
switch (mode) {
case Save:
if (prop.getCascadeInfo().isSave()) {
list.add(prop);
}
break;
case Delete:
if (prop.getCascadeInfo().isDelete()) {
list.add(prop);
}
break;
case Validate:
if (prop.getCascadeInfo().isValidate()) {
list.add(prop);
}
break;
default:
break;
}
}
}
return (BeanPropertyAssocOne[]) list.toArray(new BeanPropertyAssocOne[list.size()]);
}
private BeanPropertyAssocMany<?>[] getMany2Many() {
ArrayList<BeanPropertyAssocMany<?>> list = new ArrayList<BeanPropertyAssocMany<?>>();
for (int i = 0; i < manys.size(); i++) {
BeanPropertyAssocMany<?> prop = (BeanPropertyAssocMany<?>) manys.get(i);
if (prop.isManyToMany()) {
list.add(prop);
}
}
return (BeanPropertyAssocMany[]) list.toArray(new BeanPropertyAssocMany[list.size()]);
}
private BeanPropertyAssocMany<?>[] getMany(Mode mode) {
ArrayList<BeanPropertyAssocMany<?>> list = new ArrayList<BeanPropertyAssocMany<?>>();
for (int i = 0; i < manys.size(); i++) {
BeanPropertyAssocMany<?> prop = (BeanPropertyAssocMany<?>) manys.get(i);
switch (mode) {
case Save:
if (prop.getCascadeInfo().isSave() || prop.isManyToMany()
|| ModifyListenMode.REMOVALS.equals(prop.getModifyListenMode())) {
// Note ManyToMany always included as we always 'save'
// the relationship via insert/delete of intersection table
// REMOVALS means including PrivateOwned relationships
list.add(prop);
}
break;
case Delete:
if (prop.getCascadeInfo().isDelete()
|| ModifyListenMode.REMOVALS.equals(prop.getModifyListenMode())) {
// REMOVALS means including PrivateOwned relationships
list.add(prop);
}
break;
case Validate:
if (prop.getCascadeInfo().isValidate()) {
list.add(prop);
}
break;
default:
break;
}
}
return (BeanPropertyAssocMany[]) list.toArray(new BeanPropertyAssocMany[list.size()]);
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private BeanProperty createBeanProperty(BeanDescriptorMap owner, DeployBeanProperty deployProp) {
if (deployProp instanceof DeployBeanPropertyAssocOne) {
return new BeanPropertyAssocOne(owner, desc, (DeployBeanPropertyAssocOne) deployProp);
}
if (deployProp instanceof DeployBeanPropertySimpleCollection<?>) {
return new BeanPropertySimpleCollection(owner, desc, (DeployBeanPropertySimpleCollection)deployProp);
}
if (deployProp instanceof DeployBeanPropertyAssocMany) {
return new BeanPropertyAssocMany(owner, desc, (DeployBeanPropertyAssocMany) deployProp);
}
if (deployProp instanceof DeployBeanPropertyCompound) {
return new BeanPropertyCompound(owner, desc, (DeployBeanPropertyCompound) deployProp);
}
return new BeanProperty(owner, desc, deployProp);
}
}
package com.avaje.ebeaninternal.server.deploy.meta;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import com.avaje.ebean.bean.BeanCollection.ModifyListenMode;
import com.avaje.ebean.validation.factory.Validator;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptorMap;
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocMany;
import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocOne;
import com.avaje.ebeaninternal.server.deploy.BeanPropertyCompound;
import com.avaje.ebeaninternal.server.deploy.BeanPropertySimpleCollection;
import com.avaje.ebeaninternal.server.deploy.TableJoin;
/**
* Helper object to classify BeanProperties into appropriate lists.
*/
public class DeployBeanPropertyLists {
private BeanProperty derivedFirstVersionProp;
private final BeanDescriptor<?> desc;
private final LinkedHashMap<String, BeanProperty> propertyMap;
private final ArrayList<BeanProperty> ids = new ArrayList<BeanProperty>();
private final ArrayList<BeanProperty> version = new ArrayList<BeanProperty>();
private final ArrayList<BeanProperty> local = new ArrayList<BeanProperty>();
private final ArrayList<BeanProperty> manys = new ArrayList<BeanProperty>();
private final ArrayList<BeanProperty> nonManys = new ArrayList<BeanProperty>();
private final ArrayList<BeanProperty> ones = new ArrayList<BeanProperty>();
private final ArrayList<BeanProperty> onesExported = new ArrayList<BeanProperty>();
private final ArrayList<BeanProperty> onesImported = new ArrayList<BeanProperty>();
private final ArrayList<BeanProperty> embedded = new ArrayList<BeanProperty>();
private final ArrayList<BeanProperty> baseScalar = new ArrayList<BeanProperty>();
private final ArrayList<BeanPropertyCompound> baseCompound = new ArrayList<BeanPropertyCompound>();
private final ArrayList<BeanProperty> transients = new ArrayList<BeanProperty>();
private final ArrayList<BeanProperty> nonTransients = new ArrayList<BeanProperty>();
private final TableJoin[] tableJoins;
private final BeanPropertyAssocOne<?> unidirectional;
@SuppressWarnings({ "unchecked", "rawtypes" })
public DeployBeanPropertyLists(BeanDescriptorMap owner, BeanDescriptor<?> desc, DeployBeanDescriptor<?> deploy) {
this.desc = desc;
DeployBeanPropertyAssocOne<?> deployUnidirectional = deploy.getUnidirectional();
if (deployUnidirectional == null) {
unidirectional = null;
} else {
unidirectional = new BeanPropertyAssocOne(owner, desc, deployUnidirectional);
}
this.propertyMap = new LinkedHashMap<String, BeanProperty>();
Iterator<DeployBeanProperty> deployIt = deploy.propertiesAll();
while (deployIt.hasNext()) {
DeployBeanProperty deployProp = deployIt.next();
BeanProperty beanProp = createBeanProperty(owner, deployProp);
propertyMap.put(beanProp.getName(), beanProp);
}
Iterator<BeanProperty> it = propertyMap.values().iterator();
int order = 0;
while (it.hasNext()) {
BeanProperty prop = it.next();
prop.setDeployOrder(order++);
allocateToList(prop);
}
List<DeployTableJoin> deployTableJoins = deploy.getTableJoins();
tableJoins = new TableJoin[deployTableJoins.size()];
for (int i = 0; i < deployTableJoins.size(); i++) {
tableJoins[i] = new TableJoin(deployTableJoins.get(i), propertyMap);
}
}
/**
* Return the unidirectional.
*/
public BeanPropertyAssocOne<?> getUnidirectional() {
return unidirectional;
}
/**
* Allocate the property to a list.
*/
private void allocateToList(BeanProperty prop) {
if (prop.isTransient()) {
transients.add(prop);
return;
}
if (prop.isId()) {
ids.add(prop);
return;
} else {
nonTransients.add(prop);
}
if (desc.getInheritInfo() != null && prop.isLocal()) {
local.add(prop);
}
if (prop instanceof BeanPropertyAssocMany<?>) {
manys.add(prop);
} else {
nonManys.add(prop);
if (prop instanceof BeanPropertyAssocOne<?>) {
if (prop.isEmbedded()) {
embedded.add(prop);
} else {
ones.add(prop);
BeanPropertyAssocOne<?> assocOne = (BeanPropertyAssocOne<?>) prop;
if (assocOne.isOneToOneExported()) {
onesExported.add(prop);
} else {
onesImported.add(prop);
}
}
} else {
// its a "base" property...
if (prop.isVersion()) {
version.add(prop);
if (derivedFirstVersionProp == null) {
derivedFirstVersionProp = prop;
}
}
if (prop instanceof BeanPropertyCompound) {
baseCompound.add((BeanPropertyCompound) prop);
} else {
baseScalar.add(prop);
}
}
}
}
public BeanProperty getFirstVersion() {
return derivedFirstVersionProp;
}
public BeanProperty[] getPropertiesWithValidators(boolean recurse) {
ArrayList<BeanProperty> list = new ArrayList<BeanProperty>();
Iterator<BeanProperty> it = propertyMap.values().iterator();
while (it.hasNext()) {
BeanProperty property = (BeanProperty) it.next();
if (property.hasValidationRules(recurse)) {
list.add(property);
}
}
return list.toArray(new BeanProperty[list.size()]);
}
public Validator[] getBeanValidators() {
return new Validator[0];
}
public LinkedHashMap<String, BeanProperty> getPropertyMap() {
return propertyMap;
}
public TableJoin[] getTableJoin() {
return tableJoins;
}
/**
* Return the base scalar properties (excludes Id and secondary table
* properties).
*/
public BeanProperty[] getBaseScalar() {
return (BeanProperty[]) baseScalar.toArray(new BeanProperty[baseScalar.size()]);
}
public BeanPropertyCompound[] getBaseCompound() {
return (BeanPropertyCompound[]) baseCompound.toArray(new BeanPropertyCompound[baseCompound.size()]);
}
public BeanProperty getNaturalKey() {
String naturalKey = desc.getCacheOptions().getNaturalKey();
if (naturalKey != null){
return propertyMap.get(naturalKey);
}
return null;
}
public BeanProperty[] getId() {
return (BeanProperty[]) ids.toArray(new BeanProperty[ids.size()]);
}
public BeanProperty[] getNonTransients() {
return (BeanProperty[]) nonTransients.toArray(new BeanProperty[nonTransients.size()]);
}
public BeanProperty[] getTransients() {
return (BeanProperty[]) transients.toArray(new BeanProperty[transients.size()]);
}
public BeanProperty[] getVersion() {
return (BeanProperty[]) version.toArray(new BeanProperty[version.size()]);
}
public BeanProperty[] getLocal() {
return (BeanProperty[]) local.toArray(new BeanProperty[local.size()]);
}
public BeanPropertyAssocOne<?>[] getEmbedded() {
return (BeanPropertyAssocOne[]) embedded.toArray(new BeanPropertyAssocOne[embedded.size()]);
}
public BeanPropertyAssocOne<?>[] getOneExported() {
return (BeanPropertyAssocOne[]) onesExported.toArray(new BeanPropertyAssocOne[onesExported.size()]);
}
public BeanPropertyAssocOne<?>[] getOneImported() {
return (BeanPropertyAssocOne[]) onesImported.toArray(new BeanPropertyAssocOne[onesImported.size()]);
}
public BeanPropertyAssocOne<?>[] getOnes() {
return (BeanPropertyAssocOne[]) ones.toArray(new BeanPropertyAssocOne[ones.size()]);
}
public BeanPropertyAssocOne<?>[] getOneExportedSave() {
return getOne(false, Mode.Save);
}
public BeanPropertyAssocOne<?>[] getOneExportedDelete() {
return getOne(false, Mode.Delete);
}
public BeanPropertyAssocOne<?>[] getOneImportedSave() {
return getOne(true, Mode.Save);
}
public BeanPropertyAssocOne<?>[] getOneImportedDelete() {
return getOne(true, Mode.Delete);
}
public BeanProperty[] getNonMany() {
return (BeanProperty[]) nonManys.toArray(new BeanProperty[nonManys.size()]);
}
public BeanPropertyAssocMany<?>[] getMany() {
return (BeanPropertyAssocMany[]) manys.toArray(new BeanPropertyAssocMany[manys.size()]);
}
public BeanPropertyAssocMany<?>[] getManySave() {
return getMany(Mode.Save);
}
public BeanPropertyAssocMany<?>[] getManyDelete() {
return getMany(Mode.Delete);
}
public BeanPropertyAssocMany<?>[] getManyToMany() {
return getMany2Many();
}
/**
* Mode used to determine which BeanPropertyAssoc to include.
*/
private enum Mode {
Save, Delete, Validate;
}
private BeanPropertyAssocOne<?>[] getOne(boolean imported, Mode mode) {
ArrayList<BeanPropertyAssocOne<?>> list = new ArrayList<BeanPropertyAssocOne<?>>();
for (int i = 0; i < ones.size(); i++) {
BeanPropertyAssocOne<?> prop = (BeanPropertyAssocOne<?>) ones.get(i);
if (imported != prop.isOneToOneExported()) {
switch (mode) {
case Save:
if (prop.getCascadeInfo().isSave()) {
list.add(prop);
}
break;
case Delete:
if (prop.getCascadeInfo().isDelete()) {
list.add(prop);
}
break;
case Validate:
if (prop.getCascadeInfo().isValidate()) {
list.add(prop);
}
break;
default:
break;
}
}
}
return (BeanPropertyAssocOne[]) list.toArray(new BeanPropertyAssocOne[list.size()]);
}
private BeanPropertyAssocMany<?>[] getMany2Many() {
ArrayList<BeanPropertyAssocMany<?>> list = new ArrayList<BeanPropertyAssocMany<?>>();
for (int i = 0; i < manys.size(); i++) {
BeanPropertyAssocMany<?> prop = (BeanPropertyAssocMany<?>) manys.get(i);
if (prop.isManyToMany()) {
list.add(prop);
}
}
return (BeanPropertyAssocMany[]) list.toArray(new BeanPropertyAssocMany[list.size()]);
}
private BeanPropertyAssocMany<?>[] getMany(Mode mode) {
ArrayList<BeanPropertyAssocMany<?>> list = new ArrayList<BeanPropertyAssocMany<?>>();
for (int i = 0; i < manys.size(); i++) {
BeanPropertyAssocMany<?> prop = (BeanPropertyAssocMany<?>) manys.get(i);
switch (mode) {
case Save:
if (prop.getCascadeInfo().isSave() || prop.isManyToMany()
|| ModifyListenMode.REMOVALS.equals(prop.getModifyListenMode())) {
// Note ManyToMany always included as we always 'save'
// the relationship via insert/delete of intersection table
// REMOVALS means including PrivateOwned relationships
list.add(prop);
}
break;
case Delete:
if (prop.getCascadeInfo().isDelete()
|| ModifyListenMode.REMOVALS.equals(prop.getModifyListenMode())) {
// REMOVALS means including PrivateOwned relationships
list.add(prop);
}
break;
case Validate:
if (prop.getCascadeInfo().isValidate()) {
list.add(prop);
}
break;
default:
break;
}
}
return (BeanPropertyAssocMany[]) list.toArray(new BeanPropertyAssocMany[list.size()]);
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private BeanProperty createBeanProperty(BeanDescriptorMap owner, DeployBeanProperty deployProp) {
if (deployProp instanceof DeployBeanPropertyAssocOne) {
return new BeanPropertyAssocOne(owner, desc, (DeployBeanPropertyAssocOne) deployProp);
}
if (deployProp instanceof DeployBeanPropertySimpleCollection<?>) {
return new BeanPropertySimpleCollection(owner, desc, (DeployBeanPropertySimpleCollection)deployProp);
}
if (deployProp instanceof DeployBeanPropertyAssocMany) {
return new BeanPropertyAssocMany(owner, desc, (DeployBeanPropertyAssocMany) deployProp);
}
if (deployProp instanceof DeployBeanPropertyCompound) {
return new BeanPropertyCompound(owner, desc, (DeployBeanPropertyCompound) deployProp);
}
return new BeanProperty(owner, desc, deployProp);
}
}
@@ -1,60 +1,41 @@
/**
* Copyright (C) 2009 Authors
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy.meta;
import com.avaje.ebean.bean.BeanCollection.ModifyListenMode;
import com.avaje.ebeaninternal.server.deploy.ManyType;
import com.avaje.ebeaninternal.server.type.ScalarType;
public class DeployBeanPropertySimpleCollection<T> extends DeployBeanPropertyAssocMany<T> {
private final ScalarType<T> collectionScalarType;
public DeployBeanPropertySimpleCollection(DeployBeanDescriptor<?> desc, Class<T> targetType, ScalarType<T> scalarType, ManyType manyType) {
super(desc, targetType, manyType);
this.collectionScalarType = scalarType;
this.modifyListenMode = ModifyListenMode.ALL;
}
/**
* Return the scalarType of the collection elements.
*/
public ScalarType<T> getCollectionScalarType() {
return collectionScalarType;
}
/**
* Returns false as never a ManyToMany.
*/
@Override
public boolean isManyToMany() {
return false;
}
/**
* Returns true as always Unidirectional.
*/
@Override
public boolean isUnidirectional() {
return true;
}
}
package com.avaje.ebeaninternal.server.deploy.meta;
import com.avaje.ebean.bean.BeanCollection.ModifyListenMode;
import com.avaje.ebeaninternal.server.deploy.ManyType;
import com.avaje.ebeaninternal.server.type.ScalarType;
public class DeployBeanPropertySimpleCollection<T> extends DeployBeanPropertyAssocMany<T> {
private final ScalarType<T> collectionScalarType;
public DeployBeanPropertySimpleCollection(DeployBeanDescriptor<?> desc, Class<T> targetType, ScalarType<T> scalarType, ManyType manyType) {
super(desc, targetType, manyType);
this.collectionScalarType = scalarType;
this.modifyListenMode = ModifyListenMode.ALL;
}
/**
* Return the scalarType of the collection elements.
*/
public ScalarType<T> getCollectionScalarType() {
return collectionScalarType;
}
/**
* Returns false as never a ManyToMany.
*/
@Override
public boolean isManyToMany() {
return false;
}
/**
* Returns true as always Unidirectional.
*/
@Override
public boolean isUnidirectional() {
return true;
}
}
@@ -1,109 +1,90 @@
/**
* Copyright (C) 2006 Robin Bygrave
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy.meta;
import java.util.List;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptorMap;
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocOne;
/**
* Used for associated beans in place of a BeanDescriptor. This is done to avoid
* recursion issues due to the potentially bi-directional and circular
* relationships between beans.
* <p>
* It holds the main deployment information and not all the detail that is held
* in a BeanDescriptor.
* </p>
*/
public class DeployBeanTable {
private final Class<?> beanType;
/**
* The base table.
*/
private String baseTable;
private List<DeployBeanProperty> idProperties;
/**
* Create the BeanTable.
*/
public DeployBeanTable(Class<?> beanType) {
this.beanType = beanType;
}
/**
* Return the base table for this BeanTable.
* This is used to determine the join information
* for associations.
*/
public String getBaseTable() {
return baseTable;
}
/**
* Set the base table for this BeanTable.
*/
public void setBaseTable(String baseTable) {
this.baseTable = baseTable;
}
/**
* Return the id properties.
*/
public BeanProperty[] createIdProperties(BeanDescriptorMap owner) {
BeanProperty[] props = new BeanProperty[idProperties.size()];
for (int i = 0; i < idProperties.size(); i++) {
props[i] = createProperty(owner, idProperties.get(i));
}
return props;
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private BeanProperty createProperty(BeanDescriptorMap owner, DeployBeanProperty prop){
if (prop instanceof DeployBeanPropertyAssocOne<?>){
return new BeanPropertyAssocOne(owner, (DeployBeanPropertyAssocOne<?>)prop);
} else {
return new BeanProperty(prop);
}
}
/**
* Set the Id properties.
*/
public void setIdProperties(List<DeployBeanProperty> idProperties) {
this.idProperties = idProperties;
}
/**
* Return the class for this beanTable.
*/
public Class<?> getBeanType() {
return beanType;
}
}
package com.avaje.ebeaninternal.server.deploy.meta;
import java.util.List;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptorMap;
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocOne;
/**
* Used for associated beans in place of a BeanDescriptor. This is done to avoid
* recursion issues due to the potentially bi-directional and circular
* relationships between beans.
* <p>
* It holds the main deployment information and not all the detail that is held
* in a BeanDescriptor.
* </p>
*/
public class DeployBeanTable {
private final Class<?> beanType;
/**
* The base table.
*/
private String baseTable;
private List<DeployBeanProperty> idProperties;
/**
* Create the BeanTable.
*/
public DeployBeanTable(Class<?> beanType) {
this.beanType = beanType;
}
/**
* Return the base table for this BeanTable.
* This is used to determine the join information
* for associations.
*/
public String getBaseTable() {
return baseTable;
}
/**
* Set the base table for this BeanTable.
*/
public void setBaseTable(String baseTable) {
this.baseTable = baseTable;
}
/**
* Return the id properties.
*/
public BeanProperty[] createIdProperties(BeanDescriptorMap owner) {
BeanProperty[] props = new BeanProperty[idProperties.size()];
for (int i = 0; i < idProperties.size(); i++) {
props[i] = createProperty(owner, idProperties.get(i));
}
return props;
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private BeanProperty createProperty(BeanDescriptorMap owner, DeployBeanProperty prop){
if (prop instanceof DeployBeanPropertyAssocOne<?>){
return new BeanPropertyAssocOne(owner, (DeployBeanPropertyAssocOne<?>)prop);
} else {
return new BeanProperty(prop);
}
}
/**
* Set the Id properties.
*/
public void setIdProperties(List<DeployBeanProperty> idProperties) {
this.idProperties = idProperties;
}
/**
* Return the class for this beanTable.
*/
public Class<?> getBeanType() {
return beanType;
}
}
@@ -1,227 +1,208 @@
/**
* Copyright (C) 2006 Robin Bygrave
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy.meta;
import java.util.ArrayList;
import javax.persistence.JoinColumn;
import com.avaje.ebeaninternal.server.core.Message;
import com.avaje.ebeaninternal.server.deploy.BeanCascadeInfo;
import com.avaje.ebeaninternal.server.deploy.BeanTable;
import com.avaje.ebeaninternal.server.deploy.TableJoin;
/**
* Represents a join to another table during deployment phase.
* <p>
* This gets converted into a immutable TableJoin when complete.
* </p>
*/
public class DeployTableJoin {
/**
* Flag set when the imported key maps to the primary key.
* This occurs for intersection tables (ManyToMany).
*/
private boolean importedPrimaryKey;
/**
* The joined table.
*/
private String table;
/**
* The type of join. LEFT OUTER etc.
*/
private String type = TableJoin.JOIN;
/**
* The list of properties mapped to this joined table.
*/
private ArrayList<DeployBeanProperty> properties = new ArrayList<DeployBeanProperty>();
/**
* The list of join column pairs. Used to generate the on clause.
*/
private ArrayList<DeployTableJoinColumn> columns = new ArrayList<DeployTableJoinColumn>();
/**
* The persist cascade info.
*/
private BeanCascadeInfo cascadeInfo = new BeanCascadeInfo();
/**
* Create a DeployTableJoin.
*/
public DeployTableJoin() {
}
public String toString() {
return type + " " + table + " " + columns;
}
/**
* Return true if the imported foreign key maps to the primary key.
*/
public boolean isImportedPrimaryKey() {
return importedPrimaryKey;
}
/**
* Flag set when the imported key maps to the primary key.
* This occurs for intersection tables (ManyToMany).
*/
public void setImportedPrimaryKey(boolean importedPrimaryKey) {
this.importedPrimaryKey = importedPrimaryKey;
}
/**
* Return true if the JoinOnPair have been set.
*/
public boolean hasJoinColumns() {
return columns.size() > 0;
}
/**
* Return the persist info.
*/
public BeanCascadeInfo getCascadeInfo() {
return cascadeInfo;
}
/**
* Copy all the columns to this join potentially reversing the columns.
*/
public void setColumns(DeployTableJoinColumn[] cols, boolean reverse) {
columns = new ArrayList<DeployTableJoinColumn>();
for (int i = 0; i < cols.length; i++) {
addJoinColumn(cols[i].copy(reverse));
}
}
/**
* Add a join pair
*/
public void addJoinColumn(DeployTableJoinColumn pair) {
columns.add(pair);
}
/**
* Add a JoinColumn
* <p>
* The order is generally true for OneToMany and false for ManyToOne relationships.
* </p>
*/
public void addJoinColumn(boolean order, JoinColumn jc, BeanTable beanTable) {
if (!"".equals(jc.table())) {
setTable(jc.table());
}
addJoinColumn(new DeployTableJoinColumn(order, jc, beanTable));
}
/**
* Add a JoinColumn array.
*/
public void addJoinColumn(boolean order, JoinColumn[] jcArray, BeanTable beanTable) {
for (int i = 0; i < jcArray.length; i++) {
addJoinColumn(order, jcArray[i], beanTable);
}
}
/**
* Return the join columns.
*/
public DeployTableJoinColumn[] columns() {
return (DeployTableJoinColumn[])columns.toArray(new DeployTableJoinColumn[columns.size()]);
}
/**
* For secondary table joins returns the properties mapped to that table.
*/
public DeployBeanProperty[] properties() {
return (DeployBeanProperty[])properties.toArray(new DeployBeanProperty[properties.size()]);
}
/**
* Return the joined table name.
*/
public String getTable() {
return table;
}
/**
* set the joined table name.
*/
public void setTable(String table) {
this.table = table;
}
/**
* Return the type of join. LEFT OUTER JOIN etc.
*/
public String getType() {
return type;
}
/**
* Return true if this join is a left outer join.
*/
public boolean isOuterJoin() {
return type.equals(TableJoin.LEFT_OUTER);
}
/**
* Set the type of join.
*/
public void setType(String joinType) {
joinType = joinType.toUpperCase();
if (joinType.equalsIgnoreCase(TableJoin.JOIN)) {
type = TableJoin.JOIN;
} else if (joinType.indexOf("LEFT") > -1) {
type = TableJoin.LEFT_OUTER;
} else if (joinType.indexOf("OUTER") > -1) {
type = TableJoin.LEFT_OUTER;
} else if (joinType.indexOf("INNER") > -1) {
type = TableJoin.JOIN;
} else {
throw new RuntimeException(Message.msg("join.type.unknown", joinType));
}
}
public DeployTableJoin createInverse(String tableName) {
DeployTableJoin inverse = new DeployTableJoin();
return copyTo(inverse, true, tableName);
}
public DeployTableJoin copyTo(DeployTableJoin destJoin, boolean reverse, String tableName) {
destJoin.setTable(tableName);
destJoin.setType(type);
destJoin.setColumns(columns(), reverse);
return destJoin;
}
}
package com.avaje.ebeaninternal.server.deploy.meta;
import java.util.ArrayList;
import javax.persistence.JoinColumn;
import com.avaje.ebeaninternal.server.core.Message;
import com.avaje.ebeaninternal.server.deploy.BeanCascadeInfo;
import com.avaje.ebeaninternal.server.deploy.BeanTable;
import com.avaje.ebeaninternal.server.deploy.TableJoin;
/**
* Represents a join to another table during deployment phase.
* <p>
* This gets converted into a immutable TableJoin when complete.
* </p>
*/
public class DeployTableJoin {
/**
* Flag set when the imported key maps to the primary key.
* This occurs for intersection tables (ManyToMany).
*/
private boolean importedPrimaryKey;
/**
* The joined table.
*/
private String table;
/**
* The type of join. LEFT OUTER etc.
*/
private String type = TableJoin.JOIN;
/**
* The list of properties mapped to this joined table.
*/
private ArrayList<DeployBeanProperty> properties = new ArrayList<DeployBeanProperty>();
/**
* The list of join column pairs. Used to generate the on clause.
*/
private ArrayList<DeployTableJoinColumn> columns = new ArrayList<DeployTableJoinColumn>();
/**
* The persist cascade info.
*/
private BeanCascadeInfo cascadeInfo = new BeanCascadeInfo();
/**
* Create a DeployTableJoin.
*/
public DeployTableJoin() {
}
public String toString() {
return type + " " + table + " " + columns;
}
/**
* Return true if the imported foreign key maps to the primary key.
*/
public boolean isImportedPrimaryKey() {
return importedPrimaryKey;
}
/**
* Flag set when the imported key maps to the primary key.
* This occurs for intersection tables (ManyToMany).
*/
public void setImportedPrimaryKey(boolean importedPrimaryKey) {
this.importedPrimaryKey = importedPrimaryKey;
}
/**
* Return true if the JoinOnPair have been set.
*/
public boolean hasJoinColumns() {
return columns.size() > 0;
}
/**
* Return the persist info.
*/
public BeanCascadeInfo getCascadeInfo() {
return cascadeInfo;
}
/**
* Copy all the columns to this join potentially reversing the columns.
*/
public void setColumns(DeployTableJoinColumn[] cols, boolean reverse) {
columns = new ArrayList<DeployTableJoinColumn>();
for (int i = 0; i < cols.length; i++) {
addJoinColumn(cols[i].copy(reverse));
}
}
/**
* Add a join pair
*/
public void addJoinColumn(DeployTableJoinColumn pair) {
columns.add(pair);
}
/**
* Add a JoinColumn
* <p>
* The order is generally true for OneToMany and false for ManyToOne relationships.
* </p>
*/
public void addJoinColumn(boolean order, JoinColumn jc, BeanTable beanTable) {
if (!"".equals(jc.table())) {
setTable(jc.table());
}
addJoinColumn(new DeployTableJoinColumn(order, jc, beanTable));
}
/**
* Add a JoinColumn array.
*/
public void addJoinColumn(boolean order, JoinColumn[] jcArray, BeanTable beanTable) {
for (int i = 0; i < jcArray.length; i++) {
addJoinColumn(order, jcArray[i], beanTable);
}
}
/**
* Return the join columns.
*/
public DeployTableJoinColumn[] columns() {
return (DeployTableJoinColumn[])columns.toArray(new DeployTableJoinColumn[columns.size()]);
}
/**
* For secondary table joins returns the properties mapped to that table.
*/
public DeployBeanProperty[] properties() {
return (DeployBeanProperty[])properties.toArray(new DeployBeanProperty[properties.size()]);
}
/**
* Return the joined table name.
*/
public String getTable() {
return table;
}
/**
* set the joined table name.
*/
public void setTable(String table) {
this.table = table;
}
/**
* Return the type of join. LEFT OUTER JOIN etc.
*/
public String getType() {
return type;
}
/**
* Return true if this join is a left outer join.
*/
public boolean isOuterJoin() {
return type.equals(TableJoin.LEFT_OUTER);
}
/**
* Set the type of join.
*/
public void setType(String joinType) {
joinType = joinType.toUpperCase();
if (joinType.equalsIgnoreCase(TableJoin.JOIN)) {
type = TableJoin.JOIN;
} else if (joinType.indexOf("LEFT") > -1) {
type = TableJoin.LEFT_OUTER;
} else if (joinType.indexOf("OUTER") > -1) {
type = TableJoin.LEFT_OUTER;
} else if (joinType.indexOf("INNER") > -1) {
type = TableJoin.JOIN;
} else {
throw new RuntimeException(Message.msg("join.type.unknown", joinType));
}
}
public DeployTableJoin createInverse(String tableName) {
DeployTableJoin inverse = new DeployTableJoin();
return copyTo(inverse, true, tableName);
}
public DeployTableJoin copyTo(DeployTableJoin destJoin, boolean reverse, String tableName) {
destJoin.setTable(tableName);
destJoin.setType(type);
destJoin.setColumns(columns(), reverse);
return destJoin;
}
}
@@ -1,197 +1,178 @@
/**
* Copyright (C) 2006 Robin Bygrave
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy.meta;
import javax.persistence.JoinColumn;
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
import com.avaje.ebeaninternal.server.deploy.BeanTable;
/**
* A join pair of local and foreign properties.
*/
public class DeployTableJoinColumn {
/**
* The local database column name.
*/
String localDbColumn;
/**
* The foreign database column name.
*/
String foreignDbColumn;
boolean insertable;
boolean updateable;
/**
* Construct when automatically determining the join.
* <p>
* Assume that we want the foreign key to be insertable and updateable.
* </p>
*/
public DeployTableJoinColumn(String localDbColumn, String foreignDbColumn) {
this(localDbColumn, foreignDbColumn, true, true);
}
/**
* Construct with explicit insertable and updateable flags.
*/
public DeployTableJoinColumn(String localDbColumn, String foreignDbColumn, boolean insertable, boolean updateable) {
this.localDbColumn = nullEmptyString(localDbColumn);
this.foreignDbColumn = nullEmptyString(foreignDbColumn);
this.insertable = insertable;
this.updateable = updateable;
}
public DeployTableJoinColumn(boolean order, JoinColumn jc, BeanTable beanTable) {
this(jc.referencedColumnName(), jc.name(), jc.insertable(), jc.updatable());
setReferencedColumn(beanTable);
if (!order){
reverse();
}
}
private void setReferencedColumn(BeanTable beanTable){
if (localDbColumn == null){
BeanProperty[] idProperties = beanTable.getIdProperties();
if (idProperties.length == 1){
localDbColumn = idProperties[0].getDbColumn();
}
}
}
/**
* Reverse the direction of the join.
*/
public DeployTableJoinColumn reverse() {
String temp = localDbColumn;
localDbColumn = foreignDbColumn;
foreignDbColumn = temp;
return this;
}
/**
* Helper method to null out empty strings.
*/
private String nullEmptyString(String s){
if ("".equals(s)){
return null;
}
return s;
}
public DeployTableJoinColumn copy(boolean reverse) {
// Note that the insertable and updateable are just copied
// which may not always be the correct thing to do
// but will leave it like this for now
if (reverse){
return new DeployTableJoinColumn(foreignDbColumn, localDbColumn, insertable, updateable);
} else {
return new DeployTableJoinColumn(localDbColumn, foreignDbColumn, insertable, updateable);
}
}
public String toString() {
return localDbColumn + " = " + foreignDbColumn;
}
/**
* Return true if either the local or foreign column is null.
* <p>
* Both columns need to be defined. If one is null then typically it is
* derived as the primary key column.
* </p>
*/
public boolean hasNullColumn() {
return localDbColumn == null || foreignDbColumn == null;
}
/**
* When only ONE column has been set by deployment information return that one.
* <p>
* Used with hasNullColumn() to set the foreignDbColumn for OneToMany joins.
* </p>
*/
public String getNonNullColumn() {
if (localDbColumn == null && foreignDbColumn == null) {
throw new IllegalStateException("expecting only one null column?");
} else if (localDbColumn != null && foreignDbColumn != null) {
throw new IllegalStateException("expecting one null column?");
}
if (localDbColumn != null) {
return localDbColumn;
} else {
return foreignDbColumn;
}
}
/**
* Return true if this column should be insertable.
*/
public boolean isInsertable() {
return insertable;
}
/**
* Return true if this column should be updateable.
*/
public boolean isUpdateable() {
return updateable;
}
/**
* Return the foreign database column name.
*/
public String getForeignDbColumn() {
return foreignDbColumn;
}
/**
* Set the foreign database column name.
* <p>
* Used when this is derived from Primary Key and not set explicitly in the
* deployment information.
* </p>
*/
public void setForeignDbColumn(String foreignDbColumn) {
this.foreignDbColumn = foreignDbColumn;
}
/**
* Return the local database column name.
*/
public String getLocalDbColumn() {
return localDbColumn;
}
/**
* Set the local database column name.
*/
public void setLocalDbColumn(String localDbColumn) {
this.localDbColumn = localDbColumn;
}
}
package com.avaje.ebeaninternal.server.deploy.meta;
import javax.persistence.JoinColumn;
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
import com.avaje.ebeaninternal.server.deploy.BeanTable;
/**
* A join pair of local and foreign properties.
*/
public class DeployTableJoinColumn {
/**
* The local database column name.
*/
String localDbColumn;
/**
* The foreign database column name.
*/
String foreignDbColumn;
boolean insertable;
boolean updateable;
/**
* Construct when automatically determining the join.
* <p>
* Assume that we want the foreign key to be insertable and updateable.
* </p>
*/
public DeployTableJoinColumn(String localDbColumn, String foreignDbColumn) {
this(localDbColumn, foreignDbColumn, true, true);
}
/**
* Construct with explicit insertable and updateable flags.
*/
public DeployTableJoinColumn(String localDbColumn, String foreignDbColumn, boolean insertable, boolean updateable) {
this.localDbColumn = nullEmptyString(localDbColumn);
this.foreignDbColumn = nullEmptyString(foreignDbColumn);
this.insertable = insertable;
this.updateable = updateable;
}
public DeployTableJoinColumn(boolean order, JoinColumn jc, BeanTable beanTable) {
this(jc.referencedColumnName(), jc.name(), jc.insertable(), jc.updatable());
setReferencedColumn(beanTable);
if (!order){
reverse();
}
}
private void setReferencedColumn(BeanTable beanTable){
if (localDbColumn == null){
BeanProperty[] idProperties = beanTable.getIdProperties();
if (idProperties.length == 1){
localDbColumn = idProperties[0].getDbColumn();
}
}
}
/**
* Reverse the direction of the join.
*/
public DeployTableJoinColumn reverse() {
String temp = localDbColumn;
localDbColumn = foreignDbColumn;
foreignDbColumn = temp;
return this;
}
/**
* Helper method to null out empty strings.
*/
private String nullEmptyString(String s){
if ("".equals(s)){
return null;
}
return s;
}
public DeployTableJoinColumn copy(boolean reverse) {
// Note that the insertable and updateable are just copied
// which may not always be the correct thing to do
// but will leave it like this for now
if (reverse){
return new DeployTableJoinColumn(foreignDbColumn, localDbColumn, insertable, updateable);
} else {
return new DeployTableJoinColumn(localDbColumn, foreignDbColumn, insertable, updateable);
}
}
public String toString() {
return localDbColumn + " = " + foreignDbColumn;
}
/**
* Return true if either the local or foreign column is null.
* <p>
* Both columns need to be defined. If one is null then typically it is
* derived as the primary key column.
* </p>
*/
public boolean hasNullColumn() {
return localDbColumn == null || foreignDbColumn == null;
}
/**
* When only ONE column has been set by deployment information return that one.
* <p>
* Used with hasNullColumn() to set the foreignDbColumn for OneToMany joins.
* </p>
*/
public String getNonNullColumn() {
if (localDbColumn == null && foreignDbColumn == null) {
throw new IllegalStateException("expecting only one null column?");
} else if (localDbColumn != null && foreignDbColumn != null) {
throw new IllegalStateException("expecting one null column?");
}
if (localDbColumn != null) {
return localDbColumn;
} else {
return foreignDbColumn;
}
}
/**
* Return true if this column should be insertable.
*/
public boolean isInsertable() {
return insertable;
}
/**
* Return true if this column should be updateable.
*/
public boolean isUpdateable() {
return updateable;
}
/**
* Return the foreign database column name.
*/
public String getForeignDbColumn() {
return foreignDbColumn;
}
/**
* Set the foreign database column name.
* <p>
* Used when this is derived from Primary Key and not set explicitly in the
* deployment information.
* </p>
*/
public void setForeignDbColumn(String foreignDbColumn) {
this.foreignDbColumn = foreignDbColumn;
}
/**
* Return the local database column name.
*/
public String getLocalDbColumn() {
return localDbColumn;
}
/**
* Set the local database column name.
*/
public void setLocalDbColumn(String localDbColumn) {
this.localDbColumn = localDbColumn;
}
}
@@ -1,348 +1,329 @@
/**
* Copyright (C) 2006 Robin Bygrave
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy.parse;
import java.util.Iterator;
import javax.persistence.JoinColumn;
import javax.persistence.JoinColumns;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.MapKey;
import javax.persistence.OneToMany;
import javax.persistence.OrderBy;
import com.avaje.ebean.annotation.LdapAttribute;
import com.avaje.ebean.annotation.PrivateOwned;
import com.avaje.ebean.annotation.Where;
import com.avaje.ebean.bean.BeanCollection.ModifyListenMode;
import com.avaje.ebean.config.NamingConvention;
import com.avaje.ebean.config.TableName;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptorManager;
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
import com.avaje.ebeaninternal.server.deploy.BeanTable;
import com.avaje.ebeaninternal.server.deploy.TableJoin;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocMany;
import com.avaje.ebeaninternal.server.deploy.meta.DeployTableJoin;
import com.avaje.ebeaninternal.server.deploy.meta.DeployTableJoinColumn;
import com.avaje.ebeaninternal.server.lib.util.StringHelper;
/**
* Read the deployment annotation for Assoc Many beans.
*/
public class AnnotationAssocManys extends AnnotationParser {
private final BeanDescriptorManager factory;
/**
* Create with the DeployInfo.
*/
public AnnotationAssocManys(DeployBeanInfo<?> info, BeanDescriptorManager factory) {
super(info);
this.factory = factory;
}
/**
* Parse the annotations.
*/
public void parse() {
Iterator<DeployBeanProperty> it = descriptor.propertiesAll();
while (it.hasNext()) {
DeployBeanProperty prop = it.next();
if (prop instanceof DeployBeanPropertyAssocMany<?>) {
read((DeployBeanPropertyAssocMany<?>) prop);
}
}
}
private void read(DeployBeanPropertyAssocMany<?> prop) {
OneToMany oneToMany = get(prop, OneToMany.class);
if (oneToMany != null) {
readToOne(oneToMany, prop);
PrivateOwned privateOwned = get(prop, PrivateOwned.class);
if (privateOwned != null){
prop.setModifyListenMode(ModifyListenMode.REMOVALS);
prop.getCascadeInfo().setDelete(privateOwned.cascadeRemove());
}
}
ManyToMany manyToMany = get(prop, ManyToMany.class);
if (manyToMany != null) {
readToMany(manyToMany, prop);
}
OrderBy orderBy = get(prop, OrderBy.class);
if (orderBy != null) {
prop.setFetchOrderBy(orderBy.value());
}
MapKey mapKey = get(prop, MapKey.class);
if (mapKey != null) {
prop.setMapKey(mapKey.name());
}
Where where = get(prop, Where.class);
if (where != null) {
prop.setExtraWhere(where.clause());
}
// check for manually defined joins
BeanTable beanTable = prop.getBeanTable();
JoinColumn joinColumn = get(prop, JoinColumn.class);
if (joinColumn != null) {
prop.getTableJoin().addJoinColumn(true, joinColumn, beanTable);
}
JoinColumns joinColumns = get(prop, JoinColumns.class);
if (joinColumns != null) {
prop.getTableJoin().addJoinColumn(true, joinColumns.value(), beanTable);
}
JoinTable joinTable = get(prop, JoinTable.class);
if (joinTable != null) {
if (prop.isManyToMany()){
// expected this
readJoinTable(joinTable, prop);
} else {
// OneToMany in theory
prop.getTableJoin().addJoinColumn(true, joinTable.joinColumns(), beanTable);
}
}
LdapAttribute ldapAttribute = get(prop, LdapAttribute.class);
if (ldapAttribute != null) {
// read ldap specific property settings
readLdapAttribute(ldapAttribute, prop);
}
if (prop.getMappedBy() != null){
// the join is derived by reversing the join information
// from the mapped by property.
// Refer BeanDescriptorManager.readEntityRelationships()
return;
}
if (prop.isManyToMany()){
manyToManyDefaultJoins(prop);
return;
}
if (!prop.getTableJoin().hasJoinColumns() && beanTable != null){
// use naming convention to define join (based on the bean name for this side of relationship)
// A unidirectional OneToMany or OneToMany with no mappedBy property
NamingConvention nc = factory.getNamingConvention();
String fkeyPrefix = null;
if (nc.isUseForeignKeyPrefix()){
fkeyPrefix = nc.getColumnFromProperty(descriptor.getBeanType(), descriptor.getName());
}
// Use the owning bean table to define the join
BeanTable owningBeanTable = factory.getBeanTable(descriptor.getBeanType());
owningBeanTable.createJoinColumn(fkeyPrefix, prop.getTableJoin(), false);
}
}
/**
* Define the joins for a ManyToMany relationship.
* <p>
* This includes joins to the intersection table and from the intersection table
* to the other side of the ManyToMany.
* </p>
*/
private void readJoinTable(JoinTable joinTable, DeployBeanPropertyAssocMany<?> prop) {
String intTableName = getFullTableName(joinTable);
// set the intersection table
DeployTableJoin intJoin = new DeployTableJoin();
intJoin.setTable(intTableName);
// add the source to intersection join columns
intJoin.addJoinColumn(true, joinTable.joinColumns(), prop.getBeanTable());
// set the intersection to dest table join columns
DeployTableJoin destJoin = prop.getTableJoin();
destJoin.addJoinColumn(false, joinTable.inverseJoinColumns(), prop.getBeanTable());
intJoin.setType(TableJoin.LEFT_OUTER);
// reverse join from dest back to intersection
DeployTableJoin inverseDest = destJoin.createInverse(intTableName);
prop.setIntersectionJoin(intJoin);
prop.setInverseJoin(inverseDest);
}
/**
* Return the full table name
* @param joinTable
* @return
*/
private String getFullTableName(JoinTable joinTable) {
StringBuilder sb = new StringBuilder();
if (!StringHelper.isNull(joinTable.catalog())){
sb.append(joinTable.catalog()).append(".");
}
if (!StringHelper.isNull(joinTable.schema())){
sb.append(joinTable.schema()).append(".");
}
sb.append(joinTable.name());
return sb.toString();
}
/**
* Define intersection table and foreign key columns for ManyToMany.
* <p>
* Some of these (maybe all) have been already defined via @JoinTable
* and @JoinColumns etc.
* </p>
*/
private void manyToManyDefaultJoins(DeployBeanPropertyAssocMany<?> prop) {
String intTableName = null;
DeployTableJoin intJoin = prop.getIntersectionJoin();
if (intJoin == null){
intJoin = new DeployTableJoin();
prop.setIntersectionJoin(intJoin);
} else {
// intersection table already defined (by @JoinTable)
intTableName = intJoin.getTable();
}
BeanTable localTable = factory.getBeanTable(descriptor.getBeanType());
BeanTable otherTable = factory.getBeanTable(prop.getTargetType());
final String localTableName = localTable.getUnqualifiedBaseTable();
final String otherTableName = otherTable.getUnqualifiedBaseTable();
if (intTableName == null){
// define intersection table name
intTableName = getM2MJoinTableName(localTable, otherTable);
intJoin.setTable(intTableName);
intJoin.setType(TableJoin.LEFT_OUTER);
}
DeployTableJoin destJoin = prop.getTableJoin();
if (intJoin.hasJoinColumns() && destJoin.hasJoinColumns()){
// already defined the foreign key columns etc
return;
}
if (!intJoin.hasJoinColumns()){
// define foreign key columns
BeanProperty[] localIds = localTable.getIdProperties();
for (int i = 0; i < localIds.length; i++) {
// add the source to intersection join columns
String fkCol = localTableName+"_"+localIds[i].getDbColumn();
intJoin.addJoinColumn(new DeployTableJoinColumn(localIds[i].getDbColumn(), fkCol));
}
}
if (!destJoin.hasJoinColumns()){
// define inverse foreign key columns
BeanProperty[] otherIds = otherTable.getIdProperties();
for (int i = 0; i < otherIds.length; i++) {
// set the intersection to dest table join columns
final String fkCol = otherTableName+"_"+otherIds[i].getDbColumn();
destJoin.addJoinColumn(new DeployTableJoinColumn(fkCol, otherIds[i].getDbColumn()));
}
}
// reverse join from dest back to intersection
DeployTableJoin inverseDest = destJoin.createInverse(intTableName);
prop.setInverseJoin(inverseDest);
}
private String errorMsgMissingBeanTable(Class<?> type, String from) {
return "Error with association to ["+type+"] from ["+from+"]. Is "+type+" registered?";
}
private void readToMany(ManyToMany propAnn, DeployBeanPropertyAssocMany<?> manyProp) {
manyProp.setMappedBy(propAnn.mappedBy());
manyProp.setFetchType(propAnn.fetch());
setCascadeTypes(propAnn.cascade(), manyProp.getCascadeInfo());
Class<?> targetType = propAnn.targetEntity();
if (targetType.equals(void.class)) {
// via reflection of generics type
targetType = manyProp.getTargetType();
} else {
manyProp.setTargetType(targetType);
}
// find the other many table (not intersection)
BeanTable assoc = factory.getBeanTable(targetType);
if (assoc == null) {
String msg = errorMsgMissingBeanTable(targetType, manyProp.getFullBeanName());
throw new RuntimeException(msg);
}
manyProp.setManyToMany(true);
manyProp.setModifyListenMode(ModifyListenMode.ALL);
manyProp.setBeanTable(assoc);
manyProp.getTableJoin().setType(TableJoin.LEFT_OUTER);
}
private void readToOne(OneToMany propAnn, DeployBeanPropertyAssocMany<?> manyProp) {
manyProp.setMappedBy(propAnn.mappedBy());
manyProp.setFetchType(propAnn.fetch());
setCascadeTypes(propAnn.cascade(), manyProp.getCascadeInfo());
Class<?> targetType = propAnn.targetEntity();
if (targetType.equals(void.class)) {
// via reflection of generics type
targetType = manyProp.getTargetType();
} else {
manyProp.setTargetType(targetType);
}
BeanTable assoc = factory.getBeanTable(targetType);
if (assoc == null) {
String msg = errorMsgMissingBeanTable(targetType, manyProp.getFullBeanName());
throw new RuntimeException(msg);
}
manyProp.setBeanTable(assoc);
manyProp.getTableJoin().setType(TableJoin.LEFT_OUTER);
}
private String getM2MJoinTableName(BeanTable lhsTable, BeanTable rhsTable){
TableName lhs = new TableName(lhsTable.getBaseTable());
TableName rhs = new TableName(rhsTable.getBaseTable());
TableName joinTable = namingConvention.getM2MJoinTableName(lhs, rhs);
return joinTable.getQualifiedName();
}
}
package com.avaje.ebeaninternal.server.deploy.parse;
import java.util.Iterator;
import javax.persistence.JoinColumn;
import javax.persistence.JoinColumns;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.MapKey;
import javax.persistence.OneToMany;
import javax.persistence.OrderBy;
import com.avaje.ebean.annotation.LdapAttribute;
import com.avaje.ebean.annotation.PrivateOwned;
import com.avaje.ebean.annotation.Where;
import com.avaje.ebean.bean.BeanCollection.ModifyListenMode;
import com.avaje.ebean.config.NamingConvention;
import com.avaje.ebean.config.TableName;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptorManager;
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
import com.avaje.ebeaninternal.server.deploy.BeanTable;
import com.avaje.ebeaninternal.server.deploy.TableJoin;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocMany;
import com.avaje.ebeaninternal.server.deploy.meta.DeployTableJoin;
import com.avaje.ebeaninternal.server.deploy.meta.DeployTableJoinColumn;
import com.avaje.ebeaninternal.server.lib.util.StringHelper;
/**
* Read the deployment annotation for Assoc Many beans.
*/
public class AnnotationAssocManys extends AnnotationParser {
private final BeanDescriptorManager factory;
/**
* Create with the DeployInfo.
*/
public AnnotationAssocManys(DeployBeanInfo<?> info, BeanDescriptorManager factory) {
super(info);
this.factory = factory;
}
/**
* Parse the annotations.
*/
public void parse() {
Iterator<DeployBeanProperty> it = descriptor.propertiesAll();
while (it.hasNext()) {
DeployBeanProperty prop = it.next();
if (prop instanceof DeployBeanPropertyAssocMany<?>) {
read((DeployBeanPropertyAssocMany<?>) prop);
}
}
}
private void read(DeployBeanPropertyAssocMany<?> prop) {
OneToMany oneToMany = get(prop, OneToMany.class);
if (oneToMany != null) {
readToOne(oneToMany, prop);
PrivateOwned privateOwned = get(prop, PrivateOwned.class);
if (privateOwned != null){
prop.setModifyListenMode(ModifyListenMode.REMOVALS);
prop.getCascadeInfo().setDelete(privateOwned.cascadeRemove());
}
}
ManyToMany manyToMany = get(prop, ManyToMany.class);
if (manyToMany != null) {
readToMany(manyToMany, prop);
}
OrderBy orderBy = get(prop, OrderBy.class);
if (orderBy != null) {
prop.setFetchOrderBy(orderBy.value());
}
MapKey mapKey = get(prop, MapKey.class);
if (mapKey != null) {
prop.setMapKey(mapKey.name());
}
Where where = get(prop, Where.class);
if (where != null) {
prop.setExtraWhere(where.clause());
}
// check for manually defined joins
BeanTable beanTable = prop.getBeanTable();
JoinColumn joinColumn = get(prop, JoinColumn.class);
if (joinColumn != null) {
prop.getTableJoin().addJoinColumn(true, joinColumn, beanTable);
}
JoinColumns joinColumns = get(prop, JoinColumns.class);
if (joinColumns != null) {
prop.getTableJoin().addJoinColumn(true, joinColumns.value(), beanTable);
}
JoinTable joinTable = get(prop, JoinTable.class);
if (joinTable != null) {
if (prop.isManyToMany()){
// expected this
readJoinTable(joinTable, prop);
} else {
// OneToMany in theory
prop.getTableJoin().addJoinColumn(true, joinTable.joinColumns(), beanTable);
}
}
LdapAttribute ldapAttribute = get(prop, LdapAttribute.class);
if (ldapAttribute != null) {
// read ldap specific property settings
readLdapAttribute(ldapAttribute, prop);
}
if (prop.getMappedBy() != null){
// the join is derived by reversing the join information
// from the mapped by property.
// Refer BeanDescriptorManager.readEntityRelationships()
return;
}
if (prop.isManyToMany()){
manyToManyDefaultJoins(prop);
return;
}
if (!prop.getTableJoin().hasJoinColumns() && beanTable != null){
// use naming convention to define join (based on the bean name for this side of relationship)
// A unidirectional OneToMany or OneToMany with no mappedBy property
NamingConvention nc = factory.getNamingConvention();
String fkeyPrefix = null;
if (nc.isUseForeignKeyPrefix()){
fkeyPrefix = nc.getColumnFromProperty(descriptor.getBeanType(), descriptor.getName());
}
// Use the owning bean table to define the join
BeanTable owningBeanTable = factory.getBeanTable(descriptor.getBeanType());
owningBeanTable.createJoinColumn(fkeyPrefix, prop.getTableJoin(), false);
}
}
/**
* Define the joins for a ManyToMany relationship.
* <p>
* This includes joins to the intersection table and from the intersection table
* to the other side of the ManyToMany.
* </p>
*/
private void readJoinTable(JoinTable joinTable, DeployBeanPropertyAssocMany<?> prop) {
String intTableName = getFullTableName(joinTable);
// set the intersection table
DeployTableJoin intJoin = new DeployTableJoin();
intJoin.setTable(intTableName);
// add the source to intersection join columns
intJoin.addJoinColumn(true, joinTable.joinColumns(), prop.getBeanTable());
// set the intersection to dest table join columns
DeployTableJoin destJoin = prop.getTableJoin();
destJoin.addJoinColumn(false, joinTable.inverseJoinColumns(), prop.getBeanTable());
intJoin.setType(TableJoin.LEFT_OUTER);
// reverse join from dest back to intersection
DeployTableJoin inverseDest = destJoin.createInverse(intTableName);
prop.setIntersectionJoin(intJoin);
prop.setInverseJoin(inverseDest);
}
/**
* Return the full table name
* @param joinTable
* @return
*/
private String getFullTableName(JoinTable joinTable) {
StringBuilder sb = new StringBuilder();
if (!StringHelper.isNull(joinTable.catalog())){
sb.append(joinTable.catalog()).append(".");
}
if (!StringHelper.isNull(joinTable.schema())){
sb.append(joinTable.schema()).append(".");
}
sb.append(joinTable.name());
return sb.toString();
}
/**
* Define intersection table and foreign key columns for ManyToMany.
* <p>
* Some of these (maybe all) have been already defined via @JoinTable
* and @JoinColumns etc.
* </p>
*/
private void manyToManyDefaultJoins(DeployBeanPropertyAssocMany<?> prop) {
String intTableName = null;
DeployTableJoin intJoin = prop.getIntersectionJoin();
if (intJoin == null){
intJoin = new DeployTableJoin();
prop.setIntersectionJoin(intJoin);
} else {
// intersection table already defined (by @JoinTable)
intTableName = intJoin.getTable();
}
BeanTable localTable = factory.getBeanTable(descriptor.getBeanType());
BeanTable otherTable = factory.getBeanTable(prop.getTargetType());
final String localTableName = localTable.getUnqualifiedBaseTable();
final String otherTableName = otherTable.getUnqualifiedBaseTable();
if (intTableName == null){
// define intersection table name
intTableName = getM2MJoinTableName(localTable, otherTable);
intJoin.setTable(intTableName);
intJoin.setType(TableJoin.LEFT_OUTER);
}
DeployTableJoin destJoin = prop.getTableJoin();
if (intJoin.hasJoinColumns() && destJoin.hasJoinColumns()){
// already defined the foreign key columns etc
return;
}
if (!intJoin.hasJoinColumns()){
// define foreign key columns
BeanProperty[] localIds = localTable.getIdProperties();
for (int i = 0; i < localIds.length; i++) {
// add the source to intersection join columns
String fkCol = localTableName+"_"+localIds[i].getDbColumn();
intJoin.addJoinColumn(new DeployTableJoinColumn(localIds[i].getDbColumn(), fkCol));
}
}
if (!destJoin.hasJoinColumns()){
// define inverse foreign key columns
BeanProperty[] otherIds = otherTable.getIdProperties();
for (int i = 0; i < otherIds.length; i++) {
// set the intersection to dest table join columns
final String fkCol = otherTableName+"_"+otherIds[i].getDbColumn();
destJoin.addJoinColumn(new DeployTableJoinColumn(fkCol, otherIds[i].getDbColumn()));
}
}
// reverse join from dest back to intersection
DeployTableJoin inverseDest = destJoin.createInverse(intTableName);
prop.setInverseJoin(inverseDest);
}
private String errorMsgMissingBeanTable(Class<?> type, String from) {
return "Error with association to ["+type+"] from ["+from+"]. Is "+type+" registered?";
}
private void readToMany(ManyToMany propAnn, DeployBeanPropertyAssocMany<?> manyProp) {
manyProp.setMappedBy(propAnn.mappedBy());
manyProp.setFetchType(propAnn.fetch());
setCascadeTypes(propAnn.cascade(), manyProp.getCascadeInfo());
Class<?> targetType = propAnn.targetEntity();
if (targetType.equals(void.class)) {
// via reflection of generics type
targetType = manyProp.getTargetType();
} else {
manyProp.setTargetType(targetType);
}
// find the other many table (not intersection)
BeanTable assoc = factory.getBeanTable(targetType);
if (assoc == null) {
String msg = errorMsgMissingBeanTable(targetType, manyProp.getFullBeanName());
throw new RuntimeException(msg);
}
manyProp.setManyToMany(true);
manyProp.setModifyListenMode(ModifyListenMode.ALL);
manyProp.setBeanTable(assoc);
manyProp.getTableJoin().setType(TableJoin.LEFT_OUTER);
}
private void readToOne(OneToMany propAnn, DeployBeanPropertyAssocMany<?> manyProp) {
manyProp.setMappedBy(propAnn.mappedBy());
manyProp.setFetchType(propAnn.fetch());
setCascadeTypes(propAnn.cascade(), manyProp.getCascadeInfo());
Class<?> targetType = propAnn.targetEntity();
if (targetType.equals(void.class)) {
// via reflection of generics type
targetType = manyProp.getTargetType();
} else {
manyProp.setTargetType(targetType);
}
BeanTable assoc = factory.getBeanTable(targetType);
if (assoc == null) {
String msg = errorMsgMissingBeanTable(targetType, manyProp.getFullBeanName());
throw new RuntimeException(msg);
}
manyProp.setBeanTable(assoc);
manyProp.getTableJoin().setType(TableJoin.LEFT_OUTER);
}
private String getM2MJoinTableName(BeanTable lhsTable, BeanTable rhsTable){
TableName lhs = new TableName(lhsTable.getBaseTable());
TableName rhs = new TableName(rhsTable.getBaseTable());
TableName joinTable = namingConvention.getM2MJoinTableName(lhs, rhs);
return joinTable.getQualifiedName();
}
}
@@ -1,246 +1,227 @@
/**
* Copyright (C) 2006 Robin Bygrave
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy.parse;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.Column;
import javax.persistence.Embedded;
import javax.persistence.EmbeddedId;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinColumns;
import javax.persistence.JoinTable;
import javax.persistence.ManyToOne;
import javax.persistence.OneToOne;
import com.avaje.ebean.annotation.EmbeddedColumns;
import com.avaje.ebean.annotation.Where;
import com.avaje.ebean.config.NamingConvention;
import com.avaje.ebean.validation.NotNull;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptorManager;
import com.avaje.ebeaninternal.server.deploy.BeanTable;
import com.avaje.ebeaninternal.server.deploy.TableJoin;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocOne;
import com.avaje.ebeaninternal.server.lib.util.StringHelper;
/**
* Read the deployment annotations for Associated One beans.
*/
public class AnnotationAssocOnes extends AnnotationParser {
private final BeanDescriptorManager factory;
/**
* Create with the deploy Info.
*/
public AnnotationAssocOnes(DeployBeanInfo<?> info, BeanDescriptorManager factory) {
super(info);
this.factory = factory;
}
/**
* Parse the annotation.
*/
public void parse() {
Iterator<DeployBeanProperty> it = descriptor.propertiesAll();
while (it.hasNext()) {
DeployBeanProperty prop = it.next();
if (prop instanceof DeployBeanPropertyAssocOne<?>) {
readAssocOne((DeployBeanPropertyAssocOne<?>) prop);
}
}
}
private void readAssocOne(DeployBeanPropertyAssocOne<?> prop) {
ManyToOne manyToOne = get(prop, ManyToOne.class);
if (manyToOne != null) {
readManyToOne(manyToOne, prop);
}
OneToOne oneToOne = get(prop, OneToOne.class);
if (oneToOne != null) {
readOneToOne(oneToOne, prop);
}
Embedded embedded = get(prop, Embedded.class);
if (embedded != null) {
readEmbedded(embedded, prop);
}
EmbeddedId emId = get(prop, EmbeddedId.class);
if (emId != null) {
prop.setEmbedded(true);
prop.setId(true);
prop.setNullable(false);
}
Column column = get(prop, Column.class);
if (column != null && !isEmpty(column.name())) {
// have this in for AssocOnes used on
// Sql based beans...
prop.setDbColumn(column.name());
}
// May as well check for Id. Makes sense to me.
Id id = get(prop, Id.class);
if (id != null) {
prop.setEmbedded(true);
prop.setId(true);
prop.setNullable(false);
}
Where where = get(prop, Where.class);
if (where != null) {
// not expecting this to be used on assoc one properties
prop.setExtraWhere(where.clause());
}
NotNull notNull = get(prop, NotNull.class);
if (notNull != null) {
prop.setNullable(false);
// overrides optional attribute of ManyToOne etc
prop.getTableJoin().setType(TableJoin.JOIN);
}
// check for manually defined joins
BeanTable beanTable = prop.getBeanTable();
JoinColumn joinColumn = get(prop, JoinColumn.class);
if (joinColumn != null) {
prop.getTableJoin().addJoinColumn(false, joinColumn, beanTable);
if (!joinColumn.updatable()){
prop.setDbUpdateable(false);
}
}
JoinColumns joinColumns = get(prop, JoinColumns.class);
if (joinColumns != null) {
prop.getTableJoin().addJoinColumn(false, joinColumns.value(), beanTable);
}
JoinTable joinTable = get(prop, JoinTable.class);
if (joinTable != null) {
prop.getTableJoin().addJoinColumn(false, joinTable.joinColumns(), beanTable);
}
info.setBeanJoinType(prop, prop.isNullable());
if (!prop.getTableJoin().hasJoinColumns() && beanTable != null) {
if (prop.getMappedBy() != null) {
// the join is derived by reversing the join information
// from the mapped by property.
// Refer BeanDescriptorManager.readEntityRelationships()
} else {
// use naming convention to define join.
NamingConvention nc = factory.getNamingConvention();
String fkeyPrefix = null;
if (nc.isUseForeignKeyPrefix()){
fkeyPrefix = nc.getColumnFromProperty(beanType, prop.getName());
}
beanTable.createJoinColumn(fkeyPrefix, prop.getTableJoin(), true);
}
}
}
private String errorMsgMissingBeanTable(Class<?> type, String from) {
return "Error with association to [" + type + "] from [" + from + "]. Is " + type + " registered?";
}
private void readManyToOne(ManyToOne propAnn, DeployBeanProperty prop) {
DeployBeanPropertyAssocOne<?> beanProp = (DeployBeanPropertyAssocOne<?>) prop;
setCascadeTypes(propAnn.cascade(), beanProp.getCascadeInfo());
BeanTable assoc = factory.getBeanTable(beanProp.getPropertyType());
if (assoc == null) {
String msg = errorMsgMissingBeanTable(beanProp.getPropertyType(), prop.getFullBeanName());
throw new RuntimeException(msg);
}
beanProp.setBeanTable(assoc);
beanProp.setDbInsertable(true);
beanProp.setDbUpdateable(true);
beanProp.setNullable(propAnn.optional());
beanProp.setFetchType(propAnn.fetch());
}
private void readOneToOne(OneToOne propAnn, DeployBeanPropertyAssocOne<?> prop) {
prop.setOneToOne(true);
prop.setDbInsertable(true);
prop.setDbUpdateable(true);
prop.setNullable(propAnn.optional());
prop.setFetchType(propAnn.fetch());
prop.setMappedBy(propAnn.mappedBy());
if (!"".equals(propAnn.mappedBy())) {
prop.setOneToOneExported(true);
}
setCascadeTypes(propAnn.cascade(), prop.getCascadeInfo());
BeanTable assoc = factory.getBeanTable(prop.getPropertyType());
if (assoc == null) {
String msg = errorMsgMissingBeanTable(prop.getPropertyType(), prop.getFullBeanName());
throw new RuntimeException(msg);
}
prop.setBeanTable(assoc);
}
private void readEmbedded(Embedded propAnn, DeployBeanPropertyAssocOne<?> prop) {
prop.setEmbedded(true);
prop.setDbInsertable(true);
prop.setDbUpdateable(true);
EmbeddedColumns columns = get(prop, EmbeddedColumns.class);
if (columns != null) {
// convert into a Map
String propColumns = columns.columns();
Map<String, String> propMap = StringHelper.delimitedToMap(propColumns, ",", "=");
prop.getDeployEmbedded().putAll(propMap);
}
AttributeOverrides attrOverrides = get(prop, AttributeOverrides.class);
if (attrOverrides != null) {
HashMap<String, String> propMap = new HashMap<String, String>();
AttributeOverride[] aoArray = attrOverrides.value();
for (int i = 0; i < aoArray.length; i++) {
String propName = aoArray[i].name();
String columnName = aoArray[i].column().name();
propMap.put(propName, columnName);
}
prop.getDeployEmbedded().putAll(propMap);
}
}
}
package com.avaje.ebeaninternal.server.deploy.parse;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.Column;
import javax.persistence.Embedded;
import javax.persistence.EmbeddedId;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinColumns;
import javax.persistence.JoinTable;
import javax.persistence.ManyToOne;
import javax.persistence.OneToOne;
import com.avaje.ebean.annotation.EmbeddedColumns;
import com.avaje.ebean.annotation.Where;
import com.avaje.ebean.config.NamingConvention;
import com.avaje.ebean.validation.NotNull;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptorManager;
import com.avaje.ebeaninternal.server.deploy.BeanTable;
import com.avaje.ebeaninternal.server.deploy.TableJoin;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocOne;
import com.avaje.ebeaninternal.server.lib.util.StringHelper;
/**
* Read the deployment annotations for Associated One beans.
*/
public class AnnotationAssocOnes extends AnnotationParser {
private final BeanDescriptorManager factory;
/**
* Create with the deploy Info.
*/
public AnnotationAssocOnes(DeployBeanInfo<?> info, BeanDescriptorManager factory) {
super(info);
this.factory = factory;
}
/**
* Parse the annotation.
*/
public void parse() {
Iterator<DeployBeanProperty> it = descriptor.propertiesAll();
while (it.hasNext()) {
DeployBeanProperty prop = it.next();
if (prop instanceof DeployBeanPropertyAssocOne<?>) {
readAssocOne((DeployBeanPropertyAssocOne<?>) prop);
}
}
}
private void readAssocOne(DeployBeanPropertyAssocOne<?> prop) {
ManyToOne manyToOne = get(prop, ManyToOne.class);
if (manyToOne != null) {
readManyToOne(manyToOne, prop);
}
OneToOne oneToOne = get(prop, OneToOne.class);
if (oneToOne != null) {
readOneToOne(oneToOne, prop);
}
Embedded embedded = get(prop, Embedded.class);
if (embedded != null) {
readEmbedded(embedded, prop);
}
EmbeddedId emId = get(prop, EmbeddedId.class);
if (emId != null) {
prop.setEmbedded(true);
prop.setId(true);
prop.setNullable(false);
}
Column column = get(prop, Column.class);
if (column != null && !isEmpty(column.name())) {
// have this in for AssocOnes used on
// Sql based beans...
prop.setDbColumn(column.name());
}
// May as well check for Id. Makes sense to me.
Id id = get(prop, Id.class);
if (id != null) {
prop.setEmbedded(true);
prop.setId(true);
prop.setNullable(false);
}
Where where = get(prop, Where.class);
if (where != null) {
// not expecting this to be used on assoc one properties
prop.setExtraWhere(where.clause());
}
NotNull notNull = get(prop, NotNull.class);
if (notNull != null) {
prop.setNullable(false);
// overrides optional attribute of ManyToOne etc
prop.getTableJoin().setType(TableJoin.JOIN);
}
// check for manually defined joins
BeanTable beanTable = prop.getBeanTable();
JoinColumn joinColumn = get(prop, JoinColumn.class);
if (joinColumn != null) {
prop.getTableJoin().addJoinColumn(false, joinColumn, beanTable);
if (!joinColumn.updatable()){
prop.setDbUpdateable(false);
}
}
JoinColumns joinColumns = get(prop, JoinColumns.class);
if (joinColumns != null) {
prop.getTableJoin().addJoinColumn(false, joinColumns.value(), beanTable);
}
JoinTable joinTable = get(prop, JoinTable.class);
if (joinTable != null) {
prop.getTableJoin().addJoinColumn(false, joinTable.joinColumns(), beanTable);
}
info.setBeanJoinType(prop, prop.isNullable());
if (!prop.getTableJoin().hasJoinColumns() && beanTable != null) {
if (prop.getMappedBy() != null) {
// the join is derived by reversing the join information
// from the mapped by property.
// Refer BeanDescriptorManager.readEntityRelationships()
} else {
// use naming convention to define join.
NamingConvention nc = factory.getNamingConvention();
String fkeyPrefix = null;
if (nc.isUseForeignKeyPrefix()){
fkeyPrefix = nc.getColumnFromProperty(beanType, prop.getName());
}
beanTable.createJoinColumn(fkeyPrefix, prop.getTableJoin(), true);
}
}
}
private String errorMsgMissingBeanTable(Class<?> type, String from) {
return "Error with association to [" + type + "] from [" + from + "]. Is " + type + " registered?";
}
private void readManyToOne(ManyToOne propAnn, DeployBeanProperty prop) {
DeployBeanPropertyAssocOne<?> beanProp = (DeployBeanPropertyAssocOne<?>) prop;
setCascadeTypes(propAnn.cascade(), beanProp.getCascadeInfo());
BeanTable assoc = factory.getBeanTable(beanProp.getPropertyType());
if (assoc == null) {
String msg = errorMsgMissingBeanTable(beanProp.getPropertyType(), prop.getFullBeanName());
throw new RuntimeException(msg);
}
beanProp.setBeanTable(assoc);
beanProp.setDbInsertable(true);
beanProp.setDbUpdateable(true);
beanProp.setNullable(propAnn.optional());
beanProp.setFetchType(propAnn.fetch());
}
private void readOneToOne(OneToOne propAnn, DeployBeanPropertyAssocOne<?> prop) {
prop.setOneToOne(true);
prop.setDbInsertable(true);
prop.setDbUpdateable(true);
prop.setNullable(propAnn.optional());
prop.setFetchType(propAnn.fetch());
prop.setMappedBy(propAnn.mappedBy());
if (!"".equals(propAnn.mappedBy())) {
prop.setOneToOneExported(true);
}
setCascadeTypes(propAnn.cascade(), prop.getCascadeInfo());
BeanTable assoc = factory.getBeanTable(prop.getPropertyType());
if (assoc == null) {
String msg = errorMsgMissingBeanTable(prop.getPropertyType(), prop.getFullBeanName());
throw new RuntimeException(msg);
}
prop.setBeanTable(assoc);
}
private void readEmbedded(Embedded propAnn, DeployBeanPropertyAssocOne<?> prop) {
prop.setEmbedded(true);
prop.setDbInsertable(true);
prop.setDbUpdateable(true);
EmbeddedColumns columns = get(prop, EmbeddedColumns.class);
if (columns != null) {
// convert into a Map
String propColumns = columns.columns();
Map<String, String> propMap = StringHelper.delimitedToMap(propColumns, ",", "=");
prop.getDeployEmbedded().putAll(propMap);
}
AttributeOverrides attrOverrides = get(prop, AttributeOverrides.class);
if (attrOverrides != null) {
HashMap<String, String> propMap = new HashMap<String, String>();
AttributeOverride[] aoArray = attrOverrides.value();
for (int i = 0; i < aoArray.length; i++) {
String propName = aoArray[i].name();
String columnName = aoArray[i].column().name();
propMap.put(propName, columnName);
}
prop.getDeployEmbedded().putAll(propMap);
}
}
}
@@ -1,50 +1,31 @@
/**
* Copyright (C) 2006 Robin Bygrave
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy.parse;
import com.avaje.ebean.config.TableName;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanTable;
/**
* Read the annotations for BeanTable.
* <p>
* Refer to BeanTable but basically determining base table, table alias
* and the unique id properties.
* </p>
*/
public class AnnotationBeanTable extends AnnotationBase {
final DeployBeanTable beanTable;
public AnnotationBeanTable(DeployUtil util, DeployBeanTable beanTable){
super(util);
this.beanTable = beanTable;
}
/**
* Parse the annotations.
*/
public void parse() {
TableName tableName = namingConvention.getTableName(beanTable.getBeanType());
beanTable.setBaseTable(tableName.getQualifiedName());
}
}
package com.avaje.ebeaninternal.server.deploy.parse;
import com.avaje.ebean.config.TableName;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanTable;
/**
* Read the annotations for BeanTable.
* <p>
* Refer to BeanTable but basically determining base table, table alias
* and the unique id properties.
* </p>
*/
public class AnnotationBeanTable extends AnnotationBase {
final DeployBeanTable beanTable;
public AnnotationBeanTable(DeployUtil util, DeployBeanTable beanTable){
super(util);
this.beanTable = beanTable;
}
/**
* Parse the annotations.
*/
public void parse() {
TableName tableName = namingConvention.getTableName(beanTable.getBeanType());
beanTable.setBaseTable(tableName.getQualifiedName());
}
}
@@ -1,244 +1,225 @@
/**
* Copyright (C) 2006 Robin Bygrave
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy.parse;
import javax.persistence.Embeddable;
import javax.persistence.Entity;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import com.avaje.ebean.Query.UseIndex;
import com.avaje.ebean.annotation.CacheStrategy;
import com.avaje.ebean.annotation.LdapDomain;
import com.avaje.ebean.annotation.NamedUpdate;
import com.avaje.ebean.annotation.NamedUpdates;
import com.avaje.ebean.annotation.UpdateMode;
import com.avaje.ebean.config.TableName;
import com.avaje.ebeaninternal.server.core.CacheOptions;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor.EntityType;
import com.avaje.ebeaninternal.server.deploy.CompoundUniqueContraint;
import com.avaje.ebeaninternal.server.deploy.DeployNamedQuery;
import com.avaje.ebeaninternal.server.deploy.DeployNamedUpdate;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
/**
* Read the class level deployment annotations.
*/
public class AnnotationClass extends AnnotationParser {
public AnnotationClass(DeployBeanInfo<?> info) {
super(info);
}
/**
* Read the class level deployment annotations.
*/
public void parse() {
read(descriptor.getBeanType());
setTableName();
}
/**
* Set the table name if it has not already been set.
*/
private void setTableName() {
if (descriptor.isBaseTableType()) {
// default the TableName using NamingConvention.
TableName tableName = namingConvention.getTableName(descriptor.getBeanType());
descriptor.setBaseTable(tableName);
}
}
private String[] parseLdapObjectclasses(String objectclasses) {
if (objectclasses == null || objectclasses.length() == 0){
return null;
}
return objectclasses.split(",");
}
private boolean isXmlElement(Class<?> cls) {
XmlRootElement rootElement = cls.getAnnotation(XmlRootElement.class);
if (rootElement != null){
return true;
}
XmlType xmlType = cls.getAnnotation(XmlType.class);
if (xmlType != null){
return true;
}
return false;
}
private void read(Class<?> cls) {
LdapDomain ldapDomain = cls.getAnnotation(LdapDomain.class);
if (ldapDomain != null) {
descriptor.setName(cls.getSimpleName());
descriptor.setEntityType(EntityType.LDAP);
descriptor.setLdapBaseDn(ldapDomain.baseDn());
descriptor.setLdapObjectclasses(parseLdapObjectclasses(ldapDomain.objectclass()));
}
Entity entity = cls.getAnnotation(Entity.class);
if (entity != null){
//checkDefaultConstructor();
if (entity.name().equals("")) {
descriptor.setName(cls.getSimpleName());
} else {
descriptor.setName(entity.name());
}
} else if (isXmlElement(cls)) {
descriptor.setName(cls.getSimpleName());
descriptor.setEntityType(EntityType.XMLELEMENT);
}
Embeddable embeddable = cls.getAnnotation(Embeddable.class);
if (embeddable != null){
descriptor.setEntityType(EntityType.EMBEDDED);
descriptor.setName("Embeddable:"+cls.getSimpleName());
}
UniqueConstraint uc = cls.getAnnotation(UniqueConstraint.class);
if (uc != null){
descriptor.addCompoundUniqueConstraint(new CompoundUniqueContraint(uc.columnNames()));
}
Table table = cls.getAnnotation(Table.class);
if (table != null){
UniqueConstraint[] uniqueConstraints = table.uniqueConstraints();
if (uniqueConstraints != null){
for (UniqueConstraint c : uniqueConstraints) {
descriptor.addCompoundUniqueConstraint(new CompoundUniqueContraint(c.columnNames()));
}
}
}
UpdateMode updateMode = cls.getAnnotation(UpdateMode.class);
if (updateMode != null){
descriptor.setUpdateChangesOnly(updateMode.updateChangesOnly());
}
NamedQueries namedQueries = cls.getAnnotation(NamedQueries.class);
if (namedQueries != null){
readNamedQueries(namedQueries);
}
NamedQuery namedQuery = cls.getAnnotation(NamedQuery.class);
if (namedQuery != null){
readNamedQuery(namedQuery);
}
NamedUpdates namedUpdates = cls.getAnnotation(NamedUpdates.class);
if (namedUpdates != null){
readNamedUpdates(namedUpdates);
}
NamedUpdate namedUpdate = cls.getAnnotation(NamedUpdate.class);
if (namedUpdate != null){
readNamedUpdate(namedUpdate);
}
CacheStrategy cacheStrategy = cls.getAnnotation(CacheStrategy.class);
if (cacheStrategy != null){
readCacheStrategy(cacheStrategy);
}
}
private void readCacheStrategy(CacheStrategy cacheStrategy){
CacheOptions cacheOptions = descriptor.getCacheOptions();
cacheOptions.setUseCache(cacheStrategy.useBeanCache());
cacheOptions.setReadOnly(cacheStrategy.readOnly());
cacheOptions.setWarmingQuery(cacheStrategy.warmingQuery());
if (cacheStrategy.naturalKey().length() > 0){
String propName = cacheStrategy.naturalKey().trim();
DeployBeanProperty beanProperty = descriptor.getBeanProperty(propName);
if (beanProperty != null){
beanProperty.setNaturalKey(true);
cacheOptions.setNaturalKey(propName);
}
}
if (!UseIndex.DEFAULT.equals(cacheStrategy.useIndex())){
// a specific text index strategy has been defined
descriptor.setUseIndex(cacheStrategy.useIndex());
}
}
private void readNamedQueries(NamedQueries namedQueries) {
NamedQuery[] queries = namedQueries.value();
for (int i = 0; i < queries.length; i++) {
readNamedQuery(queries[i]);
}
}
private void readNamedQuery(NamedQuery namedQuery) {
DeployNamedQuery q = new DeployNamedQuery(namedQuery);
descriptor.add(q);
}
private void readNamedUpdates(NamedUpdates updates) {
NamedUpdate[] updateArray = updates.value();
for (int i = 0; i < updateArray.length; i++) {
readNamedUpdate(updateArray[i]);
}
}
private void readNamedUpdate(NamedUpdate update) {
DeployNamedUpdate upd = new DeployNamedUpdate(update);
descriptor.add(upd);
}
// /**
// * Check to see if the Entity bean has a default constructor.
// * <p>
// * If it does not then it is expected that this entity bean has an
// * associated BeanFinder.
// * </p>
// */
// private void checkDefaultConstructor() {
//
// Class<?> beanType = descriptor.getBeanType();
//
// Constructor<?> defaultConstructor;
// try {
// defaultConstructor = beanType.getConstructor((Class[]) null);
// if (defaultConstructor == null) {
// String m = "No default constructor on "+beanType;
// throw new PersistenceException(m);
// }
// } catch (SecurityException e) {
// String m = "Error checking for default constructor on "+beanType;
// throw new PersistenceException(m, e);
//
// } catch (NoSuchMethodException e) {
// String m = "No default constructor on "+beanType;
// throw new PersistenceException(m);
// }
// }
}
package com.avaje.ebeaninternal.server.deploy.parse;
import javax.persistence.Embeddable;
import javax.persistence.Entity;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import com.avaje.ebean.Query.UseIndex;
import com.avaje.ebean.annotation.CacheStrategy;
import com.avaje.ebean.annotation.LdapDomain;
import com.avaje.ebean.annotation.NamedUpdate;
import com.avaje.ebean.annotation.NamedUpdates;
import com.avaje.ebean.annotation.UpdateMode;
import com.avaje.ebean.config.TableName;
import com.avaje.ebeaninternal.server.core.CacheOptions;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor.EntityType;
import com.avaje.ebeaninternal.server.deploy.CompoundUniqueContraint;
import com.avaje.ebeaninternal.server.deploy.DeployNamedQuery;
import com.avaje.ebeaninternal.server.deploy.DeployNamedUpdate;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
/**
* Read the class level deployment annotations.
*/
public class AnnotationClass extends AnnotationParser {
public AnnotationClass(DeployBeanInfo<?> info) {
super(info);
}
/**
* Read the class level deployment annotations.
*/
public void parse() {
read(descriptor.getBeanType());
setTableName();
}
/**
* Set the table name if it has not already been set.
*/
private void setTableName() {
if (descriptor.isBaseTableType()) {
// default the TableName using NamingConvention.
TableName tableName = namingConvention.getTableName(descriptor.getBeanType());
descriptor.setBaseTable(tableName);
}
}
private String[] parseLdapObjectclasses(String objectclasses) {
if (objectclasses == null || objectclasses.length() == 0){
return null;
}
return objectclasses.split(",");
}
private boolean isXmlElement(Class<?> cls) {
XmlRootElement rootElement = cls.getAnnotation(XmlRootElement.class);
if (rootElement != null){
return true;
}
XmlType xmlType = cls.getAnnotation(XmlType.class);
if (xmlType != null){
return true;
}
return false;
}
private void read(Class<?> cls) {
LdapDomain ldapDomain = cls.getAnnotation(LdapDomain.class);
if (ldapDomain != null) {
descriptor.setName(cls.getSimpleName());
descriptor.setEntityType(EntityType.LDAP);
descriptor.setLdapBaseDn(ldapDomain.baseDn());
descriptor.setLdapObjectclasses(parseLdapObjectclasses(ldapDomain.objectclass()));
}
Entity entity = cls.getAnnotation(Entity.class);
if (entity != null){
//checkDefaultConstructor();
if (entity.name().equals("")) {
descriptor.setName(cls.getSimpleName());
} else {
descriptor.setName(entity.name());
}
} else if (isXmlElement(cls)) {
descriptor.setName(cls.getSimpleName());
descriptor.setEntityType(EntityType.XMLELEMENT);
}
Embeddable embeddable = cls.getAnnotation(Embeddable.class);
if (embeddable != null){
descriptor.setEntityType(EntityType.EMBEDDED);
descriptor.setName("Embeddable:"+cls.getSimpleName());
}
UniqueConstraint uc = cls.getAnnotation(UniqueConstraint.class);
if (uc != null){
descriptor.addCompoundUniqueConstraint(new CompoundUniqueContraint(uc.columnNames()));
}
Table table = cls.getAnnotation(Table.class);
if (table != null){
UniqueConstraint[] uniqueConstraints = table.uniqueConstraints();
if (uniqueConstraints != null){
for (UniqueConstraint c : uniqueConstraints) {
descriptor.addCompoundUniqueConstraint(new CompoundUniqueContraint(c.columnNames()));
}
}
}
UpdateMode updateMode = cls.getAnnotation(UpdateMode.class);
if (updateMode != null){
descriptor.setUpdateChangesOnly(updateMode.updateChangesOnly());
}
NamedQueries namedQueries = cls.getAnnotation(NamedQueries.class);
if (namedQueries != null){
readNamedQueries(namedQueries);
}
NamedQuery namedQuery = cls.getAnnotation(NamedQuery.class);
if (namedQuery != null){
readNamedQuery(namedQuery);
}
NamedUpdates namedUpdates = cls.getAnnotation(NamedUpdates.class);
if (namedUpdates != null){
readNamedUpdates(namedUpdates);
}
NamedUpdate namedUpdate = cls.getAnnotation(NamedUpdate.class);
if (namedUpdate != null){
readNamedUpdate(namedUpdate);
}
CacheStrategy cacheStrategy = cls.getAnnotation(CacheStrategy.class);
if (cacheStrategy != null){
readCacheStrategy(cacheStrategy);
}
}
private void readCacheStrategy(CacheStrategy cacheStrategy){
CacheOptions cacheOptions = descriptor.getCacheOptions();
cacheOptions.setUseCache(cacheStrategy.useBeanCache());
cacheOptions.setReadOnly(cacheStrategy.readOnly());
cacheOptions.setWarmingQuery(cacheStrategy.warmingQuery());
if (cacheStrategy.naturalKey().length() > 0){
String propName = cacheStrategy.naturalKey().trim();
DeployBeanProperty beanProperty = descriptor.getBeanProperty(propName);
if (beanProperty != null){
beanProperty.setNaturalKey(true);
cacheOptions.setNaturalKey(propName);
}
}
if (!UseIndex.DEFAULT.equals(cacheStrategy.useIndex())){
// a specific text index strategy has been defined
descriptor.setUseIndex(cacheStrategy.useIndex());
}
}
private void readNamedQueries(NamedQueries namedQueries) {
NamedQuery[] queries = namedQueries.value();
for (int i = 0; i < queries.length; i++) {
readNamedQuery(queries[i]);
}
}
private void readNamedQuery(NamedQuery namedQuery) {
DeployNamedQuery q = new DeployNamedQuery(namedQuery);
descriptor.add(q);
}
private void readNamedUpdates(NamedUpdates updates) {
NamedUpdate[] updateArray = updates.value();
for (int i = 0; i < updateArray.length; i++) {
readNamedUpdate(updateArray[i]);
}
}
private void readNamedUpdate(NamedUpdate update) {
DeployNamedUpdate upd = new DeployNamedUpdate(update);
descriptor.add(upd);
}
// /**
// * Check to see if the Entity bean has a default constructor.
// * <p>
// * If it does not then it is expected that this entity bean has an
// * associated BeanFinder.
// * </p>
// */
// private void checkDefaultConstructor() {
//
// Class<?> beanType = descriptor.getBeanType();
//
// Constructor<?> defaultConstructor;
// try {
// defaultConstructor = beanType.getConstructor((Class[]) null);
// if (defaultConstructor == null) {
// String m = "No default constructor on "+beanType;
// throw new PersistenceException(m);
// }
// } catch (SecurityException e) {
// String m = "Error checking for default constructor on "+beanType;
// throw new PersistenceException(m, e);
//
// } catch (NoSuchMethodException e) {
// String m = "No default constructor on "+beanType;
// throw new PersistenceException(m);
// }
// }
}
File diff suppressed because it is too large Load Diff
@@ -1,85 +1,66 @@
/**
* Copyright (C) 2006 Robin Bygrave
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy.parse;
import javax.persistence.CascadeType;
import javax.persistence.PersistenceException;
import com.avaje.ebean.annotation.LdapAttribute;
import com.avaje.ebean.config.ldap.LdapAttributeAdapter;
import com.avaje.ebeaninternal.server.deploy.BeanCascadeInfo;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanDescriptor;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
/**
* Base class for reading deployment annotations.
*/
public abstract class AnnotationParser extends AnnotationBase {
protected final DeployBeanInfo<?> info;
protected final DeployBeanDescriptor<?> descriptor;
protected final Class<?> beanType;
public AnnotationParser(DeployBeanInfo<?> info){
super(info.getUtil());
this.info = info;
this.beanType = info.getDescriptor().getBeanType();
this.descriptor = info.getDescriptor();
}
/**
* read the deployment annotations.
*/
public abstract void parse();
/**
* Helper method to set cascade types to the CascadeInfo on BeanProperty.
*/
protected void setCascadeTypes(CascadeType[] cascadeTypes, BeanCascadeInfo cascadeInfo) {
if (cascadeTypes != null && cascadeTypes.length > 0) {
cascadeInfo.setTypes(cascadeTypes);
}
}
protected void readLdapAttribute(LdapAttribute ldapAttribute, DeployBeanProperty prop) {
if (!isEmpty(ldapAttribute.name())){
prop.setDbColumn(ldapAttribute.name());
}
prop.setDbInsertable(ldapAttribute.insertable());
prop.setDbUpdateable(ldapAttribute.updatable());
Class<?> adapterCls = ldapAttribute.adapter();
if (adapterCls != null && !void.class.equals(adapterCls)){
try {
LdapAttributeAdapter adapter = (LdapAttributeAdapter)adapterCls.newInstance();
prop.setLdapAttributeAdapter(adapter);
} catch (Exception e){
String msg= "Error creating LdapAttributeAdapter for ["+prop.getFullBeanName()+"] "
+"with class ["+adapterCls+"] using the default constructor.";
throw new PersistenceException(msg, e);
}
}
}
}
package com.avaje.ebeaninternal.server.deploy.parse;
import javax.persistence.CascadeType;
import javax.persistence.PersistenceException;
import com.avaje.ebean.annotation.LdapAttribute;
import com.avaje.ebean.config.ldap.LdapAttributeAdapter;
import com.avaje.ebeaninternal.server.deploy.BeanCascadeInfo;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanDescriptor;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
/**
* Base class for reading deployment annotations.
*/
public abstract class AnnotationParser extends AnnotationBase {
protected final DeployBeanInfo<?> info;
protected final DeployBeanDescriptor<?> descriptor;
protected final Class<?> beanType;
public AnnotationParser(DeployBeanInfo<?> info){
super(info.getUtil());
this.info = info;
this.beanType = info.getDescriptor().getBeanType();
this.descriptor = info.getDescriptor();
}
/**
* read the deployment annotations.
*/
public abstract void parse();
/**
* Helper method to set cascade types to the CascadeInfo on BeanProperty.
*/
protected void setCascadeTypes(CascadeType[] cascadeTypes, BeanCascadeInfo cascadeInfo) {
if (cascadeTypes != null && cascadeTypes.length > 0) {
cascadeInfo.setTypes(cascadeTypes);
}
}
protected void readLdapAttribute(LdapAttribute ldapAttribute, DeployBeanProperty prop) {
if (!isEmpty(ldapAttribute.name())){
prop.setDbColumn(ldapAttribute.name());
}
prop.setDbInsertable(ldapAttribute.insertable());
prop.setDbUpdateable(ldapAttribute.updatable());
Class<?> adapterCls = ldapAttribute.adapter();
if (adapterCls != null && !void.class.equals(adapterCls)){
try {
LdapAttributeAdapter adapter = (LdapAttributeAdapter)adapterCls.newInstance();
prop.setLdapAttributeAdapter(adapter);
} catch (Exception e){
String msg= "Error creating LdapAttributeAdapter for ["+prop.getFullBeanName()+"] "
+"with class ["+adapterCls+"] using the default constructor.";
throw new PersistenceException(msg, e);
}
}
}
}
@@ -1,61 +1,42 @@
/**
* Copyright (C) 2006 Robin Bygrave
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy.parse;
import com.avaje.ebean.annotation.Sql;
import com.avaje.ebean.annotation.SqlSelect;
import com.avaje.ebeaninternal.server.deploy.DRawSqlMeta;
/**
* Read the class level deployment annotations.
*/
public class AnnotationSql extends AnnotationParser {
public AnnotationSql(DeployBeanInfo<?> info) {
super(info);
}
public void parse() {
Class<?> cls = descriptor.getBeanType();
Sql sql = cls.getAnnotation(Sql.class);
if (sql != null){
setSql(sql);
}
SqlSelect sqlSelect = cls.getAnnotation(SqlSelect.class);
if (sqlSelect != null){
setSqlSelect(sqlSelect);
}
}
private void setSql(Sql sql) {
SqlSelect[] select = sql.select();
for (int i = 0; i < select.length; i++) {
setSqlSelect(select[i]);
}
}
private void setSqlSelect(SqlSelect sqlSelect) {
DRawSqlMeta rawSqlMeta = new DRawSqlMeta(sqlSelect);
descriptor.add(rawSqlMeta);
}
}
package com.avaje.ebeaninternal.server.deploy.parse;
import com.avaje.ebean.annotation.Sql;
import com.avaje.ebean.annotation.SqlSelect;
import com.avaje.ebeaninternal.server.deploy.DRawSqlMeta;
/**
* Read the class level deployment annotations.
*/
public class AnnotationSql extends AnnotationParser {
public AnnotationSql(DeployBeanInfo<?> info) {
super(info);
}
public void parse() {
Class<?> cls = descriptor.getBeanType();
Sql sql = cls.getAnnotation(Sql.class);
if (sql != null){
setSql(sql);
}
SqlSelect sqlSelect = cls.getAnnotation(SqlSelect.class);
if (sqlSelect != null){
setSqlSelect(sqlSelect);
}
}
private void setSql(Sql sql) {
SqlSelect[] select = sql.select();
for (int i = 0; i < select.length; i++) {
setSqlSelect(select[i]);
}
}
private void setSqlSelect(SqlSelect sqlSelect) {
DRawSqlMeta rawSqlMeta = new DRawSqlMeta(sqlSelect);
descriptor.add(rawSqlMeta);
}
}
@@ -1,102 +1,83 @@
/**
* Copyright (C) 2006 Robin Bygrave
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy.parse;
import java.util.HashMap;
import com.avaje.ebeaninternal.server.deploy.TableJoin;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanDescriptor;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocOne;
import com.avaje.ebeaninternal.server.deploy.meta.DeployTableJoin;
/**
* Wraps information about a bean during deployment parsing.
*/
public class DeployBeanInfo<T> {
/**
* Holds TableJoins for secondary table properties.
*/
private final HashMap<String,DeployTableJoin> tableJoinMap = new HashMap<String, DeployTableJoin>();
private final DeployUtil util;
private final DeployBeanDescriptor<T> descriptor;
/**
* Create with a DeployUtil and BeanDescriptor.
*/
public DeployBeanInfo(DeployUtil util, DeployBeanDescriptor<T> descriptor) {
this.util = util;
this.descriptor = descriptor;
}
public String toString() {
return ""+descriptor;
}
/**
* Return the BeanDescriptor currently being processed.
*/
public DeployBeanDescriptor<T> getDescriptor() {
return descriptor;
}
/**
* Return the DeployUtil we are using.
*/
public DeployUtil getUtil() {
return util;
}
/**
* Appropriate TableJoin for a property mapped to a secondary table.
*/
public DeployTableJoin getTableJoin(String tableName) {
String key = tableName.toLowerCase();
DeployTableJoin tableJoin = (DeployTableJoin) tableJoinMap.get(key);
if (tableJoin == null) {
tableJoin = new DeployTableJoin();
tableJoin.setTable(tableName);
tableJoin.setType(TableJoin.JOIN);
descriptor.addTableJoin(tableJoin);
tableJoinMap.put(key, tableJoin);
}
return tableJoin;
}
/**
* Set a the join alias for a assoc one property.
*/
public void setBeanJoinType(DeployBeanPropertyAssocOne<?> beanProp, boolean outerJoin) {
String joinType = TableJoin.JOIN;
if (outerJoin){// && util.isUseOneToOneOptional()) {
joinType = TableJoin.LEFT_OUTER;
}
DeployTableJoin tableJoin = beanProp.getTableJoin();
tableJoin.setType(joinType);
}
}
package com.avaje.ebeaninternal.server.deploy.parse;
import java.util.HashMap;
import com.avaje.ebeaninternal.server.deploy.TableJoin;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanDescriptor;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocOne;
import com.avaje.ebeaninternal.server.deploy.meta.DeployTableJoin;
/**
* Wraps information about a bean during deployment parsing.
*/
public class DeployBeanInfo<T> {
/**
* Holds TableJoins for secondary table properties.
*/
private final HashMap<String,DeployTableJoin> tableJoinMap = new HashMap<String, DeployTableJoin>();
private final DeployUtil util;
private final DeployBeanDescriptor<T> descriptor;
/**
* Create with a DeployUtil and BeanDescriptor.
*/
public DeployBeanInfo(DeployUtil util, DeployBeanDescriptor<T> descriptor) {
this.util = util;
this.descriptor = descriptor;
}
public String toString() {
return ""+descriptor;
}
/**
* Return the BeanDescriptor currently being processed.
*/
public DeployBeanDescriptor<T> getDescriptor() {
return descriptor;
}
/**
* Return the DeployUtil we are using.
*/
public DeployUtil getUtil() {
return util;
}
/**
* Appropriate TableJoin for a property mapped to a secondary table.
*/
public DeployTableJoin getTableJoin(String tableName) {
String key = tableName.toLowerCase();
DeployTableJoin tableJoin = (DeployTableJoin) tableJoinMap.get(key);
if (tableJoin == null) {
tableJoin = new DeployTableJoin();
tableJoin.setTable(tableName);
tableJoin.setType(TableJoin.JOIN);
descriptor.addTableJoin(tableJoin);
tableJoinMap.put(key, tableJoin);
}
return tableJoin;
}
/**
* Set a the join alias for a assoc one property.
*/
public void setBeanJoinType(DeployBeanPropertyAssocOne<?> beanProp, boolean outerJoin) {
String joinType = TableJoin.JOIN;
if (outerJoin){// && util.isUseOneToOneOptional()) {
joinType = TableJoin.LEFT_OUTER;
}
DeployTableJoin tableJoin = beanProp.getTableJoin();
tableJoin.setType(joinType);
}
}
@@ -1,435 +1,416 @@
/**
* Copyright (C) 2006 Robin Bygrave
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy.parse;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.persistence.PersistenceException;
import javax.persistence.Transient;
import com.avaje.ebean.config.ScalarTypeConverter;
import com.avaje.ebeaninternal.server.core.Message;
import com.avaje.ebeaninternal.server.deploy.DetermineManyType;
import com.avaje.ebeaninternal.server.deploy.ManyType;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanDescriptor;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocMany;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocOne;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyCompound;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertySimpleCollection;
import com.avaje.ebeaninternal.server.type.CtCompoundType;
import com.avaje.ebeaninternal.server.type.ScalaOptionTypeConverter;
import com.avaje.ebeaninternal.server.type.ScalarType;
import com.avaje.ebeaninternal.server.type.TypeManager;
import com.avaje.ebeaninternal.server.type.reflect.CheckImmutableResponse;
/**
* Create the properties for a bean.
* <p>
* This also needs to determine if the property is a associated many, associated
* one or normal scalar property.
* </p>
*/
public class DeployCreateProperties {
private static final Logger logger = Logger.getLogger(DeployCreateProperties.class.getName());
private final Class<?> scalaOptionClass;
/**
* Use to wrap and unwrap Scala Option.
*/
@SuppressWarnings("rawtypes")
private final ScalarTypeConverter scalaOptionTypeConverter;
private final DetermineManyType determineManyType;
private final TypeManager typeManager;
@SuppressWarnings("rawtypes")
public DeployCreateProperties(TypeManager typeManager) {
this.typeManager = typeManager;
Class<?> tmpOptionClass = DetectScala.getScalaOptionClass();
if (tmpOptionClass == null){
scalaOptionClass = null;
scalaOptionTypeConverter = null;
} else {
scalaOptionClass = tmpOptionClass;
scalaOptionTypeConverter = new ScalaOptionTypeConverter();
}
this.determineManyType = new DetermineManyType(tmpOptionClass != null);
}
/**
* Create the appropriate properties for a bean.
*/
public void createProperties(DeployBeanDescriptor<?> desc) {
createProperties(desc, desc.getBeanType(), 0);
desc.sortProperties();
// check the transient properties...
Iterator<DeployBeanProperty> it = desc.propertiesAll();
while (it.hasNext()) {
DeployBeanProperty prop = it.next();
if (prop.isTransient()){
if (prop.getWriteMethod() == null || prop.getReadMethod() == null){
// Typically a helper method ... this is expected
logger.finest("... transient: "+prop.getFullBeanName());
} else {
// dubious, possible error...
String msg = Message.msg("deploy.property.nofield", desc.getFullName(), prop.getName());
logger.warning(msg);
}
}
}
}
/**
* Return true if we should ignore this field.
* <p>
* We want to ignore ebean internal fields and some others as well.
* </p>
*/
private boolean ignoreFieldByName(String fieldName) {
if (fieldName.startsWith("_ebean_")){
// ignore Ebean internal fields
return true;
}
if (fieldName.startsWith("ajc$instance$")) {
// ignore AspectJ internal fields
return true;
}
// we are interested in this field
return false;
}
/**
* reflect the bean properties from Class. Some of these properties may not
* map to database columns.
*/
private void createProperties(DeployBeanDescriptor<?> desc, Class<?> beanType, int level) {
boolean scalaObject = desc.isScalaObject();
try {
Method[] declaredMethods = beanType.getDeclaredMethods();
Field[] fields = beanType.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
if (Modifier.isStatic(field.getModifiers())) {
// not interested in static fields
} else if (Modifier.isTransient(field.getModifiers())) {
// not interested in transient fields
logger.finer("Skipping transient field "+field.getName()+" in "+beanType.getName());
} else if (ignoreFieldByName(field.getName())) {
// not interested this field (ebean or aspectJ field)
} else {
String fieldName = getFieldName(field, beanType);
String initFieldName = initCap(fieldName);
Method getter = findGetter(field, initFieldName, declaredMethods, scalaObject);
Method setter = findSetter(field, initFieldName, declaredMethods, scalaObject);
DeployBeanProperty prop = createProp(level, desc, field, beanType, getter, setter);
if (prop == null){
// transient annotation on unsupported type
} else {
// set a order that gives priority to inherited properties
// push Id/EmbeddedId up and CreatedTimestamp/UpdatedTimestamp down
int sortOverride = prop.getSortOverride();
prop.setSortOrder((level*10000+100-i + sortOverride));
DeployBeanProperty replaced = desc.addBeanProperty(prop);
if (replaced != null){
if (replaced.isTransient()) {
// expected for inheritance...
} else {
String msg = "Huh??? property "+prop.getFullBeanName()+" being defined twice";
msg += " but replaced property was not transient? This is not expected?";
logger.warning(msg);
}
}
}
}
}
Class<?> superClass = beanType.getSuperclass();
if (!superClass.equals(Object.class)) {
// recursively add any properties in the inheritance heirarchy
// up to the Object.class level...
createProperties(desc, superClass, level + 1);
}
} catch (PersistenceException ex) {
throw ex;
} catch (Exception ex) {
throw new PersistenceException(ex);
}
}
/**
* Make the first letter of the string upper case.
*/
private String initCap(String str){
if (str.length() > 1){
return Character.toUpperCase(str.charAt(0))+str.substring(1);
} else {
// only a single char
return str.toUpperCase();
}
}
/**
* Return the bean spec field name (trim of "is" from boolean types)
*/
private String getFieldName(Field field, Class<?> beanType){
String name = field.getName();
if ((Boolean.class.equals(field.getType()) || boolean.class.equals(field.getType()))
&& name.startsWith("is") && name.length() > 2){
// it is a boolean type field starting with "is"
char c = name.charAt(2);
if (Character.isUpperCase(c)){
String msg = "trimming off 'is' from boolean field name "+name+" in class "+beanType.getName();
logger.log(Level.INFO, msg);
return name.substring(2);
}
}
return name;
}
/**
* Find a public non-static getter method that matches this field (according to bean-spec rules).
*/
private Method findGetter(Field field, String initFieldName, Method[] declaredMethods, boolean scalaObject){
String methGetName = "get"+initFieldName;
String methIsName = "is"+initFieldName;
String scalaGet = field.getName();
for (int i = 0; i < declaredMethods.length; i++) {
Method m = declaredMethods[i];
if ((scalaObject && m.getName().equals(scalaGet))
|| m.getName().equals(methGetName) || m.getName().equals(methIsName)){
Class<?>[] params = m.getParameterTypes();
if (params.length == 0){
if (field.getType().equals(m.getReturnType())){
int modifiers = m.getModifiers();
if (Modifier.isPublic(modifiers) && !Modifier.isStatic(modifiers)) {
// we find it...
return m;
}
}
}
}
}
return null;
}
/**
* Find a public non-static setter method that matches this field (according to bean-spec rules).
*/
private Method findSetter(Field field, String initFieldName, Method[] declaredMethods, boolean scalaObject){
String methSetName = "set"+initFieldName;
String scalaSetName = field.getName()+"_$eq";
for (int i = 0; i < declaredMethods.length; i++) {
Method m = declaredMethods[i];
if ((scalaObject && m.getName().equals(scalaSetName))
|| m.getName().equals(methSetName)){
Class<?>[] params = m.getParameterTypes();
if (params.length == 1 && field.getType().equals(params[0])){
if (void.class.equals(m.getReturnType())){
int modifiers = m.getModifiers();
if (Modifier.isPublic(modifiers) && !Modifier.isStatic(modifiers)) {
return m;
}
}
}
}
}
return null;
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private DeployBeanProperty createManyType(DeployBeanDescriptor<?> desc, Class<?> targetType, ManyType manyType) {
ScalarType<?> scalarType = typeManager.getScalarType(targetType);
if (scalarType != null) {
return new DeployBeanPropertySimpleCollection(desc, targetType, scalarType, manyType);
}
//TODO: Handle Collection of CompoundType and Embedded Type
return new DeployBeanPropertyAssocMany(desc, targetType, manyType);
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private DeployBeanProperty createProp(DeployBeanDescriptor<?> desc, Field field) {
Class<?> propertyType = field.getType();
Class<?> innerType = propertyType;
ScalarTypeConverter<?, ?> typeConverter = null;
if (propertyType.equals(scalaOptionClass)){
innerType = determineTargetType(field);
typeConverter = scalaOptionTypeConverter;
}
// check for Collection type (list, set or map)
ManyType manyType = determineManyType.getManyType(propertyType);
if (manyType != null) {
// List, Set or Map based object
Class<?> targetType = determineTargetType(field);
if (targetType == null){
Transient transAnnotation = field.getAnnotation(Transient.class);
if (transAnnotation != null) {
// not supporting this field (generic type used)
return null;
}
logger.warning("Could not find parameter type (via reflection) on "+desc.getFullName()+" "+field.getName());
}
return createManyType(desc, targetType, manyType);
}
if (innerType.isEnum() || innerType.isPrimitive()){
return new DeployBeanProperty(desc, propertyType, null, typeConverter);
}
ScalarType<?> scalarType = typeManager.getScalarType(innerType);
if (scalarType != null) {
return new DeployBeanProperty(desc, propertyType, scalarType, typeConverter);
}
CtCompoundType<?> compoundType = typeManager.getCompoundType(innerType);
if (compoundType != null) {
return new DeployBeanPropertyCompound(desc, propertyType, compoundType, typeConverter);
}
if (!isTransientField(field)){
try {
CheckImmutableResponse checkImmutable = typeManager.checkImmutable(innerType);
if (checkImmutable.isImmutable()){
if (checkImmutable.isCompoundType()){
// use reflection to support compound immutable value objects
typeManager.recursiveCreateScalarDataReader(innerType);
compoundType = typeManager.getCompoundType(innerType);
if (compoundType != null) {
return new DeployBeanPropertyCompound(desc, propertyType, compoundType, typeConverter);
}
} else {
// use reflection to support simple immutable value objects
scalarType = typeManager.recursiveCreateScalarTypes(innerType);
return new DeployBeanProperty(desc, propertyType, scalarType, typeConverter);
}
}
} catch (Exception e){
logger.log(Level.SEVERE, "Error with "+desc+" field:"+field.getName(), e);
}
}
return new DeployBeanPropertyAssocOne(desc, propertyType);
}
private boolean isTransientField(Field field) {
Transient t = field.getAnnotation(Transient.class);
return (t != null);
}
private DeployBeanProperty createProp(int level, DeployBeanDescriptor<?> desc, Field field, Class<?> beanType, Method getter, Method setter) {
DeployBeanProperty prop = createProp(desc, field);
if (prop == null){
// transient annotation on unsupported type
return null;
} else {
prop.setOwningType(beanType);
prop.setName(field.getName());
// the getter or setter could be null if we are using
// javaagent type enhancement. If we are using subclass
// generation then we do need to find the getter and setter
prop.setReadMethod(getter);
prop.setWriteMethod(setter);
prop.setField(field);
return prop;
}
}
/**
* Determine the type of the List,Set or Map. Not been set explicitly so
* determine this from ParameterizedType.
*/
private Class<?> determineTargetType(Field field) {
Type genType = field.getGenericType();
if (genType instanceof ParameterizedType) {
ParameterizedType ptype = (ParameterizedType) genType;
Type[] typeArgs = ptype.getActualTypeArguments();
if (typeArgs.length == 1) {
// probably a Set or List
if (typeArgs[0] instanceof Class<?>){
return (Class<?>) typeArgs[0];
}
throw new RuntimeException("Unexpected Parameterised Type? "+typeArgs[0]);
}
if (typeArgs.length == 2) {
// this is probably a Map
if (typeArgs[1] instanceof ParameterizedType) {
// not supporting ParameterizedType on Map.
return null;
}
return (Class<?>) typeArgs[1];
}
}
// if targetType is null, then must be set in annotations
return null;
}
}
package com.avaje.ebeaninternal.server.deploy.parse;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.persistence.PersistenceException;
import javax.persistence.Transient;
import com.avaje.ebean.config.ScalarTypeConverter;
import com.avaje.ebeaninternal.server.core.Message;
import com.avaje.ebeaninternal.server.deploy.DetermineManyType;
import com.avaje.ebeaninternal.server.deploy.ManyType;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanDescriptor;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocMany;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocOne;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyCompound;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertySimpleCollection;
import com.avaje.ebeaninternal.server.type.CtCompoundType;
import com.avaje.ebeaninternal.server.type.ScalaOptionTypeConverter;
import com.avaje.ebeaninternal.server.type.ScalarType;
import com.avaje.ebeaninternal.server.type.TypeManager;
import com.avaje.ebeaninternal.server.type.reflect.CheckImmutableResponse;
/**
* Create the properties for a bean.
* <p>
* This also needs to determine if the property is a associated many, associated
* one or normal scalar property.
* </p>
*/
public class DeployCreateProperties {
private static final Logger logger = Logger.getLogger(DeployCreateProperties.class.getName());
private final Class<?> scalaOptionClass;
/**
* Use to wrap and unwrap Scala Option.
*/
@SuppressWarnings("rawtypes")
private final ScalarTypeConverter scalaOptionTypeConverter;
private final DetermineManyType determineManyType;
private final TypeManager typeManager;
@SuppressWarnings("rawtypes")
public DeployCreateProperties(TypeManager typeManager) {
this.typeManager = typeManager;
Class<?> tmpOptionClass = DetectScala.getScalaOptionClass();
if (tmpOptionClass == null){
scalaOptionClass = null;
scalaOptionTypeConverter = null;
} else {
scalaOptionClass = tmpOptionClass;
scalaOptionTypeConverter = new ScalaOptionTypeConverter();
}
this.determineManyType = new DetermineManyType(tmpOptionClass != null);
}
/**
* Create the appropriate properties for a bean.
*/
public void createProperties(DeployBeanDescriptor<?> desc) {
createProperties(desc, desc.getBeanType(), 0);
desc.sortProperties();
// check the transient properties...
Iterator<DeployBeanProperty> it = desc.propertiesAll();
while (it.hasNext()) {
DeployBeanProperty prop = it.next();
if (prop.isTransient()){
if (prop.getWriteMethod() == null || prop.getReadMethod() == null){
// Typically a helper method ... this is expected
logger.finest("... transient: "+prop.getFullBeanName());
} else {
// dubious, possible error...
String msg = Message.msg("deploy.property.nofield", desc.getFullName(), prop.getName());
logger.warning(msg);
}
}
}
}
/**
* Return true if we should ignore this field.
* <p>
* We want to ignore ebean internal fields and some others as well.
* </p>
*/
private boolean ignoreFieldByName(String fieldName) {
if (fieldName.startsWith("_ebean_")){
// ignore Ebean internal fields
return true;
}
if (fieldName.startsWith("ajc$instance$")) {
// ignore AspectJ internal fields
return true;
}
// we are interested in this field
return false;
}
/**
* reflect the bean properties from Class. Some of these properties may not
* map to database columns.
*/
private void createProperties(DeployBeanDescriptor<?> desc, Class<?> beanType, int level) {
boolean scalaObject = desc.isScalaObject();
try {
Method[] declaredMethods = beanType.getDeclaredMethods();
Field[] fields = beanType.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
if (Modifier.isStatic(field.getModifiers())) {
// not interested in static fields
} else if (Modifier.isTransient(field.getModifiers())) {
// not interested in transient fields
logger.finer("Skipping transient field "+field.getName()+" in "+beanType.getName());
} else if (ignoreFieldByName(field.getName())) {
// not interested this field (ebean or aspectJ field)
} else {
String fieldName = getFieldName(field, beanType);
String initFieldName = initCap(fieldName);
Method getter = findGetter(field, initFieldName, declaredMethods, scalaObject);
Method setter = findSetter(field, initFieldName, declaredMethods, scalaObject);
DeployBeanProperty prop = createProp(level, desc, field, beanType, getter, setter);
if (prop == null){
// transient annotation on unsupported type
} else {
// set a order that gives priority to inherited properties
// push Id/EmbeddedId up and CreatedTimestamp/UpdatedTimestamp down
int sortOverride = prop.getSortOverride();
prop.setSortOrder((level*10000+100-i + sortOverride));
DeployBeanProperty replaced = desc.addBeanProperty(prop);
if (replaced != null){
if (replaced.isTransient()) {
// expected for inheritance...
} else {
String msg = "Huh??? property "+prop.getFullBeanName()+" being defined twice";
msg += " but replaced property was not transient? This is not expected?";
logger.warning(msg);
}
}
}
}
}
Class<?> superClass = beanType.getSuperclass();
if (!superClass.equals(Object.class)) {
// recursively add any properties in the inheritance heirarchy
// up to the Object.class level...
createProperties(desc, superClass, level + 1);
}
} catch (PersistenceException ex) {
throw ex;
} catch (Exception ex) {
throw new PersistenceException(ex);
}
}
/**
* Make the first letter of the string upper case.
*/
private String initCap(String str){
if (str.length() > 1){
return Character.toUpperCase(str.charAt(0))+str.substring(1);
} else {
// only a single char
return str.toUpperCase();
}
}
/**
* Return the bean spec field name (trim of "is" from boolean types)
*/
private String getFieldName(Field field, Class<?> beanType){
String name = field.getName();
if ((Boolean.class.equals(field.getType()) || boolean.class.equals(field.getType()))
&& name.startsWith("is") && name.length() > 2){
// it is a boolean type field starting with "is"
char c = name.charAt(2);
if (Character.isUpperCase(c)){
String msg = "trimming off 'is' from boolean field name "+name+" in class "+beanType.getName();
logger.log(Level.INFO, msg);
return name.substring(2);
}
}
return name;
}
/**
* Find a public non-static getter method that matches this field (according to bean-spec rules).
*/
private Method findGetter(Field field, String initFieldName, Method[] declaredMethods, boolean scalaObject){
String methGetName = "get"+initFieldName;
String methIsName = "is"+initFieldName;
String scalaGet = field.getName();
for (int i = 0; i < declaredMethods.length; i++) {
Method m = declaredMethods[i];
if ((scalaObject && m.getName().equals(scalaGet))
|| m.getName().equals(methGetName) || m.getName().equals(methIsName)){
Class<?>[] params = m.getParameterTypes();
if (params.length == 0){
if (field.getType().equals(m.getReturnType())){
int modifiers = m.getModifiers();
if (Modifier.isPublic(modifiers) && !Modifier.isStatic(modifiers)) {
// we find it...
return m;
}
}
}
}
}
return null;
}
/**
* Find a public non-static setter method that matches this field (according to bean-spec rules).
*/
private Method findSetter(Field field, String initFieldName, Method[] declaredMethods, boolean scalaObject){
String methSetName = "set"+initFieldName;
String scalaSetName = field.getName()+"_$eq";
for (int i = 0; i < declaredMethods.length; i++) {
Method m = declaredMethods[i];
if ((scalaObject && m.getName().equals(scalaSetName))
|| m.getName().equals(methSetName)){
Class<?>[] params = m.getParameterTypes();
if (params.length == 1 && field.getType().equals(params[0])){
if (void.class.equals(m.getReturnType())){
int modifiers = m.getModifiers();
if (Modifier.isPublic(modifiers) && !Modifier.isStatic(modifiers)) {
return m;
}
}
}
}
}
return null;
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private DeployBeanProperty createManyType(DeployBeanDescriptor<?> desc, Class<?> targetType, ManyType manyType) {
ScalarType<?> scalarType = typeManager.getScalarType(targetType);
if (scalarType != null) {
return new DeployBeanPropertySimpleCollection(desc, targetType, scalarType, manyType);
}
//TODO: Handle Collection of CompoundType and Embedded Type
return new DeployBeanPropertyAssocMany(desc, targetType, manyType);
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private DeployBeanProperty createProp(DeployBeanDescriptor<?> desc, Field field) {
Class<?> propertyType = field.getType();
Class<?> innerType = propertyType;
ScalarTypeConverter<?, ?> typeConverter = null;
if (propertyType.equals(scalaOptionClass)){
innerType = determineTargetType(field);
typeConverter = scalaOptionTypeConverter;
}
// check for Collection type (list, set or map)
ManyType manyType = determineManyType.getManyType(propertyType);
if (manyType != null) {
// List, Set or Map based object
Class<?> targetType = determineTargetType(field);
if (targetType == null){
Transient transAnnotation = field.getAnnotation(Transient.class);
if (transAnnotation != null) {
// not supporting this field (generic type used)
return null;
}
logger.warning("Could not find parameter type (via reflection) on "+desc.getFullName()+" "+field.getName());
}
return createManyType(desc, targetType, manyType);
}
if (innerType.isEnum() || innerType.isPrimitive()){
return new DeployBeanProperty(desc, propertyType, null, typeConverter);
}
ScalarType<?> scalarType = typeManager.getScalarType(innerType);
if (scalarType != null) {
return new DeployBeanProperty(desc, propertyType, scalarType, typeConverter);
}
CtCompoundType<?> compoundType = typeManager.getCompoundType(innerType);
if (compoundType != null) {
return new DeployBeanPropertyCompound(desc, propertyType, compoundType, typeConverter);
}
if (!isTransientField(field)){
try {
CheckImmutableResponse checkImmutable = typeManager.checkImmutable(innerType);
if (checkImmutable.isImmutable()){
if (checkImmutable.isCompoundType()){
// use reflection to support compound immutable value objects
typeManager.recursiveCreateScalarDataReader(innerType);
compoundType = typeManager.getCompoundType(innerType);
if (compoundType != null) {
return new DeployBeanPropertyCompound(desc, propertyType, compoundType, typeConverter);
}
} else {
// use reflection to support simple immutable value objects
scalarType = typeManager.recursiveCreateScalarTypes(innerType);
return new DeployBeanProperty(desc, propertyType, scalarType, typeConverter);
}
}
} catch (Exception e){
logger.log(Level.SEVERE, "Error with "+desc+" field:"+field.getName(), e);
}
}
return new DeployBeanPropertyAssocOne(desc, propertyType);
}
private boolean isTransientField(Field field) {
Transient t = field.getAnnotation(Transient.class);
return (t != null);
}
private DeployBeanProperty createProp(int level, DeployBeanDescriptor<?> desc, Field field, Class<?> beanType, Method getter, Method setter) {
DeployBeanProperty prop = createProp(desc, field);
if (prop == null){
// transient annotation on unsupported type
return null;
} else {
prop.setOwningType(beanType);
prop.setName(field.getName());
// the getter or setter could be null if we are using
// javaagent type enhancement. If we are using subclass
// generation then we do need to find the getter and setter
prop.setReadMethod(getter);
prop.setWriteMethod(setter);
prop.setField(field);
return prop;
}
}
/**
* Determine the type of the List,Set or Map. Not been set explicitly so
* determine this from ParameterizedType.
*/
private Class<?> determineTargetType(Field field) {
Type genType = field.getGenericType();
if (genType instanceof ParameterizedType) {
ParameterizedType ptype = (ParameterizedType) genType;
Type[] typeArgs = ptype.getActualTypeArguments();
if (typeArgs.length == 1) {
// probably a Set or List
if (typeArgs[0] instanceof Class<?>){
return (Class<?>) typeArgs[0];
}
throw new RuntimeException("Unexpected Parameterised Type? "+typeArgs[0]);
}
if (typeArgs.length == 2) {
// this is probably a Map
if (typeArgs[1] instanceof ParameterizedType) {
// not supporting ParameterizedType on Map.
return null;
}
return (Class<?>) typeArgs[1];
}
}
// if targetType is null, then must be set in annotations
return null;
}
}
@@ -1,196 +1,177 @@
/**
* Copyright (C) 2006 Robin Bygrave
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy.parse;
import java.lang.annotation.Annotation;
import java.sql.Types;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorType;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Inheritance;
import com.avaje.ebeaninternal.server.core.BootupClasses;
import com.avaje.ebeaninternal.server.deploy.InheritInfo;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanDescriptor;
/**
* Builds the InheritInfo deployment information.
*/
public class DeployInherit {
private final Map<Class<?>, DeployInheritInfo> deployMap = new LinkedHashMap<Class<?>, DeployInheritInfo>();
private final Map<Class<?>, InheritInfo> finalMap = new LinkedHashMap<Class<?>, InheritInfo>();
private final BootupClasses bootupClasses;
/**
* Create the InheritInfoDeploy.
*/
public DeployInherit(BootupClasses bootupClasses) {
this.bootupClasses = bootupClasses;
initialise();
}
public void process(DeployBeanDescriptor<?> desc) {
InheritInfo inheritInfo = finalMap.get(desc.getBeanType());
desc.setInheritInfo(inheritInfo);
}
private void initialise() {
List<Class<?>> entityList = bootupClasses.getEntities();
findInheritClasses(entityList);
buildDeployTree();
buildFinalTree();
}
private void findInheritClasses(List<Class<?>> entityList) {
// go through each class and initialise the info object...
Iterator<Class<?>> it = entityList.iterator();
while (it.hasNext()) {
Class<?> cls = (Class<?>) it.next();
if (isInheritanceClass(cls)) {
DeployInheritInfo info = createInfo(cls);
deployMap.put(cls, info);
}
}
}
private void buildDeployTree() {
Iterator<DeployInheritInfo> it = deployMap.values().iterator();
while (it.hasNext()) {
DeployInheritInfo info = it.next();
if (!info.isRoot()) {
DeployInheritInfo parent = getInfo(info.getParent());
parent.addChild(info);
}
}
}
private void buildFinalTree() {
Iterator<DeployInheritInfo> it = deployMap.values().iterator();
while (it.hasNext()) {
DeployInheritInfo deploy = it.next();
if (deploy.isRoot()) {
// build tree top down...
createFinalInfo(null, null, deploy);
}
}
}
private InheritInfo createFinalInfo(InheritInfo root, InheritInfo parent,
DeployInheritInfo deploy) {
InheritInfo node = new InheritInfo(root, parent, deploy);
if (parent != null) {
parent.addChild(node);
}
finalMap.put(node.getType(), node);
if (root == null) {
root = node;
}
// buildFinalChildren(root, child, deploy);
Iterator<DeployInheritInfo> it = deploy.children();
while (it.hasNext()) {
DeployInheritInfo childDeploy = it.next();
createFinalInfo(root, node, childDeploy);
}
return node;
}
/**
* Build the InheritInfo for a given class.
*/
private DeployInheritInfo getInfo(Class<?> cls) {
return deployMap.get(cls);
}
private DeployInheritInfo createInfo(Class<?> cls) {
DeployInheritInfo info = new DeployInheritInfo(cls);
Class<?> parent = findParent(cls);
if (parent != null) {
info.setParent(parent);
} else {
// its the root of inheritance tree...
}
Inheritance ia = (Inheritance) cls.getAnnotation(Inheritance.class);
if (ia != null) {
ia.strategy();
}
DiscriminatorColumn da = (DiscriminatorColumn) cls.getAnnotation(DiscriminatorColumn.class);
if (da != null) {
info.setDiscriminatorColumn(da.name());
DiscriminatorType discriminatorType = da.discriminatorType();
if (discriminatorType.equals(DiscriminatorType.INTEGER)){
info.setDiscriminatorType(Types.INTEGER);
} else {
info.setDiscriminatorType(Types.VARCHAR);
}
info.setDiscriminatorLength(da.length());
}
DiscriminatorValue dv = (DiscriminatorValue) cls.getAnnotation(DiscriminatorValue.class);
if (dv != null) {
info.setDiscriminatorValue(dv.value());
}
return info;
}
private Class<?> findParent(Class<?> cls) {
Class<?> superCls = cls.getSuperclass();
if (isInheritanceClass(superCls)) {
return superCls;
} else {
return null;
}
}
private boolean isInheritanceClass(Class<?> cls) {
if (cls.equals(Object.class)) {
return false;
}
Annotation a = cls.getAnnotation(Inheritance.class);
if (a != null) {
return true;
}
// search up the inheritance heirarchy
return isInheritanceClass(cls.getSuperclass());
}
}
package com.avaje.ebeaninternal.server.deploy.parse;
import java.lang.annotation.Annotation;
import java.sql.Types;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorType;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Inheritance;
import com.avaje.ebeaninternal.server.core.BootupClasses;
import com.avaje.ebeaninternal.server.deploy.InheritInfo;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanDescriptor;
/**
* Builds the InheritInfo deployment information.
*/
public class DeployInherit {
private final Map<Class<?>, DeployInheritInfo> deployMap = new LinkedHashMap<Class<?>, DeployInheritInfo>();
private final Map<Class<?>, InheritInfo> finalMap = new LinkedHashMap<Class<?>, InheritInfo>();
private final BootupClasses bootupClasses;
/**
* Create the InheritInfoDeploy.
*/
public DeployInherit(BootupClasses bootupClasses) {
this.bootupClasses = bootupClasses;
initialise();
}
public void process(DeployBeanDescriptor<?> desc) {
InheritInfo inheritInfo = finalMap.get(desc.getBeanType());
desc.setInheritInfo(inheritInfo);
}
private void initialise() {
List<Class<?>> entityList = bootupClasses.getEntities();
findInheritClasses(entityList);
buildDeployTree();
buildFinalTree();
}
private void findInheritClasses(List<Class<?>> entityList) {
// go through each class and initialise the info object...
Iterator<Class<?>> it = entityList.iterator();
while (it.hasNext()) {
Class<?> cls = (Class<?>) it.next();
if (isInheritanceClass(cls)) {
DeployInheritInfo info = createInfo(cls);
deployMap.put(cls, info);
}
}
}
private void buildDeployTree() {
Iterator<DeployInheritInfo> it = deployMap.values().iterator();
while (it.hasNext()) {
DeployInheritInfo info = it.next();
if (!info.isRoot()) {
DeployInheritInfo parent = getInfo(info.getParent());
parent.addChild(info);
}
}
}
private void buildFinalTree() {
Iterator<DeployInheritInfo> it = deployMap.values().iterator();
while (it.hasNext()) {
DeployInheritInfo deploy = it.next();
if (deploy.isRoot()) {
// build tree top down...
createFinalInfo(null, null, deploy);
}
}
}
private InheritInfo createFinalInfo(InheritInfo root, InheritInfo parent,
DeployInheritInfo deploy) {
InheritInfo node = new InheritInfo(root, parent, deploy);
if (parent != null) {
parent.addChild(node);
}
finalMap.put(node.getType(), node);
if (root == null) {
root = node;
}
// buildFinalChildren(root, child, deploy);
Iterator<DeployInheritInfo> it = deploy.children();
while (it.hasNext()) {
DeployInheritInfo childDeploy = it.next();
createFinalInfo(root, node, childDeploy);
}
return node;
}
/**
* Build the InheritInfo for a given class.
*/
private DeployInheritInfo getInfo(Class<?> cls) {
return deployMap.get(cls);
}
private DeployInheritInfo createInfo(Class<?> cls) {
DeployInheritInfo info = new DeployInheritInfo(cls);
Class<?> parent = findParent(cls);
if (parent != null) {
info.setParent(parent);
} else {
// its the root of inheritance tree...
}
Inheritance ia = (Inheritance) cls.getAnnotation(Inheritance.class);
if (ia != null) {
ia.strategy();
}
DiscriminatorColumn da = (DiscriminatorColumn) cls.getAnnotation(DiscriminatorColumn.class);
if (da != null) {
info.setDiscriminatorColumn(da.name());
DiscriminatorType discriminatorType = da.discriminatorType();
if (discriminatorType.equals(DiscriminatorType.INTEGER)){
info.setDiscriminatorType(Types.INTEGER);
} else {
info.setDiscriminatorType(Types.VARCHAR);
}
info.setDiscriminatorLength(da.length());
}
DiscriminatorValue dv = (DiscriminatorValue) cls.getAnnotation(DiscriminatorValue.class);
if (dv != null) {
info.setDiscriminatorValue(dv.value());
}
return info;
}
private Class<?> findParent(Class<?> cls) {
Class<?> superCls = cls.getSuperclass();
if (isInheritanceClass(superCls)) {
return superCls;
} else {
return null;
}
}
private boolean isInheritanceClass(Class<?> cls) {
if (cls.equals(Object.class)) {
return false;
}
Annotation a = cls.getAnnotation(Inheritance.class);
if (a != null) {
return true;
}
// search up the inheritance heirarchy
return isInheritanceClass(cls.getSuperclass());
}
}
@@ -1,283 +1,264 @@
/**
* Copyright (C) 2006 Robin Bygrave
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy.parse;
import java.sql.Types;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import com.avaje.ebeaninternal.server.deploy.InheritInfo;
/**
* Represents a node in the Inheritance tree.
* Holds information regarding Super Subclass support.
*/
public class DeployInheritInfo {
/**
* the default discriminator column according to the JPA 1.0 spec.
*/
private static final String JPA_DEFAULT_DISCRIM_COLUMN = "dtype";
private int discriminatorLength;
private int discriminatorType;
private String discriminatorStringValue;
private Object discriminatorObjectValue;
private String discriminatorColumn;
private String discriminatorWhere;
private Class<?> type;
private Class<?> parent;
private ArrayList<DeployInheritInfo> children = new ArrayList<DeployInheritInfo>();
/**
* Create for a given type.
*/
public DeployInheritInfo(Class<?> type){
this.type = type;
}
/**
* return the type.
*/
public Class<?> getType() {
return type;
}
/**
* Return the type of the root object.
*/
public Class<?> getParent() {
return parent;
}
/**
* Set the type of the root object.
*/
public void setParent(Class<?> parent) {
this.parent = parent;
}
/**
* Return true if this is abstract node.
*/
public boolean isAbstract() {
return (discriminatorObjectValue == null);
}
/**
* Return true if this is the root node.
*/
public boolean isRoot(){
return parent == null;
}
/**
* Return the child nodes.
*/
public Iterator<DeployInheritInfo> children() {
return children.iterator();
}
/**
* Add a child node.
*/
public void addChild(DeployInheritInfo childInfo){
children.add(childInfo);
}
/**
* Return the derived where for the discriminator.
*/
public String getDiscriminatorWhere() {
return discriminatorWhere;
}
/**
* Set the derived where for the discriminator.
*/
public void setDiscriminatorWhere(String discriminatorWhere) {
this.discriminatorWhere = discriminatorWhere;
}
/**
* Return the column name of the discriminator.
*/
public String getDiscriminatorColumn(InheritInfo parent) {
if (discriminatorColumn == null){
if (parent == null){
discriminatorColumn = JPA_DEFAULT_DISCRIM_COLUMN;
} else {
discriminatorColumn = parent.getDiscriminatorColumn();
}
}
return discriminatorColumn;
}
/**
* Set the column name of the discriminator.
*/
public void setDiscriminatorColumn(String discriminatorColumn) {
this.discriminatorColumn = discriminatorColumn;
}
public int getDiscriminatorLength(InheritInfo parent) {
if (discriminatorLength == 0){
if (parent == null){
discriminatorLength = 10;
} else {
discriminatorLength = parent.getDiscriminatorLength();
}
}
return discriminatorLength;
}
/**
* Return the sql type of the discriminator value.
*/
public int getDiscriminatorType(InheritInfo parent) {
if (discriminatorType == 0){
if (parent == null){
discriminatorType = Types.VARCHAR;
} else {
discriminatorType = parent.getDiscriminatorType();
}
}
return discriminatorType;
}
/**
* Set the sql type of the discriminator.
*/
public void setDiscriminatorType(int discriminatorType) {
this.discriminatorType = discriminatorType;
}
/**
* Return the length of the discriminator column.
*/
public int getDiscriminatorLength() {
return discriminatorLength;
}
/**
* Set the length of the discriminator column.
*/
public void setDiscriminatorLength(int discriminatorLength) {
this.discriminatorLength = discriminatorLength;
}
/**
* Return the discriminator value for this node.
*/
public Object getDiscriminatorObjectValue() {
return discriminatorObjectValue;
}
public String getDiscriminatorStringValue() {
return discriminatorStringValue;
}
/**
* Set the discriminator value for this node.
*/
public void setDiscriminatorValue(String value) {
if (value != null){
value = value.trim();
if (value.length() == 0){
value = null;
} else {
discriminatorStringValue = value;
// convert the value if desired
if (discriminatorType == Types.INTEGER){
this.discriminatorObjectValue = Integer.valueOf(value.toString());
} else {
this.discriminatorObjectValue = value;
}
}
}
}
public String getWhere() {
List<Object> discList = new ArrayList<Object>();
appendDiscriminator(discList);
return buildWhereLiteral(discList);
}
private void appendDiscriminator(List<Object> list) {
if (discriminatorObjectValue != null){
list.add(discriminatorObjectValue);
}
for (DeployInheritInfo child : children) {
child.appendDiscriminator(list);
}
}
private String buildWhereLiteral(List<Object> discList) {
int size = discList.size();
if (size == 0){
return "";
}
StringBuilder sb = new StringBuilder();
sb.append(discriminatorColumn);
if (size == 1){
sb.append(" = ");
} else {
sb.append(" in (");
}
for (int i = 0; i < discList.size(); i++) {
appendSqlLiteralValue(i, discList.get(i), sb);
}
if (size > 1){
sb.append(")");
}
return sb.toString();
}
private void appendSqlLiteralValue(int count, Object value, StringBuilder sb) {
if (count > 0){
sb.append(",");
}
if (value instanceof String){
sb.append("'").append(value).append("'");
} else {
sb.append(value);
}
}
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("InheritInfo[").append(type.getName()).append("]");
sb.append(" root[").append(parent.getName()).append("]");
sb.append(" disValue[").append(discriminatorStringValue).append("]");
return sb.toString();
}
}
package com.avaje.ebeaninternal.server.deploy.parse;
import java.sql.Types;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import com.avaje.ebeaninternal.server.deploy.InheritInfo;
/**
* Represents a node in the Inheritance tree.
* Holds information regarding Super Subclass support.
*/
public class DeployInheritInfo {
/**
* the default discriminator column according to the JPA 1.0 spec.
*/
private static final String JPA_DEFAULT_DISCRIM_COLUMN = "dtype";
private int discriminatorLength;
private int discriminatorType;
private String discriminatorStringValue;
private Object discriminatorObjectValue;
private String discriminatorColumn;
private String discriminatorWhere;
private Class<?> type;
private Class<?> parent;
private ArrayList<DeployInheritInfo> children = new ArrayList<DeployInheritInfo>();
/**
* Create for a given type.
*/
public DeployInheritInfo(Class<?> type){
this.type = type;
}
/**
* return the type.
*/
public Class<?> getType() {
return type;
}
/**
* Return the type of the root object.
*/
public Class<?> getParent() {
return parent;
}
/**
* Set the type of the root object.
*/
public void setParent(Class<?> parent) {
this.parent = parent;
}
/**
* Return true if this is abstract node.
*/
public boolean isAbstract() {
return (discriminatorObjectValue == null);
}
/**
* Return true if this is the root node.
*/
public boolean isRoot(){
return parent == null;
}
/**
* Return the child nodes.
*/
public Iterator<DeployInheritInfo> children() {
return children.iterator();
}
/**
* Add a child node.
*/
public void addChild(DeployInheritInfo childInfo){
children.add(childInfo);
}
/**
* Return the derived where for the discriminator.
*/
public String getDiscriminatorWhere() {
return discriminatorWhere;
}
/**
* Set the derived where for the discriminator.
*/
public void setDiscriminatorWhere(String discriminatorWhere) {
this.discriminatorWhere = discriminatorWhere;
}
/**
* Return the column name of the discriminator.
*/
public String getDiscriminatorColumn(InheritInfo parent) {
if (discriminatorColumn == null){
if (parent == null){
discriminatorColumn = JPA_DEFAULT_DISCRIM_COLUMN;
} else {
discriminatorColumn = parent.getDiscriminatorColumn();
}
}
return discriminatorColumn;
}
/**
* Set the column name of the discriminator.
*/
public void setDiscriminatorColumn(String discriminatorColumn) {
this.discriminatorColumn = discriminatorColumn;
}
public int getDiscriminatorLength(InheritInfo parent) {
if (discriminatorLength == 0){
if (parent == null){
discriminatorLength = 10;
} else {
discriminatorLength = parent.getDiscriminatorLength();
}
}
return discriminatorLength;
}
/**
* Return the sql type of the discriminator value.
*/
public int getDiscriminatorType(InheritInfo parent) {
if (discriminatorType == 0){
if (parent == null){
discriminatorType = Types.VARCHAR;
} else {
discriminatorType = parent.getDiscriminatorType();
}
}
return discriminatorType;
}
/**
* Set the sql type of the discriminator.
*/
public void setDiscriminatorType(int discriminatorType) {
this.discriminatorType = discriminatorType;
}
/**
* Return the length of the discriminator column.
*/
public int getDiscriminatorLength() {
return discriminatorLength;
}
/**
* Set the length of the discriminator column.
*/
public void setDiscriminatorLength(int discriminatorLength) {
this.discriminatorLength = discriminatorLength;
}
/**
* Return the discriminator value for this node.
*/
public Object getDiscriminatorObjectValue() {
return discriminatorObjectValue;
}
public String getDiscriminatorStringValue() {
return discriminatorStringValue;
}
/**
* Set the discriminator value for this node.
*/
public void setDiscriminatorValue(String value) {
if (value != null){
value = value.trim();
if (value.length() == 0){
value = null;
} else {
discriminatorStringValue = value;
// convert the value if desired
if (discriminatorType == Types.INTEGER){
this.discriminatorObjectValue = Integer.valueOf(value.toString());
} else {
this.discriminatorObjectValue = value;
}
}
}
}
public String getWhere() {
List<Object> discList = new ArrayList<Object>();
appendDiscriminator(discList);
return buildWhereLiteral(discList);
}
private void appendDiscriminator(List<Object> list) {
if (discriminatorObjectValue != null){
list.add(discriminatorObjectValue);
}
for (DeployInheritInfo child : children) {
child.appendDiscriminator(list);
}
}
private String buildWhereLiteral(List<Object> discList) {
int size = discList.size();
if (size == 0){
return "";
}
StringBuilder sb = new StringBuilder();
sb.append(discriminatorColumn);
if (size == 1){
sb.append(" = ");
} else {
sb.append(" in (");
}
for (int i = 0; i < discList.size(); i++) {
appendSqlLiteralValue(i, discList.get(i), sb);
}
if (size > 1){
sb.append(")");
}
return sb.toString();
}
private void appendSqlLiteralValue(int count, Object value, StringBuilder sb) {
if (count > 0){
sb.append(",");
}
if (value instanceof String){
sb.append("'").append(value).append("'");
} else {
sb.append(value);
}
}
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("InheritInfo[").append(type.getName()).append("]");
sb.append(" root[").append(parent.getName()).append("]");
sb.append(" disValue[").append(discriminatorStringValue).append("]");
return sb.toString();
}
}
@@ -1,266 +1,247 @@
/**
* Copyright (C) 2006 Robin Bygrave
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy.parse;
import java.lang.annotation.Annotation;
import java.sql.Types;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.PersistenceException;
import com.avaje.ebean.config.EncryptDeploy;
import com.avaje.ebean.config.EncryptDeployManager;
import com.avaje.ebean.config.EncryptKeyManager;
import com.avaje.ebean.config.Encryptor;
import com.avaje.ebean.config.NamingConvention;
import com.avaje.ebean.config.ServerConfig;
import com.avaje.ebean.config.TableName;
import com.avaje.ebean.config.dbplatform.DatabasePlatform;
import com.avaje.ebean.validation.factory.Validator;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyCompound;
import com.avaje.ebeaninternal.server.type.DataEncryptSupport;
import com.avaje.ebeaninternal.server.type.ScalarType;
import com.avaje.ebeaninternal.server.type.ScalarTypeEnumStandard;
import com.avaje.ebeaninternal.server.type.SimpleAesEncryptor;
import com.avaje.ebeaninternal.server.type.TypeManager;
/**
* Utility object to help processing deployment information.
*/
public class DeployUtil {
private static final Logger logger = Logger.getLogger(DeployUtil.class.getName());
/**
* Assumes CLOB rather than LONGVARCHAR.
*/
private static final int dbCLOBType = Types.CLOB;
/**
* Assumes BLOB rather than LONGVARBINARY. This should probably be
* configurable.
*/
private static final int dbBLOBType = Types.BLOB;
private final NamingConvention namingConvention;
private final TypeManager typeManager;
private final ValidatorFactoryManager validatorFactoryManager;
private final String manyToManyAlias;
private final DatabasePlatform dbPlatform;
private final EncryptDeployManager encryptDeployManager;
private final EncryptKeyManager encryptKeyManager;
private final Encryptor bytesEncryptor;
public DeployUtil(TypeManager typeMgr, ServerConfig serverConfig) {
this.typeManager = typeMgr;
this.namingConvention = serverConfig.getNamingConvention();
this.dbPlatform = serverConfig.getDatabasePlatform();
this.encryptDeployManager = serverConfig.getEncryptDeployManager();
this.encryptKeyManager = serverConfig.getEncryptKeyManager();
Encryptor be = serverConfig.getEncryptor();
this.bytesEncryptor = be != null ? be : new SimpleAesEncryptor();
// this alias is used for ManyToMany lazy loading queries
this.manyToManyAlias = "zzzzzz";
this.validatorFactoryManager = new ValidatorFactoryManager();
}
public TypeManager getTypeManager() {
return typeManager;
}
public DatabasePlatform getDbPlatform() {
return dbPlatform;
}
public NamingConvention getNamingConvention() {
return namingConvention;
}
/**
* Check that the EncryptKeyManager has been defined.
*/
public void checkEncryptKeyManagerDefined(String fullPropName) {
if (encryptKeyManager == null){
String msg = "Using encryption on "+fullPropName+" but no EncryptKeyManager defined!";
throw new PersistenceException(msg);
}
}
public EncryptDeploy getEncryptDeploy(TableName table, String column) {
if (encryptDeployManager == null){
return EncryptDeploy.ANNOTATION;
}
return encryptDeployManager.getEncryptDeploy(table, column);
}
public DataEncryptSupport createDataEncryptSupport(String table, String column) {
return new DataEncryptSupport(encryptKeyManager, bytesEncryptor, table, column);
}
/**
* Return the table alias used for ManyToMany joins.
*/
public String getManyToManyAlias() {
return manyToManyAlias;
}
public void createValidator(DeployBeanProperty prop, Annotation ann) {
try {
Validator validator = validatorFactoryManager.create(ann, prop.getPropertyType());
if (validator != null){
prop.addValidator(validator);
}
} catch (Exception e){
String msg = "Error creating a validator on "+prop.getFullBeanName();
logger.log(Level.SEVERE, msg, e);
}
}
public ScalarType<?> setEnumScalarType(Enumerated enumerated, DeployBeanProperty prop) {
Class<?> enumType = prop.getPropertyType();
if (!enumType.isEnum()) {
throw new IllegalArgumentException("Class ["+enumType+"] is Not a Enum?");
}
ScalarType<?> scalarType = typeManager.getScalarType(enumType);
if (scalarType == null) {
// see if it has a Mapping in avaje.properties
scalarType = typeManager.createEnumScalarType(enumType);
if (scalarType == null){
// use JPA normal Enum type (without mapping)
EnumType type = enumerated != null? enumerated.value(): null;
scalarType = createEnumScalarTypePerSpec(enumType, type, prop.getDbType());
}
typeManager.add(scalarType);
}
prop.setScalarType(scalarType);
prop.setDbType(scalarType.getJdbcType());
return scalarType;
}
private ScalarType<?> createEnumScalarTypePerSpec(Class<?> enumType, EnumType type, int dbType) {
if (type == null) {
// default as per spec is ORDINAL
return new ScalarTypeEnumStandard.OrdinalEnum(enumType);
} else if (type == EnumType.ORDINAL) {
return new ScalarTypeEnumStandard.OrdinalEnum(enumType);
} else {
return new ScalarTypeEnumStandard.StringEnum(enumType);
}
}
/**
* Find the ScalarType for this property.
* <p>
* This determines if there is a conversion required from the logical (bean)
* type to a DB (jdbc) type. This is the case for java.util.Date etc.
* </p>
*/
public void setScalarType(DeployBeanProperty property) {
if (property.getScalarType() != null){
// already has a ScalarType assigned.
// this will be an Enum type...
return;
}
if (property instanceof DeployBeanPropertyCompound){
// compound properties have a CvoInternalType instead
return;
}
ScalarType<?> scalarType = getScalarType(property);
if (scalarType != null){
// set the jdbc type this maps to
property.setDbType(scalarType.getJdbcType());
property.setScalarType(scalarType);
}
}
private ScalarType<?> getScalarType(DeployBeanProperty property) {
// Note that Temporal types already have dbType
// set via annotations
Class<?> propType = property.getPropertyType();
ScalarType<?> scalarType = typeManager.getScalarType(propType, property.getDbType());
if (scalarType != null) {
return scalarType;
}
String msg = property.getFullBeanName()+" has no ScalarType - type[" + propType.getName() + "]";
if (!property.isTransient()){
throw new PersistenceException(msg);
} else {
// this is ok...
logger.finest("... transient property "+msg);
return null;
}
}
/**
* This property is marked as a Lob object.
*/
public void setLobType(DeployBeanProperty prop) {
// is String or byte[] ? used to determine if its a CLOB or BLOB
Class<?> type = prop.getPropertyType();
// this also sets the lob flag on DeployBeanProperty
int lobType = isClobType(type) ? dbCLOBType : dbBLOBType;
ScalarType<?> scalarType = typeManager.getScalarType(type, lobType);
if (scalarType == null) {
// this should never occur actually
throw new RuntimeException("No ScalarType for LOB type ["+type+"] ["+lobType+"]");
}
prop.setDbType(lobType);
prop.setScalarType(scalarType);
}
public boolean isClobType(Class<?> type){
if (type.equals(String.class)){
return true;
}
return false;
}
}
package com.avaje.ebeaninternal.server.deploy.parse;
import java.lang.annotation.Annotation;
import java.sql.Types;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.PersistenceException;
import com.avaje.ebean.config.EncryptDeploy;
import com.avaje.ebean.config.EncryptDeployManager;
import com.avaje.ebean.config.EncryptKeyManager;
import com.avaje.ebean.config.Encryptor;
import com.avaje.ebean.config.NamingConvention;
import com.avaje.ebean.config.ServerConfig;
import com.avaje.ebean.config.TableName;
import com.avaje.ebean.config.dbplatform.DatabasePlatform;
import com.avaje.ebean.validation.factory.Validator;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyCompound;
import com.avaje.ebeaninternal.server.type.DataEncryptSupport;
import com.avaje.ebeaninternal.server.type.ScalarType;
import com.avaje.ebeaninternal.server.type.ScalarTypeEnumStandard;
import com.avaje.ebeaninternal.server.type.SimpleAesEncryptor;
import com.avaje.ebeaninternal.server.type.TypeManager;
/**
* Utility object to help processing deployment information.
*/
public class DeployUtil {
private static final Logger logger = Logger.getLogger(DeployUtil.class.getName());
/**
* Assumes CLOB rather than LONGVARCHAR.
*/
private static final int dbCLOBType = Types.CLOB;
/**
* Assumes BLOB rather than LONGVARBINARY. This should probably be
* configurable.
*/
private static final int dbBLOBType = Types.BLOB;
private final NamingConvention namingConvention;
private final TypeManager typeManager;
private final ValidatorFactoryManager validatorFactoryManager;
private final String manyToManyAlias;
private final DatabasePlatform dbPlatform;
private final EncryptDeployManager encryptDeployManager;
private final EncryptKeyManager encryptKeyManager;
private final Encryptor bytesEncryptor;
public DeployUtil(TypeManager typeMgr, ServerConfig serverConfig) {
this.typeManager = typeMgr;
this.namingConvention = serverConfig.getNamingConvention();
this.dbPlatform = serverConfig.getDatabasePlatform();
this.encryptDeployManager = serverConfig.getEncryptDeployManager();
this.encryptKeyManager = serverConfig.getEncryptKeyManager();
Encryptor be = serverConfig.getEncryptor();
this.bytesEncryptor = be != null ? be : new SimpleAesEncryptor();
// this alias is used for ManyToMany lazy loading queries
this.manyToManyAlias = "zzzzzz";
this.validatorFactoryManager = new ValidatorFactoryManager();
}
public TypeManager getTypeManager() {
return typeManager;
}
public DatabasePlatform getDbPlatform() {
return dbPlatform;
}
public NamingConvention getNamingConvention() {
return namingConvention;
}
/**
* Check that the EncryptKeyManager has been defined.
*/
public void checkEncryptKeyManagerDefined(String fullPropName) {
if (encryptKeyManager == null){
String msg = "Using encryption on "+fullPropName+" but no EncryptKeyManager defined!";
throw new PersistenceException(msg);
}
}
public EncryptDeploy getEncryptDeploy(TableName table, String column) {
if (encryptDeployManager == null){
return EncryptDeploy.ANNOTATION;
}
return encryptDeployManager.getEncryptDeploy(table, column);
}
public DataEncryptSupport createDataEncryptSupport(String table, String column) {
return new DataEncryptSupport(encryptKeyManager, bytesEncryptor, table, column);
}
/**
* Return the table alias used for ManyToMany joins.
*/
public String getManyToManyAlias() {
return manyToManyAlias;
}
public void createValidator(DeployBeanProperty prop, Annotation ann) {
try {
Validator validator = validatorFactoryManager.create(ann, prop.getPropertyType());
if (validator != null){
prop.addValidator(validator);
}
} catch (Exception e){
String msg = "Error creating a validator on "+prop.getFullBeanName();
logger.log(Level.SEVERE, msg, e);
}
}
public ScalarType<?> setEnumScalarType(Enumerated enumerated, DeployBeanProperty prop) {
Class<?> enumType = prop.getPropertyType();
if (!enumType.isEnum()) {
throw new IllegalArgumentException("Class ["+enumType+"] is Not a Enum?");
}
ScalarType<?> scalarType = typeManager.getScalarType(enumType);
if (scalarType == null) {
// see if it has a Mapping in avaje.properties
scalarType = typeManager.createEnumScalarType(enumType);
if (scalarType == null){
// use JPA normal Enum type (without mapping)
EnumType type = enumerated != null? enumerated.value(): null;
scalarType = createEnumScalarTypePerSpec(enumType, type, prop.getDbType());
}
typeManager.add(scalarType);
}
prop.setScalarType(scalarType);
prop.setDbType(scalarType.getJdbcType());
return scalarType;
}
private ScalarType<?> createEnumScalarTypePerSpec(Class<?> enumType, EnumType type, int dbType) {
if (type == null) {
// default as per spec is ORDINAL
return new ScalarTypeEnumStandard.OrdinalEnum(enumType);
} else if (type == EnumType.ORDINAL) {
return new ScalarTypeEnumStandard.OrdinalEnum(enumType);
} else {
return new ScalarTypeEnumStandard.StringEnum(enumType);
}
}
/**
* Find the ScalarType for this property.
* <p>
* This determines if there is a conversion required from the logical (bean)
* type to a DB (jdbc) type. This is the case for java.util.Date etc.
* </p>
*/
public void setScalarType(DeployBeanProperty property) {
if (property.getScalarType() != null){
// already has a ScalarType assigned.
// this will be an Enum type...
return;
}
if (property instanceof DeployBeanPropertyCompound){
// compound properties have a CvoInternalType instead
return;
}
ScalarType<?> scalarType = getScalarType(property);
if (scalarType != null){
// set the jdbc type this maps to
property.setDbType(scalarType.getJdbcType());
property.setScalarType(scalarType);
}
}
private ScalarType<?> getScalarType(DeployBeanProperty property) {
// Note that Temporal types already have dbType
// set via annotations
Class<?> propType = property.getPropertyType();
ScalarType<?> scalarType = typeManager.getScalarType(propType, property.getDbType());
if (scalarType != null) {
return scalarType;
}
String msg = property.getFullBeanName()+" has no ScalarType - type[" + propType.getName() + "]";
if (!property.isTransient()){
throw new PersistenceException(msg);
} else {
// this is ok...
logger.finest("... transient property "+msg);
return null;
}
}
/**
* This property is marked as a Lob object.
*/
public void setLobType(DeployBeanProperty prop) {
// is String or byte[] ? used to determine if its a CLOB or BLOB
Class<?> type = prop.getPropertyType();
// this also sets the lob flag on DeployBeanProperty
int lobType = isClobType(type) ? dbCLOBType : dbBLOBType;
ScalarType<?> scalarType = typeManager.getScalarType(type, lobType);
if (scalarType == null) {
// this should never occur actually
throw new RuntimeException("No ScalarType for LOB type ["+type+"] ["+lobType+"]");
}
prop.setDbType(lobType);
prop.setScalarType(scalarType);
}
public boolean isClobType(Class<?> type){
if (type.equals(String.class)){
return true;
}
return false;
}
}
@@ -1,62 +1,43 @@
/**
* Copyright (C) 2009 Authors
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy.parse;
import java.util.logging.Logger;
import com.avaje.ebeaninternal.api.ClassUtil;
/**
* Used to detected if Scala support is required.
*
* @author rbygrave
*/
public class DetectScala {
private static final Logger logger = Logger.getLogger(DetectScala.class.getName());
private static Class<?> scalaOptionClass = initScalaOptionClass();
private static boolean hasScalaSupport = scalaOptionClass != null;
private static Class<?> initScalaOptionClass() {
try {
return ClassUtil.forName("scala.Option");
} catch (ClassNotFoundException e) {
// scala not in the classpath...
logger.fine("Scala type 'scala.Option' not found. Scala Support disabled.");
return null;
}
}
/**
* Return true if scala is in the classpath.
*/
public static boolean hasScalaSupport() {
return hasScalaSupport;
}
/**
* Return the scala.Option class or null if scala is not in the classpath.
*/
public static Class<?> getScalaOptionClass() {
return scalaOptionClass;
}
}
package com.avaje.ebeaninternal.server.deploy.parse;
import java.util.logging.Logger;
import com.avaje.ebeaninternal.api.ClassUtil;
/**
* Used to detected if Scala support is required.
*
* @author rbygrave
*/
public class DetectScala {
private static final Logger logger = Logger.getLogger(DetectScala.class.getName());
private static Class<?> scalaOptionClass = initScalaOptionClass();
private static boolean hasScalaSupport = scalaOptionClass != null;
private static Class<?> initScalaOptionClass() {
try {
return ClassUtil.forName("scala.Option");
} catch (ClassNotFoundException e) {
// scala not in the classpath...
logger.fine("Scala type 'scala.Option' not found. Scala Support disabled.");
return null;
}
}
/**
* Return true if scala is in the classpath.
*/
public static boolean hasScalaSupport() {
return hasScalaSupport;
}
/**
* Return the scala.Option class or null if scala is not in the classpath.
*/
public static Class<?> getScalaOptionClass() {
return scalaOptionClass;
}
}
@@ -1,77 +1,58 @@
/**
* Copyright (C) 2006 Robin Bygrave
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy.parse;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptorManager;
/**
* Read the deployment annotations for the bean.
*/
public class ReadAnnotations {
/**
* Read the initial non-relationship annotations included Id and EmbeddedId.
* <p>
* We then have enough to create BeanTables which are used in readAssociations
* to resolve the relationships etc.
* </p>
*/
public void readInitial(DeployBeanInfo<?> info){
try {
new AnnotationClass(info).parse();
new AnnotationFields(info).parse();
} catch (RuntimeException e){
String msg = "Error reading annotations for "+info;
throw new RuntimeException(msg, e);
}
}
/**
* Read and process the associated relationship annotations.
* <p>
* These can only be processed after the BeanTables have been created
* </p>
* <p>
* This uses the factory as a call back to get the BeanTable for a given
* associated bean.
* </p>
*/
public void readAssociations(DeployBeanInfo<?> info, BeanDescriptorManager factory){
try {
new AnnotationAssocOnes(info, factory).parse();
new AnnotationAssocManys(info, factory).parse();
// read the Sql annotations last because they may be
// dependent on field level annotations
new AnnotationSql(info).parse();
} catch (RuntimeException e){
String msg = "Error reading annotations for "+info;
throw new RuntimeException(msg, e);
}
}
}
package com.avaje.ebeaninternal.server.deploy.parse;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptorManager;
/**
* Read the deployment annotations for the bean.
*/
public class ReadAnnotations {
/**
* Read the initial non-relationship annotations included Id and EmbeddedId.
* <p>
* We then have enough to create BeanTables which are used in readAssociations
* to resolve the relationships etc.
* </p>
*/
public void readInitial(DeployBeanInfo<?> info){
try {
new AnnotationClass(info).parse();
new AnnotationFields(info).parse();
} catch (RuntimeException e){
String msg = "Error reading annotations for "+info;
throw new RuntimeException(msg, e);
}
}
/**
* Read and process the associated relationship annotations.
* <p>
* These can only be processed after the BeanTables have been created
* </p>
* <p>
* This uses the factory as a call back to get the BeanTable for a given
* associated bean.
* </p>
*/
public void readAssociations(DeployBeanInfo<?> info, BeanDescriptorManager factory){
try {
new AnnotationAssocOnes(info, factory).parse();
new AnnotationAssocManys(info, factory).parse();
// read the Sql annotations last because they may be
// dependent on field level annotations
new AnnotationSql(info).parse();
} catch (RuntimeException e){
String msg = "Error reading annotations for "+info;
throw new RuntimeException(msg, e);
}
}
}
@@ -1,70 +1,51 @@
/**
* Copyright (C) 2006 Robin Bygrave
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.deploy.parse;
import java.util.List;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanDescriptor;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocMany;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocOne;
/**
* Mark transient properties.
*/
public class TransientProperties {
public TransientProperties() {
}
/**
* Mark any additional properties as transient.
*/
public void process(DeployBeanDescriptor<?> desc) {
List<DeployBeanProperty> props = desc.propertiesBase();
for (int i = 0; i < props.size(); i++) {
DeployBeanProperty prop = props.get(i);
if (!prop.isDbRead() && !prop.isDbInsertable() && !prop.isDbUpdateable()) {
// non-transient...
prop.setTransient(true);
}
}
List<DeployBeanPropertyAssocOne<?>> ones = desc.propertiesAssocOne();
for (int i = 0; i < ones.size(); i++) {
DeployBeanPropertyAssocOne<?> prop = ones.get(i);
if (prop.getBeanTable() == null) {
if (!prop.isEmbedded()) {
prop.setTransient(true);
}
}
}
List<DeployBeanPropertyAssocMany<?>> manys = desc.propertiesAssocMany();
for (int i = 0; i < manys.size(); i++) {
DeployBeanPropertyAssocMany<?> prop = manys.get(i);
if (prop.getBeanTable() == null) {
prop.setTransient(true);
}
}
}
}
package com.avaje.ebeaninternal.server.deploy.parse;
import java.util.List;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanDescriptor;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocMany;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocOne;
/**
* Mark transient properties.
*/
public class TransientProperties {
public TransientProperties() {
}
/**
* Mark any additional properties as transient.
*/
public void process(DeployBeanDescriptor<?> desc) {
List<DeployBeanProperty> props = desc.propertiesBase();
for (int i = 0; i < props.size(); i++) {
DeployBeanProperty prop = props.get(i);
if (!prop.isDbRead() && !prop.isDbInsertable() && !prop.isDbUpdateable()) {
// non-transient...
prop.setTransient(true);
}
}
List<DeployBeanPropertyAssocOne<?>> ones = desc.propertiesAssocOne();
for (int i = 0; i < ones.size(); i++) {
DeployBeanPropertyAssocOne<?> prop = ones.get(i);
if (prop.getBeanTable() == null) {
if (!prop.isEmbedded()) {
prop.setTransient(true);
}
}
}
List<DeployBeanPropertyAssocMany<?>> manys = desc.propertiesAssocMany();
for (int i = 0; i < manys.size(); i++) {
DeployBeanPropertyAssocMany<?> prop = manys.get(i);
if (prop.getBeanTable() == null) {
prop.setTransient(true);
}
}
}
}