Author: cbrisson
Date: Thu Apr 18 15:04:54 2019
New Revision: 1857755
URL: http://svn.apache.org/viewvc?rev=1857755&view=rev
Log:
[tools/model] Initial import: Model, Entity, Attribute and Instance objects and
their dependencies
Added:
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/Action.java
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/Attribute.java
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/Entity.java
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/Instance.java
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/Model.java
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/RowAttribute.java
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/RowsetAttribute.java
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/ScalarAttribute.java
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/Transaction.java
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/WrappingInstance.java
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/impl/
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/impl/AttributeHolder.java
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/impl/BaseAttribute.java
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/impl/BaseEntity.java
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/impl/BaseModel.java
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/impl/InstanceProducer.java
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/impl/ReverseEngineer.java
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/impl/RowIterator.java
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/impl/UpdateAction.java
Added:
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/Action.java
URL:
http://svn.apache.org/viewvc/velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/Action.java?rev=1857755&view=auto
==============================================================================
---
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/Action.java
(added)
+++
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/Action.java
Thu Apr 18 15:04:54 2019
@@ -0,0 +1,59 @@
+package org.apache.velocity.tools.model;
+
+import org.apache.velocity.tools.model.impl.AttributeHolder;
+import org.apache.velocity.tools.model.sql.PooledStatement;
+
+import java.io.Serializable;
+import java.sql.SQLException;
+import java.util.Map;
+
+public class Action extends Attribute
+{
+ public Action(String name, AttributeHolder parent)
+ {
+ super(name, parent);
+
+ }
+
+ public int perform(Serializable... params) throws SQLException
+ {
+ return performImpl(getParamValues(params));
+ }
+
+ public int perform(Map source) throws SQLException
+ {
+ return performImpl(getParamValues(source));
+ }
+
+ public int perform(Map source, Serializable... params) throws SQLException
+ {
+ return performImpl(getParamValues(source, params));
+ }
+
+ protected int performImpl(Serializable... paramValues) throws SQLException
+ {
+ int changed = 0;
+ PooledStatement statement = null;
+ try
+ {
+ statement = getModel().prepareUpdate(getQuery());
+ statement.getConnection().enterBusyState();
+ changed = statement.executeUpdate(paramValues);
+ }
+ finally
+ {
+ if (statement != null)
+ {
+ statement.notifyOver();
+ statement.getConnection().leaveBusyState();
+ }
+ }
+ return changed;
+ }
+
+ @Override
+ protected String getQueryMethodName()
+ {
+ return "perform";
+ }
+}
Added:
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/Attribute.java
URL:
http://svn.apache.org/viewvc/velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/Attribute.java?rev=1857755&view=auto
==============================================================================
---
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/Attribute.java
(added)
+++
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/Attribute.java
Thu Apr 18 15:04:54 2019
@@ -0,0 +1,33 @@
+package org.apache.velocity.tools.model;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.apache.velocity.tools.model.impl.AttributeHolder;
+import org.apache.velocity.tools.model.impl.BaseAttribute;
+
+public abstract class Attribute extends BaseAttribute
+{
+ public Attribute(String name, AttributeHolder parent)
+ {
+ super(name, parent);
+ }
+
+ protected abstract String getQueryMethodName();
+}
Added:
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/Entity.java
URL:
http://svn.apache.org/viewvc/velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/Entity.java?rev=1857755&view=auto
==============================================================================
---
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/Entity.java
(added)
+++
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/Entity.java
Thu Apr 18 15:04:54 2019
@@ -0,0 +1,93 @@
+package org.apache.velocity.tools.model;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.apache.velocity.exception.VelocityException;
+import org.apache.velocity.tools.model.impl.BaseEntity;
+import org.apache.velocity.tools.model.util.TypeUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.Serializable;
+import java.lang.reflect.Method;
+import java.sql.SQLException;
+import java.util.Iterator;
+import java.util.Map;
+
+public class Entity extends BaseEntity implements Iterable<Instance>
+{
+ protected static Logger logger = LoggerFactory.getLogger(Entity.class);
+
+ public Entity(String name, Model model)
+ {
+ super(name, model);
+ setInstanceBuilder(() -> new Instance(this));
+ }
+
+ public Logger getLogger()
+ {
+ return logger;
+ }
+
+ public Iterator<Instance> iterate() throws SQLException
+ {
+ return getIterateAttribute().query();
+ }
+
+ public Iterator<Instance> iterator()
+ {
+ try
+ {
+ return iterate();
+ }
+ catch (SQLException sqle)
+ {
+ throw new VelocityException("cannot iterate on instances of " +
getName(), sqle);
+ }
+ }
+
+ public long getCount() throws SQLException
+ {
+ return TypeUtils.toLong(getCountAttribute().evaluate());
+ }
+
+ public Instance fetch(Serializable... key) throws SQLException
+ {
+ return getFetchAttribute().retrieve(key);
+ }
+
+ public Instance fetch(Map key) throws SQLException
+ {
+ return getFetchAttribute().retrieve(key);
+ }
+
+ @Override
+ protected Map<String, Method> getWrappedInstanceGetters()
+ {
+ return super.getWrappedInstanceGetters();
+ }
+
+ protected Map<String, Method> getWrappedInstanceSetters()
+ {
+ return super.getWrappedInstanceSetters();
+ }
+
+
+}
Added:
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/Instance.java
URL:
http://svn.apache.org/viewvc/velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/Instance.java?rev=1857755&view=auto
==============================================================================
---
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/Instance.java
(added)
+++
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/Instance.java
Thu Apr 18 15:04:54 2019
@@ -0,0 +1,333 @@
+package org.apache.velocity.tools.model;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.apache.velocity.tools.model.filter.ValueFilterHandler;
+import org.apache.velocity.tools.model.sql.RowValues;
+import org.apache.velocity.tools.model.util.ChainedMap;
+import org.apache.velocity.tools.model.filter.Filter;
+import org.apache.velocity.tools.model.util.SlotTreeMap;
+import org.apache.velocity.tools.model.util.TypeUtils;
+
+import java.io.Serializable;
+import java.sql.SQLException;
+import java.util.Arrays;
+import java.util.BitSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+public class Instance extends SlotTreeMap
+{
+ public Instance(Model model)
+ {
+ this.model = model;
+ this.dirtyFlags = new BitSet();
+ this.canWrite = model.getWriteAccess() != Model.WriteAccess.NONE;
+ }
+
+ protected Instance(Entity entity)
+ {
+ this(entity.getModel());
+ this.entity = entity;
+ }
+
+ public void setInitialValues(RowValues values) throws SQLException
+ {
+ Filter<String> defaultNameMapper =
getModel().getIdentifiers().getDefaultColumnLeaf();
+ ValueFilterHandler readFilters =
getModel().getFilters().getReadFilters();
+ for (String key : values.keySet())
+ {
+ Serializable value = values.get(key);
+ String colName = entity == null ? null :
entity.translateColumnName(key);
+ if (colName == null)
+ {
+ colName = defaultNameMapper.apply(key);
+ }
+ else
+ {
+ value = entity.getColumn(colName).read(value);
+ }
+ if (value != null)
+ {
+ Filter<Serializable> filter =
readFilters.getTypeEntry(value.getClass());
+ if (filter != null)
+ {
+ value = filter.apply(value);
+ }
+ }
+ setInitialValue(colName, value);
+ }
+ setClean();
+ persisted = entity != null && entity.getPrimaryKey().size() > 0;
+ }
+
+ public void setInitialValue(String columnName, Serializable value)
+ {
+ super.put(columnName, value);
+ }
+
+ public Serializable evaluate(String name, Map params) throws SQLException
+ {
+ return entity.evaluate(name, params == null ? this : new
ChainedMap(this, params));
+ }
+
+ public Serializable evaluate(String name, Serializable... params) throws
SQLException
+ {
+ return entity.evaluate(name, this, params);
+ }
+
+ public Instance retrieve(String name, Map params) throws SQLException
+ {
+ return entity.retrieve(name, params == null ? this : new
ChainedMap(this, params));
+ }
+
+ public Instance retrieve(String name, Serializable... params) throws
SQLException
+ {
+ return entity.retrieve(name, this, params);
+ }
+
+ public Iterator<Instance> query(String name, Map params) throws
SQLException
+ {
+ return entity.query(name, params == null ? this : new ChainedMap(this,
params));
+ }
+
+ public Iterator<Instance> query(String name, Serializable... params)
throws SQLException
+ {
+ return entity.query(name, this, params);
+ }
+
+ public int perform(String name, Map params) throws SQLException
+ {
+ if (!canWrite)
+ {
+ throw new SQLException("instance is read-only");
+ }
+ return entity.perform(name, params == null ? this : new
ChainedMap(this, params));
+ }
+
+ public int perform(String name, Serializable... params) throws SQLException
+ {
+ if (!canWrite)
+ {
+ throw new SQLException("instance is read-only");
+ }
+ return entity.perform(name, this, params);
+ }
+
+ public String getString(String name)
+ {
+ return TypeUtils.toString(get(name));
+ }
+
+ public Boolean getBoolean(String name)
+ {
+ return TypeUtils.toBoolean(get(name));
+ }
+
+ public Short getShort(String name)
+ {
+ return TypeUtils.toShort(get(name));
+ }
+
+ public Integer getInteger(String name)
+ {
+ return TypeUtils.toInteger(get(name));
+ }
+
+ public Long getLong(String name)
+ {
+ return TypeUtils.toLong(get(name));
+ }
+
+ public Float getFloat(String name)
+ {
+ return TypeUtils.toFloat(get(name));
+ }
+
+ public Double getDouble(String name)
+ {
+ return TypeUtils.toDouble(get(name));
+ }
+
+ public final Model getModel()
+ {
+ return model;
+ }
+
+ public final Entity getEntity()
+ {
+ return entity;
+ }
+
+ protected void setClean()
+ {
+ dirtyFlags.clear();
+ }
+
+ public Serializable[] getPrimaryKey()
+ {
+ List<Entity.Column> pk = entity.getPrimaryKey();
+ if (pk == null)
+ {
+ return null;
+ }
+ Serializable[] ret = new Serializable[pk.size()];
+ int col = 0;
+ for (Entity.Column column : pk)
+ {
+ ret[col++] = get(column.name);
+ }
+ return ret;
+ }
+
+ public BitSet getDirtyFlags()
+ {
+ return dirtyFlags;
+ }
+
+ public boolean isDirty()
+ {
+ return dirtyFlags.cardinality() > 0;
+ }
+
+ public void refresh() throws SQLException
+ {
+ ensurePersisted();
+ Instance myself = getEntity().fetch(getPrimaryKey());
+ super.putAll(myself);
+ }
+
+ public void delete() throws SQLException
+ {
+ if (!canWrite)
+ {
+ throw new SQLException("instance is read-only");
+ }
+ ensurePersisted();
+ entity.delete(this);
+ persisted = false;
+ }
+
+ public void insert() throws SQLException
+ {
+ if (!canWrite)
+ {
+ throw new SQLException("instance is read-only");
+ }
+ ensureNotPersisted();
+ entity.insert(this);
+ persisted = entity != null && entity.getPrimaryKey().size() > 0;
+ }
+
+ public void update() throws SQLException
+ {
+ if (!canWrite)
+ {
+ throw new SQLException("instance is read-only");
+ }
+ ensurePersisted();
+ if (!isDirty())
+ {
+ return;
+ }
+ entity.update(this);
+ }
+
+ @Override
+ public void putAll(Map<? extends String, ? extends Serializable> map)
+ {
+ Serializable[] pk = null;
+ if (persisted)
+ {
+ pk = getPrimaryKey();
+ }
+ super.putAll(map);
+ if (persisted)
+ {
+ Serializable[] newpk = getPrimaryKey();
+ if (Arrays.equals(pk, newpk))
+ {
+ entity.getNonKeyMask().stream().filter(col ->
map.containsKey(entity.getColumn(col).name)).forEach(col ->
dirtyFlags.set(col));
+ }
+ else
+ {
+ persisted = false;
+ }
+
+ }
+ }
+
+ protected Serializable putImpl(String key, Serializable value)
+ {
+ return super.put(key, value);
+ }
+
+ @Override
+ public final Serializable put(String key, Serializable value)
+ {
+ Serializable ret = putImpl(key, value);
+ if (persisted)
+ {
+ Entity.Column column = entity.getColumn(key);
+ if (column != null)
+ {
+ if (entity.getPrimaryKeyMask().get(column.getIndex()))
+ {
+ if (!ret.equals(value))
+ {
+ persisted = false;
+ }
+ }
+ else
+ {
+ dirtyFlags.set(column.getIndex());
+ }
+ }
+ }
+ return ret;
+ }
+
+ private void ensurePersisted()
+ {
+ if (!persisted)
+ {
+ throw new IllegalStateException("instance must be persisted");
+ }
+ }
+
+ private void ensureNotPersisted()
+ {
+ if (persisted)
+ {
+ throw new IllegalStateException("instance must not be persisted");
+ }
+ }
+
+ private Model model = null;
+
+ private Entity entity = null;
+
+ private BitSet dirtyFlags = null;
+
+ private boolean canWrite = false;
+
+ private boolean persisted = false;
+}
Added:
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/Model.java
URL:
http://svn.apache.org/viewvc/velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/Model.java?rev=1857755&view=auto
==============================================================================
---
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/Model.java
(added)
+++
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/Model.java
Thu Apr 18 15:04:54 2019
@@ -0,0 +1,69 @@
+package org.apache.velocity.tools.model;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.apache.velocity.tools.model.impl.BaseModel;
+import org.apache.velocity.tools.model.sql.ConnectionWrapper;
+import org.apache.velocity.tools.model.sql.PooledStatement;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.sql.SQLException;
+
+public class Model extends BaseModel
+{
+ protected static Logger logger = LoggerFactory.getLogger(Model.class);
+
+ public Model()
+ {
+ }
+
+ public Logger getLogger()
+ {
+ return logger;
+ }
+
+ public Model getModel()
+ {
+ return this;
+ }
+
+ /**
+ * Prepare a query.
+ *
+ * @param query an sql query
+ * @return the pooled prepared statement corresponding to the query
+ */
+ protected PooledStatement prepareQuery(String query) throws SQLException
+ {
+ return getStatementPool().prepareQuery(query);
+ }
+
+ protected PooledStatement prepareUpdate(String query) throws SQLException
+ {
+ return getStatementPool().prepareUpdate(query);
+ }
+
+ @Override
+ protected ConnectionWrapper getTransactionConnection() throws SQLException
+ {
+ return super.getTransactionConnection();
+ }
+}
Added:
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/RowAttribute.java
URL:
http://svn.apache.org/viewvc/velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/RowAttribute.java?rev=1857755&view=auto
==============================================================================
---
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/RowAttribute.java
(added)
+++
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/RowAttribute.java
Thu Apr 18 15:04:54 2019
@@ -0,0 +1,83 @@
+package org.apache.velocity.tools.model;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.apache.velocity.tools.model.impl.AttributeHolder;
+import org.apache.velocity.tools.model.sql.PooledStatement;
+
+import java.io.Serializable;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Map;
+
+public class RowAttribute extends Attribute
+{
+ public RowAttribute(String name, AttributeHolder parent)
+ {
+ super(name, parent);
+ }
+
+ public Instance retrieve(Serializable... paramValues) throws SQLException
+ {
+ return retrieveImpl(getParamValues(paramValues));
+ }
+
+ public Instance retrieve(Map source) throws SQLException
+ {
+ return retrieveImpl(getParamValues(source));
+ }
+
+ public Instance retrieve(Map source, Serializable... params) throws
SQLException
+ {
+ return retrieveImpl(getParamValues(source, params));
+ }
+
+ protected Instance retrieveImpl(Serializable... paramValues) throws
SQLException
+ {
+ Instance instance = null;
+ PooledStatement statement = null;
+ try
+ {
+ statement = getModel().prepareQuery(getQuery());
+ statement.getConnection().enterBusyState();
+ ResultSet result = statement.executeQuery(paramValues);
+ if (result.next())
+ {
+ instance = newResultInstance();
+ instance.setInitialValues(statement);
+ }
+ }
+ finally
+ {
+ if (statement != null)
+ {
+ statement.notifyOver();
+ statement.getConnection().leaveBusyState();
+ }
+ }
+ return instance;
+ }
+
+ protected String getQueryMethodName()
+ {
+ return "retrieve";
+ }
+
+}
Added:
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/RowsetAttribute.java
URL:
http://svn.apache.org/viewvc/velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/RowsetAttribute.java?rev=1857755&view=auto
==============================================================================
---
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/RowsetAttribute.java
(added)
+++
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/RowsetAttribute.java
Thu Apr 18 15:04:54 2019
@@ -0,0 +1,84 @@
+package org.apache.velocity.tools.model;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.apache.velocity.tools.model.impl.AttributeHolder;
+import org.apache.velocity.tools.model.impl.RowIterator;
+import org.apache.velocity.tools.model.sql.PooledStatement;
+
+import java.io.Serializable;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Iterator;
+import java.util.Map;
+
+public class RowsetAttribute extends Attribute
+{
+ public RowsetAttribute(String name, AttributeHolder parent)
+ {
+ super(name, parent);
+ }
+
+ public Iterator<Instance> query(Serializable... params) throws SQLException
+ {
+ return queryImpl(getParamValues(params));
+ }
+
+ public Iterator<Instance> query(Map source) throws SQLException
+ {
+ return queryImpl(getParamValues(source));
+ }
+
+ public Iterator<Instance> query(Map source, Serializable... params) throws
SQLException
+ {
+ return queryImpl(getParamValues(source, params));
+ }
+
+ protected Iterator<Instance> queryImpl(Serializable... params) throws
SQLException
+ {
+ Iterator<Instance> iterator = null;
+ PooledStatement statement = null;
+ ResultSet result = null;
+ try
+ {
+ statement = getModel().prepareQuery(getQuery());
+ statement.getConnection().enterBusyState();
+ result = statement.executeQuery(params);
+ iterator = new RowIterator(getParent(), statement, result,
getResultEntity());
+ }
+ finally
+ {
+ if (statement != null)
+ {
+ if (result == null)
+ {
+ statement.notifyOver();
+ }
+ statement.getConnection().leaveBusyState();
+ }
+ }
+ return iterator;
+ }
+
+ protected String getQueryMethodName()
+ {
+ return "query";
+ }
+}
Added:
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/ScalarAttribute.java
URL:
http://svn.apache.org/viewvc/velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/ScalarAttribute.java?rev=1857755&view=auto
==============================================================================
---
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/ScalarAttribute.java
(added)
+++
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/ScalarAttribute.java
Thu Apr 18 15:04:54 2019
@@ -0,0 +1,156 @@
+package org.apache.velocity.tools.model;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.apache.velocity.tools.model.impl.AttributeHolder;
+import org.apache.velocity.tools.model.sql.PooledStatement;
+import org.apache.velocity.tools.model.util.TypeUtils;
+
+import java.io.Serializable;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Map;
+
+public class ScalarAttribute extends Attribute
+{
+ public ScalarAttribute(String name, AttributeHolder parent)
+ {
+ super(name, parent);
+ }
+
+ public Serializable evaluate(Serializable... paramValues) throws
SQLException
+ {
+ return evaluateImpl(getParamValues(paramValues));
+ }
+
+ public Serializable evaluate(Map source) throws SQLException
+ {
+ return evaluateImpl(getParamValues(source));
+ }
+
+ public Serializable evaluate(Map source, Serializable... params) throws
SQLException
+ {
+ return evaluateImpl(getParamValues(source, params));
+ }
+
+ protected Serializable evaluateImpl(Serializable... paramValues) throws
SQLException
+ {
+ Serializable value = null;
+ PooledStatement statement = null;
+ try
+ {
+ statement = getModel().prepareQuery(getQuery());
+ statement.getConnection().enterBusyState();
+ ResultSet result = statement.executeQuery(paramValues);
+ if (result.next())
+ {
+ value = (Serializable)result.getObject(1);
+ if (result.wasNull())
+ {
+ value = null;
+ }
+ }
+ }
+ finally
+ {
+ if (statement != null)
+ {
+ statement.notifyOver();
+ statement.getConnection().leaveBusyState();
+ }
+ }
+ return value;
+ }
+
+ protected String getQueryMethodName()
+ {
+ return "evaluate";
+ }
+
+ public String getString(Serializable... paramValues) throws SQLException
+ {
+ return TypeUtils.toString(evaluate(paramValues));
+ }
+
+ public String getString(Map source) throws SQLException
+ {
+ return TypeUtils.toString(evaluate(source));
+ }
+
+ public Boolean getBoolean(Serializable... paramValues) throws SQLException
+ {
+ return TypeUtils.toBoolean(evaluate(paramValues));
+ }
+
+ public Boolean getBoolean(Map source) throws SQLException
+ {
+ return TypeUtils.toBoolean(evaluate(source));
+ }
+
+ public Short getShort(Serializable... paramValues) throws SQLException
+ {
+ return TypeUtils.toShort(evaluate(paramValues));
+ }
+
+ public Short getShort(Map source) throws SQLException
+ {
+ return TypeUtils.toShort(evaluate(source));
+ }
+
+ public Integer getInteger(Serializable... paramValues) throws SQLException
+ {
+ return TypeUtils.toInteger(evaluate(paramValues));
+ }
+
+ public Integer getInteger(Map source) throws SQLException
+ {
+ return TypeUtils.toInteger(evaluate(source));
+ }
+
+ public Long getLong(Serializable... paramValues) throws SQLException
+ {
+ return TypeUtils.toLong(evaluate(paramValues));
+ }
+
+ public Long getLong(Map source) throws SQLException
+ {
+ return TypeUtils.toLong(evaluate(source));
+ }
+
+ public Float getFloat(Serializable... paramValues) throws SQLException
+ {
+ return TypeUtils.toFloat(evaluate(paramValues));
+ }
+
+ public Float getFloat(Map source) throws SQLException
+ {
+ return TypeUtils.toFloat(evaluate(source));
+ }
+
+ public Double getDouble(Serializable... paramValues) throws SQLException
+ {
+ return TypeUtils.toDouble(evaluate(paramValues));
+ }
+
+ public Double getDouble(Map source) throws SQLException
+ {
+ return TypeUtils.toDouble(evaluate(source));
+ }
+}
Added:
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/Transaction.java
URL:
http://svn.apache.org/viewvc/velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/Transaction.java?rev=1857755&view=auto
==============================================================================
---
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/Transaction.java
(added)
+++
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/Transaction.java
Thu Apr 18 15:04:54 2019
@@ -0,0 +1,73 @@
+package org.apache.velocity.tools.model;
+
+import org.apache.velocity.tools.model.impl.AttributeHolder;
+import org.apache.velocity.tools.model.sql.ConnectionWrapper;
+
+import java.io.Serializable;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+
+public class Transaction extends Action
+{
+ public Transaction(String name, AttributeHolder parent)
+ {
+ super(name, parent);
+ }
+
+ @Override
+ public int performImpl(Serializable... paramValues) throws SQLException
+ {
+ ConnectionWrapper connection = null;
+ try
+ {
+ int changed = 0;
+ connection = getModel().getTransactionConnection();
+ connection.enterBusyState();
+ int param = 0;
+ for (String individualStatement : getStatements())
+ {
+ PreparedStatement statement =
connection.prepareStatement(individualStatement);
+ int paramCount =
statement.getParameterMetaData().getParameterCount();
+ for (int i = 1; i <= paramCount; ++i)
+ {
+ statement.setObject(i, paramValues[param++]);
+ }
+ changed += statement.executeUpdate();
+ }
+ connection.commit();
+ return changed;
+ }
+ catch (SQLException sqle)
+ {
+ if (connection != null)
+ {
+ connection.rollback();
+ }
+ throw sqle;
+ }
+ finally
+ {
+ if (connection != null)
+ {
+ connection.leaveBusyState();
+ }
+ }
+ }
+
+ private List<String> getStatements() throws SQLException
+ {
+ List<String> statements = new ArrayList<>();
+ String[] elements = getQuery().split(";");
+ for (String element : elements)
+ {
+ element = element.trim();
+ if (element.length() > 0)
+ {
+ statements.add(element);
+ }
+ }
+ return statements;
+ }
+}
Added:
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/WrappingInstance.java
URL:
http://svn.apache.org/viewvc/velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/WrappingInstance.java?rev=1857755&view=auto
==============================================================================
---
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/WrappingInstance.java
(added)
+++
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/WrappingInstance.java
Thu Apr 18 15:04:54 2019
@@ -0,0 +1,107 @@
+package org.apache.velocity.tools.model;
+
+import java.io.Serializable;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.sql.SQLException;
+import java.sql.Wrapper;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+
+public class WrappingInstance extends Instance implements Wrapper
+{
+ public WrappingInstance(Entity entity, Object pojo)
+ {
+ super(entity);
+ this.pojo = pojo;
+ this.getters =
Optional.ofNullable(entity.getWrappedInstanceGetters()).orElse(new HashMap<>());
+ this.setters =
Optional.ofNullable(entity.getWrappedInstanceSetters()).orElse(new HashMap<>());
+ }
+
+ @Override
+ public void setInitialValue(String columnName, Serializable value)
+ {
+ Method setter = setters.get(columnName);
+ if (setter == null)
+ {
+ super.setInitialValue(columnName, value);
+ }
+ else
+ {
+ try
+ {
+ setter.invoke(pojo, value);
+ }
+ catch (IllegalAccessException | InvocationTargetException e)
+ {
+ throw new RuntimeException("could not set property " +
columnName, e);
+ }
+ }
+ }
+
+ @Override
+ public Serializable get(Object key)
+ {
+ Method getter = getters.get(key);
+ if (getter == null)
+ {
+ return super.get(key);
+ }
+ else
+ {
+ try
+ {
+ return (Serializable)getter.invoke(pojo);
+ }
+ catch (IllegalAccessException | InvocationTargetException e)
+ {
+ throw new RuntimeException("could not get property " + key, e);
+ }
+ }
+ }
+
+ @Override
+ protected Serializable putImpl(String key, Serializable value)
+ {
+ Method setter = setters.get(key);
+ if (setter == null)
+ {
+ return super.putImpl(key, value);
+ }
+ else
+ {
+ try
+ {
+ return (Serializable)setter.invoke(pojo, value);
+ }
+ catch (IllegalAccessException | InvocationTargetException e)
+ {
+ throw new RuntimeException("could not set property " + key, e);
+ }
+ }
+ }
+
+ private Object pojo;
+ private Map<String, Method> getters = null;
+ private Map<String, Method> setters = null;
+
+ @Override
+ public <T> T unwrap(Class<T> iface) throws SQLException
+ {
+ if (isWrapperFor(iface))
+ {
+ return (T)pojo;
+ }
+ else
+ {
+ throw new SQLException("cannot unwrap towards " + iface.getName());
+ }
+ }
+
+ @Override
+ public boolean isWrapperFor(Class<?> iface) throws SQLException
+ {
+ return iface.isAssignableFrom(pojo.getClass());
+ }
+}
Added:
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/impl/AttributeHolder.java
URL:
http://svn.apache.org/viewvc/velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/impl/AttributeHolder.java?rev=1857755&view=auto
==============================================================================
---
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/impl/AttributeHolder.java
(added)
+++
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/impl/AttributeHolder.java
Thu Apr 18 15:04:54 2019
@@ -0,0 +1,243 @@
+package org.apache.velocity.tools.model.impl;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.apache.velocity.tools.model.Action;
+import org.apache.velocity.tools.model.Attribute;
+import org.apache.velocity.tools.model.Entity;
+import org.apache.velocity.tools.model.Instance;
+import org.apache.velocity.tools.model.Model;
+import org.apache.velocity.tools.model.RowAttribute;
+import org.apache.velocity.tools.model.RowsetAttribute;
+import org.apache.velocity.tools.model.ScalarAttribute;
+import org.slf4j.Logger;
+
+import java.io.Serializable;
+import java.sql.SQLException;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.NavigableMap;
+import java.util.TreeMap;
+
+public abstract class AttributeHolder implements Serializable
+{
+ protected abstract Model getModel();
+
+ protected abstract Logger getLogger();
+
+ protected void initializeAttributes()
+ {
+ for (Attribute attribute : attributesMap.values())
+ {
+ attribute.initialize();
+ }
+ }
+
+ public Attribute getAttribute(String name)
+ {
+ return attributesMap.get(name); // TODO resolveCase?
+ }
+
+ public Serializable evaluate(String name, Serializable... params) throws
SQLException
+ {
+ Attribute attribute = getAttribute(name);
+ if (attribute == null)
+ {
+ throw new IllegalArgumentException("unknown baseAttribute: " +
name);
+ }
+ if (!(attribute instanceof ScalarAttribute))
+ {
+ throw new IllegalArgumentException("not a scalar baseAttribute: " +
name);
+ }
+ return ((ScalarAttribute)attribute).evaluate(params);
+ }
+
+ public Serializable evaluate(String name, Map source) throws SQLException
+ {
+ Attribute attribute = getAttribute(name);
+ if (attribute == null)
+ {
+ throw new IllegalArgumentException("unknown baseAttribute: " +
name);
+ }
+ if (!(attribute instanceof ScalarAttribute))
+ {
+ throw new IllegalArgumentException("not a scalar baseAttribute: "
+ name);
+ }
+ return ((ScalarAttribute)attribute).evaluate(source);
+ }
+
+ protected Serializable evaluate(String name, Map source, Serializable...
params) throws SQLException
+ {
+ Attribute attribute = getAttribute(name);
+ if (attribute == null)
+ {
+ throw new IllegalArgumentException("unknown baseAttribute: " +
name);
+ }
+ if (!(attribute instanceof ScalarAttribute))
+ {
+ throw new IllegalArgumentException("not a scalar baseAttribute: "
+ name);
+ }
+ return ((ScalarAttribute)attribute).evaluate(source, params);
+ }
+
+ public Instance retrieve(String name, Serializable... params) throws
SQLException
+ {
+ Attribute attribute = getAttribute(name);
+ if (attribute == null)
+ {
+ throw new IllegalArgumentException("unknown baseAttribute: " +
name);
+ }
+ if (!(attribute instanceof RowAttribute))
+ {
+ throw new IllegalArgumentException("not a scalar baseAttribute: "
+ name);
+ }
+ return ((RowAttribute)attribute).retrieve(params);
+ }
+
+ public Instance retrieve(String name, Map source) throws SQLException
+ {
+ Attribute attribute = getAttribute(name);
+ if (attribute == null)
+ {
+ throw new IllegalArgumentException("unknown baseAttribute: " +
name);
+ }
+ if (!(attribute instanceof RowAttribute))
+ {
+ throw new IllegalArgumentException("not a scalar baseAttribute: "
+ name);
+ }
+ return ((RowAttribute)attribute).retrieve(source);
+ }
+
+ public Instance retrieve(String name, Map source, Serializable... params)
throws SQLException
+ {
+ Attribute attribute = getAttribute(name);
+ if (attribute == null)
+ {
+ throw new IllegalArgumentException("unknown baseAttribute: " +
name);
+ }
+ if (!(attribute instanceof RowAttribute))
+ {
+ throw new IllegalArgumentException("not a scalar baseAttribute: "
+ name);
+ }
+ return ((RowAttribute)attribute).retrieve(source, params);
+ }
+
+ public Iterator<Instance> query(String name, Serializable... params)
throws SQLException
+ {
+ Attribute attribute = getAttribute(name);
+ if (attribute == null)
+ {
+ throw new IllegalArgumentException("unknown attribute: " + name);
+ }
+ if (!(attribute instanceof RowsetAttribute))
+ {
+ throw new IllegalArgumentException("not a scalar attribute: " +
name);
+ }
+ return ((RowsetAttribute)attribute).query(params);
+ }
+
+ public Iterator<Instance> query(String name, Map source) throws
SQLException
+ {
+ Attribute attribute = getAttribute(name);
+ if (attribute == null)
+ {
+ throw new IllegalArgumentException("unknown attribute: " + name);
+ }
+ if (!(attribute instanceof RowsetAttribute))
+ {
+ throw new IllegalArgumentException("not a scalar attribute: " +
name);
+ }
+ return ((RowsetAttribute)attribute).query(source);
+ }
+
+ public Iterator<Instance> query(String name, Map source, Serializable...
params) throws SQLException
+ {
+ Attribute attribute = getAttribute(name);
+ if (attribute == null)
+ {
+ throw new IllegalArgumentException("unknown attribute: " + name);
+ }
+ if (!(attribute instanceof RowsetAttribute))
+ {
+ throw new IllegalArgumentException("not a scalar attribute: " +
name);
+ }
+ return ((RowsetAttribute)attribute).query(source, params);
+ }
+
+ public int perform(String name, Serializable... params) throws SQLException
+ {
+ Attribute attribute = getAttribute(name);
+ if (attribute == null)
+ {
+ throw new IllegalArgumentException("unknown attribute: " + name);
+ }
+ if (!(attribute instanceof Action))
+ {
+ throw new IllegalArgumentException("not an action attribute: " +
name);
+ }
+ return ((Action)attribute).perform(params);
+ }
+
+ public int perform(String name, Map source) throws SQLException
+ {
+ Attribute attribute = getAttribute(name);
+ if (attribute == null)
+ {
+ throw new IllegalArgumentException("unknown attribute: " + name);
+ }
+ if (!(attribute instanceof Action))
+ {
+ throw new IllegalArgumentException("not an action attribute: " +
name);
+ }
+ return ((Action)attribute).perform(source);
+ }
+
+ public int perform(String name, Map source, Serializable... params) throws
SQLException
+ {
+ Attribute attribute = getAttribute(name);
+ if (attribute == null)
+ {
+ throw new IllegalArgumentException("unknown attribute: " + name);
+ }
+ if (!(attribute instanceof Action))
+ {
+ throw new IllegalArgumentException("not an action attribute: " +
name);
+ }
+ return ((Action)attribute).perform(source, params);
+ }
+
+ protected Entity resolveEntity(String name)
+ {
+ return getModel().getEntity(name);
+ }
+
+ protected void addAttribute(Attribute attribute)
+ {
+ attributesMap.put(attribute.getName(), attribute);
+ }
+
+ public NavigableMap<String, Attribute> getAttributes()
+ {
+ return Collections.unmodifiableNavigableMap(attributesMap);
+ }
+
+ private NavigableMap<String, Attribute> attributesMap = new TreeMap<>();
+}
Added:
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/impl/BaseAttribute.java
URL:
http://svn.apache.org/viewvc/velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/impl/BaseAttribute.java?rev=1857755&view=auto
==============================================================================
---
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/impl/BaseAttribute.java
(added)
+++
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/impl/BaseAttribute.java
Thu Apr 18 15:04:54 2019
@@ -0,0 +1,206 @@
+package org.apache.velocity.tools.model.impl;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.apache.velocity.tools.model.Entity;
+import org.apache.velocity.tools.model.Instance;
+import org.apache.velocity.tools.model.sql.RowValues;
+
+import java.io.Serializable;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+/**
+ * <p>BaseAttribute interface</p>
+ * @author Claude Brisson
+ * @version $Revision: $
+ * @since 3.1
+ */
+
+public abstract class BaseAttribute extends InstanceProducer implements
Serializable
+{
+ public BaseAttribute(String name, AttributeHolder parent)
+ {
+ super(parent.getModel());
+ this.parent = parent;
+ this.attributeName = name;
+ }
+
+ protected void initialize()
+ {
+ if (query != null)
+ {
+ query = query.trim();
+ }
+ }
+
+ public String getName()
+ {
+ return attributeName;
+ }
+
+ public AttributeHolder getParent()
+ {
+ return parent;
+ }
+
+ protected void setResultEntity(String entityName)
+ {
+ setResultEntity(parent.resolveEntity(entityName));
+ }
+
+ public List<String> getParameterNames()
+ {
+ return Collections.unmodifiableList(parameterNames);
+ }
+
+ protected void addQueryPart(String queryPart)
+ {
+ query = query + queryPart;
+ }
+
+ protected void addParameter(String paramName)
+ {
+ parameterNames.add(paramName);
+ query = query + "?";
+ }
+
+ protected boolean getCaching()
+ {
+ return caching;
+ }
+
+ protected Serializable[] getParamValues(RowValues source) throws
SQLException
+ {
+ Serializable[] paramValues = new Serializable[parameterNames.size()];
+ for (int i = 0; i < paramValues.length; ++i)
+ {
+ paramValues[i] = source.get(parameterNames.get(i));
+ }
+ return paramValues;
+ }
+
+ protected Serializable[] getParamValues(Serializable[] paramValues) throws
SQLException
+ {
+ Entity entity = (Entity)Optional.ofNullable(getParent()).filter(x -> x
instanceof Entity).orElse(null);
+ if (entity != null)
+ {
+ for (int i = 0; i < paramValues.length; ++i)
+ {
+ String paramName = parameterNames.get(i);
+ paramValues[i] = entity.filterValue(paramName, paramValues[i]);
+ }
+ }
+ return paramValues;
+ }
+
+ protected Serializable[] getParamValues(Map source) throws SQLException
+ {
+ Serializable[] paramValues = new Serializable[parameterNames.size()];
+ Entity parentEntity =
(Entity)Optional.ofNullable(getParent()).filter(x -> x instanceof
Entity).orElse(null);
+ Entity sourceEntity = Optional.ofNullable(source).filter(x -> x
instanceof Instance).map(i -> ((Instance)i).getEntity()).orElse(null);
+ if (parentEntity == null && sourceEntity == null)
+ {
+ for (int i = 0; i < paramValues.length; ++i)
+ {
+ paramValues[i] =
(Serializable)source.get(parameterNames.get(i));
+ }
+ }
+ else if (parentEntity == null || sourceEntity == null || parentEntity
== sourceEntity)
+ {
+ Entity entity = parentEntity == null ? sourceEntity : parentEntity;
+ for (int i = 0; i < paramValues.length; ++i)
+ {
+ String paramName = parameterNames.get(i);
+ paramValues[i] = entity.filterValue(paramName,
(Serializable)source.get(paramName));
+ }
+ }
+ else
+ {
+ for (int i = 0; i < paramValues.length; ++i)
+ {
+ String paramName = parameterNames.get(i);
+ Serializable value = (Serializable)source.get(paramName);
+ paramValues[i] = parentEntity.hasColumn(paramName) ?
+ parentEntity.filterValue(paramName, value) :
+ sourceEntity.filterValue(paramName, value);
+ }
+ }
+ return paramValues;
+ }
+
+ protected Serializable[] getParamValues(Map source, Serializable[]
additionalParams) throws SQLException
+ {
+ Serializable[] paramValues = new Serializable[parameterNames.size()];
+ Entity parentEntity =
(Entity)Optional.ofNullable(getParent()).filter(x -> x instanceof
Entity).orElse(null);
+ Entity sourceEntity = Optional.ofNullable(source).filter(x -> x
instanceof Instance).map(i -> ((Instance)i).getEntity()).orElse(null);
+ int additionalParamIndex = 0;
+ if (parentEntity == null && sourceEntity == null)
+ {
+ for (int i = 0; i < paramValues.length; ++i)
+ {
+ String paramName = parameterNames.get(i);
+ paramValues[i] = source.containsKey(paramName) ?
(Serializable)source.get(paramName) : additionalParams[additionalParamIndex++];
+ }
+ }
+ else if (parentEntity == null || sourceEntity == null || parentEntity
== sourceEntity)
+ {
+ Entity entity = parentEntity == null ? sourceEntity : parentEntity;
+ for (int i = 0; i < paramValues.length; ++i)
+ {
+ String paramName = parameterNames.get(i);
+ Serializable value = source.containsKey(paramName) ?
(Serializable)source.get(paramName) : additionalParams[additionalParamIndex++];
+ paramValues[i] = entity.filterValue(paramName, value);
+ }
+ }
+ else
+ {
+ for (int i = 0; i < paramValues.length; ++i)
+ {
+ String paramName = parameterNames.get(i);
+ Serializable value = source.containsKey(paramName) ?
(Serializable)source.get(paramName) : additionalParams[additionalParamIndex++];
+ paramValues[i] = parentEntity.hasColumn(paramName) ?
+ parentEntity.filterValue(paramName, value) :
+ sourceEntity.filterValue(paramName, value);
+ }
+ }
+ if (additionalParamIndex != additionalParams.length)
+ {
+ throw new SQLException("too many parameters provided");
+ }
+ return paramValues;
+ }
+
+ protected String getQuery() throws SQLException
+ {
+ return query;
+ }
+
+ private boolean caching = false;
+ private AttributeHolder parent = null;
+ private Entity resultEntity = null;
+ private String attributeName = null;
+ private String query = "";
+ protected List<String> parameterNames = new ArrayList<>();
+}
Added:
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/impl/BaseEntity.java
URL:
http://svn.apache.org/viewvc/velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/impl/BaseEntity.java?rev=1857755&view=auto
==============================================================================
---
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/impl/BaseEntity.java
(added)
+++
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/impl/BaseEntity.java
Thu Apr 18 15:04:54 2019
@@ -0,0 +1,502 @@
+package org.apache.velocity.tools.model.impl;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.apache.velocity.tools.config.ConfigurationException;
+import org.apache.velocity.tools.model.Action;
+import org.apache.velocity.tools.model.Attribute;
+import org.apache.velocity.tools.model.Entity;
+import org.apache.velocity.tools.model.Instance;
+import org.apache.velocity.tools.model.Model;
+import org.apache.velocity.tools.model.RowAttribute;
+import org.apache.velocity.tools.model.RowsetAttribute;
+import org.apache.velocity.tools.model.ScalarAttribute;
+import org.apache.velocity.tools.model.filter.Filter;
+
+import java.beans.PropertyDescriptor;
+import java.io.Serializable;
+import java.lang.reflect.Method;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.BitSet;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+public abstract class BaseEntity extends AttributeHolder
+{
+ public BaseEntity(String name, Model model)
+ {
+ this.model = model;
+ this.name = name;
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+
+ public String getTable() { return sqlName; }
+
+ public void setTable(String table)
+ {
+ this.sqlName = table;
+ }
+
+ protected void addColumn(String name, String sqlName, int type, Integer
size, boolean generated)
+ {
+ addColumn(new Entity.Column(name, sqlName, type, size, generated));
+ }
+
+ protected void addColumn(Entity.Column column)
+ {
+ Entity.Column previous = columns.put(column.name, column);
+ if (previous != null)
+ {
+ throw new ConfigurationException("column name collision: " +
getName() + "." + column.name + " mapped on " + getTable() + "." +
previous.sqlName + " and on " + getTable() + "." + column.sqlName);
+ }
+ column.setIndex(columns.size() - 1);
+
Optional.ofNullable(getModel().getFilters().getReadFilters().getColumnEntry(sqlName,
column.sqlName)).ifPresent(filter -> column.setReadFilter(filter));
+
Optional.ofNullable(getModel().getFilters().getWriteFilters().getColumnEntry(sqlName,
column.sqlName)).ifPresent(filter -> column.setWriteFilter(filter));
+ columnsMapping.put(column.sqlName, column.name);
+ }
+
+ public List<Entity.Column> getPrimaryKey()
+ {
+ return primaryKey;
+ }
+
+ public BitSet getPrimaryKeyMask()
+ {
+ return (BitSet)primaryKeyMask.clone();
+ }
+
+ public BitSet getNonKeyMask()
+ {
+ BitSet ret = (BitSet)primaryKeyMask.clone();
+ ret.flip(0, columns.size());
+ return ret;
+ }
+
+ protected List<String> getSqlPrimaryKey()
+ {
+ return sqlPrimaryKey != null ?
Collections.unmodifiableList(sqlPrimaryKey) : null;
+ }
+
+ protected void setSqlPrimaryKey(String ... sqlPrimaryKey) // receives sql
names
+ {
+ this.sqlPrimaryKey = Arrays.asList(sqlPrimaryKey);
+
+ // now we can initialize entity internal attributes
+ initialize();
+ }
+
+ public Collection<Entity.Column> getColumns()
+ {
+ return Collections.unmodifiableCollection(columns.values());
+ }
+
+ public List<String> getColumnNames()
+ {
+ return Collections.unmodifiableList(columnNames);
+ }
+
+ public Entity.Column getColumn(int index)
+ {
+ return columns.get(columnNames.get(index));
+ }
+
+ public Entity.Column getColumn(String columnName)
+ {
+ return columns.get(columnName);
+ }
+
+ public String getColumnName(int index)
+ {
+ return columnNames.get(index);
+ }
+
+ public String translateColumnName(String sqlColumnName)
+ {
+ String ret = columnsMapping.get(sqlColumnName);
+ if (ret == null)
+ {
+ try
+ {
+ ret =
getModel().getIdentifiers().getDefaultColumnLeaf().apply(sqlColumnName);
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+ return ret;
+ }
+
+ public void delete(Map source) throws SQLException
+ {
+ delete.perform(source);
+ }
+
+ public void insert(Map source) throws SQLException
+ {
+ insert.perform(source);
+ }
+
+ public void update(Map source) throws SQLException
+ {
+ update.perform(source);
+ }
+
+ public Model getModel()
+ {
+ return model;
+ }
+
+ public Instance newInstance()
+ {
+ return instanceBuilder.create();
+ }
+
+ protected Map<String, Method> getWrappedInstanceGetters()
+ {
+ return wrappedInstanceGetters;
+ }
+
+ protected Map<String, Method> getWrappedInstanceSetters()
+ {
+ return wrappedInstanceSetters;
+ }
+
+ /**
+ * initialization
+ */
+
+ protected void initialize()
+ {
+ initializeAttributes();
+ // TODO - lazy initialization
+ if (sqlName == null)
+ {
+ sqlName = name;
+ }
+ columnNames = columns.values().stream().map(x ->
x.name).collect(Collectors.toList());
+
+ String tableIdentifier = quoteIdentifier(getTable());
+
+ iterateAttribute = new RowsetAttribute("iterate", this);
+ iterateAttribute.setResultEntity((Entity)this);
+ iterateAttribute.addQueryPart("SELECT * FROM " + tableIdentifier);
+
+ countAttribute = new ScalarAttribute("getCount", this);
+ countAttribute.addQueryPart("SELECT COUNT(*) FROM " + tableIdentifier);
+
+ if (sqlPrimaryKey != null && sqlPrimaryKey.size() > 0)
+ {
+ primaryKey = getSqlPrimaryKey().stream().map(sql ->
columns.get(columnsMapping.get(sql))).collect(Collectors.toList());
+ primaryKeyMask = new BitSet();
+ primaryKey.stream().forEach(col -> { col.setKeyColumn();
primaryKeyMask.set(col.getIndex()); });
+
+ fetchAttribute = new RowAttribute("retrieve", this);
+ fetchAttribute.setResultEntity((Entity)this);
+ fetchAttribute.addQueryPart("SELECT * FROM " + tableIdentifier + "
WHERE ");
+ addKeyMapToAttribute(fetchAttribute);
+
+ delete = new Action("delete", this);
+ delete.addQueryPart("DELETE FROM " + tableIdentifier + " WHERE ");
+ addKeyMapToAttribute(delete);
+
+ update = new UpdateAction(this);
+ update.addQueryPart("UPDATE " + tableIdentifier + " SET ");
+ update.addParameter(UpdateAction.DYNAMIC_PART);
+ update.addQueryPart(" WHERE ");
+ addKeyMapToAttribute(update);
+
+ insert = new Action("insert", this);
+ insert.addQueryPart("INSERT INTO " + tableIdentifier + "(");
+ int nonGeneratedColumns = 0;
+ List<String> params = new ArrayList<>();
+ for (Entity.Column column : columns.values())
+ {
+ if (!column.generated)
+ {
+ if (nonGeneratedColumns++ > 0)
+ {
+ insert.addQueryPart(", ");
+ }
+ insert.addQueryPart(quoteIdentifier(column.sqlName));
+ params.add(column.name);
+ }
+ }
+ insert.addQueryPart(") VALUES (");
+ int col = 0;
+ for (String param : params)
+ {
+ if (col++ > 0)
+ {
+ insert.addQueryPart(", ");
+ }
+ insert.addParameter(param);
+ }
+ insert.addQueryPart(")");
+ }
+ }
+
+ private void addKeyMapToAttribute(Attribute attribute)
+ {
+ for (int i = 0; i < sqlPrimaryKey.size(); ++i)
+ {
+ if (i > 0)
+ {
+ attribute.addQueryPart(" AND ");
+ }
+ attribute.addQueryPart(quoteIdentifier(sqlPrimaryKey.get(i)) + " =
");
+ attribute.addParameter(getColumn(i).name);
+ }
+ }
+
+ protected void declareUpstreamJoin(String upstreamAttributeName, Entity
pkEntity, List<String> fkColumns)
+ {
+ Attribute upstreamAttribute = new RowAttribute(upstreamAttributeName,
this);
+ upstreamAttribute.setResultEntity(pkEntity);
+ List<String> pkColumns = pkEntity.getSqlPrimaryKey();
+ upstreamAttribute.addQueryPart("SELECT * FROM " +
quoteIdentifier(pkEntity.getTable()) + " WHERE ");
+ for (int col = 0; col < pkColumns.size(); ++ col)
+ {
+ if (col > 0)
+ {
+ upstreamAttribute.addQueryPart(" AND ");
+ }
+ upstreamAttribute.addQueryPart(quoteIdentifier(pkColumns.get(col))
+ " = ");
+
upstreamAttribute.addParameter(translateColumnName(fkColumns.get(col)));
+ }
+ addAttribute(upstreamAttribute);
+ }
+
+ public void declareDownstreamJoin(String downstreamAttributeName, Entity
fkEntity, List<String> fkColumns)
+ {
+ Attribute downstreamAttribute = new
RowsetAttribute(downstreamAttributeName, this);
+ downstreamAttribute.setResultEntity(fkEntity);
+ downstreamAttribute.addQueryPart("SELECT * FROM " +
quoteIdentifier(fkEntity.getTable()) + " WHERE ");
+ for (int col = 0; col < sqlPrimaryKey.size(); ++ col)
+ {
+ if (col > 0)
+ {
+ downstreamAttribute.addQueryPart(" AND ");
+ }
+
downstreamAttribute.addQueryPart(quoteIdentifier(fkColumns.get(col)) + " = ");
+
downstreamAttribute.addParameter(translateColumnName(sqlPrimaryKey.get(col)));
+ }
+ addAttribute(downstreamAttribute);
+ }
+
+ public void declareExtendedJoin(String joinAttributeName, List<String>
leftFKCols, Entity joinEntity, List<String> rightFKCols, Entity rightEntity)
+ {
+ List<String> rightPK = rightEntity.getSqlPrimaryKey();
+ Attribute extendedJoin = new RowsetAttribute(joinAttributeName, this);
+ extendedJoin.setResultEntity(rightEntity);
+ extendedJoin.addQueryPart("SELECT " +
quoteIdentifier(rightEntity.getTable()) + ".* FROM " +
+ quoteIdentifier(joinEntity.getTable()) + "JOIN " +
quoteIdentifier(rightEntity.getTable()) + " ON ");
+ for (int col = 0; col < rightPK.size(); ++col)
+ {
+ if (col > 0)
+ {
+ extendedJoin.addQueryPart(" AND ");
+ }
+ extendedJoin.addQueryPart(quoteIdentifier(rightEntity.getTable())
+ "." + quoteIdentifier(rightPK.get(col)) + " = " +
quoteIdentifier(joinEntity.getTable()) + "." +
quoteIdentifier(rightFKCols.get(col)));
+ }
+ extendedJoin.addQueryPart(" WHERE ");
+ for (int col = 0; col < sqlPrimaryKey.size(); ++col)
+ {
+ if (col > 0)
+ {
+ extendedJoin.addQueryPart(" AND ");
+ }
+ extendedJoin.addQueryPart(quoteIdentifier(leftFKCols.get(col)) + "
= ");
+
extendedJoin.addParameter(translateColumnName(sqlPrimaryKey.get(col)));
+ }
+ addAttribute(extendedJoin);
+ }
+
+ protected final String quoteIdentifier(String id)
+ {
+ return getModel().quoteIdentifier(id);
+ }
+
+ protected final Serializable filterValue(String columnName, Serializable
value) throws SQLException
+ {
+ if (value != null)
+ {
+ Column column = getColumn(columnName);
+ if (column != null)
+ {
+ value = column.write(value);
+ }
+ Filter<Serializable> typeFilter =
getModel().getFilters().getWriteFilters().getTypeEntry(value.getClass());
+ if (typeFilter != null)
+ {
+ value = typeFilter.apply(value);
+ }
+ }
+ return value;
+ }
+
+ public boolean hasColumn(String key)
+ {
+ return columns.containsKey(key);
+ }
+
+ protected void setInstanceBuilder(InstanceBuilder builder)
+ {
+ setInstanceBuilder(builder, null);
+ }
+
+ protected void setInstanceBuilder(InstanceBuilder builder,
PropertyDescriptor[] properties)
+ {
+ this.instanceBuilder = builder;
+ if (properties != null)
+ {
+ wrappedInstanceGetters = new HashMap<String, Method>();
+ wrappedInstanceSetters = new HashMap<String, Method>();
+ for (PropertyDescriptor descriptor : properties)
+ {
+ String name = descriptor.getName();
+
Optional.ofNullable(descriptor.getReadMethod()).ifPresent(getter ->
wrappedInstanceGetters.put(name, getter));
+
Optional.ofNullable(descriptor.getWriteMethod()).ifPresent(setter ->
wrappedInstanceSetters.put(name, setter));
+ }
+ }
+ }
+
+ protected ScalarAttribute getCountAttribute()
+ {
+ return countAttribute;
+ }
+
+ protected RowAttribute getFetchAttribute()
+ {
+ return fetchAttribute;
+ }
+ protected RowsetAttribute getIterateAttribute()
+ {
+ return iterateAttribute;
+ }
+ private String name = null;
+ private String sqlName = null;
+ private Model model = null;
+ private Map<String, String> columnsMapping = new HashMap<>();
+ private LinkedHashMap<String, Entity.Column> columns = new
LinkedHashMap<>();
+ private List<String> columnNames = null; // redundant with 'columns'
field, but needed for random access
+ private List<String> sqlPrimaryKey = null;
+
+ private List<Entity.Column> primaryKey = null;
+ private BitSet primaryKeyMask = null;
+ private ScalarAttribute countAttribute = null;
+ private RowAttribute fetchAttribute = null;
+ private RowsetAttribute iterateAttribute = null;
+ private Action delete = null;
+
+ private Action insert = null;
+
+ private Action update = null;
+
+ private InstanceBuilder instanceBuilder = null;
+
+ private Map<String, Method> wrappedInstanceGetters = null;
+
+ private Map<String, Method> wrappedInstanceSetters = null;
+
+ @FunctionalInterface
+ protected interface InstanceBuilder
+ {
+ Instance create();
+ }
+
+ public static class Column
+ {
+ public Column(String name, String sqlName, int type, Integer size,
boolean generated)
+ {
+ this.name = name;
+ this.sqlName = sqlName;
+ this.type = type;
+ this.size = size;
+ this.generated = generated;
+ }
+
+ public int getIndex()
+ {
+ return index;
+ }
+
+ protected void setIndex(int index)
+ {
+ this.index = index;
+ }
+
+ /**
+ * Whether column is the primary key, or part of the primary key
+ * @return
+ */
+ public boolean isKeyColumn()
+ {
+ return keyColumn;
+ }
+
+ protected void setKeyColumn()
+ {
+ keyColumn = true;
+ }
+
+ protected void setReadFilter(Filter<Serializable> readFilter)
+ {
+ this.readFilter = readFilter;
+ }
+
+ protected void setWriteFilter(Filter<Serializable> writeFilter)
+ {
+ this.writeFilter = writeFilter;
+ }
+
+ public final Serializable read(Serializable value) throws SQLException
+ {
+ return readFilter.apply(value);
+ }
+
+ public final Serializable write(Serializable value) throws SQLException
+ {
+ return writeFilter.apply(value);
+ }
+
+ public final String name;
+ public final String sqlName;
+ public final int type;
+ public final Integer size;
+ public final boolean generated;
+ private int index = -1;
+ private boolean keyColumn = false;
+ private Filter<Serializable> readFilter = Filter.identity();
+ private Filter<Serializable> writeFilter = Filter.identity();
+ }
+}