/* * #! * Ontopia Engine * #- * Copyright (C) 2001 - 2013 The Ontopia Project * #- * 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 net.ontopia.topicmaps.query.impl.basic; import java.util.Iterator; import net.ontopia.topicmaps.core.AssociationRoleIF; import net.ontopia.topicmaps.core.TopicIF; import net.ontopia.topicmaps.core.TopicMapIF; import net.ontopia.topicmaps.query.core.InvalidQueryException; import net.ontopia.topicmaps.query.impl.utils.PredicateOptions; import net.ontopia.topicmaps.query.impl.utils.Prefetcher; import net.ontopia.topicmaps.query.parser.Parameter; import net.ontopia.topicmaps.query.impl.utils.PredicateDrivenCostEstimator; /** * INTERNAL: Implements the 'role-player' predicate. */ public class RolePlayerPredicate implements BasicPredicateIF { protected TopicMapIF topicmap; public RolePlayerPredicate(TopicMapIF topicmap) { this.topicmap = topicmap; } public String getName() { return "role-player"; } public String getSignature() { return "r t z?"; // predicateoptions inserted by optimizer } public int getCost(boolean[] boundparams) { if (boundparams[0] && boundparams[1]) return PredicateDrivenCostEstimator.FILTER_RESULT; else if (boundparams[0] && !boundparams[1]) return PredicateDrivenCostEstimator.SINGLE_RESULT; else if (!boundparams[0] && boundparams[1]) return PredicateDrivenCostEstimator.MEDIUM_RESULT; else return PredicateDrivenCostEstimator.WHOLE_TM_RESULT; } public QueryMatches satisfy(QueryMatches matches, Object[] arguments) throws InvalidQueryException { int roleix = matches.getIndex(arguments[0]); int topicix = matches.getIndex(arguments[1]); if (!matches.bound(roleix) && matches.bound(topicix)) { Object typecolumn = null; if (arguments.length > 2) { typecolumn = ((PredicateOptions) arguments[2]).getColumn(); // translate parameter into value // this isn't too pretty; we ought to be able to hide this if (typecolumn instanceof Parameter) typecolumn = matches.getQueryContext(). getParameterValue(((Parameter) typecolumn).getName()); } return topicToRole(matches, arguments, typecolumn); } else if (matches.bound(roleix) && !matches.bound(topicix)) { Prefetcher.prefetch(topicmap, matches, roleix, Prefetcher.AssociationRoleIF, Prefetcher.AssociationRoleIF_player, false); return PredicateUtils.objectToOne(matches, roleix, topicix, AssociationRoleIF.class, PredicateUtils.ROLE_TO_PLAYER); } else if (matches.bound(roleix) && matches.bound(topicix)) { Prefetcher.prefetch(topicmap, matches, roleix, Prefetcher.AssociationRoleIF, Prefetcher.AssociationRoleIF_player, false); return PredicateUtils.filter(matches, roleix, topicix, AssociationRoleIF.class, TopicIF.class, PredicateUtils.FILTER_ROLE_PLAYER); } else { Prefetcher.prefetch(topicmap, matches, topicix, Prefetcher.TopicIF, Prefetcher.TopicIF_roles, false); return PredicateUtils.generateFromCollection(matches, topicix, roleix, topicmap.getTopics(), PredicateUtils.GENERATE_ROLE_PLAYER); } } // internal private QueryMatches topicToRole(QueryMatches matches, Object[] arguments, Object typecolumn) { int typeix = -1; if (typecolumn != null) typeix = matches.getIndex(typecolumn); // will be -1 if typecolumn is a TopicIF constant QueryMatches result = new QueryMatches(matches); int roleix = result.getIndex(arguments[0]); int topicix = result.getIndex(arguments[1]); if (typeix == -1) Prefetcher.prefetch(topicmap, matches, topicix, Prefetcher.TopicIF, Prefetcher.TopicIF_roles, false); TopicIF roletype = null; if (typeix == -1) roletype = (TopicIF) typecolumn; // fixed role type for (int ix = 0; ix <= matches.last; ix++) { TopicIF topic = (TopicIF) matches.data[ix][topicix]; Iterator it; if (typecolumn != null) { // used when optimizer has told us the type if (typeix != -1) roletype = (TopicIF) matches.data[ix][typeix]; // dynamic role type it = topic.getRolesByType(roletype).iterator(); } else it = topic.getRoles().iterator(); while (it.hasNext()) { AssociationRoleIF role = (AssociationRoleIF) it.next(); if (result.last+1 == result.size) result.increaseCapacity(); result.last++; Object[] newRow = (Object[]) matches.data[ix].clone(); newRow[roleix] = role; result.data[result.last] = newRow; } } return result; } }