All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.obolibrary.obo2owl.OWLAPIOwl2Obo Maven / Gradle / Ivy

package org.obolibrary.obo2owl;

import java.io.UnsupportedEncodingException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.obolibrary.obo2owl.Obo2OWLConstants.Obo2OWLVocabulary;
import org.obolibrary.obo2owl.OwlStringTools.OwlStringException;
import org.obolibrary.oboformat.model.Clause;
import org.obolibrary.oboformat.model.Frame;
import org.obolibrary.oboformat.model.Frame.FrameType;
import org.obolibrary.oboformat.model.OBODoc;
import org.obolibrary.oboformat.model.QualifierValue;
import org.obolibrary.oboformat.model.Xref;
import org.obolibrary.oboformat.parser.OBOFormatConstants;
import org.obolibrary.oboformat.parser.OBOFormatConstants.OboFormatTag;
import org.semanticweb.owlapi.model.AxiomType;
import org.semanticweb.owlapi.model.IRI;
import org.semanticweb.owlapi.model.OWLAnnotation;
import org.semanticweb.owlapi.model.OWLAnnotationAssertionAxiom;
import org.semanticweb.owlapi.model.OWLAnnotationProperty;
import org.semanticweb.owlapi.model.OWLAnnotationValue;
import org.semanticweb.owlapi.model.OWLAsymmetricObjectPropertyAxiom;
import org.semanticweb.owlapi.model.OWLAxiom;
import org.semanticweb.owlapi.model.OWLClass;
import org.semanticweb.owlapi.model.OWLClassAssertionAxiom;
import org.semanticweb.owlapi.model.OWLClassExpression;
import org.semanticweb.owlapi.model.OWLDataFactory;
import org.semanticweb.owlapi.model.OWLDatatype;
import org.semanticweb.owlapi.model.OWLDeclarationAxiom;
import org.semanticweb.owlapi.model.OWLDisjointClassesAxiom;
import org.semanticweb.owlapi.model.OWLDisjointObjectPropertiesAxiom;
import org.semanticweb.owlapi.model.OWLEntity;
import org.semanticweb.owlapi.model.OWLEquivalentClassesAxiom;
import org.semanticweb.owlapi.model.OWLEquivalentObjectPropertiesAxiom;
import org.semanticweb.owlapi.model.OWLFunctionalObjectPropertyAxiom;
import org.semanticweb.owlapi.model.OWLInverseFunctionalObjectPropertyAxiom;
import org.semanticweb.owlapi.model.OWLInverseObjectPropertiesAxiom;
import org.semanticweb.owlapi.model.OWLLiteral;
import org.semanticweb.owlapi.model.OWLNamedObject;
import org.semanticweb.owlapi.model.OWLNaryPropertyAxiom;
import org.semanticweb.owlapi.model.OWLObject;
import org.semanticweb.owlapi.model.OWLObjectAllValuesFrom;
import org.semanticweb.owlapi.model.OWLObjectCardinalityRestriction;
import org.semanticweb.owlapi.model.OWLObjectComplementOf;
import org.semanticweb.owlapi.model.OWLObjectExactCardinality;
import org.semanticweb.owlapi.model.OWLObjectIntersectionOf;
import org.semanticweb.owlapi.model.OWLObjectMaxCardinality;
import org.semanticweb.owlapi.model.OWLObjectMinCardinality;
import org.semanticweb.owlapi.model.OWLObjectProperty;
import org.semanticweb.owlapi.model.OWLObjectPropertyDomainAxiom;
import org.semanticweb.owlapi.model.OWLObjectPropertyExpression;
import org.semanticweb.owlapi.model.OWLObjectPropertyRangeAxiom;
import org.semanticweb.owlapi.model.OWLObjectSomeValuesFrom;
import org.semanticweb.owlapi.model.OWLObjectUnionOf;
import org.semanticweb.owlapi.model.OWLOntology;
import org.semanticweb.owlapi.model.OWLOntologyManager;
import org.semanticweb.owlapi.model.OWLQuantifiedObjectRestriction;
import org.semanticweb.owlapi.model.OWLReflexiveObjectPropertyAxiom;
import org.semanticweb.owlapi.model.OWLSubAnnotationPropertyOfAxiom;
import org.semanticweb.owlapi.model.OWLSubClassOfAxiom;
import org.semanticweb.owlapi.model.OWLSubObjectPropertyOfAxiom;
import org.semanticweb.owlapi.model.OWLSubPropertyChainOfAxiom;
import org.semanticweb.owlapi.model.OWLSymmetricObjectPropertyAxiom;
import org.semanticweb.owlapi.model.OWLTransitiveObjectPropertyAxiom;
import org.semanticweb.owlapi.vocab.Namespaces;
import org.semanticweb.owlapi.vocab.OWL2Datatype;

/** owlapi version of Owl2Obo */
public class OWLAPIOwl2Obo {

    private static Logger LOG = Logger.getLogger(OWLAPIOwl2Obo.class.getName());
    protected OWLOntologyManager manager;
    protected OWLOntology owlOntology;
    protected OWLDataFactory fac;
    protected OBODoc obodoc;
    protected Set untranslatableAxioms;
    protected Map idSpaceMap;
    /** annotation map */
    public static Map annotationPropertyMap = initAnnotationPropertyMap();
    protected Set apToDeclare;
    protected String ontologyId;
    protected boolean strictConversion;
    protected boolean discardUntranslatable = false;

    protected void init() {
        idSpaceMap = new HashMap();
        // legacy:
        idSpaceMap.put("http://www.obofoundry.org/ro/ro.owl#", "OBO_REL");
        untranslatableAxioms = new HashSet();
        fac = manager.getOWLDataFactory();
        apToDeclare = new HashSet();
    }

    /**
     * @param translationManager
     *        translationManager
     */
    public OWLAPIOwl2Obo(OWLOntologyManager translationManager) {
        manager = translationManager;
        init();
    }

    protected static HashMap initAnnotationPropertyMap() {
        HashMap map = new HashMap();
        for (String key : OWLAPIObo2Owl.ANNOTATIONPROPERTYMAP.keySet()) {
            IRI propIRI = OWLAPIObo2Owl.ANNOTATIONPROPERTYMAP.get(key);
            map.put(propIRI.toString(), key);
        }
        return map;
    }

    /**
     * @param b
     *        strict conversion
     */
    public void setStrictConversion(boolean b) {
        strictConversion = b;
    }

    /** @return strict conversion */
    public boolean getStrictConversion() {
        return strictConversion;
    }

    /** @return the discardUntranslatable */
    public boolean isDiscardUntranslatable() {
        return discardUntranslatable;
    }

    /**
     * @param discardUntranslatable
     *        the discardUntranslatable to set
     */
    public void setDiscardUntranslatable(boolean discardUntranslatable) {
        this.discardUntranslatable = discardUntranslatable;
    }

    /** @return manager */
    public OWLOntologyManager getManager() {
        return manager;
    }

    /**
     * @param manager
     *        manager
     */
    public void setManager(OWLOntologyManager manager) {
        this.manager = manager;
    }

    /** @return obo doc */
    public OBODoc getObodoc() {
        return obodoc;
    }

    /**
     * @param obodoc
     *        obodoc
     */
    public void setObodoc(OBODoc obodoc) {
        this.obodoc = obodoc;
    }

    /**
     * @param ont
     *        ont
     * @return obo doc
     */
    public OBODoc convert(OWLOntology ont) {
        owlOntology = ont;
        if (ont != null) {
            ontologyId = getOntologyId(ont);
        } else {
            ontologyId = "TODO";
        }
        init();
        return tr();
    }

    /** @return the untranslatableAxioms */
    public Collection getUntranslatableAxioms() {
        return untranslatableAxioms;
    }

    /** @return translated obodoc */
    protected OBODoc tr() {
        obodoc = new OBODoc();
        preProcess();
        tr(owlOntology);
        for (OWLAxiom ax : owlOntology.getAxioms()) {
            if (ax instanceof OWLDeclarationAxiom) {
                tr((OWLDeclarationAxiom) ax);
            } else if (ax instanceof OWLSubClassOfAxiom) {
                tr((OWLSubClassOfAxiom) ax);
            } else if (ax instanceof OWLDisjointClassesAxiom) {
                tr((OWLDisjointClassesAxiom) ax);
            } else if (ax instanceof OWLEquivalentClassesAxiom) {
                tr((OWLEquivalentClassesAxiom) ax);
            } else if (ax instanceof OWLClassAssertionAxiom) {
                tr((OWLClassAssertionAxiom) ax);
            } else if (ax instanceof OWLEquivalentObjectPropertiesAxiom) {
                tr((OWLEquivalentObjectPropertiesAxiom) ax);
            } else if (ax instanceof OWLSubAnnotationPropertyOfAxiom) {
                tr((OWLSubAnnotationPropertyOfAxiom) ax);
            } else if (ax instanceof OWLSubObjectPropertyOfAxiom) {
                tr((OWLSubObjectPropertyOfAxiom) ax);
            } else if (ax instanceof OWLObjectPropertyRangeAxiom) {
                tr((OWLObjectPropertyRangeAxiom) ax);
            } else if (ax instanceof OWLFunctionalObjectPropertyAxiom) {
                tr((OWLFunctionalObjectPropertyAxiom) ax);
            } else if (ax instanceof OWLSymmetricObjectPropertyAxiom) {
                tr((OWLSymmetricObjectPropertyAxiom) ax);
            } else if (ax instanceof OWLAsymmetricObjectPropertyAxiom) {
                tr((OWLAsymmetricObjectPropertyAxiom) ax);
            } else if (ax instanceof OWLObjectPropertyDomainAxiom) {
                tr((OWLObjectPropertyDomainAxiom) ax);
            } else if (ax instanceof OWLInverseFunctionalObjectPropertyAxiom) {
                tr((OWLInverseFunctionalObjectPropertyAxiom) ax);
            } else if (ax instanceof OWLInverseObjectPropertiesAxiom) {
                tr((OWLInverseObjectPropertiesAxiom) ax);
            } else if (ax instanceof OWLDisjointObjectPropertiesAxiom) {
                tr((OWLDisjointObjectPropertiesAxiom) ax);
            } else if (ax instanceof OWLReflexiveObjectPropertyAxiom) {
                tr((OWLReflexiveObjectPropertyAxiom) ax);
            } else if (ax instanceof OWLTransitiveObjectPropertyAxiom) {
                tr((OWLTransitiveObjectPropertyAxiom) ax);
            } else if (ax instanceof OWLSubPropertyChainOfAxiom) {
                tr((OWLSubPropertyChainOfAxiom) ax);
            } else {
                if (!(ax instanceof OWLAnnotationAssertionAxiom)) {
                    error(ax);
                } else {
                    // we presume this has been processed
                }
            }
        }
        if (untranslatableAxioms.isEmpty() == false
                && discardUntranslatable == false) {
            try {
                String axiomString = OwlStringTools.translate(
                        untranslatableAxioms, manager);
                if (axiomString != null) {
                    Frame headerFrame = obodoc.getHeaderFrame();
                    if (headerFrame == null) {
                        headerFrame = new Frame(FrameType.HEADER);
                        obodoc.setHeaderFrame(headerFrame);
                    }
                    headerFrame.addClause(new Clause(
                            OboFormatTag.TAG_OWL_AXIOMS, axiomString));
                }
            } catch (OwlStringException e) {
                throw new RuntimeException(e);
            }
        }
        return obodoc;
    }

    protected void preProcess() {
        // converse of postProcess in obo2owl
        String viewRel = null;
        for (OWLAnnotation ann : owlOntology.getAnnotations()) {
            if (ann.getProperty()
                    .getIRI()
                    .equals(Obo2OWLVocabulary.IRI_OIO_LogicalDefinitionViewRelation
                            .getIRI())) {
                OWLAnnotationValue v = ann.getValue();
                if (v instanceof OWLLiteral) {
                    viewRel = ((OWLLiteral) v).getLiteral();
                } else {
                    viewRel = getIdentifierUsingBaseOntology((IRI) v);
                }
                break;
            }
        }
        if (viewRel != null) {
            // OWLObjectProperty vp = fac.getOWLObjectProperty(pIRI);
            Set rmAxioms = new HashSet();
            Set newAxioms = new HashSet();
            for (OWLEquivalentClassesAxiom eca : owlOntology
                    .getAxioms(AxiomType.EQUIVALENT_CLASSES)) {
                int numNamed = 0;
                Set xs = new HashSet();
                for (OWLClassExpression x : eca.getClassExpressions()) {
                    if (x instanceof OWLClass) {
                        xs.add(x);
                        numNamed++;
                        continue;
                    } else if (x instanceof OWLObjectSomeValuesFrom) {
                        OWLObjectProperty p = (OWLObjectProperty) ((OWLObjectSomeValuesFrom) x)
                                .getProperty();
                        if (this.getIdentifier(p).equals(viewRel) == false) {
                            LOG.log(Level.SEVERE, "Expected: " + viewRel
                                    + " got: " + p + " in " + eca);
                        }
                        xs.add(((OWLObjectSomeValuesFrom) x).getFiller());
                    } else {
                        LOG.log(Level.SEVERE, "Unexpected: " + eca);
                    }
                }
                if (numNamed == 1) {
                    rmAxioms.add(eca);
                    newAxioms.add(fac.getOWLEquivalentClassesAxiom(xs));
                } else {
                    LOG.log(Level.SEVERE, "ECA did not fit expected pattern: "
                            + eca);
                }
            }
            manager.removeAxioms(owlOntology, rmAxioms);
            manager.addAxioms(owlOntology, newAxioms);
        }
    }

    protected void add(Frame f) {
        if (f != null) {
            try {
                obodoc.addFrame(f);
            } catch (Exception ex) {
                LOG.log(Level.SEVERE, ex.getMessage(), ex);
            }
        }
    }

    protected boolean trObjectProperty(OWLObjectProperty prop, String tag,
            String value, Set annotations) {
        if (prop == null || value == null) {
            return false;
        }
        Frame f = getTypedefFrame(prop);
        Clause clause;
        if (OboFormatTag.TAG_ID.getTag().equals(tag)) {
            clause = f.getClause(tag);
            if (tag != null) {
                clause.setValue(value);
            } else {
                clause = new Clause(tag, value);
                f.addClause(clause);
            }
        } else {
            clause = new Clause(tag, value);
            f.addClause(clause);
        }
        addQualifiers(clause, annotations);
        return true;
    }

    protected boolean trObjectProperty(OWLObjectProperty prop, String tag,
            Boolean value, Set annotations) {
        if (prop == null || value == null) {
            return false;
        }
        Frame f = getTypedefFrame(prop);
        Clause clause = new Clause(tag);
        clause.addValue(value);
        f.addClause(clause);
        addQualifiers(clause, annotations);
        return true;
    }

    protected void trNaryPropertyAxiom(
            OWLNaryPropertyAxiom ax, String tag) {
        Set set = ax.getProperties();
        if (set.size() > 1) {
            boolean first = true;
            OWLObjectProperty prop = null;
            String disjointFrom = null;
            for (OWLObjectPropertyExpression ex : set) {
                if (ex.isBottomEntity() || ex.isTopEntity()) {
                    error(tag
                            + " using Top or Bottom entities are not supported in OBO.",
                            ax);
                    return;
                }
                if (first) {
                    first = false;
                    if (ex instanceof OWLObjectProperty) {
                        prop = (OWLObjectProperty) ex;
                    }
                } else {
                    disjointFrom = this.getIdentifier(ex); // getIdentifier(ex);
                }
            }
            if (trObjectProperty(prop, tag, disjointFrom, ax.getAnnotations())) {
                return;
            }
        }
        error(ax);
    }

    protected void tr(OWLSubPropertyChainOfAxiom ax) {
        OWLObjectPropertyExpression pEx = ax.getSuperProperty();
        if (pEx.isAnonymous()) {
            error(ax);
            return;
        }
        OWLObjectProperty p = pEx.asOWLObjectProperty();
        Frame f = getTypedefFrame(p);
        if (p.isBottomEntity() || p.isTopEntity()) {
            error("Property chains using Top or Bottom entities are not supported in OBO.",
                    ax);
            return;
        }
        List list = ax.getPropertyChain();
        if (list.size() != 2) {
            error(ax);
            return;
        }
        final OWLObjectPropertyExpression exp1 = list.get(0);
        final OWLObjectPropertyExpression exp2 = list.get(1);
        if (exp1.isBottomEntity() || exp1.isTopEntity()
                || exp2.isBottomEntity() || exp2.isTopEntity()) {
            error("Property chains using Top or Bottom entities are not supported in OBO.",
                    ax);
            return;
        }
        String rel1 = getIdentifier(exp1);
        String rel2 = getIdentifier(exp2);
        if (rel1 == null || rel2 == null) {
            error(ax);
            return;
        }
        Clause clause;
        // set of unprocessed annotations
        final Set unprocessedAnnotations = new HashSet(
                ax.getAnnotations());
        if (rel1.equals(f.getId())) {
            clause = new Clause(OboFormatTag.TAG_TRANSITIVE_OVER, rel2);
        } else {
            OboFormatTag tag = OboFormatTag.TAG_HOLDS_OVER_CHAIN;
            for (OWLAnnotation ann : ax.getAnnotations()) {
                if (OWLAPIObo2Owl.IRI_PROP_ISREVERSIBLEPROPERTYCHAIN.equals(ann
                        .getProperty().getIRI().toString())) {
                    tag = OboFormatTag.TAG_EQUIVALENT_TO_CHAIN;
                    // remove annotation from unprocessed set.
                    unprocessedAnnotations.remove(ann);
                    break;
                }
            }
            clause = new Clause(tag);
            clause.addValue(rel1);
            clause.addValue(rel2);
        }
        f.addClause(clause);
        addQualifiers(clause, unprocessedAnnotations);
    }

    protected void tr(OWLEquivalentObjectPropertiesAxiom ax) {
        trNaryPropertyAxiom(ax, OboFormatTag.TAG_EQUIVALENT_TO.getTag());
    }

    protected void tr(OWLTransitiveObjectPropertyAxiom ax) {
        OWLObjectPropertyExpression prop = ax.getProperty();
        if (prop instanceof OWLObjectProperty) {
            if (trObjectProperty((OWLObjectProperty) prop,
                    OboFormatTag.TAG_IS_TRANSITIVE.getTag(), Boolean.TRUE,
                    ax.getAnnotations())) {
                return;
            }
        }
        error(ax);
    }

    protected void tr(OWLDisjointObjectPropertiesAxiom ax) {
        trNaryPropertyAxiom(ax, OboFormatTag.TAG_DISJOINT_FROM.getTag());
    }

    protected void tr(OWLReflexiveObjectPropertyAxiom ax) {
        OWLObjectPropertyExpression prop = ax.getProperty();
        if (prop instanceof OWLObjectProperty) {
            if (trObjectProperty((OWLObjectProperty) prop,
                    OboFormatTag.TAG_IS_REFLEXIVE.getTag(), Boolean.TRUE,
                    ax.getAnnotations())) {
                return;
            }
        }
        error(ax);
    }

    protected void tr(OWLInverseFunctionalObjectPropertyAxiom ax) {
        OWLObjectPropertyExpression prop = ax.getProperty();
        if (prop instanceof OWLObjectProperty) {
            if (trObjectProperty((OWLObjectProperty) prop,
                    OboFormatTag.TAG_IS_INVERSE_FUNCTIONAL.getTag(),
                    Boolean.TRUE, ax.getAnnotations())) {
                return;
            }
        }
        error(ax);
    }

    protected void tr(OWLInverseObjectPropertiesAxiom ax) {
        OWLObjectPropertyExpression prop1 = ax.getFirstProperty();
        OWLObjectPropertyExpression prop2 = ax.getSecondProperty();
        if (prop1 instanceof OWLObjectProperty
                && prop2 instanceof OWLObjectProperty) {
            if (trObjectProperty((OWLObjectProperty) prop1,
                    OboFormatTag.TAG_INVERSE_OF.getTag(),
                    this.getIdentifier(prop2), ax.getAnnotations())) {
                return;
            }
        }
        error(ax);
    }

    protected void tr(OWLObjectPropertyDomainAxiom ax) {
        final OWLClassExpression domain = ax.getDomain();
        OWLObjectPropertyExpression propEx = ax.getProperty();
        if (propEx.isAnonymous()) {
            error(ax);
            return;
        }
        OWLObjectProperty prop = propEx.asOWLObjectProperty();
        if (domain.isBottomEntity() || domain.isTopEntity()) {
            // at least get the type def frame
            getTypedefFrame(prop);
            // now throw the error
            error("domains using top or bottom entities are not translatable to OBO.",
                    ax);
            return;
        }
        String range = this.getIdentifier(domain);
        if (range != null) {
            if (trObjectProperty(prop, OboFormatTag.TAG_DOMAIN.getTag(), range,
                    ax.getAnnotations())) {
                return;
            }
        }
        error(ax);
    }

    protected void tr(OWLAsymmetricObjectPropertyAxiom ax) {
        OWLObjectPropertyExpression prop = ax.getProperty();
        if (prop instanceof OWLObjectProperty) {
            if (trObjectProperty((OWLObjectProperty) prop,
                    OboFormatTag.TAG_IS_ASYMMETRIC.getTag(), Boolean.TRUE,
                    ax.getAnnotations())) {
                return;
            }
        }
        error(ax);
    }

    protected void tr(OWLSymmetricObjectPropertyAxiom ax) {
        OWLObjectPropertyExpression prop = ax.getProperty();
        if (prop instanceof OWLObjectProperty) {
            if (trObjectProperty((OWLObjectProperty) prop,
                    OboFormatTag.TAG_IS_SYMMETRIC.getTag(), Boolean.TRUE,
                    ax.getAnnotations())) {
                return;
            }
        }
        error(ax);
    }

    protected void tr(OWLFunctionalObjectPropertyAxiom ax) {
        OWLObjectPropertyExpression prop = ax.getProperty();
        if (prop instanceof OWLObjectProperty) {
            if (trObjectProperty((OWLObjectProperty) prop,
                    OboFormatTag.TAG_IS_FUNCTIONAL.getTag(), Boolean.TRUE,
                    ax.getAnnotations())) {
                return;
            }
        }
        error(ax);
    }

    protected void tr(OWLObjectPropertyRangeAxiom ax) {
        final OWLClassExpression owlRange = ax.getRange();
        OWLObjectPropertyExpression propEx = ax.getProperty();
        if (propEx.isAnonymous()) {
            error(ax);
        }
        OWLObjectProperty prop = propEx.asOWLObjectProperty();
        if (owlRange.isBottomEntity() || owlRange.isTopEntity()) {
            // at least create the property frame
            getTypedefFrame(prop);
            // error message
            error("ranges using top or bottom entities are not translatable to OBO.",
                    ax);
            return;
        }
        String range = this.getIdentifier(owlRange); // getIdentifier(ax.getRange());
        if (range != null) {
            if (trObjectProperty(prop, OboFormatTag.TAG_RANGE.getTag(), range,
                    ax.getAnnotations())) {
                return;
            }
        }
        error(ax);
    }

    protected void tr(OWLSubObjectPropertyOfAxiom ax) {
        OWLObjectPropertyExpression sup = ax.getSuperProperty();
        OWLObjectPropertyExpression sub = ax.getSubProperty();
        if (sub.isBottomEntity() || sub.isTopEntity() || sup.isBottomEntity()
                || sub.isTopEntity()) {
            error("SubProperties using Top or Bottom entites are not supported in OBO.");
            return;
        }
        if (sub instanceof OWLObjectProperty
                && sup instanceof OWLObjectProperty) {
            String supId = this.getIdentifier(sup);
            if (supId.startsWith("owl:")) {
                return;
            }
            Frame f = getTypedefFrame((OWLObjectProperty) sub);
            Clause clause = new Clause(OboFormatTag.TAG_IS_A, supId);
            f.addClause(clause);
            addQualifiers(clause, ax.getAnnotations());
        } else {
            error(ax);
        }
    }

    protected void tr(OWLSubAnnotationPropertyOfAxiom ax) {
        OWLAnnotationProperty sup = ax.getSuperProperty();
        OWLAnnotationProperty sub = ax.getSubProperty();
        if (sub.isBottomEntity() || sub.isTopEntity() || sup.isBottomEntity()
                || sub.isTopEntity()) {
            error("SubAnnotationProperties using Top or Bottom entites are not supported in OBO.");
            return;
        }
        String _tag = owlObjectToTag(sup);
        if (OboFormatTag.TAG_SYNONYMTYPEDEF.getTag().equals(_tag)) {
            String name = "";
            String scope = null;
            for (OWLAnnotationAssertionAxiom axiom : sub
                    .getAnnotationAssertionAxioms(owlOntology)) {
                String tg = owlObjectToTag(axiom.getProperty());
                if (OboFormatTag.TAG_NAME.getTag().equals(tg)) {
                    name = ((OWLLiteral) axiom.getValue()).getLiteral();
                } else if (OboFormatTag.TAG_SCOPE.getTag().equals(tg)) {
                    scope = owlObjectToTag(axiom.getValue());
                }
            }
            Frame hf = obodoc.getHeaderFrame();
            Clause clause = new Clause(OboFormatTag.TAG_SYNONYMTYPEDEF);
            clause.addValue(this.getIdentifier(sub));
            clause.addValue(name);
            if (scope != null) {
                clause.addValue(scope);
            }
            addQualifiers(clause, ax.getAnnotations());
            if (!hf.getClauses().contains(clause)) {
                hf.addClause(clause);
            } else {
                LOG.log(Level.WARNING, "duplicate clause: " + clause
                        + " in header");
            }
            return;
        } else if (OboFormatTag.TAG_SUBSETDEF.getTag().equals(_tag)) {
            String comment = "";
            for (OWLAnnotationAssertionAxiom axiom : sub
                    .getAnnotationAssertionAxioms(owlOntology)) {
                String tg = owlObjectToTag(axiom.getProperty());
                if (OboFormatTag.TAG_COMMENT.getTag().equals(tg)) {
                    comment = ((OWLLiteral) axiom.getValue()).getLiteral();
                    if (comment != null) {
                        break;
                    }
                }
            }
            Frame hf = obodoc.getHeaderFrame();
            Clause clause = new Clause(OboFormatTag.TAG_SUBSETDEF);
            clause.addValue(this.getIdentifier(sub));
            clause.addValue(comment);
            if (!hf.getClauses().contains(clause)) {
                hf.addClause(clause);
            } else {
                LOG.log(Level.WARNING, "duplicate clause: " + clause
                        + " in header");
            }
            addQualifiers(clause, ax.getAnnotations());
            return;
        }
        if (sub instanceof OWLObjectProperty
                && sup instanceof OWLObjectProperty) {
            String supId = this.getIdentifier(sup); // getIdentifier(sup);
            if (supId.startsWith("owl:")) {
                return;
            }
            Frame f = getTypedefFrame(sub);
            Clause clause = new Clause(OboFormatTag.TAG_IS_A, supId);
            f.addClause(clause);
            addQualifiers(clause, ax.getAnnotations());
        } else {
            error(ax);
        }
    }

    protected Pattern absoulteURLPattern = Pattern.compile("<\\s*http.*?>");

    protected void tr(OWLAnnotationAssertionAxiom aanAx, Frame frame) {
        boolean success = tr(aanAx.getProperty(), aanAx.getValue(),
                aanAx.getAnnotations(), frame);
        if (!success) {
            untranslatableAxioms.add(aanAx);
        }
    }

    protected boolean tr(OWLAnnotationProperty prop, OWLAnnotationValue annVal,
            Set qualifiers, Frame frame) {
        String tagString = owlObjectToTag(prop);
        OboFormatTag tag = null;
        if (tagString != null) {
            tag = OBOFormatConstants.getTag(tagString);
        }
        if (tag == null) {
            if (annVal instanceof IRI && FrameType.TERM.equals(frame.getType())) {
                if (isMetadataTag(prop)) {
                    String propId = this.getIdentifier(prop);
                    if (propId != null) {
                        Clause clause = new Clause(
                                OboFormatTag.TAG_RELATIONSHIP);
                        clause.addValue(propId);
                        clause.addValue(getIdentifier((IRI) annVal));
                        addQualifiers(clause, qualifiers);
                        frame.addClause(clause);
                        return true;
                    }
                }
            }
            // annotation property does not correspond to a mapping to a tag in
            // the OBO syntax -
            // use the property_value tag
            return trGenericPropertyValue(prop, annVal, qualifiers, frame);
        }
        String value = getValue(annVal, tagString);
        if (!value.isEmpty()) {
            if (tag == OboFormatTag.TAG_ID) {
                if (frame.getId().equals(value) == false) {
                    error("Conflicting id definitions: 1) " + frame.getId()
                            + "  2)" + value);
                    return false;
                }
                return true;
            }
            Clause clause = new Clause(tag);
            if (tag == OboFormatTag.TAG_DATE) {
                try {
                    clause.addValue(OBOFormatConstants.headerDateFormat.get()
                            .parseObject(value));
                } catch (ParseException e) {
                    error("Could not parse date string: " + value);
                    return false;
                }
            } else {
                clause.addValue(value);
            }
            Set unprocessedQualifiers = new HashSet(
                    qualifiers);
            if (tag == OboFormatTag.TAG_DEF) {
                for (OWLAnnotation aan : qualifiers) {
                    String propId = owlObjectToTag(aan.getProperty());
                    if ("xref".equals(propId)) {
                        OWLAnnotationValue v = aan.getValue();
                        String xrefValue;
                        if (v instanceof IRI) {
                            xrefValue = ((IRI) v).toString();
                        } else {
                            xrefValue = ((OWLLiteral) v).getLiteral();
                        }
                        Xref xref = new Xref(xrefValue);
                        clause.addXref(xref);
                        unprocessedQualifiers.remove(aan);
                    }
                }
            } else if (tag == OboFormatTag.TAG_XREF) {
                Xref xref = new Xref(value);
                for (OWLAnnotation annotation : qualifiers) {
                    if (fac.getRDFSLabel().equals(annotation.getProperty())) {
                        OWLAnnotationValue owlAnnotationValue = annotation
                                .getValue();
                        if (owlAnnotationValue instanceof OWLLiteral) {
                            unprocessedQualifiers.remove(annotation);
                            String xrefAnnotation = ((OWLLiteral) owlAnnotationValue)
                                    .getLiteral();
                            if (xrefAnnotation != null) {
                                xrefAnnotation = xrefAnnotation.trim();
                                if (xrefAnnotation.length() > 0) {
                                    xref.setAnnotation(xrefAnnotation);
                                }
                            }
                        }
                    }
                }
                clause.setValue(xref);
            } else if (tag == OboFormatTag.TAG_EXACT
                    || tag == OboFormatTag.TAG_NARROW
                    || tag == OboFormatTag.TAG_BROAD
                    || tag == OboFormatTag.TAG_RELATED) {
                handleSynonym(qualifiers, tag.getTag(), clause,
                        unprocessedQualifiers);
            } else if (tag == OboFormatTag.TAG_SYNONYM) {
                // This should never happen.
                // All synonyms need to be qualified with a type.
                String synonymType = null;
                handleSynonym(qualifiers, synonymType, clause,
                        unprocessedQualifiers);
            }
            addQualifiers(clause, unprocessedQualifiers);
            // before adding the clause check for redundant clauses
            boolean redundant = false;
            for (Clause frameClause : frame.getClauses()) {
                if (clause.equals(frameClause)) {
                    redundant = handleDuplicateClause(frame, frameClause);
                }
            }
            if (!redundant) {
                frame.addClause(clause);
            }
        } else {
            return false;
        }
        return true;
    }

    private boolean isMetadataTag(OWLAnnotationProperty p) {
        final IRI metadataTagIRI = IRI
                .create(Obo2OWLConstants.OIOVOCAB_IRI_PREFIX
                        + OboFormatTag.TAG_IS_METADATA_TAG.getTag());
        Set axioms = owlOntology
                .getAnnotationAssertionAxioms(p.getIRI());
        for (OWLAnnotationAssertionAxiom ax : axioms) {
            if (metadataTagIRI.equals(ax.getProperty().getIRI())) {
                return true;
            }
        }
        return false;
    }

    protected void handleSynonym(Set qualifiers, String scope,
            Clause clause, Set unprocessedQualifiers) {
        clause.setTag(OboFormatTag.TAG_SYNONYM.getTag());
        String type = null;
        clause.setXrefs(new Vector());
        for (OWLAnnotation aan : qualifiers) {
            String propId = owlObjectToTag(aan.getProperty());
            if (OboFormatTag.TAG_XREF.getTag().equals(propId)) {
                OWLAnnotationValue v = aan.getValue();
                String xrefValue;
                if (v instanceof IRI) {
                    xrefValue = ((IRI) v).toString();
                } else {
                    xrefValue = ((OWLLiteral) v).getLiteral();
                }
                Xref xref = new Xref(xrefValue);
                clause.addXref(xref);
                unprocessedQualifiers.remove(aan);
            } else if (OboFormatTag.TAG_HAS_SYNONYM_TYPE.getTag()
                    .equals(propId)) {
                type = getIdentifier(aan.getValue());
                unprocessedQualifiers.remove(aan);
            }
        }
        if (scope != null) {
            clause.addValue(scope);
            if (type != null) {
                clause.addValue(type);
            }
        }
    }

    /**
     * Handle a duplicate clause in a frame during translation.
     * 
     * @param frame
     *        frame
     * @param clause
     *        clause
     * @return true if the clause is to be marked as redundant and will not be
     *         added to the
     */
    protected boolean handleDuplicateClause(Frame frame, Clause clause) {
        // default is to report it via the logger and remove it.
        LOG.log(Level.WARNING, "Duplicate clause '" + clause
                + "' generated in frame: " + frame.getId());
        return true;
    }

    protected boolean trGenericPropertyValue(OWLAnnotationProperty prop,
            OWLAnnotationValue annVal, Set qualifiers,
            Frame frame) {
        // no built-in obo tag for this: use the generic property_value tag
        Clause clause = new Clause(OboFormatTag.TAG_PROPERTY_VALUE.getTag());
        String propId = this.getIdentifier(prop);
        addQualifiers(clause, qualifiers);
        if (propId.equals("shorthand") == false) {
            clause.addValue(propId);
            if (annVal instanceof OWLLiteral) {
                OWLLiteral owlLiteral = (OWLLiteral) annVal;
                clause.addValue(owlLiteral.getLiteral());
                OWLDatatype datatype = owlLiteral.getDatatype();
                IRI dataTypeIri = datatype.getIRI();
                if (!OWL2Datatype.isBuiltIn(dataTypeIri)) {
                    error("Untranslatable axiom due to unknown data type: "
                            + annVal);
                    return false;
                }
                if (Namespaces.XSD.inNamespace(dataTypeIri)) {
                    clause.addValue(dataTypeIri.prefixedBy("xsd:"));
                } else if (dataTypeIri.isPlainLiteral()) {
                    clause.addValue("xsd:string");
                } else {
                    clause.addValue(dataTypeIri.toString());
                }
            } else if (annVal instanceof IRI) {
                clause.addValue(getIdentifierUsingBaseOntology((IRI) annVal));
            }
            frame.addClause(clause);
        }
        return true;
    }

    protected String getValue(OWLAnnotationValue annVal, String tag) {
        String value = annVal.toString();
        if (annVal instanceof OWLLiteral) {
            value = ((OWLLiteral) annVal).getLiteral();
        } else if (annVal instanceof IRI) {
            value = getIdentifierUsingBaseOntology((IRI) annVal);
        }
        if (OboFormatTag.TAG_EXPAND_EXPRESSION_TO.getTag().equals(tag)) {
            Matcher matcher = absoulteURLPattern.matcher(value);
            while (matcher.find()) {
                String m = matcher.group();
                m = m.replace("<", "");
                m = m.replace(">", "");
                int i = m.lastIndexOf("/");
                m = m.substring(i + 1);
                value = value.replace(matcher.group(), m);
            }
        }
        return value;
    }

    protected void addQualifiers(Clause c, Set qualifiers) {
        for (OWLAnnotation ann : qualifiers) {
            String prop = owlObjectToTag(ann.getProperty());
            if (prop == null) {
                prop = ann.getProperty().getIRI().toString();
            }
            if (prop.equals("gci_relation") || prop.equals("gci_filler")
                    || prop.equals("cardinality")
                    || prop.equals("minCardinality")
                    || prop.equals("maxCardinality") || prop.equals("all_some")
                    || prop.equals("all_only")) {
                continue;
            }
            String value = ann.getValue().toString();
            if (ann.getValue() instanceof OWLLiteral) {
                value = ((OWLLiteral) ann.getValue()).getLiteral();
            } else if (ann.getValue() instanceof IRI) {
                value = getIdentifierUsingBaseOntology((IRI) ann.getValue()); // getIdentifier((IRI)aanAx.getValue());
            }
            QualifierValue qv = new QualifierValue(prop, value);
            c.addQualifierValue(qv);
        }
    }

    /**
     * if does not match this pattern, then retain original IRI
     * 
     * @param ontology
     *        ontology
     * @return The OBO ID of the ontology
     */
    public static String getOntologyId(OWLOntology ontology) {
        return getOntologyId(ontology.getOntologyID().getOntologyIRI());
    }

    /**
     * @param iriObj
     *        iriObj
     * @return ontology id
     */
    public static String getOntologyId(IRI iriObj) {
        // String id = getIdentifier(ontology.getOntologyID().getOntologyIRI());
        String iri = iriObj.toString();
        String id;
        if (iri.startsWith("http://purl.obolibrary.org/obo/")) {
            id = iri.replace("http://purl.obolibrary.org/obo/", "");
            if (id.endsWith(".owl")) {
                id = id.replaceFirst(".owl$", "");
            }
        } else {
            id = iri;
        }
        return id;
    }

    /**
     * @param ontology
     *        ontology
     * @return data version
     */
    public static String getDataVersion(OWLOntology ontology) {
        String oid = getOntologyId(ontology);
        IRI v = ontology.getOntologyID().getVersionIRI();
        if (v != null) {
            String vs = v.toString().replace("http://purl.obolibrary.org/obo/",
                    "");
            vs = vs.replaceFirst(oid + "/", "");
            vs = vs.replace("/" + oid + ".owl", "");
            return vs;
        }
        return null;
    }

    protected void tr(OWLOntology ontology) {
        Frame f = new Frame(FrameType.HEADER);
        obodoc.setHeaderFrame(f);
        for (IRI iri : ontology.getDirectImportsDocuments()) {
            Clause c = new Clause(OboFormatTag.TAG_IMPORT.getTag());
            // c.setValue(getOntologyId(iri));
            c.setValue(iri.toString());
            f.addClause(c);
        }
        String id = getOntologyId(owlOntology);
        Clause c = new Clause(OboFormatTag.TAG_ONTOLOGY.getTag());
        c.setValue(id);
        f.addClause(c);
        String vid = getDataVersion(owlOntology);
        if (vid != null) {
            Clause c2 = new Clause(OboFormatTag.TAG_DATA_VERSION.getTag());
            c2.setValue(vid);
            f.addClause(c2);
        }
        for (OWLAnnotation ann : ontology.getAnnotations()) {
            OWLAnnotationProperty property = ann.getProperty();
            String tagString = owlObjectToTag(property);
            if (OboFormatTag.TAG_COMMENT.getTag().equals(tagString)) {
                property = fac.getOWLAnnotationProperty(OWLAPIObo2Owl
                        .trTagToIRI(OboFormatTag.TAG_REMARK.getTag()));
            }
            tr(property, ann.getValue(), ann.getAnnotations(), f);
        }
    }

    protected void tr(OWLEquivalentClassesAxiom ax) {
        /*
         * Assumption: the underlying data structure is a set The order is not
         * guaranteed to be preserved.
         */
        Set expressions = ax.getClassExpressions();
        // handle expression list with size other than two elements as error
        if (expressions.size() != 2) {
            error(ax);
            return;
        }
        Iterator it = expressions.iterator();
        OWLClassExpression ce1 = it.next();
        OWLClassExpression ce2 = it.next();
        if (ce1.isBottomEntity() || ce1.isTopEntity() || ce2.isBottomEntity()
                || ce2.isTopEntity()) {
            error("Equivalent classes axioms using Top or Bottom entities are not supported in OBO.",
                    ax);
            return;
        }
        if (ce1 instanceof OWLClass == false) {
            // check whether ce2 is the actual OWLEntity
            if (ce2 instanceof OWLClass) {
                // three way exchange
                OWLClassExpression temp = ce2;
                ce2 = ce1;
                ce1 = temp;
            } else {
                // this might happen for some GCI axioms, which are not
                // expressible in OBO
                error("GCI axioms are not expressible in OBO.", ax);
                return;
            }
        }
        Frame f = getTermFrame(ce1.asOWLClass());
        if (f == null) {
            error(ax);
            return;
        }
        boolean isUntranslateable = false;
        List equivalenceAxiomClauses = new ArrayList();
        String cls2 = this.getIdentifier(ce2);
        if (cls2 != null) {
            Clause c = new Clause(OboFormatTag.TAG_EQUIVALENT_TO.getTag());
            c.setValue(cls2);
            f.addClause(c);
            addQualifiers(c, ax.getAnnotations());
        } else if (ce2 instanceof OWLObjectUnionOf) {
            List list2 = ((OWLObjectUnionOf) ce2)
                    .getOperandsAsList();
            for (OWLClassExpression oce : list2) {
                String id = this.getIdentifier(oce);
                Clause c = new Clause(OboFormatTag.TAG_UNION_OF.getTag());
                if (id == null) {
                    isUntranslateable = true;
                    error(ax);
                    return;
                }
                c.setValue(id);
                equivalenceAxiomClauses.add(c);
                addQualifiers(c, ax.getAnnotations());
            }
        } else if (ce2 instanceof OWLObjectIntersectionOf) {
            List list2 = ((OWLObjectIntersectionOf) ce2)
                    .getOperandsAsList();
            for (OWLClassExpression ce : list2) {
                String r = null;
                cls2 = this.getIdentifier(ce);
                Integer exact = null; // cardinality
                Integer min = null; // minCardinality
                Integer max = null; // maxCardinality
                Boolean allSome = null; // all_some
                Boolean allOnly = null; // all_only
                if (ce instanceof OWLObjectSomeValuesFrom) {
                    OWLObjectSomeValuesFrom ristriction = (OWLObjectSomeValuesFrom) ce;
                    r = this.getIdentifier(ristriction.getProperty());
                    cls2 = this.getIdentifier(ristriction.getFiller());
                } else if (ce instanceof OWLObjectExactCardinality) {
                    OWLObjectExactCardinality card = (OWLObjectExactCardinality) ce;
                    r = this.getIdentifier(card.getProperty());
                    cls2 = this.getIdentifier(card.getFiller());
                    exact = card.getCardinality();
                } else if (ce instanceof OWLObjectMinCardinality) {
                    OWLObjectMinCardinality card = (OWLObjectMinCardinality) ce;
                    r = this.getIdentifier(card.getProperty());
                    cls2 = this.getIdentifier(card.getFiller());
                    min = card.getCardinality();
                } else if (ce instanceof OWLObjectMaxCardinality) {
                    OWLObjectMaxCardinality card = (OWLObjectMaxCardinality) ce;
                    r = this.getIdentifier(card.getProperty());
                    cls2 = this.getIdentifier(card.getFiller());
                    max = card.getCardinality();
                } else if (ce instanceof OWLObjectAllValuesFrom) {
                    OWLObjectAllValuesFrom all = (OWLObjectAllValuesFrom) ce;
                    final OWLClassExpression filler = all.getFiller();
                    if (filler instanceof OWLClass) {
                        r = this.getIdentifier(all.getProperty());
                        cls2 = this.getIdentifier(filler);
                        allOnly = Boolean.TRUE;
                    } else if (filler instanceof OWLObjectComplementOf) {
                        OWLObjectComplementOf restriction = (OWLObjectComplementOf) filler;
                        r = this.getIdentifier(all.getProperty());
                        cls2 = this.getIdentifier(restriction.getOperand());
                        exact = 0;
                    }
                } else if (ce instanceof OWLObjectIntersectionOf) {
                    // either a min-max or a some-all combination
                    Set operands = ((OWLObjectIntersectionOf) ce)
                            .getOperands();
                    if (operands.size() == 2) {
                        for (OWLClassExpression operand : operands) {
                            if (operand instanceof OWLObjectMinCardinality) {
                                OWLObjectMinCardinality card = (OWLObjectMinCardinality) operand;
                                r = this.getIdentifier(card.getProperty());
                                cls2 = this.getIdentifier(card.getFiller());
                                min = card.getCardinality();
                            } else if (operand instanceof OWLObjectMaxCardinality) {
                                OWLObjectMaxCardinality card = (OWLObjectMaxCardinality) operand;
                                r = this.getIdentifier(card.getProperty());
                                cls2 = this.getIdentifier(card.getFiller());
                                max = card.getCardinality();
                            } else if (operand instanceof OWLObjectAllValuesFrom) {
                                OWLObjectAllValuesFrom all = (OWLObjectAllValuesFrom) operand;
                                r = this.getIdentifier(all.getProperty());
                                cls2 = this.getIdentifier(all.getFiller());
                                allOnly = Boolean.TRUE;
                            } else if (operand instanceof OWLObjectSomeValuesFrom) {
                                OWLObjectSomeValuesFrom all = (OWLObjectSomeValuesFrom) operand;
                                r = this.getIdentifier(all.getProperty());
                                cls2 = this.getIdentifier(all.getFiller());
                                allSome = Boolean.TRUE;
                            }
                        }
                    }
                }
                if (cls2 != null) {
                    Clause c = new Clause(
                            OboFormatTag.TAG_INTERSECTION_OF.getTag());
                    if (r != null) {
                        c.addValue(r);
                    }
                    c.addValue(cls2);
                    equivalenceAxiomClauses.add(c);
                    if (exact != null) {
                        c.addQualifierValue(new QualifierValue("cardinality",
                                exact.toString()));
                    }
                    if (min != null) {
                        c.addQualifierValue(new QualifierValue(
                                "minCardinality", min.toString()));
                    }
                    if (max != null) {
                        c.addQualifierValue(new QualifierValue(
                                "maxCardinality", max.toString()));
                    }
                    if (allSome != null) {
                        c.addQualifierValue(new QualifierValue("all_some",
                                allSome.toString()));
                    }
                    if (allOnly != null) {
                        c.addQualifierValue(new QualifierValue("all_only",
                                allOnly.toString()));
                    }
                    addQualifiers(c, ax.getAnnotations());
                } else if (f.getClauses(OboFormatTag.TAG_INTERSECTION_OF)
                        .size() > 0) {
                    error("The axiom is not translated (maximimum one IntersectionOf EquivalenceAxiom)",
                            ax);
                } else {
                    isUntranslateable = true;
                    error(ax);
                }
            }
        } else {
            isUntranslateable = true;
            error(ax);
        }
        // Only add clauses if the *entire* equivalence axiom can be translated
        if (!isUntranslateable) {
            for (Clause c : equivalenceAxiomClauses) {
                f.addClause(c);
            }
        }
    }

    protected void tr(OWLDisjointClassesAxiom ax) {
        // use set, the OWL-API does not provide an order
        Set set = ax.getClassExpressions();
        if (set.size() != 2) {
            error("Expected two classes in a disjoin classes axiom.", ax);
        }
        Iterator it = set.iterator();
        OWLClassExpression ce1 = it.next();
        OWLClassExpression ce2 = it.next();
        if (ce1.isBottomEntity() || ce1.isTopEntity() || ce2.isBottomEntity()
                || ce2.isTopEntity()) {
            error("Disjoint classes axiom using Top or Bottom entities are not supported.",
                    ax);
        }
        String cls2 = this.getIdentifier(ce2);
        if (cls2 == null) {
            error(ax);
            return;
        }
        if (ce1.isAnonymous()) {
            error(ax);
            return;
        }
        OWLClass cls1 = ce1.asOWLClass();
        Frame f = getTermFrame(cls1);
        Clause c = new Clause(OboFormatTag.TAG_DISJOINT_FROM.getTag());
        c.setValue(cls2);
        f.addClause(c);
        addQualifiers(c, ax.getAnnotations());
    }

    protected void tr(OWLDeclarationAxiom axiom) {
        OWLEntity entity = axiom.getEntity();
        if (entity.isBottomEntity() || entity.isTopEntity()) {
            return;
        }
        Set set = entity
                .getAnnotationAssertionAxioms(owlOntology);
        if (set.isEmpty()) {
            return;
        }
        boolean isClass = entity.isOWLClass();
        boolean isObjectProperty = entity.isOWLObjectProperty();
        boolean isAnnotationProperty = entity.isOWLAnnotationProperty();
        // check whether the entity is an alt_id
        OboAltIdCheckResult altIdOptional = checkForOboAltId(set, entity);
        if (altIdOptional != null) {
            // the entity will not be translated
            // instead create the appropriate alt_id in the replaced_by frame
            String currentId = getIdentifier(entity.getIRI());
            addAltId(altIdOptional.replacedBy, currentId, isClass,
                    isObjectProperty);
            // add unrelated annotations to untranslatableAxioms axioms
            untranslatableAxioms.addAll(altIdOptional.unrelated);
            return;
        }
        // translate
        Frame f = null;
        if (isClass) {
            f = getTermFrame(entity.asOWLClass());
        } else if (isObjectProperty) {
            f = getTypedefFrame(entity.asOWLObjectProperty());
        } else if (isAnnotationProperty) {
            for (OWLAnnotationAssertionAxiom ax : set) {
                OWLAnnotationProperty prop = ax.getProperty();
                String tag = owlObjectToTag(prop);
                if (OboFormatTag.TAG_IS_METADATA_TAG.getTag().equals(tag)) {
                    f = getTypedefFrame(entity);
                    break;
                }
            }
        }
        if (f != null) {
            for (OWLAnnotationAssertionAxiom aanAx : set) {
                tr(aanAx, f);
            }
            add(f);
        }
    }

    private void addAltId(String replacedBy, String altId, boolean isClass,
            boolean isProperty) {
        Frame replacedByFrame = null;
        if (isClass) {
            replacedByFrame = getTermFrame(replacedBy);
        } else if (isProperty) {
            replacedByFrame = getTypedefFrame(replacedBy);
        }
        if (replacedByFrame != null) {
            boolean addClause = true;
            // check existing alt_ids to avoid duplicate clauses
            Collection existing = replacedByFrame
                    .getClauses(OboFormatTag.TAG_ALT_ID);
            for (Clause clause : existing) {
                if (altId.equals(clause.getValue(String.class))) {
                    addClause = false;
                }
            }
            if (addClause) {
                replacedByFrame.addClause(new Clause(OboFormatTag.TAG_ALT_ID,
                        altId));
            }
        }
    }

    /**
     * Helper class: allow to return two values for the alt id check.
     */
    private static class OboAltIdCheckResult {

        final String replacedBy;
        final Set unrelated;

        OboAltIdCheckResult(String replacedBy,
                Set unrelated) {
            this.replacedBy = replacedBy;
            this.unrelated = unrelated;
        }
    }

    /**
     * Check the entity annotations for axioms declaring it to be an obsolete
     * entity, with 'obsolescence reason' being 'term merge', and a non-empty
     * 'replaced by' literal. This corresponds to an OBO alternate identifier.
     * Track non related annotations.
     * 
     * @param annotations
     *        set of annotations for the entity
     * @param entity
     * @return replaced_by if it is an alt_id
     */
    private OboAltIdCheckResult checkForOboAltId(
            Set annotations, OWLEntity entity) {
        String replacedBy = null;
        boolean isMerged = false;
        boolean isDeprecated = false;
        final Set unrelatedAxioms = new HashSet();
        for (OWLAnnotationAssertionAxiom axiom : annotations) {
            OWLAnnotationProperty prop = axiom.getProperty();
            if (prop.isDeprecated()) {
                isDeprecated = true;
            } else if (Obo2OWLConstants.IRI_IAO_0000231.equals(prop.getIRI())) {
                OWLAnnotationValue value = axiom.getValue();
                if (value instanceof IRI) {
                    isMerged = Obo2OWLConstants.IRI_IAO_0000227.equals(value);
                } else {
                    unrelatedAxioms.add(axiom);
                }
            } else if (Obo2OWLVocabulary.IRI_IAO_0100001.iri.equals(prop
                    .getIRI())) {
                OWLAnnotationValue value = axiom.getValue();
                if (value instanceof OWLLiteral) {
                    replacedBy = ((OWLLiteral) value).getLiteral();
                } else {
                    // fallback: also check for an IRI
                    if (value instanceof IRI) {
                        // translate IRI to OBO style ID
                        replacedBy = getIdentifier((IRI) value);
                    } else {
                        unrelatedAxioms.add(axiom);
                    }
                }
            } else {
                unrelatedAxioms.add(axiom);
            }
        }
        if (replacedBy != null && isMerged && isDeprecated) {
            return new OboAltIdCheckResult(replacedBy, unrelatedAxioms);
        }
        return null;
    }

    /**
     * @param obj
     *        obj
     * @return identifier
     */
    public String getIdentifier(OWLObject obj) {
        try {
            return getIdentifierFromObject(obj, owlOntology);
        } catch (UntranslatableAxiomException e) {
            error(e.getMessage());
        }
        return null;
    }

    /** untranslatable axiom exception */
    public static class UntranslatableAxiomException extends Exception {

        // generated
        private static final long serialVersionUID = 4674805484349471665L;

        /**
         * @param message
         *        message
         * @param cause
         *        cause
         */
        public UntranslatableAxiomException(String message, Throwable cause) {
            super(message, cause);
        }

        /**
         * @param message
         *        message
         */
        public UntranslatableAxiomException(String message) {
            super(message);
        }
    }

    /**
     * Retrieve the identifier for a given {@link OWLObject}. This methods uses
     * also shorthand hints to resolve the identifier. Should the translation
     * process encounter a problem or not find an identifier the defaultValue is
     * returned.
     * 
     * @param obj
     *        the {@link OWLObject} to resolve
     * @param ont
     *        the target ontology
     * @param defaultValue
     *        the value to return in case of an error or no id
     * @return identifier or the default value
     */
    public static String getIdentifierFromObject(OWLObject obj,
            OWLOntology ont, String defaultValue) {
        String id = defaultValue;
        try {
            id = getIdentifierFromObject(obj, ont);
            if (id == null) {
                id = defaultValue;
            }
        } catch (UntranslatableAxiomException e) {
            LOG.log(Level.WARNING, e.getMessage());
        }
        return id;
    }

    /**
     * Retrieve the identifier for a given {@link OWLObject}. This methods uses
     * also shorthand hints to resolve the identifier. Should the translation
     * process encounter an unexpected axiom an
     * {@link UntranslatableAxiomException} is thrown.
     * 
     * @param obj
     *        the {@link OWLObject} to resolve
     * @param ont
     *        the target ontology
     * @return identifier or null
     * @throws UntranslatableAxiomException
     *         UntranslatableAxiomException
     */
    public static String
            getIdentifierFromObject(OWLObject obj, OWLOntology ont)
                    throws UntranslatableAxiomException {
        if (obj instanceof OWLObjectProperty
                || obj instanceof OWLAnnotationProperty) {
            OWLEntity entity = (OWLEntity) obj;
            final Set axioms = entity
                    .getAnnotationAssertionAxioms(ont);
            for (OWLAnnotationAssertionAxiom ax : axioms) {
                String propId = getIdentifierFromObject(ax.getProperty()
                        .getIRI(), ont);
                // see BFOROXrefTest
                // 5.9.3. Special Rules for Relations
                if (propId.equals("shorthand")) {
                    final OWLAnnotationValue value = ax.getValue();
                    if (value != null && value instanceof OWLLiteral) {
                        return ((OWLLiteral) value).getLiteral();
                    }
                    throw new UntranslatableAxiomException(
                            "Untranslatable axiom, expected literal value, but was: "
                                    + value + " in axiom: " + ax);
                }
            }
        }
        if (obj instanceof OWLEntity) {
            return getIdentifier(((OWLEntity) obj).getIRI(), ont);
        }
        if (obj instanceof IRI) {
            return getIdentifier((IRI) obj, ont);
        }
        return null;
    }

    /**
     * See table 5.9.2. Translation of identifiers
     * 
     * @param iriId
     *        iriId
     * @return obo identifier or null
     */
    public static String getIdentifier(IRI iriId) {
        return getIdentifier(iriId, null);
    }

    protected String getIdentifierUsingBaseOntology(IRI iriId) {
        return getIdentifier(iriId, owlOntology);
    }

    /**
     * @param iriId
     *        iriId
     * @param baseOntology
     *        baseOntology
     * @return identifier
     */
    public static String getIdentifier(IRI iriId, OWLOntology baseOntology) {
        if (iriId == null) {
            return null;
        }
        String iri = iriId.toString();
        // canonical IRIs
        // if (iri.startsWith("http://purl.obolibrary.org/obo/")) {
        // String canonicalId = iri.replace("http://purl.obolibrary.org/obo/",
        // "");
        // }
        int indexSlash = iri.lastIndexOf("/");
        String id = null;
        if (indexSlash > -1) {
            id = iri.substring(indexSlash + 1);
        } else {
            id = iri;
        }
        String[] s = id.split("#_");
        // table 5.9.2 row 2 - NonCanonical-Prefixed-ID
        if (s.length > 1) {
            return s[0] + ":" + s[1];
        }
        // row 3 - Unprefixed-ID
        s = id.split("#");
        if (s.length > 1) {
            // prefixURI = prefixURI + s[0] + "#";
            // if(!(s[1].contains("#") || s[1].contains("_"))){
            String prefix = "";
            if ("owl".equals(s[0]) || "rdf".equals(s[0]) || "rdfs".equals(s[0])) {
                prefix = s[0] + ":";
            }
            // TODO: the following implements behavior in current spec, but this
            // leads to undesirable results
            // else if (baseOntology != null) {
            // String oid = getOntologyId(baseOntology); // OBO-style ID
            // if (oid.equals(s[0]))
            // prefix = "";
            // else {
            // return iri;
            // }
            // //prefix = s[0];
            // }
            return prefix + s[1];
        }
        // row 1 - Canonical-Prefixed-ID
        s = id.split("_");
        if (s.length == 2 && !id.contains("#") && !s[1].contains("_")) {
            String localId;
            try {
                localId = java.net.URLDecoder.decode(s[1], "UTF-8");
                return s[0] + ":" + localId;
            } catch (UnsupportedEncodingException e) {
                throw new RuntimeException(
                        "UTF-8 not supported, JRE corrupted?", e);
            }
        }
        if (s.length > 2 && !id.contains("#")) {
            if (s[s.length - 1].replaceAll("[0-9]", "").length() == 0) {
                StringBuffer sb = new StringBuffer();
                for (int i = 0; i < s.length; i++) {
                    if (i > 0) {
                        if (i == s.length - 1) {
                            sb.append(":");
                        } else {
                            sb.append("_");
                        }
                    }
                    sb.append(s[i]);
                }
                return sb.toString();
            }
        }
        return iri;
    }

    /**
     * @param obj
     *        obj
     * @return tag for object
     */
    public static String owlObjectToTag(OWLObject obj) {
        IRI iriObj = null;
        if (obj instanceof OWLNamedObject) {
            iriObj = ((OWLNamedObject) obj).getIRI();
        } else if (obj instanceof IRI) {
            iriObj = (IRI) obj;
        }
        if (iriObj == null) {
            return null;
        }
        String iri = iriObj.toString();
        String tag = annotationPropertyMap.get(iri);
        if (tag == null) {
            // hardcoded values for legacy annotation properties: (TEMPORARY)
            if (iri.startsWith(Obo2OWLConstants.DEFAULT_IRI_PREFIX + "IAO_")) {
                String legacyId = iri.replace(
                        Obo2OWLConstants.DEFAULT_IRI_PREFIX, "");
                if (legacyId.equals("IAO_xref")) {
                    return OboFormatTag.TAG_XREF.getTag();
                }
                if (legacyId.equals("IAO_id")) {
                    return OboFormatTag.TAG_ID.getTag();
                }
                if (legacyId.equals("IAO_namespace")) {
                    return OboFormatTag.TAG_NAMESPACE.getTag();
                }
            }
            String prefix = Obo2OWLConstants.OIOVOCAB_IRI_PREFIX;
            if (iri.startsWith(prefix)) {
                tag = iri.substring(prefix.length());
            }
        }
        return tag;
    }

    protected Frame getTermFrame(OWLClass entity) {
        String id = getIdentifierUsingBaseOntology(entity.getIRI());
        return getTermFrame(id);
    }

    private Frame getTermFrame(String id) {
        Frame f = obodoc.getTermFrame(id);
        if (f == null) {
            f = new Frame(FrameType.TERM);
            f.setId(id);
            f.addClause(new Clause(OboFormatTag.TAG_ID, id));
            add(f);
        }
        return f;
    }

    protected Frame getTypedefFrame(OWLEntity entity) {
        String id = this.getIdentifier(entity);
        return getTypedefFrame(id);
    }

    private Frame getTypedefFrame(String id) {
        Frame f = obodoc.getTypedefFrame(id);
        if (f == null) {
            f = new Frame(FrameType.TYPEDEF);
            f.setId(id);
            f.addClause(new Clause(OboFormatTag.TAG_ID, id));
            add(f);
        }
        return f;
    }

    protected void tr(OWLClassAssertionAxiom ax) {
        /*
         * OWLObject cls = ax.getClassExpression(); if(!(cls instanceof
         * OWLClass)) return; String clsIRI = ((OWLClass)
         * cls).getIRI().toString();
         * if(Obo2Owl.IRI_CLASS_SYNONYMTYPEDEF.equals(clsIRI)){ Frame f =
         * this.obodoc.getHeaderFrame(); Clause c = new Clause();
         * c.setTag(OboFormatTag.TAG_SYNONYMTYPEDEF.getTag());
         * OWLNamedIndividual indv =(OWLNamedIndividual) ax.getIndividual();
         * String indvId = this.getIdentifier(indv); // TODO: full specify this
         * in the spec document. // we may want to allow full IDs for subsets in
         * future. // here we would have a convention that an unprefixed
         * subsetdef/synonymtypedef // gets placed in a temp ID space, and only
         * this id space is stripped indvId = indvId.replaceFirst(".*:", "");
         * c.addValue(indvId); c.addValue(indvId); String nameValue = ""; String
         * scopeValue = null; for(OWLAnnotation ann:
         * indv.getAnnotationsWithOptionalExpansionMarker(owlOntology)){ String propId =
         * ann.getProperty().getIRI().toString(); String value = ((OWLLiteral)
         * ann.getValue()).getLiteral();
         * if(OWLRDFVocabulary.RDFS_LABEL.getIRI().toString().equals(propId)){
         * nameValue = "\"" +value + "\""; }else scopeValue = value; }
         * c.addValue(nameValue); if(scopeValue != null){
         * c.addValue(scopeValue); } f.addClause(c); }else
         * if(Obo2Owl.IRI_CLASS_SUBSETDEF.equals(clsIRI)){ Frame f =
         * this.obodoc.getHeaderFrame(); Clause c = new Clause();
         * c.setTag(OboFormatTag.TAG_SUBSETDEF.getTag()); OWLNamedIndividual
         * indv =(OWLNamedIndividual) ax.getIndividual(); String indvId =
         * this.getIdentifier(indv); // TODO: full specify this in the spec
         * document. // we may want to allow full IDs for subsets in future. //
         * here we would have a convention that an unprefixed
         * subsetdef/synonymtypedef // gets placed in a temp ID space, and only
         * this id space is stripped indvId = indvId.replaceFirst(".*:", "");
         * c.addValue(indvId); String nameValue = ""; for(OWLAnnotation ann:
         * indv.getAnnotationsWithOptionalExpansionMarker(owlOntology)){ String propId =
         * ann.getProperty().getIRI().toString(); String value = ((OWLLiteral)
         * ann.getValue()).getLiteral();
         * if(OWLRDFVocabulary.RDFS_LABEL.getIRI().toString().equals(propId)){
         * nameValue = "\"" +value + "\""; } } c.addValue(nameValue);
         * f.addClause(c); }else{ //TODO: individual }
         */
    }

    protected void tr(OWLSubClassOfAxiom ax) {
        OWLClassExpression sub = ax.getSubClass();
        OWLClassExpression sup = ax.getSuperClass();
        Set qvs = new HashSet();
        if (sub.isOWLNothing() || sub.isTopEntity() || sup.isTopEntity()
                || sup.isOWLNothing()) {
            error("Assertions using owl:Thing or owl:Nothing are not translateable OBO",
                    ax);
            return;
        }
        // 5.2.2
        if (sub instanceof OWLObjectIntersectionOf) {
            Set xs = ((OWLObjectIntersectionOf) sub)
                    .getOperands();
            // obo-format is limited to very restricted GCIs - the LHS of the
            // axiom
            // must correspond to ObjectIntersectionOf(cls
            // ObjectSomeValuesFrom(p filler))
            if (xs.size() == 2) {
                OWLClass c = null;
                OWLObjectSomeValuesFrom r = null;
                OWLObjectProperty p = null;
                OWLClass filler = null;
                for (OWLClassExpression x : xs) {
                    if (x instanceof OWLClass) {
                        c = (OWLClass) x;
                    }
                    if (x instanceof OWLObjectSomeValuesFrom) {
                        r = (OWLObjectSomeValuesFrom) x;
                        if (r.getProperty() instanceof OWLObjectProperty) {
                            if (r.getFiller() instanceof OWLClass) {
                                p = (OWLObjectProperty) r.getProperty();
                                filler = (OWLClass) r.getFiller();
                            }
                        }
                    }
                }
                if (c != null && p != null && filler != null) {
                    sub = c;
                    qvs.add(new QualifierValue("gci_relation", getIdentifier(p)));
                    qvs.add(new QualifierValue("gci_filler",
                            getIdentifier(filler)));
                }
            }
        }
        if (sub instanceof OWLClass) {
            Frame f = getTermFrame((OWLClass) sub);
            if (sup instanceof OWLClass) {
                Clause c = new Clause(OboFormatTag.TAG_IS_A.getTag());
                c.setValue(this.getIdentifier(sup));
                c.setQualifierValues(qvs);
                f.addClause(c);
                addQualifiers(c, ax.getAnnotations());
            } else if (sup instanceof OWLQuantifiedObjectRestriction) {
                // OWLObjectSomeValuesFrom
                // OWLObjectAllValuesFrom
                OWLQuantifiedObjectRestriction r = (OWLQuantifiedObjectRestriction) sup;
                final OWLClassExpression filler = r.getFiller();
                if (filler.isBottomEntity() || filler.isTopEntity()) {
                    error("Assertions using owl:Thing or owl:Nothing are not translateable OBO",
                            ax);
                    return;
                }
                String fillerId = this.getIdentifier(filler);
                if (fillerId == null) {
                    error(ax);
                    return;
                }
                f.addClause(createRelationshipClauseWithRestrictions(r,
                        fillerId, qvs, ax));
            } else if (sup instanceof OWLObjectCardinalityRestriction) {
                // OWLObjectExactCardinality
                // OWLObjectMinCardinality
                // OWLObjectMaxCardinality
                OWLObjectCardinalityRestriction cardinality = (OWLObjectCardinalityRestriction) sup;
                final OWLClassExpression filler = cardinality.getFiller();
                if (filler.isBottomEntity() || filler.isTopEntity()) {
                    error("Assertions using owl:Thing or owl:Nothing are not translateable OBO",
                            ax);
                    return;
                }
                String fillerId = this.getIdentifier(filler);
                if (fillerId == null) {
                    error(ax);
                    return;
                }
                f.addClause(createRelationshipClauseWithCardinality(
                        cardinality, fillerId, qvs, ax));
            } else if (sup instanceof OWLObjectIntersectionOf) {
                OWLObjectIntersectionOf i = (OWLObjectIntersectionOf) sup;
                List clauses = new ArrayList();
                for (OWLClassExpression operand : i.getOperands()) {
                    if (operand instanceof OWLQuantifiedObjectRestriction) {
                        OWLQuantifiedObjectRestriction restriction = (OWLQuantifiedObjectRestriction) operand;
                        final OWLClassExpression filler = restriction
                                .getFiller();
                        if (filler.isBottomEntity() || filler.isTopEntity()) {
                            error("Assertions using owl:Thing or owl:Nothing are not translateable OBO",
                                    ax);
                            return;
                        }
                        String fillerId = this.getIdentifier(filler);
                        if (fillerId == null) {
                            error(ax);
                            return;
                        }
                        clauses.add(createRelationshipClauseWithRestrictions(
                                restriction, fillerId,
                                new HashSet(qvs), ax));
                    } else if (operand instanceof OWLObjectCardinalityRestriction) {
                        OWLObjectCardinalityRestriction restriction = (OWLObjectCardinalityRestriction) operand;
                        final OWLClassExpression filler = restriction
                                .getFiller();
                        if (filler.isBottomEntity() || filler.isTopEntity()) {
                            error("Assertions using owl:Thing or owl:Nothing are not translateable OBO",
                                    ax);
                            return;
                        }
                        String fillerId = this.getIdentifier(filler);
                        if (fillerId == null) {
                            error(ax);
                            return;
                        }
                        clauses.add(createRelationshipClauseWithCardinality(
                                restriction, fillerId,
                                new HashSet(qvs), ax));
                    } else {
                        error(ax);
                        return;
                    }
                }
                if (clauses.isEmpty()) {
                    error(ax);
                    return;
                }
                clauses = normalizeRelationshipClauses(clauses);
                for (Clause clause : clauses) {
                    f.addClause(clause);
                }
            } else {
                error(ax);
                return;
            }
        } else {
            error(ax);
            return;
        }
    }

    protected Clause createRelationshipClauseWithRestrictions(
            OWLQuantifiedObjectRestriction r, String fillerId,
            Set qvs, OWLSubClassOfAxiom ax) {
        Clause c = new Clause(OboFormatTag.TAG_RELATIONSHIP.getTag());
        c.addValue(this.getIdentifier(r.getProperty()));
        c.addValue(fillerId);
        c.setQualifierValues(qvs);
        addQualifiers(c, ax.getAnnotations());
        return c;
    }

    protected Clause createRelationshipClauseWithCardinality(
            OWLObjectCardinalityRestriction restriction, String fillerId,
            Set qvs, OWLSubClassOfAxiom ax) {
        Clause c = new Clause(OboFormatTag.TAG_RELATIONSHIP.getTag());
        c.addValue(this.getIdentifier(restriction.getProperty()));
        c.addValue(fillerId);
        c.setQualifierValues(qvs);
        String q = "cardinality";
        if (restriction instanceof OWLObjectMinCardinality) {
            q = "minCardinality";
        } else if (restriction instanceof OWLObjectMaxCardinality) {
            q = "maxCardinality";
        }
        c.addQualifierValue(new QualifierValue(q, Integer.toString(restriction
                .getCardinality())));
        addQualifiers(c, ax.getAnnotations());
        return c;
    }

    /**
     * Join clauses and its {@link QualifierValue} which have the same
     * relationship type and target. Try to resolve conflicts for multiple
     * statements. E.g., min=2 and min=3 is resolved to min=2, or max=2 and
     * max=4 is resolved to max=4. It will not merge conflicting exact
     * cardinality statements. TODO How to merge "all_some", and "all_only"?
     * 
     * @param clauses
     *        clauses
     * @return normalized list of {@link Clause}
     */
    public static List
            normalizeRelationshipClauses(List clauses) {
        final List normalized = new ArrayList();
        while (!clauses.isEmpty()) {
            final Clause target = clauses.remove(0);
            List similar = findSimilarClauses(clauses, target);
            normalized.add(target);
            mergeSimilarIntoTarget(target, similar);
        }
        return normalized;
    }

    static List findSimilarClauses(List clauses,
            final Clause target) {
        final String targetTag = target.getTag();
        final Object targetValue = target.getValue();
        final Object targetValue2 = target.getValue2();
        List similar = new ArrayList();
        Iterator iterator = clauses.iterator();
        while (iterator.hasNext()) {
            final Clause current = iterator.next();
            final Object currentValue = current.getValue();
            final Object currentValue2 = current.getValue2();
            if (targetTag.equals(current.getTag())
                    && targetValue.equals(currentValue)) {
                if (targetValue2 == null) {
                    if (currentValue2 == null) {
                        similar.add(current);
                        iterator.remove();
                    }
                } else if (targetValue2.equals(currentValue2)) {
                    similar.add(current);
                    iterator.remove();
                }
            }
        }
        return similar;
    }

    static void
            mergeSimilarIntoTarget(final Clause target, List similar) {
        if (similar.isEmpty()) {
            return;
        }
        final Collection targetQVs = target
                .getQualifierValues();
        for (Clause current : similar) {
            final Collection newQVs = current
                    .getQualifierValues();
            for (QualifierValue newQV : newQVs) {
                final String newQualifier = newQV.getQualifier();
                // if min or max cardinality check for possible merges
                if ("minCardinality".equals(newQualifier)
                        || "maxCardinality".equals(newQualifier)) {
                    QualifierValue match = findMatchingQualifierValue(newQV,
                            targetQVs);
                    if (match != null) {
                        mergeQualifierValues(match, newQV);
                    } else {
                        target.addQualifierValue(newQV);
                    }
                } else {
                    target.addQualifierValue(newQV);
                }
            }
        }
    }

    static QualifierValue findMatchingQualifierValue(QualifierValue query,
            Collection list) {
        String queryQualifier = query.getQualifier();
        for (QualifierValue qv : list) {
            if (queryQualifier.equals(qv.getQualifier())) {
                return qv;
            }
        }
        return null;
    }

    static void
            mergeQualifierValues(QualifierValue target, QualifierValue newQV) {
        // do nothing, if they are equal
        if (!target.getValue().equals(newQV.getValue())) {
            if ("minCardinality".equals(target.getQualifier())) {
                // try to merge, parse as integers
                int currentValue = Integer.parseInt(target.getValue()
                        .toString());
                int newValue = Integer.parseInt(newQV.getValue().toString());
                int mergedValue = Math.min(currentValue, newValue);
                target.setValue(Integer.toString(mergedValue));
            } else if ("maxCardinality".equals(target.getQualifier())) {
                // try to merge, parse as integers
                int currentValue = Integer.parseInt(target.getValue()
                        .toString());
                int newValue = Integer.parseInt(newQV.getValue().toString());
                int mergedValue = Math.max(currentValue, newValue);
                target.setValue(Integer.toString(mergedValue));
            }
        }
    }

    protected void error(String message, OWLAxiom ax) {
        untranslatableAxioms.add(ax);
        error(message + ax);
    }

    protected void error(OWLAxiom ax) {
        untranslatableAxioms.add(ax);
        error("the axiom is not translated : " + ax);
    }

    protected void error(String message) {
        LOG.log(Level.WARNING, message);
        if (strictConversion) {
            throw new RuntimeException("The conversion is halted: " + message);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy