Package vg.modules.opener.system

Source Code of vg.modules.opener.system.GraphMLDecoder

package vg.modules.opener.system;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Stack;
import java.util.Date;
import java.text.DateFormat;

import java.util.logging.Level;
import java.util.logging.Logger;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.DefaultHandler;
import org.apache.commons.lang.StringEscapeUtils;

import vg.core.AModel;
import vg.core.IProgressTask;
import vg.core.VisualGraph;
import vg.core.exception.CoreException;
import vg.core.exception.EnumCriticalityException;
import vg.core.storableGraph.StorableAttribute;
import vg.core.storableGraph.StorableEdge;
import vg.core.storableGraph.StorableGraph;
import vg.core.storableGraph.StorableSubGraph;
import vg.core.storableGraph.StorableVertex;

/**
* This class reads graph in GraphML file format. It's port from
* <a href="http://http://prefuse.org//">prefuse visualization toolkit</a>.<BR>
* GraphML is an XML format supporting graph structure and typed data
* schemas for both nodes and edges. For more information about the
* format, please see the
* <a href="http://graphml.graphdrawing.org/">GraphML home page</a>.
*
* @author dkolbin
*/
public class GraphMLDecoder implements IDecoder {

    /**
     * @see vg.modules.opener.system.IDecoder
     */
    public Integer decode(String fileName, AModel model, String graphName) throws CoreException{
        try {
            SAXParserFactory factory = SAXParserFactory.newInstance();
            SAXParser saxParser = factory.newSAXParser();

            GraphMLHandler handler = new GraphMLHandler(model, graphName);
            File  f = new File(fileName);
            final long fileSize = (int) f.length()
            final FileInputStream fis = new FileInputStream(f);

            if (fis != null)
              fis.getChannel().position();
           
            IProgressTask task = new IProgressTask() {
       
        @Override
        public long getValue() {
                if (fis.getChannel() != null)
            try {
              return fis.getChannel().position();
            } catch (IOException e) {
           
            }
          return getLength();
        }
       
        @Override
        public long getLength() {
          return fileSize;
        }
      };
           
            VisualGraph.progressManager.addTask(task);
           
            saxParser.parse(fis, handler);
            VisualGraph.progressManager.removeTask(task);
            return handler.getGraphID();
        } catch (CoreException e) {
          throw e;
        } catch (ParserConfigurationException e) {
      VisualGraph.log.printStackTrace(e.getStackTrace());
      throw new CoreException(e.getMessage(), EnumCriticalityException.FAILED);
    } catch (SAXParseException e) {
      VisualGraph.log.printStackTrace(e.getStackTrace());     
      throw new CoreException(fileName  + ":" + e.getLineNumber() + ":" + e.getColumnNumber()
          + " " + e.getMessage(), EnumCriticalityException.FAILED);
    } catch (SAXException e) {
      VisualGraph.log.printStackTrace(e.getStackTrace());
      throw new CoreException(fileName  + ":" + e.getMessage(), EnumCriticalityException.FAILED);
    } catch (FileNotFoundException e) {
      VisualGraph.log.printStackTrace(e.getStackTrace());
      throw new CoreException("File " + fileName + " don't found", EnumCriticalityException.FAILED);
    } catch (IOException e) {
      VisualGraph.log.printStackTrace(e.getStackTrace());
      throw new CoreException(e.getMessage(), EnumCriticalityException.FAILED);
    }       
    }
   

    /**
     * String tokens used in the GraphML format.
     */
    private interface Tokens {

        public static final String ID = "id";
        public static final String GRAPH = "graph";
        public static final String EDGEDEF = "edgedefault";
        public static final String DIRECTED = "directed";
        public static final String UNDIRECTED = "undirected";
        public static final String KEY = "key";
        public static final String FOR = "for";
        public static final String ALL = "all";
        public static final String ATTRNAME = "attr.name";
        public static final String ATTRTYPE = "attr.type";
        public static final String DEFAULT = "default";
        public static final String NODE = "node";
        public static final String EDGE = "edge";
        public static final String SOURCE = "source";
        public static final String TARGET = "target";
        public static final String DATA = "data";
        public static final String TYPE = "type";
        public static final String INT = "int";
        public static final String INTEGER = "integer";
        public static final String LONG = "long";
        public static final String FLOAT = "float";
        public static final String DOUBLE = "double";
        public static final String REAL = "real";
        public static final String BOOLEAN = "boolean";
        public static final String STRING = "string";
        public static final String DATE = "date";
    }

    /**
     * A SAX Parser for GraphML data files.
     */
    private static class GraphMLHandler extends DefaultHandler implements Tokens {
      private AModel model;
      private String graphName;
        private static final String SRC = SOURCE;
        private static final String TRG = TARGET;
        private String m_graphid;
        private StorableGraph m_graph = null;
        // schema parsing
        private String m_id;
        private String m_for;
        private String m_name;
        private String m_type;
        private String m_dflt;
        private String error;
        private StringBuffer m_sbuf = new StringBuffer();
        // node,edge,data parsing
        private String m_key;
        private Stack<NestedGraph> lastGraph = new Stack<NestedGraph>();
        private HashMap<String,Attr> m_vertData = new HashMap<String, Attr>();
        private HashMap<String,Attr> m_edjeData = new HashMap<String, Attr>();
        private boolean m_directed = false;
        private boolean inSchema;
        private Stack<StorableVertex> lastVertex = new Stack<StorableVertex>();
        private PseudoEdge lastEdge = null;
        private Stack<ArrayList <Attr> > lastProperties = new Stack<ArrayList <Attr> >();       
        private boolean graphSection = false;
        private ArrayList<Integer> subgraphIDs = new ArrayList<Integer>();

        class PseudoEdge {

            String left;
            String right;
            String id;
            ArrayList<Attr> properties;
            PseudoEdge(String aLeft, String aRight, String id) {
                left = aLeft;
                right = aRight;
                properties = new ArrayList <Attr>();
                this.id = id;
            }
            public void addAttribute(String key, Class<?> aType, String value)
            {
                properties.add(new Attr(key, aType, value));
            }
        }

        class Attr {
            String name;
            Class<?> type;
            Object value;

            Attr(String aName, Class<?> aType, Object aValue)
            {
                name = aName;
                type = aType;
                value = aValue;
            }
        }

        private class NestedGraph {
            boolean directed;
            String id;
            ArrayList<StorableVertex> nestedVertex;
            ArrayList<PseudoEdge> nestedEdge;
            String name;
            private HashMap<String, StorableVertex> m_nodeMap = new HashMap<String, StorableVertex>();

            NestedGraph(String id, boolean directed) {
                this.id = id;
                this.directed = directed;
                nestedVertex = new ArrayList<StorableVertex>();
                nestedEdge = new ArrayList<PseudoEdge>();
            }

            void addVertex(String id) {
                lastVertex.push(new StorableVertex(id));
                m_nodeMap.put(id, lastVertex.lastElement());
                nestedVertex.add(lastVertex.lastElement());
            }

        }
        GraphMLHandler(AModel model, String graphName)
        {
          this.model = model;
          this.graphName = graphName;
        }

        @Override
        public void startDocument() {
            inSchema = true;
        }

        @Override
        public void endDocument() throws SAXException {
            // now create the graph
            int root = subgraphIDs.get(subgraphIDs.size() - 1);
            m_graph = new StorableGraph(graphName, null, root);
            model.addStorableGraph(m_graph, subgraphIDs);
        }

        @Override
        public void startElement(String namespaceURI, String localName,
                String qName, Attributes atts) {
            // first clear the character buffer
            m_sbuf.delete(0, m_sbuf.length());

            if (qName.equals(GRAPH)) {
                // parse directedness default
                String edef = atts.getValue(EDGEDEF);
                m_directed = DIRECTED.equalsIgnoreCase(edef);
                m_graphid = atts.getValue(ID);

                lastProperties.push(new ArrayList<Attr>());
                lastGraph.push(new NestedGraph(m_graphid, m_directed));
                graphSection = true;
            } else if (qName.equals(KEY)) {
                if (!inSchema) {
                    error("\"" + KEY + "\" elements can not"
                            + " occur after the first node or edge declaration.");
                }
                m_for = atts.getValue(FOR);
                m_id = atts.getValue(ID);
                m_name = atts.getValue(ATTRNAME);
                m_type = atts.getValue(ATTRTYPE);
            } else if (qName.equals(NODE)) {
                inSchema = false;
                graphSection = false;

                String id = atts.getValue(ID);
                lastGraph.lastElement().addVertex(id);
                lastProperties.push(new ArrayList<Attr>());
                for(Attr a:m_vertData.values())
                {
                    if (a.value != null)
                        lastProperties.lastElement().add(new Attr(a.name,a.type, a.value));
                }
            } else if (qName.equals(EDGE)) {
                inSchema = false;
                graphSection = false;
                // do not use the id value
//                String id = atts.getValue(ID);
//                if ( id != null ) {
//                    if ( !m_edges.canGetString(ID) )
//                        m_edges.addColumn(ID, String.class);
//                    m_edges.setString(m_row, ID, id);
//                }
                String id = atts.getValue(ID);
                lastEdge = new PseudoEdge(atts.getValue(SRC), atts.getValue(TRG), id);
                /*graphs.get(lastGraph.lastElement()).nestedEdge.add(
                        (new PseudoEdge(atts.getValue(SRC), atts.getValue(TRG))));
                */
                // currently only global directedness is used
                // ignore directed edge value for now
//                String dir = atts.getValue(DIRECTED);
//                boolean d = m_directed;
//                if ( dir != null ) {
//                    d = dir.equalsIgnoreCase("false");
//                }
//                m_edges.setBoolean(m_row, DIRECTED, d);
                lastProperties.push(new ArrayList<Attr>());
                for(Attr a:m_edjeData.values())
                {
                    if (a.value != null)
                        lastProperties.lastElement().add(new Attr(a.name,a.type, a.value));
                }
            } else if (qName.equals(DATA)) {
                m_key = atts.getValue(KEY);
            }
        }

        @Override
        public void endElement(String namespaceURI,
                String localName, String qName) throws SAXException {
            if (qName.equals(DEFAULT)) {
                // value is in the buffer
                m_dflt = m_sbuf.toString();
            } else if (qName.equals(KEY)) {
                // time to add to the proper schema(s)
                addToSchema();
            } else if (qName.equals(GRAPH)) {
              NestedGraph e = lastGraph.pop();
              ArrayList<StorableEdge> edges = new ArrayList<StorableEdge>();
              for (int j = 0; j < e.nestedEdge.size(); j++) {
                     String src = e.nestedEdge.get(j).left;
                     if (!e.m_nodeMap.containsKey(src)) {
                       VisualGraph.log.printInfo("Skip edge between different nested graphs");
                         continue;
                     }

                     String trg = e.nestedEdge.get(j).right;
                     if (!e.m_nodeMap.containsKey(trg)) {
                       VisualGraph.log.printInfo("Skip edge between different nested graphs");
                         continue;
                     }
                     StorableEdge ed = new StorableEdge(e.m_nodeMap.get(src), e.m_nodeMap.get(trg),e.nestedEdge.get(j).id);
                     for (Attr a:e.nestedEdge.get(j).properties) {
                       ed.addStorableAttribute(new StorableAttribute(a.name,(String) a.value,  a.type.toString()));
                     }
                     edges.add(ed);
                }
              if (e.name == "")
                e.name = e.id;
              StorableSubGraph ssg = new StorableSubGraph(e.id, e.name, e.nestedVertex, edges, e.directed);
                if (lastVertex.size() != 0) {
                    lastVertex.lastElement().setInnerGraph(ssg.getStorableId());
                }
                this.model.addStorableSubGraph(ssg);
                subgraphIDs.add(ssg.getStorableId());
               
                lastProperties.pop();
                graphSection = false;
            } else if (qName.equals(NODE)) {
                ArrayList<Attr> p = lastProperties.pop();
                for (Attr a: p) {
                  if(lastVertex.lastElement().addStorableAttribute(new StorableAttribute(a.name,
                      a.value.toString(), a.type.toString())) == false)
                  {
                        VisualGraph.log.printError("[" + this.getClass().getName() + ".endElement] [BAD] Can't add attribute to vertex");
                    }
                }
                lastVertex.pop();
                graphSection = true;
            } else if (qName.equals(EDGE)) {
              ArrayList<Attr> p = lastProperties.pop();
              for (Attr a: p) {
                    lastEdge.addAttribute(a.name, a.type, a.value.toString());
                }
                lastGraph.lastElement().nestedEdge.add(lastEdge);
                graphSection = true;
            } else if (qName.equals(DATA)) {
                // value is in the buffer
                String value = StringEscapeUtils.unescapeJava(m_sbuf.toString());               

                if (graphSection)
                {
                  Attr a = m_vertData.get(m_key);
                  if (a == null)
                      a = m_edjeData.get(m_key);
                  if (a == null)
                      error("found data tag in wrong position");

                  if (a.name.toLowerCase().compareTo("name") == 0)
                  {
                    lastGraph.lastElement().name = value;
                  }
                } else {
                    Class<?> type;
                  Attr a = m_vertData.get(m_key);                 
                  if (a == null)
                      a = m_edjeData.get(m_key);
                  if (a == null)
                      error("found data tag in wrong position");
                  try {
                    Object val = parse(value, a.type);
                    boolean newattr = true;
                    for (Attr attr :lastProperties.lastElement()) {
                      if (attr.name.equals(a.name)) {
                        attr.value = val;
                        newattr = false;
                      }
                    }
                    if (newattr)
                      lastProperties.lastElement().add(new Attr(a.name, a.type, val));
                  } catch (ParseException ex) {
                      Logger.getLogger(GraphMLDecoder.class.getName()).log(Level.SEVERE, null, ex);
                  }                 
                }
              
            }
        }

        // --------------------------------------------------------------------
        @Override
        public void characters(char[] ch, int start, int length) throws SAXException {
            m_sbuf.append(ch, start, length);
        }

        private void addToSchema() {
            if (m_name == null || m_name.length() == 0) {
                error("Empty " + KEY + " name.");
            }
            if (m_type == null || m_type.length() == 0) {
                error("Empty " + KEY + " type.");
            }

            Class<?> type = parseType(m_type);
            Object dflt = null;
            try {
                dflt = m_dflt == null ? null : parse(m_dflt, type);
            } catch (ParseException ex) {
                Logger.getLogger(GraphMLDecoder.class.getName()).log(Level.SEVERE, null, ex);
            }

            if (m_for == null || m_for.equals(ALL)) {
                m_vertData.put(m_id, new Attr(m_name,type, dflt));
                m_edjeData.put(m_id, new Attr(m_name,type, dflt));
            } else if (m_for.equals(NODE)) {
                m_vertData.put(m_id, new Attr(m_name,type, dflt));
            } else if (m_for.equals(EDGE)) {
                m_edjeData.put(m_id, new Attr(m_name,type, dflt));
            } else {
                error("Unrecognized \"" + FOR + "\" value: " + m_for);
            }

            m_dflt = null;

        }

        private Class<?> parseType(String type) {
            type = type.toLowerCase();
            if (type.equals(INT) || type.equals(INTEGER)) {
                return Integer.class;
            } else if (type.equals(LONG)) {
                return Long.class;
            } else if (type.equals(FLOAT)) {
                return Float.class;
            } else if (type.equals(DOUBLE) || type.equals(REAL)) {
                return Double.class;
            } else if (type.equals(BOOLEAN)) {
                return Boolean.class;
            } else if (type.equals(STRING)) {
                return String.class;
            } else if (type.equals(DATE)) {
                return Date.class;
            } else {
                error("Unrecognized data type: " + type);
                return null;
            }
        }

        private Object parse(String s, Class<?> type) throws ParseException {
            if (type == Integer.class) {
                return Integer.valueOf(s);
            } else if (type == Long.class) {
                return Long.valueOf(s);
            } else if (type == Float.class) {
                return Float.valueOf(s);
            } else if (type == Double.class) {
                return Double.valueOf(s);
            } else if (type == Boolean.class) {
                return Boolean.valueOf(s);
            } else if (type == String.class) {
                return s;
            } else if (type == Date.class) {
                return DateFormat.getInstance().parse(s);               
            }
            return type.cast(s);
        }

        public Integer getGraphID() throws CoreException{
          if (m_graph == null)
            throw new CoreException(error, EnumCriticalityException.FAILED);
            return m_graph.getStorableId();
        }

        private void error(String s) {
            throw new RuntimeException(s);
        }

    } // end of inner class GraphMLHandler
} // end of class XMLGraphReader

TOP

Related Classes of vg.modules.opener.system.GraphMLDecoder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.