/* * #! * 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.rdbms; import java.util.List; import net.ontopia.infoset.core.LocatorIF; import net.ontopia.persistence.query.jdo.JDOContains; import net.ontopia.persistence.query.jdo.JDOEquals; import net.ontopia.persistence.query.jdo.JDOField; import net.ontopia.persistence.query.jdo.JDONotEquals; import net.ontopia.persistence.query.jdo.JDONull; import net.ontopia.persistence.query.jdo.JDOObject; import net.ontopia.persistence.query.jdo.JDOValueIF; import net.ontopia.topicmaps.core.TopicIF; import net.ontopia.topicmaps.core.TopicMapIF; import net.ontopia.topicmaps.impl.rdbms.Association; import net.ontopia.topicmaps.impl.rdbms.AssociationRole; import net.ontopia.topicmaps.query.core.InvalidQueryException; import net.ontopia.topicmaps.query.parser.Pair; /** * INTERNAL: Implements dynamic association predicates. */ public class DynamicAssociationPredicate extends net.ontopia.topicmaps.query.impl.basic.DynamicAssociationPredicate implements JDOPredicateIF { public DynamicAssociationPredicate(TopicMapIF topicmap, LocatorIF base, TopicIF type) { super(topicmap, base, type); } // --- JDOPredicateIF implementation public boolean isRecursive() { return false; } public void prescan(QueryBuilder builder, List arguments) { } public boolean buildQuery(QueryBuilder builder, List expressions, List arguments) throws InvalidQueryException { // Interpret arguments Object[] args = arguments.toArray(); // TOLOG: assoc-type ( PLAYER1 : RTYPE1, ..., PLAYERn : RTYPEn ) JDOValueIF jv_assoc = builder.createJDOVariable("A", Association.class); JDOValueIF jv_atype = builder.createJDOValue(type); // JDOQL: A.type = AT expressions.add(new JDOEquals(new JDOField(jv_assoc, "type"), jv_atype)); // if variable: filter out nulls if (jv_atype.getType() == JDOValueIF.VARIABLE) expressions.add(new JDONotEquals(jv_atype, new JDONull())); // JDOQL: A.topicmap = TOPICMAP expressions.add(new JDOEquals(new JDOField(jv_assoc, "topicmap"), new JDOObject(topicmap))); JDOValueIF[] jv_roles = new JDOValueIF[args.length]; for (int i=0; i < args.length; i++) { Object arg = args[i]; Pair pair = (Pair)arg; Object first = pair.getFirst(); Object second = pair.getSecond(); JDOValueIF jv_player = builder.createJDOValue(first); JDOValueIF jv_rtype = builder.createJDOValue(second); JDOValueIF jv_role = builder.createJDOVariable("R", AssociationRole.class); jv_roles[i] = jv_role; // JDOQL: A.roles.contains(R) & R.type = RT & R.player = RP expressions.add(new JDOContains(new JDOField(jv_assoc, "roles"), jv_role)); expressions.add(new JDOEquals(new JDOField(jv_role, "player"), jv_player)); expressions.add(new JDOEquals(new JDOField(jv_role, "type"), jv_rtype)); // if variable: filter out nulls if (jv_rtype.getType() == JDOValueIF.VARIABLE) expressions.add(new JDONotEquals(jv_rtype, new JDONull())); // if variable: filter out nulls if (jv_player.getType() == JDOValueIF.VARIABLE) expressions.add(new JDONotEquals(jv_player, new JDONull())); } // TODO: Append expression that makes sure that there are no // duplicates among the R1, ..., Rn tables. if (jv_roles.length == 2) { expressions.add(new JDONotEquals(jv_roles[0], jv_roles[1])); } else if (jv_roles.length == 3) { expressions.add(new JDONotEquals(jv_roles[0], jv_roles[1])); expressions.add(new JDONotEquals(jv_roles[1], jv_roles[2])); expressions.add(new JDONotEquals(jv_roles[0], jv_roles[2])); } else { // FIXME: add support for more than two and three roles } return true; // TODO: All association predicates get it's topic map bound by // the fact that the association predicate is a fixed topic. If we // in the future can let the association type be a varibale we // need to make sure that the topic map is bound properly. // FIXME: The AssociationIF cannot be a tolog variable at this // time, but if it can we must make sure that the topic map is // bound. // Need to make sure that just get results for the current topic map //! if (builder.getAttribute("TOPICMAP") == null ) { //! expressions.add(new JDOEquals(new JDOField(jv_atype, "topicmap"), //! new JDOObject(topicmap))); //! builder.setAttribute("TOPICMAP", topicmap); //! } } }