001/*
002 *                    BioJava development code
003 *
004 * This code may be freely distributed and modified under the
005 * terms of the GNU Lesser General Public Licence.  This should
006 * be distributed with the code.  If you do not have a copy,
007 * see:
008 *
009 *      http://www.gnu.org/copyleft/lesser.html
010 *
011 * Copyright for this code is held jointly by the individual
012 * authors.  These should be listed in @author doc comments.
013 *
014 * For more information on the BioJava project and its aims,
015 * or to join the biojava-l mailing list, visit the home page
016 * at:
017 *
018 *      http://www.biojava.org/
019 *
020 * Created on Sep 14, 2011
021 * Author: Amr AL-Hossary
022 *
023 */
024package org.biojava.nbio.core.util;
025
026import org.slf4j.Logger;
027import org.slf4j.LoggerFactory;
028import org.w3c.dom.Document;
029import org.w3c.dom.DocumentType;
030import org.w3c.dom.NamedNodeMap;
031import org.w3c.dom.Node;
032import org.xml.sax.SAXException;
033
034import javax.xml.parsers.DocumentBuilder;
035import javax.xml.parsers.DocumentBuilderFactory;
036import javax.xml.parsers.ParserConfigurationException;
037import java.io.*;
038import java.util.AbstractCollection;
039import java.util.Iterator;
040import java.util.Scanner;
041
042
043/**
044 * A utility class for common {@link String} manipulation tasks.
045 * All functions are static methods.
046 *
047 * @author Amr AL-Hossary
048 */
049public class StringManipulationHelper  {
050
051        private final static Logger logger = LoggerFactory.getLogger(StringManipulationHelper.class);
052
053        /**
054         * we are using Unix endline here, since this is used for testing XML and it
055         * is part of the XML recommendations: <a href
056         * ="http://www.w3.org/TR/REC-xml/#sec-line-ends"
057         * >http://www.w3.org/TR/REC-xml/#sec-line-ends</a>
058         */
059        private static final String UNIX_NEWLINE = "\n";
060
061        private StringManipulationHelper() {
062                // to prevent instantiation
063        }
064
065
066
067
068
069        /**
070         * @author andreas
071         * @param stream
072         * @return
073         */
074        public static String convertStreamToString(InputStream stream) {
075                BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
076                StringBuilder sb = new StringBuilder();
077
078                String line = null;
079                try {
080                        while ((line = reader.readLine()) != null) {
081
082                sb.append(line).append(UNIX_NEWLINE);
083                        }
084                } catch (IOException e) {
085                        // logger.error("Exception: ", e);
086                } finally {
087                        try {
088                                stream.close();
089                        } catch (IOException e) {
090                                logger.error("Exception: ", e);
091                        }
092                }
093
094                return sb.toString();
095        }
096
097        /**
098         * compares two strings for equality, line by line, ignoring any difference
099         * of end line delimiters contained within the 2 Strings. This method should
100         * be used if and only if two Strings are considered identical when all nodes
101         * are identical including their relative order. Generally useful when
102         * asserting identity of <b>automatically regenerated</b> XML or PDB.
103         *
104         * @param expected
105         * @param actual
106         */
107        public static boolean equalsToIgnoreEndline(String expected, String actual) {
108                if (expected == null && actual == null) {
109                        return true;
110                }
111                if (expected != null ^ actual != null) {
112                        return false;
113                }
114                Scanner scanner1 = new Scanner(expected);
115                Scanner scanner2 = new Scanner(actual);
116                String line1, line2;
117                while (scanner1.hasNextLine()) {
118                        line1 = scanner1.nextLine();
119                        line2 = scanner2.nextLine();
120                        if (! line1.equals(line2)) {
121                                scanner1.close();
122                                scanner2.close();
123                                return false;
124                        }
125                }
126                if (scanner2.hasNextLine()) {
127                        scanner1.close();
128                        scanner2.close();
129                        return false;
130                }
131
132                scanner1.close();
133                scanner2.close();
134                return true;
135        }
136
137
138        public static boolean equalsToXml(String expected, String actual) {
139                Document expectedDocument=null;
140                Document actualDocument=null;
141                try {
142                        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
143                        DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
144                        expectedDocument = documentBuilder.parse(new ByteArrayInputStream(expected.getBytes()));
145                        actualDocument = documentBuilder.parse(new ByteArrayInputStream(actual.getBytes()));
146                } catch (ParserConfigurationException e) {
147                        logger.error("Exception: ", e);
148                        throw new RuntimeException("Couldn't Parse XML", e);
149                } catch (SAXException e) {
150                        logger.error("Exception: ", e);
151                        throw new RuntimeException("Couldn't Parse XML", e);
152                } catch (IOException e) {
153                        logger.error("Exception: ", e);
154                        throw new RuntimeException("Couldn't Parse XML", e);
155                }
156                final DocumentType doctype1 = expectedDocument.getDoctype();
157                final DocumentType doctype2 = actualDocument.getDoctype();
158                if (doctype1==null ^ doctype2 == null) {
159                        return false;
160                }else if (doctype1!= null /*&& doctype2 != null*/) {
161                        NamedNodeMap expectedNotations = doctype1.getNotations();
162                        NamedNodeMap actualNotations = doctype2.getNotations();
163                        if (expectedNotations.getLength() == actualNotations.getLength()) {
164                                for (int i = 0; i < expectedNotations.getLength(); i++) {
165                                        Node node= expectedNotations.item(i);
166                                        node.isEqualNode(null);
167                                }
168                        }else{
169                                return false;
170                        }
171
172                }
173
174                throw new UnsupportedOperationException("not yet implemented");
175        }
176
177        public static String padLeft(String s, int n) {
178            return String.format("%1$" + n + "s", s);
179        }
180
181        public static String padRight(String s, int n) {
182             return String.format("%1$-" + n + "s", s);
183        }
184
185        public static String join(AbstractCollection<String> s, String delimiter) {
186            if (s == null || s.isEmpty()) return "";
187            Iterator<String> iter = s.iterator();
188            StringBuilder builder = new StringBuilder(iter.next());
189            while( iter.hasNext() )
190            {
191                builder.append(delimiter).append(iter.next());
192            }
193            return builder.toString();
194        }
195
196}