blob: 10a73d9c4fbaeda366119586efad02458370c985 [file] [log] [blame]
/*
* 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.
*/
package org.ofbiz.entity.sql;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import javolution.util.FastList;
import org.ofbiz.entity.condition.EntityCondition;
import org.ofbiz.entity.model.DynamicViewEntity;
import org.ofbiz.entity.model.ModelKeyMap;
import org.ofbiz.entity.model.ModelViewEntity.ComplexAlias;
import org.ofbiz.entity.model.ModelViewEntity.ComplexAliasField;
import org.ofbiz.entity.model.ModelViewEntity.ComplexAliasMember;
import org.ofbiz.sql.ConstantValue;
import org.ofbiz.sql.FieldAll;
import org.ofbiz.sql.FieldDef;
import org.ofbiz.sql.FieldValue;
import org.ofbiz.sql.FunctionCall;
import org.ofbiz.sql.Joined;
import org.ofbiz.sql.KeyMap;
import org.ofbiz.sql.MathValue;
import org.ofbiz.sql.NumberValue;
import org.ofbiz.sql.OrderByItem;
import org.ofbiz.sql.Planner;
import org.ofbiz.sql.Relation;
import org.ofbiz.sql.SQLDelete;
import org.ofbiz.sql.SQLInsert;
import org.ofbiz.sql.SQLSelect;
import org.ofbiz.sql.SQLUpdate;
import org.ofbiz.sql.SQLView;
import org.ofbiz.sql.SelectGroup;
import org.ofbiz.sql.StaticValue;
import org.ofbiz.sql.StringValue;
import org.ofbiz.sql.Table;
import org.ofbiz.sql.TableName;
import org.ofbiz.sql.Unioned;
import org.ofbiz.sql.Value;
public class EntityPlanner extends Planner<EntityPlanner, EntityCondition, EntityDeletePlan, EntityInsertPlan, EntitySelectPlan, EntityUpdatePlan, EntityViewPlan> {
public EntityPlanner() {
super(new EntityConditionPlanner());
}
@Override
public EntityDeletePlan planDelete(SQLDelete deleteStatement) {
return null;
}
@Override
public EntityInsertPlan planInsert(SQLInsert insertStatement) {
return null;
}
@Override
public EntitySelectPlan planSelect(SQLSelect selectStatement) {
DynamicViewEntity dve = new DynamicViewEntity();
Unioned unioned = selectStatement.getUnioned();
if (unioned != null) {
throw new IllegalArgumentException("union views not yet supported");
}
SelectGroup selectGroup = unioned.getGroup();
Table table = selectGroup.getTable();
addMember(dve, table.getTableName());
addJoined(dve, table.getTableName().getAlias(), table.getJoined());
if (selectGroup.getFieldAlls() != null) {
for (FieldAll fieldAll: selectGroup.getFieldAlls()) {
List<String> excludes = new LinkedList<String>();
for (String exclude: fieldAll) {
excludes.add(exclude);
}
if (excludes.isEmpty()) {
excludes = null;
}
dve.addAliasAll(fieldAll.getAlias(), null, excludes);
}
}
if (selectStatement.getRelations() != null) {
for (Relation relation: selectStatement.getRelations().values()) {
dve.addRelation(relation.getType(), relation.getTitle(), relation.getEntityName(), buildKeyMaps(relation));
}
}
List<String> groupBy = selectGroup.getGroupBy();
if (groupBy == null) {
groupBy = Collections.emptyList();
}
if (selectGroup.getFieldDefs() != null) {
for (FieldDef fieldDef: selectGroup.getFieldDefs()) {
addFieldDef(dve, groupBy, fieldDef.getAlias(), fieldDef);
}
}
List<String> orderBy;
if (selectStatement.getOrderBy() == null) {
orderBy = null;
} else {
orderBy = new LinkedList<String>();
for (OrderByItem orderByItem: selectStatement.getOrderBy()) {
orderBy.add(orderByItem.toString());
}
}
return new EntitySelectPlan(dve, plan(selectGroup.getWhereCondition()), plan(selectGroup.getHavingCondition()), orderBy);
}
@Override
public EntityUpdatePlan planUpdate(SQLUpdate updateStatement) {
return null;
}
@Override
public EntityViewPlan planView(SQLView viewStatement) {
return null;
}
private static void addFieldDef(DynamicViewEntity dve, List<String> groupBy, String alias, FieldDef fieldDef) {
StaticValue value = fieldDef.getValue();
if (value instanceof FieldValue) {
addFieldDef(dve, groupBy, fieldDef.getAlias(), (FieldValue) value, null);
} else if (value instanceof ConstantValue) {
addFieldDef(dve, groupBy, fieldDef.getAlias(), value);
} else {
throw new UnsupportedOperationException(alias + "[" + fieldDef + "]:" + fieldDef.getClass());
}
}
private static void addFieldDef(DynamicViewEntity dve, List<String> groupBy, String alias, FieldValue fieldValue, String function) {
dve.addAlias(fieldValue.getTableName(), alias, fieldValue.getFieldName(), null, null, groupBy.contains(alias), function);
}
private static void addFieldDef(DynamicViewEntity dve, List<String> groupBy, String alias, ComplexAliasMember member) {
dve.addAlias(null, alias, null, null, null, groupBy.contains(alias), null, member);
}
private static void addFieldDef(DynamicViewEntity dve, List<String> groupBy, String alias, ConstantValue value) {
if (value instanceof FieldValue) {
addFieldDef(dve, groupBy, alias, (FieldValue) value, null);
return;
} else if (value instanceof FunctionCall) {
FunctionCall fc = (FunctionCall) value;
String name = fc.getName().toLowerCase();
Iterator<Value> it = fc.iterator();
if (it.hasNext()) {
Value firstValue = it.next();
if (!it.hasNext()) {
if (firstValue instanceof FieldValue) {
addFieldDef(dve, groupBy, alias, (FieldValue) firstValue, name);
return;
}
}
}
}
addFieldDef(dve, groupBy, alias, buildComplexMember(value));
}
private static ComplexAliasMember buildComplexMember(Value value) {
if (value instanceof FieldValue) {
FieldValue fv = (FieldValue) value;
return new ComplexAliasField(fv.getTableName(), fv.getFieldName(), null, null);
} else if (value instanceof FunctionCall) {
FunctionCall fc = (FunctionCall) value;
String name = fc.getName().toLowerCase();
if (fc.getArgCount() == 1) {
Value firstValue = fc.iterator().next();
if (firstValue instanceof FieldValue) {
FieldValue fv = (FieldValue) firstValue;
return new ComplexAliasField(fv.getTableName(), fv.getFieldName(), null, name);
} else if (firstValue instanceof FunctionCall) {
FunctionCall fc2 = (FunctionCall) firstValue;
if (fc2.getName().equalsIgnoreCase("coalesce") && fc2.getArgCount() == 2) {
Iterator<Value> it = fc2.iterator();
Value f1 = it.next(), f2 = it.next();
if (f1 instanceof FieldValue) {
FieldValue fv = (FieldValue) f1;
if (f2 instanceof NumberValue<?>) {
return new ComplexAliasField(fv.getTableName(), fv.getFieldName(), ((NumberValue<?>) f2).getNumber().toString(), name);
} else if (f2 instanceof StringValue) {
return new ComplexAliasField(fv.getTableName(), fv.getFieldName(), "'" + ((StringValue) f2).getString() + "'", name);
}
}
}
}
} else if (fc.getName().equalsIgnoreCase("coalesce") && fc.getArgCount() == 2) {
Iterator<Value> it = fc.iterator();
Value f1 = it.next(), f2 = it.next();
if (f1 instanceof FieldValue) {
FieldValue fv = (FieldValue) f1;
if (f2 instanceof NumberValue<?>) {
return new ComplexAliasField(fv.getTableName(), fv.getFieldName(), ((NumberValue<?>) f2).getNumber().toString(), null);
} else if (f2 instanceof StringValue) {
return new ComplexAliasField(fv.getTableName(), fv.getFieldName(), "'" + ((StringValue) f2).getString() + "'", null);
}
}
}
} else if (value instanceof MathValue) {
MathValue mv = (MathValue) value;
ComplexAlias complexAlias = new ComplexAlias(mv.getOp());
for (ConstantValue constantValue: mv) {
complexAlias.addComplexAliasMember(buildComplexMember(constantValue));
}
return complexAlias;
}
throw new UnsupportedOperationException(value + ":" + value.getClass());
}
private static void addMember(DynamicViewEntity dve, TableName member) {
dve.addMemberEntity(member.getAlias(), member.getTableName());
}
private static void addJoined(DynamicViewEntity dve, String leftAlias, Joined joined) {
if (joined == null) return;
addMember(dve, joined.getTableName());
dve.addViewLink(leftAlias, joined.getTableName().getAlias(), joined.isOptional(), buildKeyMaps(joined));
addJoined(dve, joined.getTableName().getAlias(), joined.getJoined());
}
private static List<ModelKeyMap> buildKeyMaps(Iterable<KeyMap> keyMaps) {
List<ModelKeyMap> entityKeyMaps = FastList.newInstance();
for (KeyMap keyMap: keyMaps) {
entityKeyMaps.add(new ModelKeyMap(keyMap.getLeftFieldName(), keyMap.getRightFieldName()));
}
return entityKeyMaps;
}
}