/************************************************************************ * Copyright (c) 2014-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.api; import iot.jcypher.domain.genericmodel.DomainObject; import iot.jcypher.domain.internal.DomainAccess.InternalDomainAccess; import iot.jcypher.domainquery.ast.TraversalExpression; import iot.jcypher.domainquery.ast.TraversalExpression.Step; import iot.jcypher.domainquery.internal.QueryRecorder; public class TraversalStep extends APIObject { TraversalStep(TraversalExpression te) { this.astObject = te; } /** * Traverse forward via an attribute * @param attributeName * @return */ public TraversalStep FORTH(String attributeName) { TraversalExpression te = (TraversalExpression)this.astObject; te.step(attributeName, 0); TraversalStep ret = new TraversalStep(te); QueryRecorder.recordInvocation(this, "FORTH", ret, QueryRecorder.literal(attributeName)); return ret; } /** * Traverse backward via an attribute * @param attributeName * @return */ public TraversalStep BACK(String attributeName) { TraversalExpression te = (TraversalExpression)this.astObject; te.step(attributeName, 1); TraversalStep ret = new TraversalStep(te); QueryRecorder.recordInvocation(this, "BACK", ret, QueryRecorder.literal(attributeName)); return ret; } /** * Define the distance in terms of how many hops to take when navigating the domain graph along a given attribute. * The default is one hop (minDistance = maxDistance = 1), * maxDistance -1 means hop as far as you will get (either to a leaf in the graph or to a detected loop). * @param minDistance the minimum number of hops to navigate * @param maxDistance the maximum number of hops to navigate * @return */ public TraversalStep DISTANCE(int minDistance, int maxDistance) { TraversalExpression te = (TraversalExpression)this.astObject; Step step = te.getSteps().get(te.getSteps().size() - 1); step.setMinDistance(minDistance); step.setMaxDistance(maxDistance); QueryRecorder.recordInvocation(this, "DISTANCE", this, QueryRecorder.literal(minDistance), QueryRecorder.literal(maxDistance)); return this; } /** * End the traversal of the domain object graph matching a specific type of domain objects * @param domainObjectType * @return a DomainObjectMatch */ public <T> DomainObjectMatch<T> TO(Class<T> domainObjectType) { TraversalExpression te = (TraversalExpression)this.astObject; DomainObjectMatch<T> ret =APIAccess.createDomainObjectMatch(domainObjectType, te.getQueryExecutor().getDomainObjectMatches().size(), te.getQueryExecutor().getMappingInfo()); te.getQueryExecutor().getDomainObjectMatches().add(ret); te.setEnd(ret); QueryRecorder.recordAssignment(this, "TO", ret, QueryRecorder.literal(domainObjectType.getName())); return ret; } /** * End the traversal of the domain object graph matching a specific type of domain objects. * <b>TO_GENERIC</b> is used when navigating a generic domain model. * @param domainObjectTypeName * @return a DomainObjectMatch */ public DomainObjectMatch<DomainObject> TO_GENERIC(String domainObjectTypeName) { Boolean br_old = null; try { TraversalExpression te = (TraversalExpression)this.astObject; InternalDomainAccess iAccess = te.getQueryExecutor().getMappingInfo().getInternalDomainAccess(); iAccess.loadDomainInfoIfNeeded(); Class<?> clazz = iAccess.getClassForName(domainObjectTypeName); br_old = QueryRecorder.blockRecording.get(); QueryRecorder.blockRecording.set(Boolean.TRUE); DomainObjectMatch<?> delegate = TO(clazz); QueryRecorder.blockRecording.set(br_old); DomainObjectMatch<DomainObject> ret = APIAccess.createDomainObjectMatch(DomainObject.class, delegate); QueryRecorder.recordAssignment(this, "TO_GENERIC", delegate, QueryRecorder.literal(domainObjectTypeName)); return ret; } catch (Throwable e) { if (e instanceof RuntimeException) throw (RuntimeException)e; else throw new RuntimeException(e); } finally { if (br_old != null) QueryRecorder.blockRecording.set(br_old); } } }