org.obolibrary.oboformat.writer.OBOFormatWriter Maven / Gradle / Ivy
package org.obolibrary.oboformat.writer;
import static org.semanticweb.owlapi.model.parameters.Navigation.IN_SUB_POSITION;
import static org.semanticweb.owlapi.util.OWLAPIPreconditions.checkNotNull;
import static org.semanticweb.owlapi.util.OWLAPIStreamUtils.asList;
import java.io.*;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.*;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import org.obolibrary.obo2owl.OWLAPIObo2Owl;
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.obolibrary.oboformat.parser.OBOFormatParser;
import org.obolibrary.oboformat.parser.OBOFormatParserException;
import org.semanticweb.owlapi.model.*;
import org.semanticweb.owlapi.model.parameters.Imports;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import gnu.trove.map.hash.TObjectIntHashMap;
/**
* The Class OBOFormatWriter.
*
* @author Shahid Manzoor
*/
@ParametersAreNonnullByDefault
public class OBOFormatWriter {
private static final Logger LOG = LoggerFactory.getLogger(OBOFormatWriter.class);
@Nonnull private static final TObjectIntHashMap TAGSPRIORITIES = buildTagsPriorities();
@Nonnull private static final TObjectIntHashMap TYPEDEFTAGSPRIORITIES = buildTypeDefTagsPriorities();
private static final Comparator framesComparator = Comparator.comparing(Frame::getId);
private static final TObjectIntHashMap HEADERTAGSPRIORITIES = buildHeaderTagsPriorities();
private static final Set TAGSINFORMATIVE = buildTagsInformative();
private static final Comparator headerTagsComparator = Comparator.comparingInt(
OBOFormatWriter::getHeaderPriority);
/**
* This comparator sorts clauses with the same tag in the specified write
* order.
*/
private static final Comparator clauseComparator = (o1, o2) -> compare(o1, o2);
private static Comparator termsTagsComparator = Comparator.comparingInt(OBOFormatWriter::getPriority);
private static Comparator typeDefTagsComparator = Comparator.comparingInt(
OBOFormatWriter::getTypedefPriority);
private static Comparator clauseListComparator = Comparator.comparing(Clause::getTag, termsTagsComparator)
.thenComparing(clauseComparator);
private boolean isCheckStructure = true;
private static int getHeaderPriority(String s) {
return actualGet(s, HEADERTAGSPRIORITIES);
}
protected static int actualGet(String s, TObjectIntHashMap map) {
int i = map.get(s);
if (i == map.getNoEntryValue()) {
return 10000;
}
return i;
}
private static int getPriority(String s) {
return actualGet(s, TAGSPRIORITIES);
}
private static int getTypedefPriority(String s) {
return actualGet(s, TYPEDEFTAGSPRIORITIES);
}
/**
* @return true, if is check structure
*/
public boolean isCheckStructure() {
return isCheckStructure;
}
/**
* @param isCheckStructure
* the new check structure
*/
public void setCheckStructure(boolean isCheckStructure) {
this.isCheckStructure = isCheckStructure;
}
private static Set buildTagsInformative() {
Set set = new HashSet<>();
set.add(OboFormatTag.TAG_IS_A.getTag());
set.add(OboFormatTag.TAG_RELATIONSHIP.getTag());
set.add(OboFormatTag.TAG_DISJOINT_FROM.getTag());
set.add(OboFormatTag.TAG_INTERSECTION_OF.getTag());
set.add(OboFormatTag.TAG_UNION_OF.getTag());
set.add(OboFormatTag.TAG_EQUIVALENT_TO.getTag());
// removed OboFormatTag.TAG_REPLACED_BY to be compatible with OBO-Edit
set.add(OboFormatTag.TAG_PROPERTY_VALUE.getTag());
set.add(OboFormatTag.TAG_DOMAIN.getTag());
set.add(OboFormatTag.TAG_RANGE.getTag());
set.add(OboFormatTag.TAG_INVERSE_OF.getTag());
set.add(OboFormatTag.TAG_TRANSITIVE_OVER.getTag());
// removed OboFormatTag.TAG_HOLDS_OVER_CHAIN to be compatible with
// OBO-Edit
set.add(OboFormatTag.TAG_EQUIVALENT_TO_CHAIN.getTag());
set.add(OboFormatTag.TAG_DISJOINT_OVER.getTag());
return set;
}
/**
* @param fn
* the file name to read in
* @param writer
* the writer
* @throws IOException
* Signals that an I/O exception has occurred.
* @throws OBOFormatParserException
* the oBO format parser exception
*/
public void write(String fn, Writer writer) throws IOException {
if (fn.startsWith("http:")) {
write(new URL(fn), writer);
} else {
try (FileReader r = new FileReader(new File(fn)); Reader reader = new BufferedReader(r);) {
write(reader, writer);
}
}
}
/**
* Write.
*
* @param url
* the url
* @param writer
* the writer
* @throws IOException
* Signals that an I/O exception has occurred.
* @throws OBOFormatParserException
* the oBO format parser exception
*/
public void write(URL url, Writer writer) throws IOException {
Reader reader = new BufferedReader(new InputStreamReader(url.openStream()));
write(reader, writer);
}
/**
* @param reader
* the reader
* @param writer
* the writer
* @throws IOException
* Signals that an I/O exception has occurred.
* @throws OBOFormatParserException
* the oBO format parser exception
*/
public void write(Reader reader, Writer writer) throws IOException {
OBOFormatParser parser = new OBOFormatParser();
OBODoc doc = parser.parse(reader);
write(doc, writer);
}
/**
* @param doc
* the doc
* @param outFilename
* the out file name
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public void write(OBODoc doc, String outFilename) throws IOException {
write(doc, new File(outFilename));
}
/**
* @param doc
* the doc
* @param outFile
* the out file
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public void write(OBODoc doc, File outFile) throws IOException {
try (FileOutputStream os = new FileOutputStream(outFile);
OutputStreamWriter osw = new OutputStreamWriter(os, StandardCharsets.UTF_8);
Writer bw = new BufferedWriter(osw);) {
write(doc, bw);
}
}
/**
* @param doc
* the doc
* @param writer
* the writer
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public void write(OBODoc doc, Writer writer) throws IOException {
NameProvider nameProvider = new OBODocNameProvider(doc);
write(doc, writer, nameProvider);
}
/**
* @param doc
* the doc
* @param writer
* the writer
* @param nameProvider
* the name provider
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public void write(OBODoc doc, Writer writer, NameProvider nameProvider) throws IOException {
if (isCheckStructure) {
doc.check();
}
Frame headerFrame = doc.getHeaderFrame();
writeHeader(checkNotNull(headerFrame), writer, nameProvider);
List termFrames = new ArrayList<>();
termFrames.addAll(doc.getTermFrames());
Collections.sort(termFrames, framesComparator);
List typeDefFrames = new ArrayList<>();
typeDefFrames.addAll(doc.getTypedefFrames());
Collections.sort(typeDefFrames, framesComparator);
List instanceFrames = new ArrayList<>();
typeDefFrames.addAll(doc.getInstanceFrames());
Collections.sort(instanceFrames, framesComparator);
for (Frame f : termFrames) {
write(f, writer, nameProvider);
}
for (Frame f : typeDefFrames) {
write(f, writer, nameProvider);
}
for (Frame f : instanceFrames) {
write(f, writer, nameProvider);
}
// to be save always flush writer
writer.flush();
}
private static void writeLine(StringBuilder ln, Writer writer) throws IOException {
ln.append('\n');
writer.write(ln.toString());
}
private static void writeLine(String ln, Writer writer) throws IOException {
writer.write(ln + '\n');
}
private static void writeEmptyLine(Writer writer) throws IOException {
writer.write("\n");
}
private static List duplicateTags(Set src) {
return new ArrayList<>(src);
}
/**
* Write header.
*
* @param frame
* the frame
* @param writer
* the writer
* @param nameProvider
* the name provider
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public void writeHeader(Frame frame, Writer writer, NameProvider nameProvider) throws IOException {
List tags = duplicateTags(frame.getTags());
Collections.sort(tags, headerTagsComparator);
write(new Clause(OboFormatTag.TAG_FORMAT_VERSION.getTag(), "1.2"), writer, nameProvider);
for (String tag : tags) {
if (tag.equals(OboFormatTag.TAG_FORMAT_VERSION.getTag())) {
continue;
}
List clauses = new ArrayList<>(frame.getClauses(tag));
Collections.sort(clauses, clauseComparator);
for (Clause clause : clauses) {
if (tag.equals(OboFormatTag.TAG_SUBSETDEF.getTag())) {
writeSynonymtypedef(clause, writer);
} else if (tag.equals(OboFormatTag.TAG_SYNONYMTYPEDEF.getTag())) {
writeSynonymtypedef(clause, writer);
} else if (tag.equals(OboFormatTag.TAG_DATE.getTag())) {
writeHeaderDate(clause, writer);
} else if (tag.equals(OboFormatTag.TAG_PROPERTY_VALUE.getTag())) {
writePropertyValue(clause, writer);
} else if (tag.equals(OboFormatTag.TAG_IDSPACE.getTag())) {
writeIdSpace(clause, writer);
} else {
write(clause, writer, nameProvider);
}
}
}
writeEmptyLine(writer);
}
/**
* @param frame
* the frame
* @param writer
* the writer
* @param nameProvider
* the name provider
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public void write(Frame frame, Writer writer, @Nullable NameProvider nameProvider) throws IOException {
Comparator comparator = null;
if (frame.getType() == FrameType.TERM) {
writeLine("[Term]", writer);
comparator = termsTagsComparator;
} else if (frame.getType() == FrameType.TYPEDEF) {
writeLine("[Typedef]", writer);
comparator = typeDefTagsComparator;
} else if (frame.getType() == FrameType.INSTANCE) {
writeLine("[Instance]", writer);
comparator = typeDefTagsComparator;
}
String id = frame.getId();
if (id != null) {
Object label = frame.getTagValue(OboFormatTag.TAG_NAME);
String extra = "";
if (label == null && nameProvider != null) {
// the name clause may not be present in this OBODoc - however,
// the name provider may be able to provide one, in which case,
// we
// write it as a parser-invisible comment, thus preserving the
// document structure but providing useful information for any
// person that inspects the obo file
label = nameProvider.getName(id);
if (label != null) {
extra = " ! " + label;
}
}
writeLine(OboFormatTag.TAG_ID.getTag() + ": " + id + extra, writer);
}
List tags = duplicateTags(frame.getTags());
Collections.sort(tags, comparator);
String defaultOboNamespace = null;
if (nameProvider != null) {
defaultOboNamespace = nameProvider.getDefaultOboNamespace();
}
for (String tag : tags) {
List clauses = new ArrayList<>(frame.getClauses(tag));
Collections.sort(clauses, clauseComparator);
for (Clause clause : clauses) {
String clauseTag = clause.getTag();
if (OboFormatTag.TAG_ID.getTag().equals(clauseTag)) {
continue;
} else if (OboFormatTag.TAG_DEF.getTag().equals(clauseTag)) {
writeDef(clause, writer);
} else if (OboFormatTag.TAG_SYNONYM.getTag().equals(clauseTag)) {
writeSynonym(clause, writer);
} else if (OboFormatTag.TAG_PROPERTY_VALUE.getTag().equals(clauseTag)) {
writePropertyValue(clause, writer);
} else if (OboFormatTag.TAG_EXPAND_EXPRESSION_TO.getTag().equals(clauseTag)
|| OboFormatTag.TAG_EXPAND_ASSERTION_TO.getTag().equals(clauseTag)) {
writeClauseWithQuotedString(clause, writer);
} else if (OboFormatTag.TAG_XREF.getTag().equals(clauseTag)) {
writeXRefClause(clause, writer);
} else if (OboFormatTag.TAG_NAMESPACE.getTag().equals(clauseTag)) {
// only write OBO namespace,
// if it is different from the default OBO namespace
if (defaultOboNamespace == null || !clause.getValue().equals(defaultOboNamespace)) {
write(clause, writer, nameProvider);
}
} else {
write(clause, writer, nameProvider);
}
}
}
writeEmptyLine(writer);
}
private static void writeXRefClause(Clause clause, Writer writer) throws IOException {
Xref xref = clause.getValue(Xref.class);
StringBuilder sb = new StringBuilder();
sb.append(clause.getTag());
sb.append(": ");
String idref = xref.getIdref();
int colonPos = idref.indexOf(':');
if (colonPos > 0) {
sb.append(escapeOboString(idref.substring(0, colonPos), EscapeMode.XREF));
sb.append(':');
sb.append(escapeOboString(idref.substring(colonPos + 1), EscapeMode.XREF));
} else {
sb.append(escapeOboString(idref, EscapeMode.XREF));
}
String annotation = xref.getAnnotation();
if (annotation != null) {
sb.append(" \"");
sb.append(escapeOboString(annotation, EscapeMode.QUOTES));
sb.append('"');
}
appendQualifiers(sb, clause);
writeLine(sb, writer);
}
private static void writeSynonymtypedef(Clause clause, Writer writer) throws IOException {
StringBuilder sb = new StringBuilder();
sb.append(clause.getTag());
sb.append(": ");
Iterator
© 2015 - 2025 Weber Informatics LLC | Privacy Policy