001package org.biopax.paxtools.pattern.miner;
002
003import org.biopax.paxtools.controller.PathAccessor;
004import org.biopax.paxtools.model.BioPAXElement;
005
006import java.io.IOException;
007import java.io.OutputStream;
008import java.io.OutputStreamWriter;
009import java.io.Writer;
010import java.util.*;
011
012/**
013 * This class is used for writing the binary interactions to a text output stream in the old
014 * EXTENDED_BINARY_SIF format.
015 *
016 * @author Ozgun Babur
017 */
018public class OldFormatWriter
019{
020        /**
021         * Path accessors for participant properties.
022         */
023        private static final PathAccessor[] ACCS = new PathAccessor[]{
024                new PathAccessor("Named/displayName"),
025                new PathAccessor("XReferrable/xref:UnificationXref"),
026                new PathAccessor("XReferrable/xref:RelationshipXref")};
027
028        /**
029         * Writes down the given interactions into the given output stream in the old
030         * EXTENDED_BINARY_SIF format. Closes the stream at the end.
031         * @param inters binary interactions
032         * @param out stream to write
033         * @return true if any output produced successfully
034         */
035        public static boolean write(Set<SIFInteraction> inters, OutputStream out)
036        {
037                SIFToText stt = new CustomFormat(
038                        OutputColumn.Type.RESOURCE.name(),
039                        OutputColumn.Type.PUBMED.name(),
040                        OutputColumn.Type.PATHWAY.name());
041
042                if (!inters.isEmpty())
043                {
044                        List<SIFInteraction> interList = new ArrayList<SIFInteraction>(inters);
045                        Collections.sort(interList);
046                        try
047                        {
048                                OutputStreamWriter writer = new OutputStreamWriter(out);
049                                writer.write("PARTICIPANT_A\tINTERACTION_TYPE\tPARTICIPANT_B\t" +
050                                        "INTERACTION_DATA_SOURCE\tINTERACTION_PUBMED_ID\tPATHWAY_NAMES");
051                                for (SIFInteraction inter : interList)
052                                {
053                                        writer.write("\n" + stt.convert(inter));
054                                }
055                                writeSourceAndTargetDetails(inters, writer);
056                                writer.close();
057                                return true;
058                        }
059                        catch (IOException e)
060                        {
061                                e.printStackTrace();
062                        }
063                }
064                return false;
065        }
066
067        private static void writeSourceAndTargetDetails(Collection<SIFInteraction> inters, Writer writer)
068                throws IOException
069        {
070                Map<String, Set<BioPAXElement>> map = collectEntityRefs(inters);
071
072                writer.write("\n\nPARTICIPANT\tPARTICIPANT_TYPE\tPARTICIPANT_NAME\t" +
073                        "UNIFICATION_XREF\tRELATIONSHIP_XREF");
074
075                for (String id : map.keySet())
076                {
077                        writer.write("\n" + id + "\t" + getParticipantTypes(map.get(id)));
078
079                        for (PathAccessor acc : ACCS)
080                        {
081                                writer.write("\t" + getValue(map.get(id), acc));
082                        }
083                }
084        }
085
086        /**
087         * Collects the sources and targets in given interactions.
088         * @param inters binary interactions
089         * @return map from the primary id to the set of related source and target elements.
090         */
091        private static Map<String, Set<BioPAXElement>> collectEntityRefs(Collection<SIFInteraction> inters)
092        {
093                Map<String, Set<BioPAXElement>> map = new HashMap<String, Set<BioPAXElement>>();
094
095                for (SIFInteraction inter : inters)
096                {
097                        if (!map.containsKey(inter.sourceID))
098                                map.put(inter.sourceID, new HashSet<BioPAXElement>());
099                        if (!map.containsKey(inter.targetID))
100                                map.put(inter.targetID, new HashSet<BioPAXElement>());
101
102                        map.get(inter.sourceID).addAll(inter.sourceERs);
103                        map.get(inter.targetID).addAll(inter.targetERs);
104                }
105                return map;
106        }
107
108        private static String getParticipantTypes(Set<BioPAXElement> elements)
109        {
110                Set<String> set = new HashSet<String>();
111                for (BioPAXElement ele : elements)
112                {
113                        String name = ele.getModelInterface().getName();
114                        set.add(name.substring(name.lastIndexOf(".") + 1));
115                }
116                List<String> list = new ArrayList<String>(set);
117                Collections.sort(list);
118                return concat(list);
119        }
120
121        private static String getValue(Set<BioPAXElement> elements, PathAccessor pa)
122        {
123                Set<String> set = new HashSet<String>();
124                for (Object o : pa.getValueFromBeans(elements))
125                {
126                        set.add(o.toString());
127                }
128                List<String> list = new ArrayList<String>(set);
129                Collections.sort(list);
130                return concat(list);
131        }
132
133        /**
134         * Concatenates the given collection of strings into a single string where values are separated
135         * with a semicolon.
136         * @param col string collection
137         * @return concatenated string
138         */
139        private static String concat(Collection<String> col)
140        {
141                StringBuilder b = new StringBuilder();
142                boolean first = true;
143                for (String s : col)
144                {
145                        if (first) first = false;
146                        else b.append(";");
147
148                        b.append(s);
149                }
150                return b.toString();
151        }
152}