/******************************************************************************* * Copyright (C) 2006-2012 Dominik Jain. * * This file is part of ProbCog. * * ProbCog is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * ProbCog 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with ProbCog. If not, see <http://www.gnu.org/licenses/>. ******************************************************************************/ package probcog.srldb; import java.io.PrintStream; import java.io.Serializable; import java.util.Map.Entry; import probcog.srl.directed.ABLModel; import probcog.srl.mln.MLNWriter; import probcog.srldb.datadict.DDAttribute; import probcog.srldb.datadict.DDException; import probcog.srldb.datadict.IDDRelationArgument; import probcog.srldb.datadict.domain.BooleanDomain; import edu.tum.cs.util.StringTool; /** * Represents a link between two or more objects in a relational database. * @author Dominik Jain */ public class Link extends Item implements Serializable { private static final long serialVersionUID = 1L; protected String linkName; protected IRelationArgument[] arguments; /** * whether the link is present (if false, the link does not exist) */ protected boolean exists; public Link(Database database, String linkName, IRelationArgument arg1, IRelationArgument arg2) { this(database, linkName, new IRelationArgument[]{arg1, arg2}); } public Link(Database database, String linkName, IRelationArgument[] arguments) { this(database, linkName, arguments, true); } public Link(Database database, String linkName, IRelationArgument[] arguments, boolean exists) { super(database); this.linkName = linkName; this.arguments = arguments; this.exists = true; } public void setExists(boolean exists) { this.exists = exists; } /*public void addAttribute(String attribute, String value, DataTypeEnum type) { addAttribute(attribute, value, type, "L"); }*/ /** * gets a string representation of the literal represented by this link */ public String getLogicalAtom() { return (exists ? "" : "!") + linkName + "(" + StringTool.join(", ", arguments) + ")"; } public void MLNprintFacts(java.io.PrintStream out) throws DDException { String[] params = new String[this.arguments.length]; for(int i = 0; i < params.length; i++) params[i] = MLNWriter.formatAsConstant(arguments[i].getConstantName()); String allParams = StringTool.join(", ", params); String atom = linkName + "(" + allParams + ")"; // print the relation fact if(!exists) out.print('!'); out.println(atom); // if the link has boolean attributes, output further facts with the attribute // name as the predicate name for(String attribName : attribs.keySet()) { DDAttribute ddAttr = database.getDataDictionary().getAttribute(attribName); //RelDatabase.AttributeData data = this.attributes.get(attribName); if(/*data != null) { if(data.type == DataTypeEnum.STR &&*/ ddAttr.isBoolean()) { out.print(((BooleanDomain)ddAttr.getDomain()).isTrue(attribs.get(attribName)) ? "" : "!"); out.println(attribName + "(" + allParams + ")"); //} } else throw new DDException("Non-boolean attributes of links not handled for MLNs"); } } /** * prints facts on this link object (for BLOG databases) * @param out * @throws Exception */ public void BLOGprintFacts(PrintStream out) throws Exception { String[] params = new String[this.arguments.length]; for(int i = 0; i < params.length; i++) { params[i] = Database.upperCaseString(arguments[i].getConstantName()); if(!ABLModel.isValidEntityName(params[i])) throw new Exception("'" + params[i] + "' is not a valid entity name"); } String allParams = StringTool.join(", ", params); String atom = linkName + "(" + allParams + ")"; out.printf("%s = %s;\n", atom, exists ? probcog.srl.BooleanDomain.True : probcog.srl.BooleanDomain.False); // attributes String linkObjects = allParams; for(Entry<String, String> entry : getAttributes().entrySet()) { String predName = Database.stdPredicateName(entry.getKey()); DDAttribute ddAttrib = database.getDataDictionary().getAttribute(entry.getKey()); if(ddAttrib.isDiscarded()) continue; String value = Database.upperCaseString(entry.getValue()); if(!ABLModel.isValidEntityName(value)) throw new DDException("\"" + value + "\" is not a valid entity name"); out.printf("%s(%s) = %s;\n", predName, linkObjects, value); } } public String toString() { return getLogicalAtom(); } /** * adds this link to the database given at construction * @throws DDException */ public void commit() throws DDException { addTo(this.database); } /** * adds this link to the given database * @param db * @throws DDException */ public void addTo(Database db) throws DDException { if(db == this.database) // this is a commit immutable = true; // add the link to the database db.addLink(this); // get the objects that are linked here (this creates objects for constant arguments); // creating objects may be required depending on how the database is read (it is e.g. necessary for Proximity databases) for(int i = 0; i < this.arguments.length; i++) getArgumentObject(db, i); } public Object getArgumentObject(Database db, int i) throws DDException { if(arguments[i] instanceof ConstantArgument) { IDDRelationArgument argType = database.getDataDictionary().getRelation(this.linkName).getArguments()[i]; return db.getConstantAsObject(argType.getDomainName(), arguments[i].getConstantName()); } else return (Object)arguments[i]; } public String getName() { return this.linkName; } /** * @return the relation arguments */ public IRelationArgument[] getArguments() { return this.arguments; } /** * gets the relation arguments as objects, converting constant arguments * to objects beforehand * @return an array of objects * @throws DDException */ public Object[] getArgumentObjects() throws DDException { Object[] ret = new Object[arguments.length]; for(int i = 0; i < arguments.length; i++) ret[i] = getArgumentObject(this.database, i); return ret; } public void setSecondArgument(IRelationArgument arg) { arguments[1] = arg; } public void setFirstArgument(IRelationArgument arg) { arguments[0] = arg; } public void setArguments(IRelationArgument[] arguments) { this.arguments = arguments; } public void printData() { super.printData(); System.out.printf(" link: %s(", linkName); for(int i = 0; i < arguments.length; i++) { if(i > 0) System.out.print(", "); if(arguments[i] instanceof Item) System.out.printf("Item%d:", ((Item)arguments[i]).id); System.out.print(arguments[i]); } System.out.println(")"); } }