package org.obo.annotation.base;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.commons.lang.ObjectUtils;
import org.obo.app.model.AbstractPropertyChangeObject;
import org.obo.app.util.Collections;
import org.obo.datamodel.Link;
import org.obo.datamodel.OBOClass;
import org.obo.datamodel.OBOObject;
import org.obo.datamodel.OBOProperty;
import org.obo.datamodel.OBORestriction;
import org.obo.datamodel.TermSubset;
import org.obo.datamodel.impl.OBOClassImpl;
import org.obo.datamodel.impl.OBORestrictionImpl;
public class OBOUtil {
public static OBOClass createPostComposition(OBOClass genus,
List<Differentium> differentia) {
final String id = createPostcompositionID(genus, differentia);
final String name = createPostcompositionName(genus, differentia);
final OBOClass postComposition = new OBOClassImpl(name, id);
final OBORestrictionImpl genusRelation = new OBORestrictionImpl(
postComposition, OBOProperty.IS_A, genus);
genusRelation.setCompletes(true);
postComposition.addParent(genusRelation);
for (Differentium differentium : differentia) {
final OBORestrictionImpl differentiumRelation = new OBORestrictionImpl(
postComposition, differentium.getRelation(),
differentium.getTerm());
differentiumRelation.setCompletes(true);
postComposition.addParent(differentiumRelation);
}
return postComposition;
}
private static String createPostcompositionID(OBOClass genus,
List<Differentium> differentia) {
final StringBuffer sb = new StringBuffer();
sb.append(genus.getID());
for (Differentium differentium : differentia) {
sb.append(createDifferentiumID(differentium));
}
return sb.toString();
}
public static String generateManchesterIDExpression(OBOClass term) {
if (!isPostCompTerm(term)) {
return term.getID();
} else {
final List<String> differentiae = new ArrayList<String>();
for (Link diff : getAllDifferentia(term)) {
differentiae.add(generateManchesterIDExpression(diff));
}
final String diffs = Collections.join(differentiae, " and ");
final OBOClass genus = getGenusTerm(term);
final String fillerFormat;
if (isPostCompTerm(genus)) {
fillerFormat = "(%s)";
} else {
fillerFormat = "%s";
}
return String.format(fillerFormat,
generateManchesterIDExpression(getGenusTerm(term)))
+ " and " + diffs;
}
}
private static String generateManchesterIDExpression(Link diff) {
final OBOClass parent = (OBOClass) (diff.getParent());
final String fillerFormat;
if (isPostCompTerm(parent)) {
fillerFormat = "(%s)";
} else {
fillerFormat = "%s";
}
return "("
+ diff.getType().getID()
+ " some "
+ String.format(fillerFormat,
generateManchesterIDExpression(parent)) + ")";
}
public static String generateManchesterLabelExpression(OBOClass term) {
if (!isPostCompTerm(term)) {
final String name = term.getName();
if (name == null) {
return term.getID();
} else if (name.contains(" ")) {
return "'" + name + "'";
} else {
return name;
}
} else {
final List<String> differentiae = new ArrayList<String>();
for (Link diff : getAllDifferentia(term)) {
differentiae.add(generateManchesterLabelExpression(diff));
}
final String diffs = Collections.join(differentiae, " and ");
final OBOClass genus = getGenusTerm(term);
final String fillerFormat;
if (isPostCompTerm(genus)) {
fillerFormat = "(%s)";
} else {
fillerFormat = "%s";
}
return String.format(fillerFormat,
generateManchesterLabelExpression(getGenusTerm(term)))
+ " and " + diffs;
}
}
private static String generateManchesterLabelExpression(Link diff) {
final OBOClass parent = (OBOClass) (diff.getParent());
final String fillerFormat;
if (isPostCompTerm(parent)) {
fillerFormat = "(%s)";
} else {
fillerFormat = "%s";
}
return "("
+ diff.getType().getName()
+ " some "
+ String.format(fillerFormat,
generateManchesterLabelExpression(parent)) + ")";
}
private static String createPostcompositionName(OBOClass genus,
List<Differentium> differentia) {
final StringBuffer sb = new StringBuffer();
sb.append(genus.getName());
for (Differentium differentium : differentia) {
sb.append(createDifferentiumName(differentium));
}
return sb.toString();
}
private static String relationDifferentiumFormat(String r, String d) {
return "^" + r + "(" + d + ")";
}
private static String createDifferentiumID(Differentium differentium) {
return relationDifferentiumFormat(differentium.getRelation().getID(),
differentium.getTerm().getID());
}
private static String createDifferentiumName(Differentium differentium) {
return relationDifferentiumFormat(differentium.getRelation().getName(),
differentium.getTerm().getName());
}
/** for non post comp returns term itself */
public static OBOClass getGenusTerm(OBOClass term) {
if (isPostCompTerm(term)) {
for (Object o : term.getParents()) {
OBORestriction r = (OBORestriction) o;
if (r.getCompletes() && r.getType().equals(OBOProperty.IS_A))
return (OBOClass) r.getParent(); // check downcast?
}
// error msg?
}
return term;
}
public static boolean isPostCompTerm(OBOObject term) {
if (term.getID().indexOf('^') < 0) {
return false;
}
for (Link l : term.getParents()) {
if (isLinkToDiff(l)) {
return true;
}
}
return false;
}
public static boolean isLinkToDiff(Link l) {
if (!isOboRestriction(l))
return false;
return isLinkToDiff(getOboRestriction(l));
}
public static boolean isLinkToDiff(OBORestriction r) {
// i guess there is a case where isa is completes - but why?
return r.getCompletes() && !r.getType().equals(OBOProperty.IS_A);
}
public static boolean isOboRestriction(Link l) {
return l instanceof OBORestriction;
}
public static OBORestriction getOboRestriction(Link l) {
if (!isOboRestriction(l))
return null;
return (OBORestriction) l;
}
public static List<Link> getAllDifferentia(OBOClass postComp) {
final List<Link> restrictions = new ArrayList<Link>();
for (Link l : postComp.getParents()) {
if (isLinkToDiff(l))
restrictions.add(l);
}
return restrictions;
}
/**
* Finds and returns the closest attribute ancestor for a value term from
* PATO. Returns the input term if it is itself an attribute, or null if no
* attribute is found.
*/
public static OBOClass getAttributeForValue(OBOClass valueTerm) {
final Set<TermSubset> categories = valueTerm.getSubsets();
final Set<String> categoryNames = new HashSet<String>();
if (categories != null) {
for (TermSubset category : categories) {
categoryNames.add(category.getName());
}
if (categoryNames.contains("attribute_slim")) {
return valueTerm;
} else if ((categoryNames.contains("value_slim"))) {
return getAttributeForValue(getIsaParentForTerm(valueTerm));
}
}
return null;
}
public static OBOClass getCharacterForValue(OBOClass valueTerm) {
final Set<TermSubset> categories = valueTerm.getSubsets();
final Set<String> categoryNames = new HashSet<String>();
if (categories != null) {
for (TermSubset category : categories) {
categoryNames.add(category.getName());
}
if (categoryNames.contains("character_slim")) {
return valueTerm;
} else {
final OBOClass parent = getIsaParentForTerm(valueTerm);
if (parent != null) {
return getCharacterForValue(parent);
}
}
}
return null;
}
/**
* Returns the "is_a" parent for an OBO term, or null if one is not found.
*/
public static OBOClass getIsaParentForTerm(OBOClass term) {
final Collection<Link> parents = term.getParents();
for (Link link : parents) {
if (link.getType().getName().equals("is_a")) {
return (OBOClass) (link.getParent());
}
}
return null;
}
// if (ObjectUtils.equals(this.validName, validName)) return;
// final OBOClass oldValue = this.validName;
// this.validName = validName;
// this.firePropertyChange(VALID_NAME, oldValue, validName);
public static class Differentium extends AbstractPropertyChangeObject {
public static final String RELATION = "relation";
public static final String TERM = "term";
private OBOProperty relation;
private OBOClass term;
public OBOProperty getRelation() {
return this.relation;
}
public void setRelation(OBOProperty relation) {
if (ObjectUtils.equals(this.relation, relation))
return;
final OBOProperty oldValue = this.relation;
this.relation = relation;
this.firePropertyChange(RELATION, oldValue, relation);
}
public OBOClass getTerm() {
return this.term;
}
public void setTerm(OBOClass term) {
if (ObjectUtils.equals(this.term, term))
return;
final OBOClass oldValue = this.term;
this.term = term;
this.firePropertyChange(TERM, oldValue, term);
}
public boolean isComplete() {
return (this.relation != null) && (this.term != null);
}
@Override
public Class<?> getClass(String propertyKey)
throws UndefinedKeyException {
if (propertyKey.equals(TERM)) {
return OBOClass.class;
} else if (propertyKey.equals(RELATION)) {
return OBOProperty.class;
} else {
return super.getClass(propertyKey);
}
}
}
}