/************************************************************************ * Copyright (c) 2015 IoT-Solutions e.U. * * Licensed 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 iot.jcypher.domainquery.ast; import iot.jcypher.domainquery.AbstractDomainQuery; import iot.jcypher.domainquery.AbstractDomainQuery.IntAccess; import iot.jcypher.domainquery.api.APIAccess; import iot.jcypher.domainquery.api.DomainObjectMatch; import iot.jcypher.domainquery.internal.IASTObjectsContainer; import iot.jcypher.domainquery.internal.QueryExecutor; import java.util.ArrayList; import java.util.List; public class SelectExpression<T> implements IASTObject, IASTObjectsContainer { private IntAccess domainQueryIntAccess; private DomainObjectMatch<?> start; private Class<T> startType; private DomainObjectMatch<?> end; private List<IASTObject> astObjects; private List<DomainObjectMatch<?>> traversalResults; private boolean reject; public SelectExpression(Class<T> startType, DomainObjectMatch<?> start, IntAccess domainQueryIntAccess) { this(startType, start, domainQueryIntAccess, false); } public SelectExpression(Class<T> startType, DomainObjectMatch<?> start, IntAccess domainQueryIntAccess, boolean reject) { super(); this.start = start; this.startType = startType; this.astObjects = new ArrayList<IASTObject>(); this.domainQueryIntAccess = domainQueryIntAccess; this.reject = reject; } public List<IASTObject> getAstObjects() { return astObjects; } @Override public void addAstObject(IASTObject astObj) { this.astObjectToAdd(astObj); this.astObjects.add(astObj); } public void replaceAstObject(int idx, List<IASTObject> replacements) { this.astObjects.addAll(idx, replacements); this.astObjects.remove(idx + replacements.size()); for (IASTObject astObj : replacements) { this.astObjectToAdd(astObj); } } public void addAstObjects(List<IASTObject> astObjs) { this.astObjects.addAll(astObjs); for (IASTObject astObj : astObjs) { this.astObjectToAdd(astObj); } } private void astObjectToAdd(IASTObject astObj) { if (astObj instanceof PredicateExpression) { // this must represent either the source set or a set derived from the source set by traversal DomainObjectMatch<?> dom = ((PredicateExpression)astObj).getStartDOM(); // must be a derived set if (dom != this.start) { UnionExpression ue = APIAccess.getUnionExpression(dom); DomainObjectMatch<?> src = ue != null ? ue.getCommonTraversalSource() : APIAccess.getTraversalSource(dom); if (src != this.start) throw new RuntimeException( "Predicate expressions within a collection expression must express constraints on " + "either the source set or on a set directly derived from the source set by traversal"); else { addTraversalResult(dom); } } } } public void addTraversalResult(DomainObjectMatch<?> dom) { if (this.traversalResults == null) this.traversalResults = new ArrayList<DomainObjectMatch<?>>(); if (!this.traversalResults.contains(dom)) this.traversalResults.add(dom); } public void setEnd(DomainObjectMatch<?> end) { this.end = end; if (this.traversalResults != null) { for (DomainObjectMatch<?> dom : this.traversalResults) { // add the collection owner to a traversal owner APIAccess.addCollectExpressionOwner(dom, this.end); } } } public DomainObjectMatch<?> getEnd() { return end; } public DomainObjectMatch<?> getStart() { return start; } public Class<T> getStartType() { return this.startType; } public QueryExecutor getQueryExecutor() { return this.domainQueryIntAccess.getQueryExecutor(); } public AbstractDomainQuery getDomainQuery() { return this.domainQueryIntAccess.getDomainQuery(); } public List<DomainObjectMatch<?>> getTraversalResults() { return traversalResults; } public boolean isReject() { return reject; } public void resetAstObjectsContainer() { this.domainQueryIntAccess.resetAstObjectsContainer(); } }