/jaxrs/eagledns/src/main/java/se/unlogic/standardutils/dao/SimplifiedOneToManyRelation.java
Java | 364 lines | 215 code | 127 blank | 22 comment | 49 complexity | 3a5109779e4bf8e19debfe81a3804c72 MD5 | raw file
- /*******************************************************************************
- * Copyright (c) 2010 Robert "Unlogic" Olofsson (unlogic@unlogic.se).
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the GNU Lesser Public License v3
- * which accompanies this distribution, and is available at
- * http://www.gnu.org/licenses/lgpl-3.0-standalone.html
- ******************************************************************************/
- package se.unlogic.standardutils.dao;
-
- import se.unlogic.standardutils.collections.CollectionUtils;
- import se.unlogic.standardutils.dao.annotations.DAOManaged;
- import se.unlogic.standardutils.dao.annotations.Key;
- import se.unlogic.standardutils.dao.annotations.SimplifiedRelation;
- import se.unlogic.standardutils.dao.enums.Order;
- import se.unlogic.standardutils.dao.querys.ArrayListQuery;
- import se.unlogic.standardutils.dao.querys.PreparedStatementQuery;
- import se.unlogic.standardutils.dao.querys.UpdateQuery;
- import se.unlogic.standardutils.populators.BeanStringPopulator;
- import se.unlogic.standardutils.populators.QueryParameterPopulator;
- import se.unlogic.standardutils.reflection.ReflectionUtils;
- import se.unlogic.standardutils.string.StringUtils;
-
- import java.lang.reflect.Field;
- import java.lang.reflect.InvocationTargetException;
- import java.lang.reflect.Method;
- import java.sql.Connection;
- import java.sql.SQLException;
- import java.util.ArrayList;
- import java.util.List;
-
- public class SimplifiedOneToManyRelation<LocalType, RemoteType> implements OneToManyRelation<LocalType, RemoteType> {
-
- private final AnnotatedDAO<LocalType> localDAO;
- private final Field field;
-
- private String selectSQL;
- private String insertSQL;
- private String deleteSQL;
-
- private boolean preserveListOrder;
- private String indexColumnName;
-
- private QueryParameterPopulator<RemoteType> queryParameterPopulator;
- private Method preparedStatementMethod;
-
- private BeanResultSetPopulator<RemoteType> beanResultSetPopulator;
-
- private Field keyField;
- private Column<LocalType, ?> keyColumn;
-
- private final String remoteTableName;
- private String remoteKeyColumnName;
- private final String remoteValueColumnName;
- private Order order;
-
- private boolean initialized;
-
- @SuppressWarnings("unchecked")
- public SimplifiedOneToManyRelation(Class<LocalType> beanClass, Class<RemoteType> remoteClass, Field field, AnnotatedDAO<LocalType> localDAO, List<? extends BeanStringPopulator<?>> typePopulators, List<? extends QueryParameterPopulator<?>> queryParameterPopulators) {
-
- super();
- this.localDAO = localDAO;
- this.field = field;
-
- SimplifiedRelation simplifiedRelation = field.getAnnotation(SimplifiedRelation.class);
-
- remoteKeyColumnName = simplifiedRelation.remoteKeyColumnName();
- remoteValueColumnName = simplifiedRelation.remoteValueColumnName();
- order = simplifiedRelation.order();
-
- if(simplifiedRelation.addTablePrefix()){
-
- if(simplifiedRelation.deplurifyTablePrefix() && localDAO.getTableName().endsWith("s")){
-
- remoteTableName = localDAO.getTableName().substring(0, localDAO.getTableName().length()-1) + simplifiedRelation.table();
-
- }else{
-
- remoteTableName = localDAO.getTableName() + simplifiedRelation.table();
- }
- }else{
-
- remoteTableName = simplifiedRelation.table();
- }
-
- if (!StringUtils.isEmpty(simplifiedRelation.keyField())) {
-
- try {
- keyField = ReflectionUtils.getField(beanClass, simplifiedRelation.keyField());
-
- if (keyField == null) {
-
- throw new RuntimeException("Unable to find field " + simplifiedRelation.keyField() + " in " + beanClass.getClass());
- }
-
- } catch (SecurityException e) {
-
- throw new RuntimeException(e);
-
- }
-
- } else {
-
- List<Field> fields = ReflectionUtils.getFields(beanClass);
-
- for (Field localBeanField : fields) {
-
- if (localBeanField.isAnnotationPresent(DAOManaged.class) && localBeanField.isAnnotationPresent(Key.class)) {
-
- if (this.keyField == null) {
-
- keyField = localBeanField;
-
- } else {
-
- throw new RuntimeException("Multiple fields marked with @Key annotation found in class " + beanClass + " therefore keyField has to set on the @SimplifiedRelation annotation of field " + field.getName());
- }
- }
- }
- }
-
- if (queryParameterPopulators != null) {
-
- for (QueryParameterPopulator<?> queryParameterPopulator : queryParameterPopulators) {
-
- if (queryParameterPopulator.getType().equals(remoteClass)) {
-
- this.queryParameterPopulator = (QueryParameterPopulator<RemoteType>) queryParameterPopulator;
- }
- }
- }
-
- if (this.queryParameterPopulator == null) {
-
- preparedStatementMethod = PreparedStatementQueryMethods.getQueryMethod(remoteClass);
-
- if (preparedStatementMethod == null) {
-
- throw new RuntimeException("Unable to to find a query parameter populator or prepared statement method matching " + remoteClass + " of @SimplfiedRelation and @OneToMany annotated field " + field.getName() + " in " + beanClass);
- }
- }
-
- if (typePopulators != null) {
-
- for (BeanStringPopulator<?> typePopulator : typePopulators) {
-
- if (typePopulator.getType().equals(remoteClass)) {
-
- beanResultSetPopulator = new TypeBasedResultSetPopulator<RemoteType>((BeanStringPopulator<RemoteType>) typePopulator, remoteValueColumnName);
- }
- }
- }
-
- if (beanResultSetPopulator == null) {
-
- Method resultSetMethod = ResultSetMethods.getColumnNameMethod(remoteClass);
-
- if (resultSetMethod != null) {
-
- beanResultSetPopulator = new MethodBasedResultSetPopulator<RemoteType>(resultSetMethod, remoteValueColumnName);
-
- } else {
-
- throw new RuntimeException("Unable to to find a type populator or resultset method matching " + remoteClass + " of @SimplfiedRelation and @OneToMany annotated field " + field.getName() + " in " + beanClass);
- }
- }
-
- if(simplifiedRelation.preserveListOrder()){
-
- if(StringUtils.isEmpty(simplifiedRelation.indexColumn())){
-
- throw new RuntimeException("Preserve list order enabled but no index column specified for @SimplifiedRelation annotated field " + field.getName() + " in " + beanClass);
- }
-
- preserveListOrder = true;
- indexColumnName = simplifiedRelation.indexColumn();
- }
- }
-
- private void init() {
-
- this.keyColumn = localDAO.getColumn(keyField);
-
- if (StringUtils.isEmpty(remoteKeyColumnName)) {
-
- remoteKeyColumnName = keyColumn.getColumnName();
- }
-
- this.deleteSQL = "DELETE FROM " + remoteTableName + " WHERE " + remoteKeyColumnName + "=?";
-
- if(preserveListOrder){
-
- this.selectSQL = "SELECT * FROM " + remoteTableName + " WHERE " + remoteKeyColumnName + " = ? ORDER BY " + indexColumnName + " " + order;
- this.insertSQL = "INSERT INTO " + remoteTableName + "(" + remoteKeyColumnName + "," + remoteValueColumnName + "," + indexColumnName + ") VALUES (?,?,?)";
-
- }else{
-
- this.selectSQL = "SELECT * FROM " + remoteTableName + " WHERE " + remoteKeyColumnName + " = ? ORDER BY " + remoteValueColumnName + " " + order;
- this.insertSQL = "INSERT INTO " + remoteTableName + "(" + remoteKeyColumnName + "," + remoteValueColumnName + ") VALUES (?,?)";
- }
-
- this.initialized = true;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see se.unlogic.utils.dao.OneToManyRelation#setValue(LocalType, java.sql.Connection, java.lang.reflect.Field[])
- */
- public void getRemoteValue(LocalType bean, Connection connection, RelationQuery relationQuery) throws SQLException {
-
- if (!initialized) {
- init();
- }
-
- try {
- ArrayListQuery<RemoteType> query = new ArrayListQuery<RemoteType>(connection, false, selectSQL, beanResultSetPopulator);
-
- setKey(query, bean);
-
- ArrayList<RemoteType> list = query.executeQuery();
-
- if (list != null) {
-
- CollectionUtils.removeNullValues(list);
- }
-
- field.set(bean, list);
-
- } catch (IllegalArgumentException e) {
-
- throw new RuntimeException(e);
-
- } catch (IllegalAccessException e) {
-
- throw new RuntimeException(e);
- }
- }
-
- private void setKey(PreparedStatementQuery query, LocalType bean) throws SQLException {
-
- if (keyColumn.getQueryParameterPopulator() != null) {
-
- keyColumn.getQueryParameterPopulator().populate(query, 1, bean);
-
- } else {
-
- try {
- keyColumn.getQueryMethod().invoke(query, 1, keyColumn.getBeanValue(bean));
-
- } catch (IllegalArgumentException e) {
-
- throw new RuntimeException(e);
-
- } catch (IllegalAccessException e) {
-
- throw new RuntimeException(e);
-
- } catch (InvocationTargetException e) {
-
- throw new RuntimeException(e);
- }
- }
- }
-
- private void setValue(RemoteType value, UpdateQuery query) throws SQLException {
-
- if (queryParameterPopulator != null) {
-
- queryParameterPopulator.populate(query, 2, value);
-
- } else {
-
- try {
- preparedStatementMethod.invoke(query, 2, value);
-
- } catch (IllegalArgumentException e) {
-
- throw new RuntimeException(e);
-
- } catch (IllegalAccessException e) {
-
- throw new RuntimeException(e);
-
- } catch (InvocationTargetException e) {
-
- throw new RuntimeException(e);
- }
- }
-
- }
-
- /*
- * (non-Javadoc)
- *
- * @see se.unlogic.utils.dao.OneToManyRelation#add(LocalType, java.sql.Connection, java.lang.reflect.Field[])
- */
- @SuppressWarnings("unchecked")
- public void add(LocalType bean, Connection connection, RelationQuery relationQuery) throws SQLException {
-
- if (!initialized) {
- init();
- }
-
- try {
- List<RemoteType> values = (List<RemoteType>) field.get(bean);
-
- if (values != null) {
-
- int listIndex = 0;
-
- for (RemoteType value : values) {
-
- UpdateQuery query = new UpdateQuery(connection, false, insertSQL);
-
- setKey(query, bean);
-
- setValue(value, query);
-
- if(preserveListOrder){
-
- query.setInt(3, listIndex);
- listIndex++;
- }
-
- query.executeUpdate();
- }
- }
-
- } catch (IllegalArgumentException e) {
-
- throw new RuntimeException(e);
-
- } catch (IllegalAccessException e) {
-
- throw new RuntimeException(e);
- }
- }
-
- /*
- * (non-Javadoc)
- *
- * @see se.unlogic.utils.dao.OneToManyRelation#update(LocalType, java.sql.Connection, java.lang.reflect.Field[])
- */
- public void update(LocalType bean, Connection connection, RelationQuery relationQuery) throws SQLException {
-
- if (!initialized) {
- init();
- }
-
- UpdateQuery query = new UpdateQuery(connection, false, deleteSQL);
-
- setKey(query, bean);
-
- query.executeUpdate();
-
- this.add(bean, connection, relationQuery);
- }
-
- public static <LT, RT> OneToManyRelation<LT, RT> getGenericInstance(Class<LT> beanClass, Class<RT> remoteClass, Field field, AnnotatedDAO<LT> localDAO, List<? extends BeanStringPopulator<?>> typePopulators, List<? extends QueryParameterPopulator<?>> queryParameterPopulators) {
-
- return new SimplifiedOneToManyRelation<LT, RT>(beanClass, remoteClass, field, localDAO, typePopulators, queryParameterPopulators);
- }
- }