/******************************************************************************* * 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.apache.ofbiz.entity.condition; import java.util.LinkedList; import java.util.List; import java.util.Map; import org.apache.ofbiz.base.util.UtilMisc; import org.apache.ofbiz.base.util.UtilValidate; import org.apache.ofbiz.entity.Delegator; import org.apache.ofbiz.entity.GenericEntity; import org.apache.ofbiz.entity.GenericModelException; import org.apache.ofbiz.entity.config.model.Datasource; import org.apache.ofbiz.entity.model.ModelEntity; import org.apache.ofbiz.entity.model.ModelField; import org.apache.ofbiz.entity.model.ModelViewEntity; import org.apache.ofbiz.entity.model.ModelViewEntity.ModelAlias; /** * Field value expression. * */ @SuppressWarnings("serial") public class EntityFieldValue extends EntityConditionValue { public static final String module = EntityFieldValue.class.getName(); protected String fieldName = null; protected String entityAlias = null; protected List<String> entityAliasStack = null; protected ModelViewEntity modelViewEntity = null; public static EntityFieldValue makeFieldValue(String fieldName) { EntityFieldValue efv = new EntityFieldValue(); efv.init(fieldName, null, null, null); return efv; } public static EntityFieldValue makeFieldValue(String fieldName, String entityAlias, List<String> entityAliasStack, ModelViewEntity modelViewEntity) { EntityFieldValue efv = new EntityFieldValue(); efv.init(fieldName, entityAlias, entityAliasStack, modelViewEntity); return efv; } public void init(String fieldName, String entityAlias, List<String> entityAliasStack, ModelViewEntity modelViewEntity) { this.fieldName = fieldName; this.entityAlias = entityAlias; if (UtilValidate.isNotEmpty(entityAliasStack)) { this.entityAliasStack = new LinkedList<String>(); this.entityAliasStack.addAll(entityAliasStack); } this.modelViewEntity = modelViewEntity; if (UtilValidate.isNotEmpty(this.entityAliasStack) && UtilValidate.isEmpty(this.entityAlias)) { // look it up on the view entity so it can be part of the big list, this only happens for aliased fields, so find the entity-alias and field-name for the alias ModelAlias modelAlias = this.modelViewEntity.getAlias(this.fieldName); if (modelAlias != null) { this.entityAlias = modelAlias.getEntityAlias(); this.fieldName = modelAlias.getField(); } // TODO/NOTE: this will ignore function, group-by, etc... should maybe support those in conditions too at some point } } public void reset() { this.fieldName = null; this.entityAlias = null; this.entityAliasStack = null; this.modelViewEntity = null; } public String getFieldName() { return fieldName; } @Override public int hashCode() { int hash = fieldName.hashCode(); if (this.entityAlias != null) hash |= this.entityAlias.hashCode(); if (this.entityAliasStack != null) hash |= this.entityAliasStack.hashCode(); if (this.modelViewEntity != null) hash |= this.modelViewEntity.hashCode(); return hash; } @Override public boolean equals(Object obj) { if (!(obj instanceof EntityFieldValue)) return false; EntityFieldValue otherValue = (EntityFieldValue) obj; if (!fieldName.equals(otherValue.fieldName)) return false; if (UtilMisc.compare(this.entityAlias, otherValue.entityAlias) != 0) return false; if (UtilMisc.compare(this.entityAliasStack, otherValue.entityAliasStack) != 0) return false; return true; } @Override public ModelField getModelField(ModelEntity modelEntity) { if (this.modelViewEntity != null) { if (this.entityAlias != null) { ModelEntity memberModelEntity = modelViewEntity.getMemberModelEntity(entityAlias); return getField(memberModelEntity, fieldName); } else { return getField(modelViewEntity, fieldName); } } return getField(modelEntity, fieldName); } @Override public void setModelField(ModelField field) { // do nothing } @Override public void addSqlValue(StringBuilder sql, Map<String, String> tableAliases, ModelEntity modelEntity, List<EntityConditionParam> entityConditionParams, boolean includeTableNamePrefix, Datasource datasourceInfo) { if (this.modelViewEntity != null) { // NOTE: this section is a bit of a hack; the other code is terribly complex and really needs to be refactored to incorporate support for this if (UtilValidate.isNotEmpty(entityAlias)) { ModelEntity memberModelEntity = modelViewEntity.getMemberModelEntity(entityAlias); ModelField modelField = memberModelEntity.getField(fieldName); // using entityAliasStack (ordered top to bottom) build a big long alias; not that dots will be replaced after it is combined with the column name in the SQL gen if (UtilValidate.isNotEmpty(this.entityAliasStack)) { boolean dotUsed = false; for (String curEntityAlias: entityAliasStack) { sql.append(curEntityAlias); if (dotUsed) { sql.append("_"); } else { sql.append("."); dotUsed = true; } } sql.append(entityAlias); sql.append("_"); sql.append(modelField.getColName()); } else { sql.append(entityAlias); sql.append("."); sql.append(modelField.getColName()); } } else { sql.append(getColName(tableAliases, modelViewEntity, fieldName, includeTableNamePrefix, datasourceInfo)); } } else { sql.append(getColName(tableAliases, modelEntity, fieldName, includeTableNamePrefix, datasourceInfo)); } } @Override public void validateSql(ModelEntity modelEntity) throws GenericModelException { ModelField field = getModelField(modelEntity); if (field == null) { throw new GenericModelException("Field with name " + fieldName + " not found in the " + modelEntity.getEntityName() + " Entity"); } } @Override public Object getValue(Delegator delegator, Map<String, ? extends Object> map) { if (map == null) { return null; } if (map instanceof GenericEntity.NULL) { return null; } else { return map.get(fieldName); } } @Override public void visit(EntityConditionVisitor visitor) { visitor.acceptEntityFieldValue(this); } @Override public void accept(EntityConditionVisitor visitor) { visitor.acceptEntityFieldValue(this); } @Override public EntityConditionValue freeze() { return this; } }