Author: clopes
Date: 2012-08-13 15:04:21 -0700 (Mon, 13 Aug 2012)
New Revision: 30178

Added:
   
core3/impl/trunk/io-impl/impl/src/test/resources/testData/xgmml/bare_ampersands.xgmml
Modified:
   
core3/impl/trunk/io-impl/impl/src/main/java/org/cytoscape/io/internal/read/xgmml/GenericXGMMLReader.java
   
core3/impl/trunk/io-impl/impl/src/test/java/org/cytoscape/io/internal/read/xgmml/GenericXGMMLReaderTest.java
Log:
Fixes #1289 : system property "cytoscape.xgmml.repair.bare.ampersands" is now 
supported by Cytoscape 3

Modified: 
core3/impl/trunk/io-impl/impl/src/main/java/org/cytoscape/io/internal/read/xgmml/GenericXGMMLReader.java
===================================================================
--- 
core3/impl/trunk/io-impl/impl/src/main/java/org/cytoscape/io/internal/read/xgmml/GenericXGMMLReader.java
    2012-08-13 21:15:44 UTC (rev 30177)
+++ 
core3/impl/trunk/io-impl/impl/src/main/java/org/cytoscape/io/internal/read/xgmml/GenericXGMMLReader.java
    2012-08-13 22:04:21 UTC (rev 30178)
@@ -29,6 +29,7 @@
 
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.PushbackInputStream;
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
@@ -66,6 +67,8 @@
 
 public class GenericXGMMLReader extends AbstractNetworkReader {
 
+       public static final String REPAIR_BARE_AMPERSANDS_PROPERTY = 
"cytoscape.xgmml.repair.bare.ampersands";
+       
        protected final ReadDataManager readDataMgr;
        protected final XGMMLParser parser;
        protected final UnrecognizedVisualPropertyManager 
unrecognizedVisualPropertyMgr;
@@ -74,17 +77,24 @@
        private static final Logger logger = 
LoggerFactory.getLogger(GenericXGMMLReader.class);
        
        public GenericXGMMLReader(final InputStream inputStream,
-                                                          final 
CyNetworkViewFactory cyNetworkViewFactory,
-                                                          final 
CyNetworkFactory cyNetworkFactory,
-                                                          final 
RenderingEngineManager renderingEngineMgr,
-                                                          final 
ReadDataManager readDataMgr,
-                                                          final XGMMLParser 
parser,
-                                                          final 
UnrecognizedVisualPropertyManager unrecognizedVisualPropertyMgr) {
+                                                         final 
CyNetworkViewFactory cyNetworkViewFactory,
+                                                         final 
CyNetworkFactory cyNetworkFactory,
+                                                         final 
RenderingEngineManager renderingEngineMgr,
+                                                         final ReadDataManager 
readDataMgr,
+                                                         final XGMMLParser 
parser,
+                                                         final 
UnrecognizedVisualPropertyManager unrecognizedVisualPropertyMgr) {
                super(inputStream, cyNetworkViewFactory, cyNetworkFactory);
                this.readDataMgr = readDataMgr;
                this.parser = parser;
                this.unrecognizedVisualPropertyMgr = 
unrecognizedVisualPropertyMgr;
                this.visualLexicon = 
renderingEngineMgr.getDefaultVisualLexicon();
+               
+               // This should only be used when an XGMML file or session 
cannot be read due to improperly encoded ampersands,
+               // as it slows down the reading process.
+               final boolean attemptRepair = 
Boolean.getBoolean(REPAIR_BARE_AMPERSANDS_PROPERTY);
+               
+               if (attemptRepair)
+                       this.inputStream = new 
RepairBareAmpersandsInputStream(inputStream, 512);
        }
 
        @Override
@@ -289,4 +299,83 @@
 
                return s;
        }
+       
+       private static class RepairBareAmpersandsInputStream extends 
PushbackInputStream {
+               private final byte[] encodedAmpersand = new byte[] { 'a', 'm', 
'p', ';' };
+
+               public RepairBareAmpersandsInputStream(final InputStream in) {
+                       super(in);
+               }
+
+               public RepairBareAmpersandsInputStream(final InputStream in, 
final int size) {
+                       super(in, size);
+               }
+
+               @Override
+               public int read() throws IOException {
+                       int c;
+
+                       c = super.read();
+                       if (c == (int) '&') {
+                               byte[] b = new byte[7];
+                               int cnt;
+
+                               cnt = read(b);
+                               if (cnt > 0) {
+                                       boolean isEntity;
+                                       int i;
+
+                                       isEntity = false;
+                                       i = 0;
+                                       while ((i < cnt) && (!isEntity)) {
+                                               isEntity = (b[i] == ';');
+                                               i++;
+                                       }
+
+                                       byte[] pb = new byte[cnt];
+                                       for (int p = 0; p < cnt; p++) {
+                                               pb[p] = b[p];
+                                       }
+                                       unread(pb);
+
+                                       if (!isEntity) {
+                                               unread(encodedAmpersand);
+                                       }
+                               }
+                       }
+
+                       return c;
+               }
+
+               @Override
+               public int read(byte[] b, int off, int len) throws IOException {
+                       if (b == null) {
+                               throw new NullPointerException();
+                       } else if (off < 0 || len < 0 || len > b.length - off) {
+                               throw new IndexOutOfBoundsException();
+                       } else if (len == 0) {
+                               return 0;
+                       }
+
+                       int cnt;
+                       int c = -1;
+
+                       cnt = 0;
+                       while (cnt < len) {
+                               c = read();
+                               if (c == -1) {
+                                       break;
+                               }
+                               b[off] = (byte) c;
+                               off++;
+                               cnt++;
+                       }
+
+                       if ((c == -1) && (cnt == 0)) {
+                               cnt = -1;
+                       }
+
+                       return cnt;
+               }
+       }
 }

Modified: 
core3/impl/trunk/io-impl/impl/src/test/java/org/cytoscape/io/internal/read/xgmml/GenericXGMMLReaderTest.java
===================================================================
--- 
core3/impl/trunk/io-impl/impl/src/test/java/org/cytoscape/io/internal/read/xgmml/GenericXGMMLReaderTest.java
        2012-08-13 21:15:44 UTC (rev 30177)
+++ 
core3/impl/trunk/io-impl/impl/src/test/java/org/cytoscape/io/internal/read/xgmml/GenericXGMMLReaderTest.java
        2012-08-13 22:04:21 UTC (rev 30178)
@@ -11,6 +11,7 @@
 import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.io.FileInputStream;
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -321,6 +322,22 @@
                assertEquals("SansSerif,bold,12", 
GenericXGMMLReader.convertOldFontValue("SansSerif,bold,12"));
        }
        
+       @Test(expected=IOException.class)
+       public void testRepairBareAmpersandsPropertyFalse() throws Exception {
+               
System.setProperty(GenericXGMMLReader.REPAIR_BARE_AMPERSANDS_PROPERTY, "false");
+               getViews("bare_ampersands.xgmml");
+       }
+       
+       @Test
+       public void testRepairBareAmpersandsPropertyTrue() throws Exception {
+               
System.setProperty(GenericXGMMLReader.REPAIR_BARE_AMPERSANDS_PROPERTY, "true");
+               List<CyNetworkView> views = getViews("bare_ampersands.xgmml");
+               CyNetwork net = checkSingleNetwork(views, 1, 1);
+               assertEquals("&ABC", net.getRow(net).get("&net_att_1", 
String.class));
+               assertEquals("CDE&", 
net.getRow(net.getNodeList().get(0)).get("node_att_$1", String.class));
+               assertEquals(25, 
net.getRow(net.getEdgeList().get(0)).get("edge_att_1$", 
Integer.class).intValue());
+       }
+       
        private void assertCustomColumnsAreMutable(CyNetwork net) {
                // User or non-default columns should be immutable
                List<CyTable> tables = new ArrayList<CyTable>();

Added: 
core3/impl/trunk/io-impl/impl/src/test/resources/testData/xgmml/bare_ampersands.xgmml
===================================================================
--- 
core3/impl/trunk/io-impl/impl/src/test/resources/testData/xgmml/bare_ampersands.xgmml
                               (rev 0)
+++ 
core3/impl/trunk/io-impl/impl/src/test/resources/testData/xgmml/bare_ampersands.xgmml
       2012-08-13 22:04:21 UTC (rev 30178)
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<graph label="Network A" xmlns:dc="http://purl.org/dc/elements/1.1/";
+       xmlns:xlink="http://www.w3.org/1999/xlink"; 
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#";
+       xmlns:cy="http://www.cytoscape.org"; xmlns="http://www.cs.rpi.edu/XGMML";
+       directed="1">
+       
+       <att type="string" name="&net_att_1" value="&ABC"/>
+       
+       <node label="node1" id="1">
+               <att type="string" name="node_att_$1" value="CDE&" />
+       </node>
+       <edge label="node1 (DirectedEdge) node1" source="1" target="1">
+               <att type="integer" name="edge_att_1$" value="25" />
+       </edge>
+</graph>
\ No newline at end of file

-- 
You received this message because you are subscribed to the Google Groups 
"cytoscape-cvs" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/cytoscape-cvs?hl=en.

Reply via email to