Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.efaps.db.print.OneSelect Maven / Gradle / Ivy
Go to download
eFaps is a framework used to map objects with or without attached files to
a relational database and optional file systems (only for attaches files). Configurable access control can be provided down to object and attribute level depending on implementation and use case. Depending on requirements, events (like triggers) allow to implement business logic and to separate business logic from user interface.
The framework includes integrations (e.g. webdav, full text search) and a web application as 'simple' configurable user interface. Some best practises, example web application modules (e.g. team work module) support administrators and implementers using this framework.
/*
* Copyright 2003 - 2012 The eFaps Team
*
* Licensed 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.
*
* Revision: $Rev: 8564 $
* Last Changed: $Date: 2013-01-21 10:09:37 -0500 (Mon, 21 Jan 2013) $
* Last Changed By: $Author: [email protected] $
*/
package org.efaps.db.print;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.efaps.admin.datamodel.Attribute;
import org.efaps.admin.datamodel.AttributeSet;
import org.efaps.admin.datamodel.Type;
import org.efaps.db.AbstractPrintQuery;
import org.efaps.db.Instance;
import org.efaps.db.print.value.AbstractValueSelect;
import org.efaps.db.print.value.AttributeValueSelect;
import org.efaps.db.print.value.BaseValueSelect;
import org.efaps.db.print.value.ClassificationValueSelect;
import org.efaps.db.print.value.FormatValueSelect;
import org.efaps.db.print.value.IDValueSelect;
import org.efaps.db.print.value.InstanceValueSelect;
import org.efaps.db.print.value.LabelValueSelect;
import org.efaps.db.print.value.LengthValueSelect;
import org.efaps.db.print.value.OIDValueSelect;
import org.efaps.db.print.value.TypeValueSelect;
import org.efaps.db.print.value.UUIDValueSelect;
import org.efaps.db.print.value.UoMValueSelect;
import org.efaps.db.print.value.ValueValueSelect;
import org.efaps.db.wrapper.SQLSelect;
import org.efaps.util.EFapsException;
/**
* This class is used as a part of one complete statement to be executed
* against the eFaps database. It will normally return the object for one
* attribute. The OneSelect can consist from only one attribute or of a
* series of PrintQuery.ISelectPart
*
* @author The eFaps Team
* @version $Id: OneSelect.java 8564 2013-01-21 15:09:37Z [email protected] $
*/
public class OneSelect
{
/**
* The select this OneSelect belongs to.
*/
private final String selectStmt;
/**
* List of select parts.
*/
private final List selectParts = new ArrayList();
/**
* FromSelect this OneSelect belong to.
*/
private LinkFromSelect fromSelect;
/**
* List of objects retrieved from the ResultSet returned
* from the eFaps database. It represent one row in a result set.
*/
private final List objectList = new ArrayList();
/**
* List of ids retrieved from the ResultSet returned
* from the eFaps database. It represent one row in a result set.
*/
private final List idList = new ArrayList();
/**
* If this OneSelect is a FromSelect the relation Ids are stored in this
* List.
*/
private final List relIdList = new ArrayList();
/**
* table index for this table. It will finally contain the index of
* the table the attribute belongs to.
*/
private int tableIndex;
/**
* PrintQuery this ONeSelct belongs to.
*/
private final AbstractPrintQuery query;
/**
* Iterator for the objects.
*/
private Iterator objectIterator;
/**
* Iterator for the ids.
*/
private Iterator idIterator;
/**
* current id.
*/
private Long currentId;
/**
* Currecnt object.
*/
private Object currentObject;
/**
* Valueselect of this oneselect.
*/
private AbstractValueSelect valueSelect;
/**
* @param _query PrintQuery this OneSelect belongs to
* @param _selectStmt selectStatement this OneSelect belongs to
*/
public OneSelect(final AbstractPrintQuery _query,
final String _selectStmt)
{
this.query = _query;
this.selectStmt = _selectStmt;
}
/**
* @param _query AbstractPrintQuery this OneSelect belongs to
* @param _attr attribute to be used in this OneSelect
*/
public OneSelect(final AbstractPrintQuery _query,
final Attribute _attr)
{
this.query = _query;
this.selectStmt = null;
this.valueSelect = new AttributeValueSelect(this, _attr);
}
/**
* Getter method for instance variable {@link #valueSelect}.
*
* @return value of instance variable {@link #valueSelect}
*/
public AbstractValueSelect getValueSelect()
{
return this.valueSelect;
}
/**
* Setter method for instance variable {@link #valueSelect}.
*
* @param _valueSelect value for instance variable {@link #valueSelect}
*/
public void setValueSelect(final AbstractValueSelect _valueSelect)
{
this.valueSelect = _valueSelect;
}
/**
* Getter method for instance variable {@link #selectStmt}.
*
* @return value of instance variable {@link #selectStmt}
*/
public String getSelectStmt()
{
return this.selectStmt;
}
/**
* Getter method for instance variable {@link #selectParts}.
*
* @return value of instance variable {@link #selectParts}
*/
public List getSelectParts()
{
return this.selectParts;
}
/**
* Setter method for instance variable {@link #attribute}.
* @param _attribute Attribute to set
*/
public void setAttribute(final Attribute _attribute)
{
this.valueSelect = new AttributeValueSelect(this, _attribute);
}
/**
* Add an Object for this OneSelect.
*
* @param _rs ResultSet from the eFaps database
* @throws SQLException on error
*/
public void addObject(final ResultSet _rs)
throws SQLException
{
final ResultSetMetaData metaData = _rs.getMetaData();
// store the ids also
this.idList.add(_rs.getLong(1));
if (getFromSelect() != null) {
final int column = "id".equals(this.valueSelect.getValueType())
? this.valueSelect.getColIndexs().get(0) : 2;
this.relIdList.add(_rs.getLong(column));
}
Object object = null;
AbstractValueSelect tmpValueSelect;
if (this.valueSelect == null) {
tmpValueSelect = this.fromSelect.getMainOneSelect().getValueSelect();
} else {
tmpValueSelect = this.valueSelect;
}
if (tmpValueSelect.getParentSelectPart() != null) {
tmpValueSelect.getParentSelectPart().addObject(_rs);
}
if (tmpValueSelect.getColIndexs().size() > 1) {
final Object[] objArray = new Object[tmpValueSelect.getColIndexs().size()];
int i = 0;
for (final Integer colIndex : tmpValueSelect.getColIndexs()) {
switch (metaData.getColumnType(colIndex)) {
case java.sql.Types.TIMESTAMP:
objArray[i] = _rs.getTimestamp(colIndex);
break;
default:
objArray[i] = _rs.getObject(colIndex);
}
i++;
}
object = objArray;
} else if (tmpValueSelect.getColIndexs().size() > 0) {
switch (metaData.getColumnType(tmpValueSelect.getColIndexs().get(0))) {
case java.sql.Types.TIMESTAMP:
object = _rs.getTimestamp(tmpValueSelect.getColIndexs().get(0));
break;
default:
object = _rs.getObject(tmpValueSelect.getColIndexs().get(0));
}
}
this.objectList.add(object);
}
/**
* Add a classification name evaluated from an
* class[CLASSIFICATIONNAME]
part of an select statement.
* @param _classificationName name of the classification
*/
public void addClassificationSelectPart(final String _classificationName)
{
this.selectParts.add(new ClassSelectPart(_classificationName));
}
/**
* Add the name of the attribute the link must go to, evaluated from an
* linkTo[ATTRIBUTENAME]
part of an select statement.
* @param _linkTo name of the attribute the link must go to
*/
public void addLinkToSelectPart(final String _linkTo)
{
Type type;
// if a previous select exists it is based on the previous select,
// else it is based on the basic table
if (this.selectParts.size() > 0) {
type = this.selectParts.get(this.selectParts.size() - 1).getType();
} else {
type = this.query.getMainType();
}
final LinkToSelectPart linkto = new LinkToSelectPart(_linkTo, type);
this.selectParts.add(linkto);
}
/**
* Add the select part to connect the general store.
*/
public void addFileSelectPart()
{
Type type;
// if a previous select exists it is based on the previous select,
// else it is based on the basic table
if (this.selectParts.size() > 0) {
type = this.selectParts.get(this.selectParts.size() - 1).getType();
} else {
type = this.query.getMainType();
}
final FileSelectPart linkto = new FileSelectPart(type);
this.selectParts.add(linkto);
}
/**
* Add the select part to connect the general instances.
*/
public void addGenInstSelectPart()
{
Type type;
// if a previous select exists it is based on the previous select,
// else it is based on the basic table
if (this.selectParts.size() > 0) {
type = this.selectParts.get(this.selectParts.size() - 1).getType();
} else {
type = this.query.getMainType();
}
final GenInstSelectPart linkto = new GenInstSelectPart(type);
this.selectParts.add(linkto);
}
/**
* Add the name of the attribute the link must go to, evaluated from an
* attributeSet[ATTRIBUTESETNAME]
part of an select statement.
* @param _attributeSet name of the attribute the link must go to
*/
public void addAttributeSetSelectPart(final String _attributeSet)
{
Type type;
// if a previous select exists it is based on the previous select,
// else it is based on the basic table
if (this.selectParts.size() > 0) {
type = this.selectParts.get(this.selectParts.size() - 1).getType();
} else {
type = this.query.getMainType();
}
final AttributeSet set = AttributeSet.find(type.getName(), _attributeSet);
final String linkFrom = set.getName() + "#" + set.getAttributeName();
this.fromSelect = new LinkFromSelect(linkFrom);
}
/**
* Add the name of the type and attribute the link comes from,
* evaluated from an linkTo[TYPENAME#ATTRIBUTENAME]
* part of an select statement.
* @param _linkFrom name of the attribute the link comes from
*/
public void addLinkFromSelectPart(final String _linkFrom)
{
this.fromSelect = new LinkFromSelect(_linkFrom);
}
/**
* Method used to append to the from part of an SQL statement.
*
* @param _select SQL select wrapper
*/
public void append2SQLFrom(final SQLSelect _select)
{
// for attributes it must be evaluated if the attribute is inside a child table
if ((this.valueSelect != null) && "attribute".equals(this.valueSelect.getValueType())) {
Type type;
if (this.selectParts.size() > 0) {
type = this.selectParts.get(this.selectParts.size() - 1).getType();
} else {
type = this.query.getMainType();
}
Attribute attr = this.valueSelect.getAttribute();
if (attr == null) {
attr = type.getAttribute(((AttributeValueSelect) this.valueSelect).getAttrName());
}
// if the attr is still null that means that the type does not have this attribute, so last
// chance to find the attribute is to search in the child types
if (attr == null) {
for (final Type childType : type.getChildTypes()) {
attr = childType.getAttribute(((AttributeValueSelect) this.valueSelect).getAttrName());
if (attr != null) {
((AttributeValueSelect) this.valueSelect).setAttribute(attr);
break;
}
}
}
if (attr != null && attr.getTable() != null && !attr.getTable().equals(type.getMainTable())) {
final ChildTableSelectPart childtable = new ChildTableSelectPart(type, attr.getTable());
this.selectParts.add(childtable);
}
}
for (final ISelectPart sel : this.selectParts) {
this.tableIndex = sel.join(this, _select, this.tableIndex);
}
}
/**
* Method used to append to the select part of an SQL statement.
*
* @param _select SQL select statement
* @param _colIndex actual column index
* @return number of columns added in this part of the SQL statement
*/
public int append2SQLSelect(final SQLSelect _select,
final int _colIndex)
{
Type type;
if (this.selectParts.size() > 0) {
type = this.selectParts.get(this.selectParts.size() - 1).getType();
} else {
type = this.query.getMainType();
}
int ret;
if (this.valueSelect == null) {
ret = this.fromSelect.getMainOneSelect().getValueSelect().append2SQLSelect(type, _select, this.tableIndex,
_colIndex);
} else {
ret = this.valueSelect.append2SQLSelect(type, _select, this.tableIndex, _colIndex);
}
return ret;
}
/**
* Method used to append to the where part of an SQL statement.
*
* @param _select SQL select wrapper
*/
public void append2SQLWhere(final SQLSelect _select)
{
for (final ISelectPart part : this.selectParts) {
part.add2Where(this, _select);
}
}
/**
* Method to analyse the select statement. Meaning the the different
* select parts will be added to {@link #selectParts}.
* @throws EFapsException on error
*/
public void analyzeSelectStmt() throws EFapsException
{
final Pattern mainPattern = Pattern.compile("[a-z]+\\[.+?\\]|[a-z]+");
final Pattern attrPattern = Pattern.compile("(?<=\\[)[0-9a-zA-Z_]*(?=\\])");
final Pattern linkfomPat = Pattern.compile("(?<=\\[)[0-9a-zA-Z_#:]*(?=\\])");
final Pattern formatPat = Pattern.compile("(?<=\\[).*(?=\\])");
final Matcher mainMatcher = mainPattern.matcher(this.selectStmt);
OneSelect currentSelect = this;
while (mainMatcher.find()) {
final String part = mainMatcher.group();
if (part.startsWith("class[")) {
final Matcher matcher = attrPattern.matcher(part);
if (matcher.find()) {
currentSelect.addClassificationSelectPart(matcher.group());
}
} else if (part.startsWith("linkto")) {
final Matcher matcher = attrPattern.matcher(part);
if (matcher.find()) {
currentSelect.addLinkToSelectPart(matcher.group());
}
} else if (part.startsWith("attributeset")) {
final Matcher matcher = attrPattern.matcher(part);
if (matcher.find()) {
currentSelect.addValueSelect(new IDValueSelect(currentSelect));
currentSelect.addAttributeSetSelectPart(matcher.group());
currentSelect = currentSelect.fromSelect.getMainOneSelect();
}
} else if (part.startsWith("attribute")) {
final Matcher matcher = attrPattern.matcher(part);
if (matcher.find()) {
currentSelect.addValueSelect(new AttributeValueSelect(currentSelect, matcher.group()));
}
} else if (part.startsWith("linkfrom")) {
final Matcher matcher = linkfomPat.matcher(part);
if (matcher.find()) {
currentSelect.addValueSelect(new IDValueSelect(currentSelect));
currentSelect.addLinkFromSelectPart(matcher.group());
currentSelect = currentSelect.fromSelect.getMainOneSelect();
}
} else if (part.equalsIgnoreCase("oid")) {
currentSelect.addValueSelect(new OIDValueSelect(currentSelect));
} else if (part.equalsIgnoreCase("type")) {
currentSelect.addValueSelect(new TypeValueSelect(currentSelect));
} else if (part.equalsIgnoreCase("instance")) {
currentSelect.addValueSelect(new InstanceValueSelect(currentSelect));
} else if (part.equalsIgnoreCase("label")) {
currentSelect.addValueSelect(new LabelValueSelect(currentSelect));
} else if (part.equalsIgnoreCase("id")) {
currentSelect.addValueSelect(new IDValueSelect(currentSelect));
} else if (part.equalsIgnoreCase("uuid")) {
currentSelect.addValueSelect(new UUIDValueSelect(currentSelect));
} else if (part.equalsIgnoreCase("class")) {
currentSelect.addValueSelect(new ClassificationValueSelect(currentSelect));
} else if (part.equalsIgnoreCase("value")) {
currentSelect.addValueSelect(new ValueValueSelect(currentSelect));
} else if (part.equalsIgnoreCase("base")) {
currentSelect.addValueSelect(new BaseValueSelect(currentSelect));
} else if (part.equalsIgnoreCase("uom")) {
currentSelect.addValueSelect(new UoMValueSelect(currentSelect));
} else if (part.equalsIgnoreCase("file")) {
currentSelect.addFileSelectPart();
} else if (part.equalsIgnoreCase("length")) {
currentSelect.addValueSelect(new LengthValueSelect(currentSelect));
} else if (part.startsWith("format")) {
final Matcher matcher = formatPat.matcher(part);
if (matcher.find()) {
currentSelect.addValueSelect(new FormatValueSelect(currentSelect, matcher.group()));
}
}
}
}
/**
* @param _valueSelect AbstractValueSelect to add
* @throws EFapsException on error
*/
private void addValueSelect(final AbstractValueSelect _valueSelect) throws EFapsException
{
if (this.valueSelect != null) {
this.valueSelect.addChildValueSelect(_valueSelect);
} else if (this.fromSelect != null && !(this.query instanceof LinkFromSelect)) {
this.fromSelect.getMainOneSelect().addValueSelect(_valueSelect);
} else {
this.valueSelect = _valueSelect;
}
}
/**
* Get an object from a n to 1 Relation.Therefore the given object
* is used to filter only the valid values from the by the Database
* returned objects.
* @param _object Object used as filter (must be an Long
Id)
* @return Object
* @throws EFapsException on error
*/
private Object getObject(final Object _object) throws EFapsException
{
Object ret = null;
// inside a fromobject the correct value must be set
if (_object instanceof Number && this.fromSelect != null) {
final List tmpList = new ArrayList();
final Long id = ((Number) _object).longValue();
final Iterator relIter = this.relIdList.iterator();
final Iterator objIter = this.objectList.iterator();
while (relIter.hasNext()) {
final Long rel = relIter.next();
final Object obj = objIter.next();
if (rel.equals(id)) {
tmpList.add(obj);
}
}
ret = this.valueSelect.getValue(tmpList);
} else {
ret = this.getObject();
}
return ret;
}
/**
* Method to get the Object for this OneSelect.
* @return object for this OneSelect
* @throws EFapsException on error
*/
public Object getObject() throws EFapsException
{
Object ret = null;
if (this.valueSelect == null) {
if (this.fromSelect.hasResult()) {
ret = this.fromSelect.getMainOneSelect().getObject(this.currentObject);
}
} else {
// if the currentObject is not null it means that the values are
// retrieved by iteration through the object list
if (this.currentId != null) {
ret = this.valueSelect.getValue(this.currentObject);
} else {
ret = this.valueSelect.getValue(this.objectList);
}
}
return ret;
}
/**
* Method returns the instances this OneSelect has returned.
*
* @return Collection of Instances
* @throws EFapsException on error
*/
@SuppressWarnings("unchecked")
public List getInstances()
throws EFapsException
{
final List ret = new ArrayList();
// no value select means, that the from select must be asked
if (this.valueSelect == null) {
ret.addAll(this.fromSelect.getMainOneSelect().getInstances());
} else {
// if an oid select was given the oid is evaluated
if ("oid".equals(this.valueSelect.getValueType())) {
for (final Object object : this.objectList) {
final Instance inst = Instance.get((String) this.valueSelect.getValue(object));
if (inst.isValid()) {
ret.add(inst);
}
}
} else {
List idTmp;
if (this.valueSelect.getParentSelectPart() != null
&& this.valueSelect.getParentSelectPart() instanceof LinkToSelectPart) {
idTmp = (List) this.valueSelect.getParentSelectPart().getObject();
} else {
idTmp = this.idList;
}
for (final Long id : idTmp) {
ret.add(Instance.get(this.valueSelect.getAttribute().getParent(), id.toString()));
}
}
}
return ret;
}
/**
* Getter method for instance variable {@link #attribute}.
*
* @return value of instance variable {@link #attribute}
*/
public Attribute getAttribute()
{
Attribute ret;
if (this.valueSelect == null) {
ret = this.fromSelect.getMainOneSelect().getAttribute();
} else {
ret = this.valueSelect.getAttribute();
}
return ret;
}
/**
* Getter method for instance variable {@link #fromSelect}.
*
* @return value of instance variable {@link #fromSelect}
*/
public LinkFromSelect getFromSelect()
{
return this.fromSelect;
}
/**
* Setter method for instance variable {@link #fromSelect}.
*
* @param _fromSelect value for instance variable {@link #fromSelect}
*/
public void setFromSelect(final LinkFromSelect _fromSelect)
{
this.fromSelect = _fromSelect;
}
/**
* Method to determine if this OneSelect does return more than one value.
* @param _object Object used as filter (must be an Long
Id)
* @return true if more than one value is returned, else false
* @throws EFapsException on error
*/
private boolean isMultiple(final Object _object)
throws EFapsException
{
boolean ret;
if (_object instanceof Long && this.fromSelect != null) {
final Object object = this.getObject(_object);
if (object instanceof List>) {
ret = true;
} else {
ret = false;
}
} else {
ret = this.isMultiple();
}
return ret;
}
/**
* Method to determine if this OneSelect does return more than one value.
* @return true if more than one value is returned, else false
* @throws EFapsException on error
*/
public boolean isMultiple()
throws EFapsException
{
boolean ret;
if (this.valueSelect == null) {
ret = this.fromSelect.getMainOneSelect().isMultiple(this.currentObject);
} else {
ret = this.objectList.size() > 1;
}
return ret;
}
/**
* Get a new table index and add the table to the map of existing table
* indexes. The method calls in case that this OneSelect is related
* to a FromSelect the method
* {@link org.efaps.db.PrintQuery.FromSelect#getNewTableIndex(String, Integer)},
* else in PrintQuery the method
* {@link org.efaps.db.PrintQuery#getNewTableIndex(String, Integer)}.
*
* @param _tableName tablename the index is wanted for
* @param _column name of the column, used for the relation
* @param _relIndex relation the table is used in
* @return new index for the table
*/
public Integer getNewTableIndex(final String _tableName, final String _column, final Integer _relIndex)
{
int ret;
if (this.valueSelect == null && this.fromSelect != null) {
ret = this.fromSelect.getNewTableIndex(_tableName, _column, _relIndex);
} else {
ret = this.query.getNewTableIndex(_tableName, _column, _relIndex);
}
return ret;
}
/**
* Method to get an table index from {@link #sqlTable2Index}.
* Get a new table index and add the table to the map of existing table
* indexes. The method calls in case that this OneSelect is related
* to a FromSelect the method
* {@link org.efaps.db.PrintQuery.FromSelect#getTableIndex(String, Integer)},
* else in PrintQuery the method
* {@link org.efaps.db.PrintQuery#getTableIndex(String, Integer)}
* @param _tableName tablename the index is wanted for
* @param _column name of the column, used for the relation
* @param _relIndex relation the table is used in
* @return index of the table or null if not found
*/
public Integer getTableIndex(final String _tableName,
final String _column,
final int _relIndex)
{
Integer ret;
if (this.valueSelect == null && this.fromSelect != null) {
ret = this.fromSelect.getTableIndex(_tableName, _column, _relIndex);
} else {
ret = this.query.getTableIndex(_tableName, _column, _relIndex);
}
return ret;
}
/**
* @return true if next, else false
*/
public boolean next()
{
boolean ret = false;
if (this.objectIterator == null) {
this.objectIterator = this.objectList.iterator();
}
if (this.idIterator == null) {
this.idIterator = this.idList.iterator();
}
if (this.objectIterator.hasNext()) {
this.currentObject = this.objectIterator.next();
this.currentId = this.idIterator.next();
ret = true;
}
return ret;
}
/**
* Getter method for the instance variable {@link #query}.
*
* @return value of instance variable {@link #query}
*/
public AbstractPrintQuery getQuery()
{
return this.query;
}
/**
* Getter method for the instance variable {@link #objectList}.
*
* @return value of instance variable {@link #objectList}
*/
public List getObjectList()
{
return this.objectList;
}
/**
* Method sorts the object and idList.
* @param _targetList list of instances
* @param _currentList list if instances how it is sorted now
*/
public void sortByInstanceList(final List _targetList,
final Map _currentList)
{
final List idListNew = new ArrayList();
final List objectListNew = new ArrayList();
for (final Instance instance : _targetList) {
if (_currentList.containsKey(instance)) {
final Integer i = _currentList.get(instance);
idListNew.add(this.idList.get(i));
objectListNew.add(this.objectList.get(i));
}
}
this.idList.clear();
this.idList.addAll(idListNew);
this.objectList.clear();
this.objectList.addAll(objectListNew);
}
}