package er.neo4jadaptor.query.expression; import static er.neo4jadaptor.query.expression.sentence.operators.ComparisonOperator.EQUAL; import static er.neo4jadaptor.query.expression.sentence.operators.ComparisonOperator.GREATER_OR_EQUAL; import static er.neo4jadaptor.query.expression.sentence.operators.ComparisonOperator.GREATER_THAN; import static er.neo4jadaptor.query.expression.sentence.operators.ComparisonOperator.ILIKE; import static er.neo4jadaptor.query.expression.sentence.operators.ComparisonOperator.LESS_OR_EQUAL; import static er.neo4jadaptor.query.expression.sentence.operators.ComparisonOperator.LESS_THAN; import static er.neo4jadaptor.query.expression.sentence.operators.ComparisonOperator.LIKE; import static er.neo4jadaptor.query.expression.sentence.operators.ComparisonOperator.MATCHES; import static er.neo4jadaptor.query.expression.sentence.operators.ComparisonOperator.NOT_EQUAL; import java.util.ArrayList; import java.util.Collection; import com.webobjects.eoaccess.EOAttribute; import com.webobjects.eoaccess.EOEntity; import com.webobjects.eoaccess.EORelationship; import com.webobjects.eocontrol.EOAndQualifier; import com.webobjects.eocontrol.EOKeyValueQualifier; import com.webobjects.eocontrol.EONotQualifier; import com.webobjects.eocontrol.EOOrQualifier; import com.webobjects.eocontrol.EOQualifier; import com.webobjects.foundation.NSKeyValueCoding; import com.webobjects.foundation.NSSelector; import er.neo4jadaptor.ersatz.webobjects.NSTranslator; import er.neo4jadaptor.query.expression.sentence.BinaryJoined; import er.neo4jadaptor.query.expression.sentence.Comparison; import er.neo4jadaptor.query.expression.sentence.Negation; import er.neo4jadaptor.query.expression.sentence.Sentence; import er.neo4jadaptor.query.expression.sentence.operators.BinaryOperator; import er.neo4jadaptor.query.expression.sentence.operators.ComparisonOperator; public class Converter { private final EOEntity entity; public Converter(EOEntity entity) { this.entity = entity; } public Sentence convert(EOQualifier q) { if (q instanceof EOAndQualifier) { Collection<Sentence> components = convertCollection(((EOAndQualifier) q).qualifiers()); return new BinaryJoined(BinaryOperator.AND, components); } else if (q instanceof EOOrQualifier) { Collection<Sentence> components = convertCollection(((EOOrQualifier) q).qualifiers()); return new BinaryJoined(BinaryOperator.OR, components); } else if (q instanceof EONotQualifier) { Sentence component = convert(((EONotQualifier) q).qualifier()); return new Negation(component); } else if (q instanceof EOKeyValueQualifier) { return convertComparison((EOKeyValueQualifier) q); } else { throw new IllegalArgumentException(); } } private Collection<Sentence> convertCollection(Collection<EOQualifier> qualifiers) { Collection<Sentence> components = new ArrayList<>(); for (EOQualifier q : qualifiers) { components.add(convert(q)); } return components; } private ComparisonOperator operator(NSSelector<?> operator) { if (operator.equals(EOKeyValueQualifier.QualifierOperatorEqual)) { return EQUAL; } else if (operator.equals(EOKeyValueQualifier.QualifierOperatorNotEqual)) { return NOT_EQUAL; } else if (operator.equals(EOKeyValueQualifier.QualifierOperatorLessThanOrEqualTo)) { return LESS_OR_EQUAL; } else if (operator.equals(EOKeyValueQualifier.QualifierOperatorLessThan)) { return LESS_THAN; } else if (operator.equals(EOKeyValueQualifier.QualifierOperatorGreaterThanOrEqualTo)) { return GREATER_OR_EQUAL; } else if (operator.equals(EOKeyValueQualifier.QualifierOperatorGreaterThan)) { return GREATER_THAN; } else if (operator.equals(EOKeyValueQualifier.QualifierOperatorLike)) { return LIKE; } else if (operator.equals(EOKeyValueQualifier.QualifierOperatorCaseInsensitiveLike)) { return ILIKE; } else if (ComparisonOperator.MATCHES.asString.equals(operator.name())) { return MATCHES; } else { // case not covered throw new UnsupportedOperationException(operator.toString()); } } private Comparison convertComparison(EOKeyValueQualifier qual) { ComparisonOperator operator = operator(qual.selector()); String key = qual.key(); Object value = NSTranslator.instance.toNeutralValue(qual.value(), entity.attributeNamed(key)); EOEntity currentEntity = entity; String [] splits = key.split("\\."); Collection<EORelationship> rels = new ArrayList<>(); for (int i=0; i<splits.length - 1; i++) { EORelationship rel = currentEntity.relationshipNamed(splits[i]); rels.add(rel); currentEntity = rel.destinationEntity(); } // now process the last bit String last = splits[splits.length-1]; if (entity.attributeNamed(last) != null) { // it's a plain attribute value comparison return new Comparison(rels, entity.attributeNamed(last), operator, value); } else { // it's a relationship value comparison, let's represent it as attribute comparison EORelationship lastRel = entity.relationshipNamed(last); EOAttribute srcAtt = asOne(lastRel.sourceAttributes()); EOAttribute dstAtt = asOne(lastRel.destinationAttributes()); rels.add(lastRel); if (value != null) { value = ((NSKeyValueCoding) value).valueForKey(dstAtt.name()); } return new Comparison(rels, srcAtt, operator, value); } } private <T> T asOne(Collection<T> col) { if (col.size() != 1) { throw new IllegalArgumentException(); } else { return col.iterator().next(); } } }