/*******************************************************************************
* 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.util.HashMap;
import java.util.Map.Entry;
import probcog.srl.directed.ABLModel;
import probcog.srldb.datadict.DDAttribute;
import probcog.srldb.datadict.DDException;
import probcog.srldb.datadict.domain.BooleanDomain;
/**
* Represents an object appearing in a relational database.
* @author Dominik Jain
*/
public class Object extends Item implements IRelationArgument, java.io.Serializable {
private static final long serialVersionUID = 1L;
protected HashMap<String, Link> links;
protected String objTypeName;
protected String constantName = null;
/**
* creates an object for the given database;
* Since a type name is not provided but is determined from the actual class name,
* this constructor cannot be used directly - it can only be used in derived classes
* that actually have a meaningful name.
* @param database the database the object is to be part of (upon commit)
*/
protected Object(Database database) {
this(database, null);
objTypeName = getClass().getSimpleName();
}
/**
* creates an object of the given type name
* @param database the database the object is to be part of (upon commit)
* @param objTypeName the type name
*/
public Object(Database database, String objTypeName) {
super(database);
links = null;
this.objTypeName = objTypeName;
}
public Object(Database database, String objTypeName, String constantName) {
this(database, objTypeName);
this.constantName = constantName;
}
/**
* links this object to another object
* @param linkName the name of the link/relation
* @param otherObj the object to link to
* @return a reference to the newly created link object
* @throws DDException
*/
public Link link(String linkName, Object otherObj) throws DDException {
checkMutable();
Link link = new Link(database, linkName, this, otherObj);
if(links == null)
links = new HashMap<String, Link>();
links.put(linkName, link);
return link;
}
/**
* links this object to several other objects
* @param linkName the name of the link/relation
* @param otherObjects the objects to link to
* @return a reference to the newly created link object
* @throws DDException
*/
public Link link(String linkName, Object[] otherObjects) throws DDException {
checkMutable();
Object[] objs = new Object[1+otherObjects.length];
objs[0] = this;
for(int i = 0; i < otherObjects.length; i++)
objs[i+1] = otherObjects[i];
Link link = new Link(database, linkName, objs);
links.put(linkName, link);
return link;
}
/**
* @return a string, i.e. a constant name, that (uniquely) identifies this object in a database
*/
public String getConstantName() {
if(constantName == null)
return "O" + objType() + id;
else
return constantName;
}
public String toString() {
return getConstantName();
}
public void MLNprintFacts(PrintStream out) throws DDException {
for(String attribName : attribs.keySet()) {
MLNprintFact(attribName, out);
}
}
public void MLNprintFact(String attribName, PrintStream out) throws DDException {
DDAttribute ddAttrib = database.getDataDictionary().getAttribute(attribName);
if(ddAttrib.isDiscarded())
return;
String strValue = attribs.get(attribName);
String predicate = Database.stdPredicateName(attribName);
// check if the attribute is boolean and if so, use a predicate that has no
// parameters other than the object name
if(ddAttrib.isBoolean()) {
BooleanDomain bd = BooleanDomain.getInstance();
out.println((!bd.isTrue(strValue) ? "!" : "") + predicate + "(" + getConstantName() + ")");
}
// otherwise use a predicate with two parameters: object name and value
else {
out.println(predicate + "(" + getConstantName() + ", " + Database.stdAttribStringValue(strValue) + ")");
}
}
public void BLOGprintFacts(PrintStream out) throws DDException {
if(getAttributes().size() == 0)
return;
String constant = getConstantName();
if(!ABLModel.isValidEntityName(constant))
throw new DDException("\"" + constant + "\" is not a valid entity name");
for(Entry<String, String> entry : getAttributes().entrySet()) {
String functionName = Database.stdPredicateName(entry.getKey());
DDAttribute ddAttrib = database.getDataDictionary().getAttribute(functionName);
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", functionName, constant, value);
}
}
/**
* gets the object type name for this object
* @return the object type name; class name by default (unless overridden during construction)
*/
public String objType() {
return objTypeName;
}
/**
* adds the object and all attached links to the database this object is associated with
* @throws DDException
*/
public void commit() throws DDException {
addTo(this.database);
}
/**
* adds the object and all attached links 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 object
db.addObject(this);
// add links
if(links != null) {
for(Link link : links.values()) {
// add linked objects
for(IRelationArgument arg : link.arguments)
if(arg instanceof Object && arg != this)
((Object)arg).addTo(db);
// add link itself
link.addTo(db);
}
}
}
public Link getLink(String linkName) {
if(links == null)
return null;
return links.get(linkName);
}
public void printData() {
super.printData();
System.out.println(" object type: " + this.objTypeName);
System.out.println(" constant: " + this.constantName);
}
}