blob: fcdedacffdbe573f4efe1aa8219d0c305ecf286a [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.condition;
import java.util.List;
import java.util.Map;
import org.ofbiz.base.util.UtilGenerics;
import org.ofbiz.entity.Delegator;
import org.ofbiz.entity.GenericModelException;
import org.ofbiz.entity.config.model.Datasource;
import org.ofbiz.entity.model.ModelEntity;
import org.ofbiz.entity.model.ModelField;
/**
* Base class for entity functions.
*
*/
@SuppressWarnings("serial")
public abstract class EntityFunction<T extends Comparable<?>> extends EntityConditionValue {
public static interface Fetcher<T> {
T getValue(Object value);
}
public static enum SQLFunction {
LENGTH, TRIM, UPPER, LOWER;
}
public static final int ID_LENGTH = SQLFunction.LENGTH.ordinal();
public static final int ID_TRIM = SQLFunction.TRIM.ordinal();
public static final int ID_UPPER = SQLFunction.UPPER.ordinal();
public static final int ID_LOWER = SQLFunction.LOWER.ordinal();
public static EntityFunction<Integer> LENGTH(EntityConditionValue nested) { return new LENGTH(nested); }
public static EntityFunction<Integer> LENGTH(Object value) { return new LENGTH(value); }
public static EntityFunction<String> TRIM(EntityConditionValue nested) { return new TRIM(nested); }
public static EntityFunction<String> TRIM(Object value) { return new TRIM(value); }
public static EntityFunction<String> UPPER(EntityConditionValue nested) { return new UPPER(nested); }
public static EntityFunction<String> UPPER(Object value) { return new UPPER(value); }
public static EntityFunction<String> UPPER_FIELD(String fieldName) { return new UPPER(EntityFieldValue.makeFieldValue(fieldName)); }
public static EntityFunction<String> LOWER(EntityConditionValue nested) { return new LOWER(nested); }
public static EntityFunction<String> LOWER(Object value) { return new LOWER(value); }
/**
* Length() entity function.
*
*/
public static class LENGTH extends EntityFunctionSingle<Integer> {
public static Fetcher<Integer> FETCHER = new Fetcher<Integer>() {
public Integer getValue(Object value) { return value.toString().length(); }
};
private LENGTH(Object value) {
super(FETCHER, SQLFunction.LENGTH, value);
}
}
/**
* Trim() entity function.
*
*/
public static class TRIM extends EntityFunctionSingle<String> {
public static Fetcher<String> FETCHER = new Fetcher<String>() {
public String getValue(Object value) { return value.toString().trim(); }
};
private TRIM(Object value) {
super(FETCHER, SQLFunction.TRIM, value);
}
}
/**
* Upper() entity function.
*
*/
public static class UPPER extends EntityFunctionSingle<String> {
public static Fetcher<String> FETCHER = new Fetcher<String>() {
public String getValue(Object value) { return value.toString().toUpperCase(); }
};
private UPPER(Object value) {
super(FETCHER, SQLFunction.UPPER, value);
}
}
/**
* Lower() entity function.
*
*/
public static class LOWER extends EntityFunctionSingle<String> {
public static Fetcher<String> FETCHER = new Fetcher<String>() {
public String getValue(Object value) { return value.toString().toLowerCase(); }
};
private LOWER(Object value) {
super(FETCHER, SQLFunction.LOWER, value);
}
}
public static abstract class EntityFunctionSingle<T extends Comparable<?>> extends EntityFunction<T> {
protected EntityFunctionSingle(Fetcher<T> fetcher, SQLFunction function, Object value) {
super(fetcher, function, value);
}
}
public static abstract class EntityFunctionNested<T extends Comparable<?>> extends EntityFunction<T> {
protected EntityFunctionNested(Fetcher<T> fetcher, SQLFunction function, EntityConditionValue nested) {
super(fetcher, function, nested);
}
}
protected final SQLFunction function;
protected final EntityConditionValue nested;
protected final Object value;
protected final Fetcher<T> fetcher;
protected ModelField field;
protected EntityFunction(Fetcher<T> fetcher, SQLFunction function, EntityConditionValue nested) {
this.fetcher = fetcher;
this.function = function;
this.nested = nested;
this.value = null;
}
protected EntityFunction(Fetcher<T> fetcher, SQLFunction function, Object value) {
this.fetcher = fetcher;
this.function = function;
if (value instanceof EntityConditionValue) {
this.nested = (EntityConditionValue) value;
this.value = null;
} else {
this.nested = null;
this.value = value;
}
}
@Override
public EntityConditionValue freeze() {
if (nested != null) {
return new EntityFunctionNested<T>(fetcher, function, nested.freeze()) {};
} else {
return new EntityFunctionSingle<T>(fetcher, function, value) {};
}
}
public String getCode() {
return function.name();
}
public Object getOriginalValue() {
return this.value;
}
public int getId() {
return function.ordinal();
}
@Override
public int hashCode() {
return function.hashCode();
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof EntityFunction<?>)) return false;
EntityFunction<?> otherFunc = UtilGenerics.cast(obj);
return (this.function == otherFunc.function &&
(this.nested != null ? nested.equals(otherFunc.nested) : otherFunc.nested == null) &&
(this.value != null ? value.equals(otherFunc.value) : otherFunc.value == null));
}
@Override
public void addSqlValue(StringBuilder sql, Map<String, String> tableAliases, ModelEntity modelEntity, List<EntityConditionParam> entityConditionParams, boolean includeTableNamePrefix, Datasource datasourceinfo) {
sql.append(function.name()).append('(');
if (nested != null) {
nested.addSqlValue(sql, tableAliases, modelEntity, entityConditionParams, includeTableNamePrefix, datasourceinfo);
} else {
addValue(sql, null, value, entityConditionParams);
}
sql.append(')');
}
@Override
public void visit(EntityConditionVisitor visitor) {
if (nested != null) {
visitor.acceptEntityConditionValue(nested);
} else {
visitor.acceptObject(value);
}
}
@Override
public void accept(EntityConditionVisitor visitor) {
visitor.acceptEntityFunction(this);
}
@Override
public ModelField getModelField(ModelEntity modelEntity) {
if (nested != null) {
return nested.getModelField(modelEntity);
}
return field;
}
@Override
public void setModelField(ModelField field) {
this.field = field;
}
@Override
public void validateSql(ModelEntity modelEntity) throws GenericModelException {
if (nested != null) {
nested.validateSql(modelEntity);
}
}
@Override
public Object getValue(Delegator delegator, Map<String, ? extends Object> map) {
Object value = nested != null ? nested.getValue(delegator, map) : this.value;
return value != null ? fetcher.getValue(value) : null;
}
}