package uk.ac.manchester.cs.jfact.kernel; /* This file is part of the JFact DL reasoner Copyright 2011-2013 by Ignazio Palmisano, Dmitry Tsarkov, University of Manchester This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA*/ import static uk.ac.manchester.cs.jfact.kernel.Token.*; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import org.semanticweb.owlapi.reasoner.ReasonerInternalException; import uk.ac.manchester.cs.jfact.datatypes.Datatype; import uk.ac.manchester.cs.jfact.datatypes.DatatypeEntry; import uk.ac.manchester.cs.jfact.datatypes.DatatypeExpression; import uk.ac.manchester.cs.jfact.datatypes.Literal; import uk.ac.manchester.cs.jfact.datatypes.LiteralEntry; import uk.ac.manchester.cs.jfact.helpers.DLTree; import uk.ac.manchester.cs.jfact.helpers.DLTreeFactory; import uk.ac.manchester.cs.jfact.kernel.dl.ConceptAnd; import uk.ac.manchester.cs.jfact.kernel.dl.ConceptBottom; import uk.ac.manchester.cs.jfact.kernel.dl.ConceptDataExactCardinality; import uk.ac.manchester.cs.jfact.kernel.dl.ConceptDataExists; import uk.ac.manchester.cs.jfact.kernel.dl.ConceptDataForall; import uk.ac.manchester.cs.jfact.kernel.dl.ConceptDataMaxCardinality; import uk.ac.manchester.cs.jfact.kernel.dl.ConceptDataMinCardinality; import uk.ac.manchester.cs.jfact.kernel.dl.ConceptDataValue; import uk.ac.manchester.cs.jfact.kernel.dl.ConceptName; import uk.ac.manchester.cs.jfact.kernel.dl.ConceptNot; import uk.ac.manchester.cs.jfact.kernel.dl.ConceptObjectExactCardinality; import uk.ac.manchester.cs.jfact.kernel.dl.ConceptObjectExists; import uk.ac.manchester.cs.jfact.kernel.dl.ConceptObjectForall; import uk.ac.manchester.cs.jfact.kernel.dl.ConceptObjectMaxCardinality; import uk.ac.manchester.cs.jfact.kernel.dl.ConceptObjectMinCardinality; import uk.ac.manchester.cs.jfact.kernel.dl.ConceptObjectSelf; import uk.ac.manchester.cs.jfact.kernel.dl.ConceptObjectValue; import uk.ac.manchester.cs.jfact.kernel.dl.ConceptOneOf; import uk.ac.manchester.cs.jfact.kernel.dl.ConceptOr; import uk.ac.manchester.cs.jfact.kernel.dl.ConceptTop; import uk.ac.manchester.cs.jfact.kernel.dl.DataAnd; import uk.ac.manchester.cs.jfact.kernel.dl.DataBottom; import uk.ac.manchester.cs.jfact.kernel.dl.DataNot; import uk.ac.manchester.cs.jfact.kernel.dl.DataOneOf; import uk.ac.manchester.cs.jfact.kernel.dl.DataOr; import uk.ac.manchester.cs.jfact.kernel.dl.DataRoleBottom; import uk.ac.manchester.cs.jfact.kernel.dl.DataRoleName; import uk.ac.manchester.cs.jfact.kernel.dl.DataRoleTop; import uk.ac.manchester.cs.jfact.kernel.dl.DataTop; import uk.ac.manchester.cs.jfact.kernel.dl.IndividualName; import uk.ac.manchester.cs.jfact.kernel.dl.ObjectRoleBottom; import uk.ac.manchester.cs.jfact.kernel.dl.ObjectRoleChain; import uk.ac.manchester.cs.jfact.kernel.dl.ObjectRoleInverse; import uk.ac.manchester.cs.jfact.kernel.dl.ObjectRoleName; import uk.ac.manchester.cs.jfact.kernel.dl.ObjectRoleProjectionFrom; import uk.ac.manchester.cs.jfact.kernel.dl.ObjectRoleProjectionInto; import uk.ac.manchester.cs.jfact.kernel.dl.ObjectRoleTop; import uk.ac.manchester.cs.jfact.kernel.dl.interfaces.Expression; import uk.ac.manchester.cs.jfact.kernel.dl.interfaces.NAryExpression; import uk.ac.manchester.cs.jfact.kernel.dl.interfaces.NamedEntity; import uk.ac.manchester.cs.jfact.kernel.dl.interfaces.ObjectRoleExpression; import uk.ac.manchester.cs.jfact.split.TSignature; import uk.ac.manchester.cs.jfact.visitors.DLExpressionVisitorEx; import conformance.Original; import conformance.PortedFrom; /** expression translator */ @PortedFrom(file = "tExpressionTranslator.h", name = "TExpressionTranslator") public class ExpressionTranslator implements DLExpressionVisitorEx<DLTree>, Serializable { private static final long serialVersionUID = 11000L; /** TBox to get access to the named entities */ @PortedFrom(file = "tExpressionTranslator.h", name = "kb") private final TBox tbox; /** * signature of non-trivial entities; used in semantic locality checkers * only */ @PortedFrom(file = "tExpressionTranslator.h", name = "sig") private TSignature sig; /** * @param entity * entity * @return true iff ENTRY is not in signature */ @PortedFrom(file = "tExpressionTranslator.h", name = "nc") private boolean nc(NamedEntity entity) { return sig != null && !sig.containsNamedEntity(entity); } /** * set internal signature to a given signature S * * @param s * signature */ @PortedFrom(file = "tExpressionTranslator.h", name = "setSignature") public void setSignature(TSignature s) { sig = s; } /** * @param kb * kb */ public ExpressionTranslator(TBox kb) { tbox = kb; } // concept expressions @Override public DLTree visit(ConceptTop expr) { return DLTreeFactory.createTop(); } @Override public DLTree visit(ConceptBottom expr) { return DLTreeFactory.createBottom(); } @Override public DLTree visit(ConceptName expr) { if (nc(expr)) { return sig.topCLocal() ? DLTreeFactory.createTop() : DLTreeFactory .createBottom(); } else { NamedEntry entry = expr.getEntry(); if (entry == null) { entry = matchEntry(tbox.getConcept(expr.getName()), expr); } return DLTreeFactory.buildTree(new Lexeme(CNAME, entry)); } } /** * create DLTree of given TAG and named ENTRY; set the entry's ENTITY if * * @param entry * entry * @param entity * entity * @return updated named entry */ // necessary @PortedFrom(file = "tExpressionTranslator.h", name = "matchEntry") private NamedEntry matchEntry(NamedEntry entry, NamedEntity entity) { entry.setEntity(entity); entity.setEntry(entry); return entry; } @Override public DLTree visit(ConceptNot expr) { return DLTreeFactory.createSNFNot(expr.getConcept().accept(this)); } @Original private List<DLTree> visitArgs(NAryExpression<? extends Expression> expr) { List<DLTree> args = new ArrayList<DLTree>(); List<? extends Expression> list = expr.getArguments(); for (int i = 0; i < list.size(); i++) { args.add(list.get(i).accept(this)); } return args; } @Override public DLTree visit(ConceptAnd expr) { return DLTreeFactory.createSNFAnd(visitArgs(expr)); } @Override public DLTree visit(ConceptOr expr) { return DLTreeFactory.createSNFOr(visitArgs(expr)); } @Override public DLTree visit(ConceptOneOf<?> expr) { return DLTreeFactory.createSNFOr(visitArgs(expr)); } @Override public DLTree visit(ConceptObjectSelf expr) { DLTree r = expr.getOR().accept(this); return DLTreeFactory.createSNFSelf(r); } @Override public DLTree visit(ConceptObjectValue expr) { return DLTreeFactory.createSNFExists(expr.getOR().accept(this), expr .getIndividual().accept(this)); } @Override public DLTree visit(ConceptObjectExists expr) { return DLTreeFactory.createSNFExists(expr.getOR().accept(this), expr .getConcept().accept(this)); } @Override public DLTree visit(ConceptObjectForall expr) { return DLTreeFactory.createSNFForall(expr.getOR().accept(this), expr .getConcept().accept(this)); } @Override public DLTree visit(ConceptObjectMinCardinality expr) { return DLTreeFactory.createSNFGE(expr.getCardinality(), expr.getOR() .accept(this), expr.getConcept().accept(this)); } @Override public DLTree visit(ConceptObjectMaxCardinality expr) { return DLTreeFactory.createSNFLE(expr.getCardinality(), expr.getOR() .accept(this), expr.getConcept().accept(this)); } @Override public DLTree visit(ConceptObjectExactCardinality expr) { DLTree le = DLTreeFactory.createSNFLE(expr.getCardinality(), expr .getOR().accept(this).copy(), expr.getConcept().accept(this) .copy()); DLTree ge = DLTreeFactory.createSNFGE(expr.getCardinality(), expr .getOR().accept(this).copy(), expr.getConcept().accept(this) .copy()); return DLTreeFactory.createSNFAnd(ge, le); } @Override public DLTree visit(ConceptDataValue expr) { return DLTreeFactory.createSNFExists(expr.getDataRoleExpression() .accept(this), expr.getExpr().accept(this)); } @Override public DLTree visit(ConceptDataExists expr) { return DLTreeFactory.createSNFExists(expr.getDataRoleExpression() .accept(this), expr.getExpr().accept(this)); } @Override public DLTree visit(ConceptDataForall expr) { return DLTreeFactory.createSNFForall(expr.getDataRoleExpression() .accept(this), expr.getExpr().accept(this)); } @Override public DLTree visit(ConceptDataMinCardinality expr) { return DLTreeFactory.createSNFGE(expr.getCardinality(), expr .getDataRoleExpression().accept(this), expr.getExpr().accept(this)); } @Override public DLTree visit(ConceptDataMaxCardinality expr) { return DLTreeFactory.createSNFLE(expr.getCardinality(), expr .getDataRoleExpression().accept(this), expr.getExpr().accept(this)); } @Override public DLTree visit(ConceptDataExactCardinality expr) { DLTree le = DLTreeFactory.createSNFLE(expr.getCardinality(), expr .getDataRoleExpression().accept(this).copy(), expr.getExpr() .accept(this).copy()); DLTree ge = DLTreeFactory.createSNFGE(expr.getCardinality(), expr .getDataRoleExpression().accept(this).copy(), expr.getExpr() .accept(this).copy()); return DLTreeFactory.createSNFAnd(ge, le); } // individual expressions @Override public DLTree visit(IndividualName expr) { NamedEntry entry = expr.getEntry(); if (entry == null) { entry = matchEntry(tbox.getIndividual(expr.getName()), expr); } return DLTreeFactory.buildTree(new Lexeme(INAME, entry)); } // object role expressions @Override public DLTree visit(ObjectRoleTop expr) { throw new ReasonerInternalException( "Unsupported expression 'top object role' in transformation"); } @Override public DLTree visit(ObjectRoleBottom expr) { throw new ReasonerInternalException( "Unsupported expression 'bottom object role' in transformation"); } @Override public DLTree visit(ObjectRoleName expr) { RoleMaster RM = tbox.getORM(); NamedEntry role; if (nc(expr)) { role = sig.topRLocal() ? RM.getTopRole() : RM.getBotRole(); } else { role = expr.getEntry(); if (role == null) { role = matchEntry(RM.ensureRoleName(expr.getName()), expr); } } return DLTreeFactory.buildTree(new Lexeme(RNAME, role)); } @Override public DLTree visit(ObjectRoleInverse expr) { return DLTreeFactory.createInverse(expr.getOR().accept(this)); } @Override public DLTree visit(ObjectRoleChain expr) { List<ObjectRoleExpression> l = new ArrayList<ObjectRoleExpression>( expr.getArguments()); if (l.isEmpty()) { throw new ReasonerInternalException( "Unsupported expression 'empty role chain' in transformation"); } DLTree acc = l.get(0).accept(this); for (int i = 1; i < l.size(); i++) { // TODO this is still a binary tree while it should be n-ary with // enforced order acc = DLTreeFactory.buildTree(new Lexeme(RCOMPOSITION), acc, l.get(i).accept(this)); } return acc; } @Override public DLTree visit(ObjectRoleProjectionFrom expr) { return DLTreeFactory.buildTree(new Lexeme(PROJFROM), expr.getOR() .accept(this), expr.getConcept().accept(this)); } @Override public DLTree visit(ObjectRoleProjectionInto expr) { return DLTreeFactory.buildTree(new Lexeme(PROJINTO), expr.getOR() .accept(this), expr.getConcept().accept(this)); } // data role expressions @Override public DLTree visit(DataRoleTop expr) { throw new ReasonerInternalException( "Unsupported expression 'top data role' in transformation"); } @Override public DLTree visit(DataRoleBottom expr) { throw new ReasonerInternalException( "Unsupported expression 'bottom data role' in transformation"); } @Override public DLTree visit(DataRoleName expr) { RoleMaster RM = tbox.getDRM(); NamedEntry role; if (nc(expr)) { role = sig.topRLocal() ? RM.getTopRole() : RM.getBotRole(); } else { role = expr.getEntry(); if (role == null) { role = matchEntry(RM.ensureRoleName(expr.getName()), expr); } } return DLTreeFactory.buildTree(new Lexeme(DNAME, role)); } // data expressions @Override public DLTree visit(DataTop expr) { return DLTreeFactory.createTop(); } @Override public DLTree visit(DataBottom expr) { return DLTreeFactory.createBottom(); } @Override public DLTree visit(Datatype<?> expr) { DatatypeEntry entry = new DatatypeEntry(expr); return DLTreeFactory.wrap(entry); } @Override public DLTree visit(DatatypeExpression<?> expr) { DatatypeEntry entry = new DatatypeEntry(expr); return DLTreeFactory.wrap(entry); } @Override public DLTree visit(Literal<?> expr) { // process type LiteralEntry entry = new LiteralEntry(expr.value()); entry.setLiteral(expr); return DLTreeFactory.wrap(entry); } @Override public DLTree visit(DataNot expr) { return DLTreeFactory.createSNFNot(expr.getExpr().accept(this)); } @Override public DLTree visit(DataAnd expr) { return DLTreeFactory.createSNFAnd(visitArgs(expr)); } @Override public DLTree visit(DataOr expr) { return DLTreeFactory.createSNFOr(visitArgs(expr)); } @Override public DLTree visit(DataOneOf expr) { return DLTreeFactory.createSNFOr(visitArgs(expr)); } }