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

org.obolibrary.oboformat.model.Clause Maven / Gradle / Ivy

Go to download

A java library for converting obo format documents to OWL, and for converting (a subset of) OWL to obo format. This version has been slightly modified to be included directly in the OWL API. The upstream code for this module and its authors can be found at https://code.google.com/p/oboformat/.

There is a newer version: 5.5.1
Show newest version
package org.obolibrary.oboformat.model;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

import org.obolibrary.oboformat.parser.OBOFormatConstants.OboFormatTag;

/** Clause */
public class Clause {

    protected String tag;
    @Nonnull
    protected List values = new ArrayList<>();
    @Nonnull
    protected Collection xrefs = new ArrayList<>();
    @Nonnull
    protected Collection qualifierValues = new ArrayList<>();

    /**
     * @param tag tag
     */
    public Clause(@Nonnull OboFormatTag tag) {
        this(tag.getTag());
    }

    /**
     * @param tag tag
     */
    public Clause(String tag) {
        this.tag = tag;
    }

    /**
     * @param tag tag
     * @param value value
     */
    public Clause(String tag, String value) {
        this(tag);
        setValue(value);
    }

    /**
     * @param tag tag
     * @param value value
     */
    public Clause(@Nonnull OboFormatTag tag, String value) {
        this(tag.getTag(), value);
    }

    /**
     * default constructor
     * 
     * @deprecated use Clause(String). Using this constructor makes the hashcode variable.
     */
    @Deprecated
    public Clause() {}

    /**
     * freezing a clause signals that the clause has become quiescent, and that data structures can
     * be adjusted to increase performance, or reduce memory consumption.
     */
    void freeze() {
        freezeValues();
        freezeXrefs();
        freezeQualifiers();
    }

    void freezeValues() {
        switch (values.size()) {
            case 0:
                values = Collections.emptyList();
                break;
            case 1:
                Object o = values.iterator().next();
                values = Collections.singletonList(o);
                break;
            default:
                ((ArrayList) values).trimToSize();
        }
    }

    void freezeXrefs() {
        switch (xrefs.size()) {
            case 0:
                xrefs = Collections.emptyList();
                break;
            case 1:
                Xref xref = xrefs.iterator().next();
                xrefs = Collections.singletonList(xref);
                break;
            default:
                if (xrefs instanceof ArrayList) {
                    ((ArrayList) xrefs).trimToSize();
                }
        }
    }

    void freezeQualifiers() {
        switch (qualifierValues.size()) {
            case 0:
                qualifierValues = Collections.emptyList();
                break;
            case 1:
                QualifierValue qualifierValue = qualifierValues.iterator().next();
                qualifierValues = Collections.singletonList(qualifierValue);
                break;
            default:
                if (qualifierValues instanceof ArrayList) {
                    ((ArrayList) qualifierValues).trimToSize();
                }
        }
    }



    /**
     * @return true if no xrefs or qualifiers exist
     */
    public boolean hasNoAnnotations() {
        return xrefs.isEmpty() && qualifierValues.isEmpty();
    }

    /**
     * @return tag
     */
    public String getTag() {
        return tag;
    }

    /**
     * @param tag tag
     */
    public void setTag(String tag) {
        this.tag = tag;
    }

    /**
     * @return values
     */
    @Nonnull
    public Collection getValues() {
        return values;
    }

    /**
     * @param values values
     */
    public void setValues(@Nonnull Collection values) {
        if (!(this.values instanceof ArrayList)) {
            switch (values.size()) {
                case 0:
                    this.values = Collections.emptyList();
                    break;
                case 1:
                    Object o = values.iterator().next();
                    this.values = Collections.singletonList(o);
                    break;
                default:
                    this.values = new ArrayList<>(values);
            }
        } else {
            this.values.clear();
            this.values.addAll(values);
        }
    }

    /**
     * @param v v
     */
    public void setValue(Object v) {
        if (values instanceof ArrayList) {
            values.clear(); // TODO: Remove this line after profile gathering
            values.add(v);
        } else {
            values = Collections.singletonList(v);
        }
    }

    /**
     * @param v v
     */
    public void addValue(Object v) {
        if (!(values instanceof ArrayList)) {
            List newValues = new ArrayList<>(values.size() + 1);
            newValues.addAll(values);
            values = newValues;
        }
        values.add(v);
    }

    /**
     * @return value
     */
    @Nullable
    public Object getValue() {
        Object value = null;
        if (!values.isEmpty()) {
            value = values.get(0);
        }
        return value;
    }

    /**
     * @param cls cls
     * @param  value type
     * @return value
     */
    @Nullable
    public  T getValue(@Nonnull Class cls) {
        Object value = getValue();
        if (value != null && value.getClass().isAssignableFrom(cls)) {
            return cls.cast(value);
        }
        return null;
    }

    /**
     * @return value2
     */
    @Nullable
    public Object getValue2() {
        Object value = null;
        if (values.size() > 1) {
            value = values.get(1);
        }
        return value;
    }

    /**
     * @param cls cls
     * @param  value type
     * @return value2
     */
    @Nullable
    public  T getValue2(@Nonnull Class cls) {
        Object value = getValue2();
        if (value != null && value.getClass().isAssignableFrom(cls)) {
            return cls.cast(value);
        }
        return null;
    }

    /**
     * @return xrefs
     */
    @Nonnull
    public Collection getXrefs() {
        return xrefs;
    }

    /**
     * @param xrefs xrefs
     */
    public void setXrefs(@Nonnull Collection xrefs) {
        if (!(this.xrefs instanceof ArrayList)) {
            switch (xrefs.size()) {
                case 0:
                    this.xrefs = Collections.emptyList();
                    break;
                case 1:
                    Xref xref = xrefs.iterator().next();
                    this.xrefs = Collections.singletonList(xref);
                    break;
                default:
                    this.xrefs = new ArrayList<>(xrefs);
            }
        } else {
            this.xrefs.clear();
            this.xrefs.addAll(xrefs);
        }
    }

    /**
     * @param xref xref
     */
    public void addXref(Xref xref) {
        if (!(xrefs instanceof ArrayList)) {
            List newXrefs = new ArrayList<>(xrefs.size() + 1);
            newXrefs.addAll(xrefs);
            xrefs = newXrefs;
        }
        xrefs.add(xref);
    }

    /**
     * @return qualifier values
     */
    @Nonnull
    public Collection getQualifierValues() {
        return qualifierValues;
    }

    /**
     * @param qualifierValues qualifierValues
     */
    public void setQualifierValues(@Nonnull Collection qualifierValues) {
        if (!(this.qualifierValues instanceof ArrayList)) {
            switch (qualifierValues.size()) {
                case 0:
                    this.qualifierValues = Collections.emptyList();
                    break;
                case 1:
                    QualifierValue qualifierValue = qualifierValues.iterator().next();
                    this.qualifierValues = Collections.singletonList(qualifierValue);
                    break;
                default:
                    this.qualifierValues = new ArrayList<>(qualifierValues);
            }
        } else {
            this.qualifierValues.clear();
            this.qualifierValues.addAll(qualifierValues);
        }
    }


    /**
     * @param qv qv
     */
    public void addQualifierValue(QualifierValue qv) {
        if (!(qualifierValues instanceof ArrayList)) {
            List newQualifierValues = new ArrayList<>(qualifierValues.size() + 1);
            newQualifierValues.addAll(qualifierValues);
            qualifierValues = newQualifierValues;
        }

        qualifierValues.add(qv);
    }

    @Nonnull
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder(tag);
        sb.append('(');
        for (Object ob : values) {
            sb.append(' ');
            sb.append(ob);
        }
        if (!qualifierValues.isEmpty()) {
            sb.append('{');
            for (QualifierValue qv : qualifierValues) {
                sb.append(qv);
                sb.append(' ');
            }
            sb.append('}');
        }
        if (!xrefs.isEmpty()) {
            sb.append('[');
            for (Xref x : xrefs) {
                sb.append(x);
                sb.append(' ');
            }
            sb.append(']');
        }
        sb.append(')');
        return sb.toString();
    }

    private static boolean collectionsEquals(@Nullable Collection c1,
        @Nullable Collection c2) {
        if (c1 == null || c1.isEmpty()) {
            return c2 == null || c2.isEmpty();
        }
        if (c2 == null) {
            return false;
        }
        if (c1.size() != c2.size()) {
            return false;
        }
        // xrefs are stored as lists to preserve order, but order is not import
        // for comparisons
        for (Object x : c1) {
            if (!c2.contains(x)) {
                return false;
            }
        }
        return true;
    }

    @Override
    public int hashCode() {
        return 31 * 31 * 31 * qualifierValues.hashCode() + 31 * xrefs.hashCode()
            + 31 * 31 * values.hashCode() + (tag == null ? 0 : tag.hashCode());
    }

    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof Clause)) {
            return false;
        }
        if (obj == this) {
            return true;
        }
        Clause other = (Clause) obj;
        if (!getTag().equals(other.getTag())) {
            return false;
        }
        if (getValues().size() == 1 && other.getValues().size() == 1) {
            // special case for comparing booleans
            // this is a bit of a hack - ideally owl2obo would use the correct
            // types
            Object v1 = getValue();
            Object v2 = other.getValue();
            if (v1 != v2 && !Objects.equals(v1, v2)) {
                if (Boolean.TRUE.equals(v1) && "true".equals(v2)) {
                    // special case - OK
                } else if (Boolean.TRUE.equals(v2) && "true".equals(v1)) {
                    // special case - OK
                } else if (Boolean.FALSE.equals(v1) && "false".equals(v2)) {
                    // special case - OK
                } else if (Boolean.FALSE.equals(v2) && "false".equals(v1)) {
                    // special case - OK
                } else {
                    return false;
                }
            }
        } else {
            if (!getValues().equals(other.getValues())) {
                return false;
            }
        }
        if (!collectionsEquals(xrefs, other.getXrefs())) {
            return false;
        }
        /*
         * if (xrefs != null) { if (other.getXrefs() == null) return false; if
         * (!xrefs.equals(other.getXrefs())) return false; } else { if (other.getXrefs() != null &&
         * other.getXrefs().size() > 0) { return false; } }
         */
        return collectionsEquals(qualifierValues, other.getQualifierValues());
    }

}