Package org.ofbiz.entity.finder

Source Code of org.ofbiz.entity.finder.EntityFinderUtil$UseIterator

/*******************************************************************************
* 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.finder;

import static org.ofbiz.base.util.UtilGenerics.cast;

import java.io.Serializable;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javolution.util.FastMap;

import org.ofbiz.base.util.Debug;
import org.ofbiz.base.util.ObjectType;
import org.ofbiz.base.util.StringUtil;
import org.ofbiz.base.util.UtilFormatOut;
import org.ofbiz.base.util.UtilGenerics;
import org.ofbiz.base.util.UtilValidate;
import org.ofbiz.base.util.UtilXml;
import org.ofbiz.base.util.collections.FlexibleMapAccessor;
import org.ofbiz.base.util.string.FlexibleStringExpander;
import org.ofbiz.entity.GenericEntityException;
import org.ofbiz.entity.GenericValue;
import org.ofbiz.entity.condition.EntityComparisonOperator;
import org.ofbiz.entity.condition.EntityCondition;
import org.ofbiz.entity.condition.EntityFunction;
import org.ofbiz.entity.condition.EntityJoinOperator;
import org.ofbiz.entity.condition.EntityOperator;
import org.ofbiz.entity.model.ModelEntity;
import org.ofbiz.entity.model.ModelFieldTypeReader;
import org.ofbiz.entity.util.EntityListIterator;
import org.w3c.dom.Element;

/**
* Uses the delegator to find entity values by a condition
*
*/
public class EntityFinderUtil {

    public static final String module = EntityFinderUtil.class.getName();

    public static Map<FlexibleMapAccessor<Object>, Object> makeFieldMap(Element element) {
        Map<FlexibleMapAccessor<Object>, Object> fieldMap = null;
        List<? extends Element> fieldMapElementList = UtilXml.childElementList(element, "field-map");
        if (fieldMapElementList.size() > 0) {
            fieldMap = FastMap.newInstance();
            for (Element fieldMapElement: fieldMapElementList) {
                // set the env-name for each field-name, noting that if no field-name is specified it defaults to the env-name
                String fieldName = fieldMapElement.getAttribute("field-name");
                String envName = fieldMapElement.getAttribute("from-field");
                if (UtilValidate.isEmpty(envName)) {
                    envName = fieldMapElement.getAttribute("env-name");
                }
                String value = fieldMapElement.getAttribute("value");
                if (UtilValidate.isEmpty(fieldName)) {
                    // no fieldName, use envName for both
                    fieldMap.put(FlexibleMapAccessor.getInstance(envName), FlexibleMapAccessor.getInstance(envName));
                } else {
                    if (UtilValidate.isNotEmpty(value)) {
                        fieldMap.put(FlexibleMapAccessor.getInstance(fieldName), FlexibleStringExpander.getInstance(value));
                    } else {
                        // at this point we have a fieldName and no value, do we have a envName?
                        if (UtilValidate.isNotEmpty(envName)) {
                            fieldMap.put(FlexibleMapAccessor.getInstance(fieldName), FlexibleMapAccessor.getInstance(envName));
                        } else {
                            // no envName, use fieldName for both
                            fieldMap.put(FlexibleMapAccessor.getInstance(fieldName), FlexibleMapAccessor.getInstance(fieldName));
                        }
                    }
                }
            }
        }
        return fieldMap;
    }

    public static void expandFieldMapToContext(Map<FlexibleMapAccessor<Object>, Object> fieldMap, Map<String, Object> context, Map<String, Object> outContext) {
        //Debug.logInfo("fieldMap: " + fieldMap, module);
        if (fieldMap != null) {
            for (Map.Entry<FlexibleMapAccessor<Object>, Object> entry: fieldMap.entrySet()) {
                FlexibleMapAccessor<Object> serviceContextFieldAcsr = entry.getKey();
                Object valueSrc = entry.getValue();
                if (valueSrc instanceof FlexibleMapAccessor<?>) {
                    FlexibleMapAccessor<Object> contextEnvAcsr = cast(valueSrc);
                    serviceContextFieldAcsr.put(outContext, contextEnvAcsr.get(context));
                } else if (valueSrc instanceof FlexibleStringExpander) {
                    FlexibleStringExpander valueExdr = (FlexibleStringExpander) valueSrc;
                    serviceContextFieldAcsr.put(outContext, valueExdr.expandString(context));
                } else {
                    // hmmmm...
                }
            }
        }
    }

    public static List<FlexibleStringExpander> makeSelectFieldExpanderList(Element element) {
        List<FlexibleStringExpander> selectFieldExpanderList = null;
        List<? extends Element> selectFieldElementList = UtilXml.childElementList(element, "select-field");
        if (selectFieldElementList.size() > 0) {
            selectFieldExpanderList = new LinkedList<FlexibleStringExpander>();
            for (Element selectFieldElement: selectFieldElementList) {
                selectFieldExpanderList.add(FlexibleStringExpander.getInstance(selectFieldElement.getAttribute("field-name")));
            }
        }
        return selectFieldExpanderList;
    }

    public static Set<String> makeFieldsToSelect(List<FlexibleStringExpander> selectFieldExpanderList, Map<String, Object> context) {
        Set<String> fieldsToSelect = null;
        if (UtilValidate.isNotEmpty(selectFieldExpanderList)) {
            fieldsToSelect = new HashSet<String>();
            for (FlexibleStringExpander selectFieldExpander: selectFieldExpanderList) {
                fieldsToSelect.add(selectFieldExpander.expandString(context));
            }
        }
        return fieldsToSelect;
    }

    public static List<String> makeOrderByFieldList(List<FlexibleStringExpander> orderByExpanderList, Map<String, Object> context) {
        List<String> orderByFields = null;
        if (UtilValidate.isNotEmpty(orderByExpanderList)) {
            orderByFields = new LinkedList<String>();
            for (FlexibleStringExpander orderByExpander: orderByExpanderList) {
                orderByFields.add(orderByExpander.expandString(context));
            }
        }
        return orderByFields;
    }

    public static interface Condition extends Serializable {
        public EntityCondition createCondition(Map<String, ? extends Object> context, ModelEntity modelEntity, ModelFieldTypeReader modelFieldTypeReader);
    }
    @SuppressWarnings("serial")
    public static class ConditionExpr implements Condition {
        protected FlexibleStringExpander fieldNameExdr;
        protected FlexibleStringExpander operatorExdr;
        protected FlexibleMapAccessor<Object> envNameAcsr;
        protected FlexibleStringExpander valueExdr;
        protected FlexibleStringExpander ignoreExdr;
        protected boolean ignoreIfNull;
        protected boolean ignoreIfEmpty;
        protected boolean ignoreCase;

        public ConditionExpr(Element conditionExprElement) {
            this.fieldNameExdr = FlexibleStringExpander.getInstance(conditionExprElement.getAttribute("field-name"));
            if (this.fieldNameExdr.isEmpty()) {
                // no "field-name"? try "name"
                this.fieldNameExdr = FlexibleStringExpander.getInstance(conditionExprElement.getAttribute("name"));
            }

            this.operatorExdr = FlexibleStringExpander.getInstance(UtilFormatOut.checkEmpty(conditionExprElement.getAttribute("operator"), "equals"));
            if (UtilValidate.isNotEmpty(conditionExprElement.getAttribute("from-field"))) {
                this.envNameAcsr = FlexibleMapAccessor.getInstance(conditionExprElement.getAttribute("from-field"));
            } else {
                this.envNameAcsr = FlexibleMapAccessor.getInstance(conditionExprElement.getAttribute("env-name"));
            }
            this.valueExdr = FlexibleStringExpander.getInstance(conditionExprElement.getAttribute("value"));
            this.ignoreIfNull = "true".equals(conditionExprElement.getAttribute("ignore-if-null"));
            this.ignoreIfEmpty = "true".equals(conditionExprElement.getAttribute("ignore-if-empty"));
            this.ignoreCase = "true".equals(conditionExprElement.getAttribute("ignore-case"));
            this.ignoreExdr = FlexibleStringExpander.getInstance(conditionExprElement.getAttribute("ignore"));
        }

        public EntityCondition createCondition(Map<String, ? extends Object> context, ModelEntity modelEntity, ModelFieldTypeReader modelFieldTypeReader) {
            String fieldName = fieldNameExdr.expandString(context);

            Object value = null;
            // start with the environment variable, will override if exists and a value is specified
            if (envNameAcsr != null) {
                value = envNameAcsr.get(context);
            }
            // no value so far, and a string value is specified, use that
            if (value == null && valueExdr != null) {
                value = valueExdr.expandString(context);
            }

            String operatorName = operatorExdr.expandString(context);
            EntityOperator<?,?,?> operator = EntityOperator.lookup(operatorName);
            if (operator == null) {
                throw new IllegalArgumentException("Could not find an entity operator for the name: " + operatorName);
            }

            // If IN or BETWEEN operator, see if value is a literal list and split it
            if ((operator.equals(EntityOperator.IN) || operator.equals(EntityOperator.BETWEEN) || operator.equals(EntityOperator.NOT_IN))
                    && value instanceof String) {
                String delim = null;
                if (((String)value).indexOf("|") >= 0) {
                    delim = "|";
                } else if (((String)value).indexOf(",") >= 0) {
                    delim = ",";
                }
                if (UtilValidate.isNotEmpty(delim)) {
                    value = StringUtil.split((String)value, delim);
                }
            }

            if (modelEntity.getField(fieldName) == null) {
                throw new IllegalArgumentException("Error in Entity Find: could not find field [" + fieldName + "] in entity with name [" + modelEntity.getEntityName() + "]");
            }

            // don't convert the field to the desired type if this is an IN or BETWEEN operator and we have a Collection
            if (!((operator.equals(EntityOperator.IN) || operator.equals(EntityOperator.BETWEEN) || operator.equals(EntityOperator.NOT_IN))
                    && value instanceof Collection<?>)) {
                // now to a type conversion for the target fieldName
                value = modelEntity.convertFieldValue(modelEntity.getField(fieldName), value, modelFieldTypeReader, context);
            }

            if (Debug.verboseOn()) Debug.logVerbose("Got value for fieldName [" + fieldName + "]: " + value, module);

            if (this.ignoreIfNull && value == null) {
                return null;
            }
            if (this.ignoreIfEmpty && ObjectType.isEmpty(value)) {
                return null;
            }

            if ("true".equals(this.ignoreExdr.expandString(context))) {
                return null;
            }

            if (operator == EntityOperator.NOT_EQUAL && value != null) {
                // since some databases don't consider nulls in != comparisons, explicitly include them
                // this makes more sense logically, but if anyone ever needs it to not behave this way we should add an "or-null" attribute that is true by default
                if (ignoreCase) {
                    return EntityCondition.makeCondition(
                            EntityCondition.makeCondition(EntityFunction.UPPER_FIELD(fieldName), UtilGenerics.<EntityComparisonOperator<?,?>>cast(operator), EntityFunction.UPPER(value)),
                            EntityOperator.OR,
                            EntityCondition.makeCondition(fieldName, EntityOperator.EQUALS, null));
                } else {
                    return EntityCondition.makeCondition(
                            EntityCondition.makeCondition(fieldName, UtilGenerics.<EntityComparisonOperator<?,?>>cast(operator), value),
                            EntityOperator.OR,
                            EntityCondition.makeCondition(fieldName, EntityOperator.EQUALS, null));
                }
            } else {
                if (ignoreCase) {
                    // use the stuff to upper case both sides
                    return EntityCondition.makeCondition(EntityFunction.UPPER_FIELD(fieldName), UtilGenerics.<EntityComparisonOperator<?,?>>cast(operator), EntityFunction.UPPER(value));
                } else {
                    return EntityCondition.makeCondition(fieldName, UtilGenerics.<EntityComparisonOperator<?,?>>cast(operator), value);
                }
            }
        }
    }

    @SuppressWarnings("serial")
    public static class ConditionList implements Condition {
        List<Condition> conditionList = new LinkedList<Condition>();
        FlexibleStringExpander combineExdr;

        public ConditionList(Element conditionListElement) {
            this.combineExdr = FlexibleStringExpander.getInstance(conditionListElement.getAttribute("combine"));

            List<? extends Element> subElements = UtilXml.childElementList(conditionListElement);
            for (Element subElement: subElements) {
                if ("condition-expr".equals(subElement.getNodeName())) {
                    conditionList.add(new ConditionExpr(subElement));
                } else if ("condition-list".equals(subElement.getNodeName())) {
                    conditionList.add(new ConditionList(subElement));
                } else if ("condition-object".equals(subElement.getNodeName())) {
                    conditionList.add(new ConditionObject(subElement));
                } else {
                    throw new IllegalArgumentException("Invalid element with name [" + subElement.getNodeName() + "] found under a condition-list element.");
                }
            }
        }

        public EntityCondition createCondition(Map<String, ? extends Object> context, ModelEntity modelEntity, ModelFieldTypeReader modelFieldTypeReader) {
            if (this.conditionList.size() == 0) {
                return null;
            }
            if (this.conditionList.size() == 1) {
                Condition condition = this.conditionList.get(0);
                return condition.createCondition(context, modelEntity, modelFieldTypeReader);
            }

            List<EntityCondition> entityConditionList = new LinkedList<EntityCondition>();
            for (Condition curCondition: conditionList) {
                EntityCondition econd = curCondition.createCondition(context, modelEntity, modelFieldTypeReader);
                if (econd != null) {
                    entityConditionList.add(econd);
                }
            }

            String operatorName = combineExdr.expandString(context);
            EntityOperator<?,?,?> operator = EntityOperator.lookup(operatorName);
            if (operator == null) {
                throw new IllegalArgumentException("Could not find an entity operator for the name: " + operatorName);
            }

            return EntityCondition.makeCondition(entityConditionList, UtilGenerics.<EntityJoinOperator>cast(operator));
        }
    }
    @SuppressWarnings("serial")
    public static class ConditionObject implements Condition {
        protected FlexibleMapAccessor<Object> fieldNameAcsr;

        public ConditionObject(Element conditionExprElement) {
            this.fieldNameAcsr = FlexibleMapAccessor.getInstance(conditionExprElement.getAttribute("field"));
            if (this.fieldNameAcsr.isEmpty()) {
                // no "field"? try "field-name"
                this.fieldNameAcsr = FlexibleMapAccessor.getInstance(conditionExprElement.getAttribute("field-name"));
            }
        }

        public EntityCondition createCondition(Map<String, ? extends Object> context, ModelEntity modelEntity, ModelFieldTypeReader modelFieldTypeReader) {
            EntityCondition condition = (EntityCondition) fieldNameAcsr.get(context);
            return condition;
        }
    }

    public static interface OutputHandler extends Serializable {
        public void handleOutput(EntityListIterator eli, Map<String, Object> context, FlexibleMapAccessor<Object> listAcsr);
        public void handleOutput(List<GenericValue> results, Map<String, Object> context, FlexibleMapAccessor<Object> listAcsr);
    }
    @SuppressWarnings("serial")
    public static class LimitRange implements OutputHandler {
        FlexibleStringExpander startExdr;
        FlexibleStringExpander sizeExdr;

        public LimitRange(Element limitRangeElement) {
            this.startExdr = FlexibleStringExpander.getInstance(limitRangeElement.getAttribute("start"));
            this.sizeExdr = FlexibleStringExpander.getInstance(limitRangeElement.getAttribute("size"));
        }

        int getStart(Map<String, Object> context) {
            String startStr = this.startExdr.expandString(context);
            try {
                return Integer.parseInt(startStr);
            } catch (NumberFormatException e) {
                String errMsg = "The limit-range start number \"" + startStr + "\" was not valid: " + e.toString();
                Debug.logError(e, errMsg, module);
                throw new IllegalArgumentException(errMsg);
            }
        }

        int getSize(Map<String, Object> context) {
            String sizeStr = this.sizeExdr.expandString(context);
            try {
                return Integer.parseInt(sizeStr);
            } catch (NumberFormatException e) {
                String errMsg = "The limit-range size number \"" + sizeStr + "\" was not valid: " + e.toString();
                Debug.logError(e, errMsg, module);
                throw new IllegalArgumentException(errMsg);
            }
        }

        public void handleOutput(EntityListIterator eli, Map<String, Object> context, FlexibleMapAccessor<Object> listAcsr) {
            int start = getStart(context);
            int size = getSize(context);
            try {
                listAcsr.put(context, eli.getPartialList(start, size));
                eli.close();
            } catch (GenericEntityException e) {
                String errMsg = "Error getting partial list in limit-range with start=" + start + " and size=" + size + ": " + e.toString();
                Debug.logError(e, errMsg, module);
                throw new IllegalArgumentException(errMsg);
            }
        }

        public void handleOutput(List<GenericValue> results, Map<String, Object> context, FlexibleMapAccessor<Object> listAcsr) {
            int start = getStart(context);
            int size = getSize(context);

            int end = start + size;
            if (end > results.size()) end = results.size();

            listAcsr.put(context, results.subList(start, end));
        }
    }
    @SuppressWarnings("serial")
    public static class LimitView implements OutputHandler {
        FlexibleStringExpander viewIndexExdr;
        FlexibleStringExpander viewSizeExdr;

        public LimitView(Element limitViewElement) {
            this.viewIndexExdr = FlexibleStringExpander.getInstance(limitViewElement.getAttribute("view-index"));
            this.viewSizeExdr = FlexibleStringExpander.getInstance(limitViewElement.getAttribute("view-size"));
        }

        int getIndex(Map<String, Object> context) {
            String viewIndexStr = this.viewIndexExdr.expandString(context);
            try {
                return Integer.parseInt(viewIndexStr);
            } catch (NumberFormatException e) {
                String errMsg = "The limit-view view-index number \"" + viewIndexStr + "\" was not valid: " + e.toString();
                Debug.logError(e, errMsg, module);
                throw new IllegalArgumentException(errMsg);
            }
        }

        int getSize(Map<String, Object> context) {
            String viewSizeStr = this.viewSizeExdr.expandString(context);
            try {
                return Integer.parseInt(viewSizeStr);
            } catch (NumberFormatException e) {
                String errMsg = "The limit-view view-size number \"" + viewSizeStr + "\" was not valid: " + e.toString();
                Debug.logError(e, errMsg, module);
                throw new IllegalArgumentException(errMsg);
            }
        }

        public void handleOutput(EntityListIterator eli, Map<String, Object> context, FlexibleMapAccessor<Object> listAcsr) {
            int index = this.getIndex(context);
            int size = this.getSize(context);

            try {
                listAcsr.put(context, eli.getPartialList(((index - 1) * size) + 1, size));
                eli.close();
            } catch (GenericEntityException e) {
                String errMsg = "Error getting partial list in limit-view with index=" + index + " and size=" + size + ": " + e.toString();
                Debug.logError(e, errMsg, module);
                throw new IllegalArgumentException(errMsg);
            }
        }

        public void handleOutput(List<GenericValue> results, Map<String, Object> context, FlexibleMapAccessor<Object> listAcsr) {
            int index = this.getIndex(context);
            int size = this.getSize(context);

            int begin = index * size;
            int end = index * size + size;
            if (end > results.size()) end = results.size();

            listAcsr.put(context, results.subList(begin, end));
        }
    }
    @SuppressWarnings("serial")
    public static class UseIterator implements OutputHandler {
        public UseIterator(Element useIteratorElement) {
            // no parameters, nothing to do
        }

        public void handleOutput(EntityListIterator eli, Map<String, Object> context, FlexibleMapAccessor<Object> listAcsr) {
            listAcsr.put(context, eli);
        }

        public void handleOutput(List<GenericValue> results, Map<String, Object> context, FlexibleMapAccessor<Object> listAcsr) {
            throw new IllegalArgumentException("Cannot handle output with use-iterator when the query is cached, or the result in general is not an EntityListIterator");
        }
    }
    @SuppressWarnings("serial")
    public static class GetAll implements OutputHandler {
        public GetAll() {
            // no parameters, nothing to do
        }

        public void handleOutput(EntityListIterator eli, Map<String, Object> context, FlexibleMapAccessor<Object> listAcsr) {
            try {
                listAcsr.put(context, eli.getCompleteList());
                eli.close();
            } catch (GenericEntityException e) {
                String errorMsg = "Error getting list from EntityListIterator: " + e.toString();
                Debug.logError(e, errorMsg, module);
                throw new IllegalArgumentException(errorMsg);
            }
        }

        public void handleOutput(List<GenericValue> results, Map<String, Object> context, FlexibleMapAccessor<Object> listAcsr) {
            listAcsr.put(context, results);
        }
    }
}
TOP

Related Classes of org.ofbiz.entity.finder.EntityFinderUtil$UseIterator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.