/* * ==================================================================== * * The ObjectStyle Group Software License, Version 1.0 * * Copyright (c) 2006 The ObjectStyle Group and individual authors of the * software. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * 3. The end-user documentation included with the redistribution, if any, must * include the following acknowlegement: "This product includes software * developed by the ObjectStyle Group (http://objectstyle.org/)." Alternately, * this acknowlegement may appear in the software itself, if and wherever such * third-party acknowlegements normally appear. * * 4. The names "ObjectStyle Group" and "Cayenne" must not be used to endorse or * promote products derived from this software without prior written permission. * For written permission, please contact andrus@objectstyle.org. * * 5. Products derived from this software may not be called "ObjectStyle" nor * may "ObjectStyle" appear in their names without prior written permission of * the ObjectStyle Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * OBJECTSTYLE GROUP OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many individuals on * behalf of the ObjectStyle Group. For more information on the ObjectStyle * Group, please see <http://objectstyle.org/>. * */ package org.objectstyle.wolips.eomodeler.core.model; import java.text.ParseException; 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 org.objectstyle.wolips.eomodeler.core.model.qualifier.EOAggregateQualifier; import org.objectstyle.wolips.eomodeler.core.model.qualifier.EOAndQualifier; import org.objectstyle.wolips.eomodeler.core.model.qualifier.EOKeyComparisonQualifier; import org.objectstyle.wolips.eomodeler.core.model.qualifier.EOKeyValueQualifier; import org.objectstyle.wolips.eomodeler.core.model.qualifier.EONamedQualifierVariable; import org.objectstyle.wolips.eomodeler.core.model.qualifier.EONotQualifier; import org.objectstyle.wolips.eomodeler.core.model.qualifier.EOOrQualifier; import org.objectstyle.wolips.eomodeler.core.model.qualifier.EOQualifier; import org.objectstyle.wolips.eomodeler.core.model.qualifier.EOQualifierBinding; import org.objectstyle.wolips.eomodeler.core.model.qualifier.EOQualifierParser; import org.objectstyle.wolips.eomodeler.core.model.qualifier.EOQualifierVariable; public class EOQualifierFactory { private static class SelectorMap { private String _methodName; private String _operatorName; public SelectorMap(String methodName, String operatorName) { _methodName = methodName; _operatorName = operatorName; } public String getMethodName() { return _methodName; } public String getOperatorName() { return _operatorName; } } private static List<SelectorMap> _selectorMaps; static { _selectorMaps = new LinkedList<SelectorMap>(); _selectorMaps.add(new SelectorMap("isEqualTo:", "=")); _selectorMaps.add(new SelectorMap("isEqualTo", "=")); _selectorMaps.add(new SelectorMap("isNotEqualTo:", "<>")); _selectorMaps.add(new SelectorMap("isNotEqualTo", "<>")); _selectorMaps.add(new SelectorMap("isLessThan:", "<")); _selectorMaps.add(new SelectorMap("isLessThan", "<")); _selectorMaps.add(new SelectorMap("isGreaterThan:", ">")); _selectorMaps.add(new SelectorMap("isGreaterThan", ">")); _selectorMaps.add(new SelectorMap("isLessThanOrEqualTo:", "<=")); _selectorMaps.add(new SelectorMap("isLessThanOrEqualTo", "<=")); _selectorMaps.add(new SelectorMap("isGreaterThanOrEqualTo:", ">=")); _selectorMaps.add(new SelectorMap("isGreaterThanOrEqualTo", ">=")); _selectorMaps.add(new SelectorMap("doesContain:", "contains")); _selectorMaps.add(new SelectorMap("doesContain", "contains")); _selectorMaps.add(new SelectorMap("isLike:", "like")); _selectorMaps.add(new SelectorMap("isLike", "like")); _selectorMaps.add(new SelectorMap("isCaseInsensitiveLike:", "caseInsensitiveLike")); _selectorMaps.add(new SelectorMap("isCaseInsensitiveLike", "caseInsensitiveLike")); // To correct the previous Cayenne syntax ... Just in case you had // either one in your fetch specs. _selectorMaps.add(new SelectorMap("likeIgnoreCase", "caseInsensitiveLike")); _selectorMaps.add(new SelectorMap("likeIgnoreCase:", "caseInsensitiveLike")); } public static EOQualifier fromString(String qualifierString) { try { EOQualifier qualifier = new EOQualifierParser().parseQualifier(qualifierString); return qualifier; } catch (ParseException e) { throw new RuntimeException("Failed to parse qualfier.", e); } } public static String toString(EOQualifier qualifier) { String qualifierString; if (qualifier == null) { qualifierString = null; } else { qualifierString = qualifier.toString(); } return qualifierString; } protected static String operatorNameForMethodNamed(String methodName) { for (SelectorMap selectorMap : _selectorMaps) { if (selectorMap.getMethodName().equalsIgnoreCase(methodName)) { return selectorMap.getOperatorName(); } } return methodName; } protected static String methodNameForOperatorNamed(String operatorName) { for (SelectorMap selectorMap : _selectorMaps) { if (selectorMap.getOperatorName().equalsIgnoreCase(operatorName)) { return selectorMap.getMethodName(); } } return operatorName; } public static EOQualifier createQualifierFromQualifierMap(EOModelMap qualifierMap) { EOQualifier qualifier = null; if (qualifierMap != null) { String className = qualifierMap.getString("class", true); if ("EOAndQualifier".equals(className) || "com.webobjects.eocontrol.EOAndQualifier".equals(className)) { qualifier = new EOAndQualifier(EOQualifierFactory.createQualifiersFromQualifierMaps(qualifierMap.getList("qualifiers"))); } else if ("EOOrQualifier".equals(className) || "com.webobjects.eocontrol.EOOrQualifier".equals(className)) { qualifier = new EOOrQualifier(EOQualifierFactory.createQualifiersFromQualifierMaps(qualifierMap.getList("qualifiers"))); } else if ("EONotQualifier".equals(className) || "com.webobjects.eocontrol.EONotQualifier".equals(className)) { qualifier = new EONotQualifier(EOQualifierFactory.createQualifierFromQualifierMap(new EOModelMap(qualifierMap.getMap("qualifier")))); } else if ("EOKeyValueQualifier".equals(className) || "com.webobjects.eocontrol.EOKeyValueQualifier".equals(className)) { String key = qualifierMap.getString("key", true); Object value = EOQualifierFactory.createValue(qualifierMap.get("value")); String selectorName = EOQualifierFactory.operatorNameForMethodNamed(qualifierMap.getString("selectorName", true)); qualifier = EOQualifierFactory.createKeyValueExpression(key, selectorName, value); } else if ("EOKeyComparisonQualifier".equals(className) || "com.webobjects.eocontrol.EOKeyComparisonQualifier".equals(className)) { String leftKey = qualifierMap.getString("leftKey", true); String rightKey = qualifierMap.getString("rightKey", true); String selectorName = EOQualifierFactory.operatorNameForMethodNamed(qualifierMap.getString("selectorName", true)); qualifier = EOQualifierFactory.createKeyComparisonExpression(leftKey, selectorName, rightKey); } else { throw new IllegalArgumentException("Unknown qualifier className '" + className + "'."); } } return qualifier; } private static EOQualifier createKeyValueExpression(String key, String selectorName, Object value) { EOQualifier qualifier = new EOKeyValueQualifier(key, selectorName, value); return qualifier; } private static EOQualifier createKeyComparisonExpression(String leftKey, String selectorName, String rightKey) { EOQualifier qualifier = new EOKeyComparisonQualifier(leftKey, selectorName, rightKey); return qualifier; } private static Object createValue(Object _rawValue) { Object value; if (_rawValue instanceof Map) { EOModelMap valueMap = new EOModelMap((Map) _rawValue); String valueClass = valueMap.getString("class", true); if ("EONull".equals(valueClass) || "com.webobjects.eocontrol.EONull".equals(valueClass)) { value = null; } else if ("EOQualifierVariable".equals(valueClass) || "com.webobjects.eocontrol.EOQualifierVariable".equals(valueClass)) { String variableKey = valueMap.getString("_key", true); // Fix up previously broken _key's if (variableKey.startsWith("$")) { variableKey = variableKey.substring(1); } value = new EONamedQualifierVariable(variableKey); } else if ("NSNumber".equals(valueClass)) { value = valueMap.get("value"); if (value instanceof String) { String valueStr = (String) value; if (valueStr.indexOf('.') == -1) { value = Integer.parseInt(valueStr); if (!String.valueOf(value).equals(valueStr)) { value = Long.parseLong(valueStr); } } else { value = Float.parseFloat(valueStr); } } } else { throw new IllegalArgumentException("Unknown EOKeyValueQualifier value class " + valueClass); } } else { value = _rawValue; } return value; } private static Collection<EOQualifier> createQualifiersFromQualifierMaps(Collection<Map<Object, Object>> _qualifiers) { List<EOQualifier> qualifiers = new LinkedList<EOQualifier>(); if (_qualifiers != null) { for (Map<Object, Object> qualifierMap : _qualifiers) { EOQualifier exp = EOQualifierFactory.createQualifierFromQualifierMap(new EOModelMap(qualifierMap)); qualifiers.add(exp); } } return qualifiers; } private static Object createQualifierValue(Object value) { Object qualifierValue; if (value == null) { EOModelMap map = new EOModelMap(); map.setString("class", "EONull", false); qualifierValue = map; } else if (value instanceof EONamedQualifierVariable) { EOModelMap map = new EOModelMap(); String name = ((EONamedQualifierVariable) value).getName(); map.setString("_key", name, true); map.setString("class", "EOQualifierVariable", false); qualifierValue = map; } else if (value instanceof EOQualifierVariable) { EOModelMap map = new EOModelMap(); String name = ((EOQualifierVariable) value).getName(); map.setString("_key", name, true); map.setString("class", "EOQualifierVariable", false); qualifierValue = map; } else if (value instanceof Number) { EOModelMap map = new EOModelMap(); map.setString("class", "NSNumber", false); map.put("value", value); qualifierValue = map; } else if (value instanceof Boolean) { EOModelMap map = new EOModelMap(); map.setString("class", "NSNumber", false); map.put("value", value); qualifierValue = map; } else if (value instanceof String) { qualifierValue = value; } else { throw new IllegalArgumentException("Unknown qualifier value type: " + value + " (type = " + value.getClass().getName() + ")"); } return qualifierValue; } private static EOModelMap createQualifierMapFromKeyComparisonQualifier(EOKeyComparisonQualifier qualifier) { String leftKey = qualifier.getLeftKey(); String rightKey = qualifier.getRightKey(); EOModelMap map = new EOModelMap(); map.setString("class", "EOKeyComparisonQualifier", false); map.setString("leftKey", leftKey, false); map.setString("rightKey", rightKey, false); EOQualifier.Comparison comparison = qualifier.getComparison(); String selectorName = (comparison == null) ? null : EOQualifierFactory.methodNameForOperatorNamed(comparison.getName()); map.setString("selectorName", selectorName, false); return map; } private static EOModelMap createQualifierMapFromKeyValueQualifier(EOKeyValueQualifier qualifier) { String key = qualifier.getKey(); Object value = qualifier.getValue(); EOModelMap map = new EOModelMap(); map.setString("class", "EOKeyValueQualifier", false); Object processedValue = createQualifierValue(value); map.setString("key", key, false); EOQualifier.Comparison comparison = qualifier.getComparison(); String selectorName = (comparison == null) ? null : EOQualifierFactory.methodNameForOperatorNamed(comparison.getName()); map.setString("selectorName", selectorName, false); map.put("value", processedValue); return map; } private static List<EOModelMap> createQualifierMapsFromAggregateQualifier(EOAggregateQualifier aggregateQualifier) { List<EOModelMap> qualifierMaps = new LinkedList<EOModelMap>(); for (EOQualifier qualifier : aggregateQualifier.getQualifiers()) { qualifierMaps.add(EOQualifierFactory.createQualifierMapFromQualifier(qualifier)); } return qualifierMaps; } public static EOModelMap createQualifierMapFromQualifier(EOQualifier qualifier) { EOModelMap map; if (qualifier instanceof EOKeyValueQualifier) { map = EOQualifierFactory.createQualifierMapFromKeyValueQualifier((EOKeyValueQualifier) qualifier); } else if (qualifier instanceof EOKeyComparisonQualifier) { map = EOQualifierFactory.createQualifierMapFromKeyComparisonQualifier((EOKeyComparisonQualifier) qualifier); } else if (qualifier instanceof EOAndQualifier) { map = new EOModelMap(); map.setString("class", "EOAndQualifier", false); map.setList("qualifiers", createQualifierMapsFromAggregateQualifier((EOAndQualifier) qualifier), true); } else if (qualifier instanceof EOOrQualifier) { map = new EOModelMap(); map.setString("class", "EOOrQualifier", false); map.setList("qualifiers", createQualifierMapsFromAggregateQualifier((EOOrQualifier) qualifier), true); } else if (qualifier instanceof EONotQualifier) { map = new EOModelMap(); map.setString("class", "EONotQualifier", false); map.setMap("qualifier", createQualifierMapFromQualifier(((EONotQualifier) qualifier).getQualifier()), true); } else { throw new IllegalArgumentException("Unknown qualifier " + qualifier + "."); } return map; } public static Set<String> getQualifierKeysFromQualifierString(String qualifierString) { EOQualifier qualifier = EOQualifierFactory.fromString(qualifierString); return EOQualifierFactory.getQualifierKeysFromQualifier(qualifier); } public static Set<String> getQualifierKeysFromQualifier(EOQualifier expression) { Set<String> keys = new HashSet<String>(); try { EOQualifierFactory.fillInQualifierKeysFromQualifier(expression, keys); } catch (Throwable t) { t.printStackTrace(); } return keys; } public static void fillInQualifierKeysFromQualifier(EOQualifier qualifier, Set<String> keys) { if (qualifier instanceof EOKeyValueQualifier) { String key = ((EOKeyValueQualifier) qualifier).getKey(); keys.add(key); } else if (qualifier instanceof EOKeyComparisonQualifier) { String leftKey = ((EOKeyComparisonQualifier) qualifier).getLeftKey(); keys.add(leftKey); String rightKey = ((EOKeyComparisonQualifier) qualifier).getRightKey(); keys.add(rightKey); } else if (qualifier instanceof EOAggregateQualifier) { for (EOQualifier childQualifier : ((EOAggregateQualifier) qualifier).getQualifiers()) { EOQualifierFactory.fillInQualifierKeysFromQualifier(childQualifier, keys); } } else if (qualifier instanceof EONotQualifier) { EOQualifierFactory.fillInQualifierKeysFromQualifier(((EONotQualifier) qualifier).getQualifier(), keys); } else { throw new IllegalArgumentException("Unknown expression " + qualifier + "."); } } public static List<EOQualifierBinding> getQualifierBindingsFromQualifierString(EOEntity entity, String qualifierString) { EOQualifier qualifier = EOQualifierFactory.fromString(qualifierString); return EOQualifierFactory.getQualifierBindingsFromQualifier(entity, qualifier); } public static List<EOQualifierBinding> getQualifierBindingsFromQualifier(EOEntity entity, EOQualifier qualifier) { List<EOQualifierBinding> bindings = new LinkedList<EOQualifierBinding>(); try { if (qualifier != null) { EOQualifierFactory.fillInQualifierBindingsFromQualifier(entity, qualifier, bindings); } } catch (Throwable t) { t.printStackTrace(); } return bindings; } public static void fillInQualifierBindingsFromQualifier(EOEntity entity, EOQualifier qualifier, List<EOQualifierBinding> bindings) { if (qualifier instanceof EOKeyValueQualifier) { String key = ((EOKeyValueQualifier) qualifier).getKey(); Object value = ((EOKeyValueQualifier) qualifier).getValue(); if (value instanceof EONamedQualifierVariable) { String bindingName = ((EONamedQualifierVariable) value).getName(); EOQualifierBinding binding = new EOQualifierBinding(entity, bindingName, key); bindings.add(binding); } } else if (qualifier instanceof EOKeyComparisonQualifier) { // DO NOTHING } else if (qualifier instanceof EOAggregateQualifier) { for (EOQualifier aggregatedQualifier : ((EOAggregateQualifier) qualifier).getQualifiers()) { EOQualifierFactory.fillInQualifierBindingsFromQualifier(entity, aggregatedQualifier, bindings); } } else if (qualifier instanceof EONotQualifier) { EOQualifierFactory.fillInQualifierBindingsFromQualifier(entity, ((EONotQualifier) qualifier).getQualifier(), bindings); } else { throw new IllegalArgumentException("Unknown qualifier '" + qualifier + "'."); } } }