001    /*
002     * TemplateParser.java
003     *
004     * Developed for the "Rethinking CS101" project. See http://www.cs101.org, the
005     * CS101 homepage or email las@olin.edu.
006     *
007     * Please do not redistribute without obtaining permission.
008     * Created on January 8, 2004, 2:53 PM
009     */
010    
011    package nodenet;
012    
013    import org.xml.sax.XMLReader;
014    import org.xml.sax.Attributes;
015    import org.xml.sax.InputSource;
016    import org.xml.sax.SAXException;
017    import org.xml.sax.helpers.DefaultHandler;
018    
019    import java.io.FileNotFoundException;
020    import java.io.FileReader;
021    import java.io.IOException;
022    
023    import java.util.List;
024    import java.util.Vector;
025    import java.util.HashMap;
026    import java.util.ArrayList;
027    
028    import javax.xml.parsers.SAXParser;
029    import javax.xml.parsers.SAXParserFactory;
030    import javax.xml.parsers.ParserConfigurationException;
031    
032    import cs101.xml.SimpleErrorHandler;
033    
034    
035    
036    
037    /**
038     * A class for reading a template file and converting it into a List
039     * of {@link NodeNetElement}.
040     *
041     * @author  Patrick G. Heck, gus.heck@olin.edu
042     * @version $Id: TemplateParser.java,v 1.4 2004/01/14 21:43:17 gus Exp $
043     */
044    public class TemplateParser {
045        
046        private NodeBehaviorProvider provider;
047        private List elements;
048        private List warnings;
049        
050        /** Creates a new instance of TemplateParser */
051        public TemplateParser(NodeBehaviorProvider provider) {
052            this.provider = provider;
053        }
054        
055        public List parse(String fName) throws FileNotFoundException,
056        ParserConfigurationException, SAXException {
057            this.warnings = new ArrayList();
058            
059            elements = new Vector();
060            FileReader fr = new FileReader(fName);
061            InputSource is = new InputSource(fr);
062            is.setSystemId(DTDResolver.KLUDGE);
063            
064            SAXParserFactory spf = SAXParserFactory.newInstance();
065            spf.setValidating(true);
066            SAXParser parser = spf.newSAXParser();
067            XMLReader xRead = parser.getXMLReader();
068            xRead.setErrorHandler(new SimpleErrorHandler());
069            xRead.setContentHandler(new myContentHandler());
070            xRead.setEntityResolver(new DTDResolver());
071            try {
072                xRead.parse(is);
073                fr.close();
074            } catch (IOException ioe) {
075                throw new SAXException(ioe);
076            }
077            
078            return elements;
079        }
080        
081        /**
082         * Getter for property warnings.
083         *
084         * @return Value of property warnings.
085         */
086        public java.util.List getWarnings() {
087            return warnings;
088        }
089        
090        /**
091         * Add a message to the warnings.
092         */
093        
094        private void warn(String msg) {
095            warnings.add(msg);
096        }
097        
098        private class myContentHandler extends DefaultHandler {
099            
100            /**
101             * keep track of what ID was assigned to the node created
102             * and relate it to the ID in the file with this map.
103             */
104            HashMap nodeMap = new HashMap();
105            
106            public void startElement(String uri, String localName,
107            String qname, Attributes attributes) throws SAXException {
108                
109                if ("node".equals(qname)) {
110                    String idVal = attributes.getValue("id");
111                    
112                    String nbVal = attributes.getValue("type");
113                    String xVal = attributes.getValue("x");
114                    String yVal = attributes.getValue("y");
115                    String showVal = attributes.getValue("showName");
116                    String enabledVal = attributes.getValue("enabled");
117                    
118                    String name = attributes.getValue("name"); // no conversion
119                    
120                    idVal = idVal.replaceFirst("node", "");
121                    Integer id = new Integer(idVal);
122                    int x = new Integer(xVal).intValue();
123                    int y = new Integer(yVal).intValue();
124                    boolean show = new Boolean(showVal).booleanValue();
125                    boolean enabled = new Boolean(enabledVal).booleanValue();
126                    
127                    Class nb = null;
128                    if ("Generator".equals(nbVal)) {
129                        nb = GeneratorNodeBehavior.class;
130                    }
131                    
132                    if ("Terminator".equals(nbVal)) {
133                        nb = TerminatorNodeBehavior.class;
134                    }
135                    
136                    if (nb == null) {
137                        nbVal = nbVal.replaceFirst("Behavior", "");
138                        int n = new Integer(nbVal).intValue();
139                        int numBehaviors = provider.getNodeBehaviors().length;
140                        if (n >= numBehaviors) {
141                            Class substitution = TemplateParser.
142                            this.provider.getNodeBehaviors()[0];
143                            TemplateParser.this.warn( "Template has more node " +
144                            "types than you have loaded.\n" + substitution.getName() +
145                            " has been substituted for the missing node type(s).");
146                            nb = substitution;
147                        } else {
148                            nb = provider.getNodeBehaviors()[n];
149                        }
150                    }
151                    
152                    Node n = new Node(nb, x, y, name, show, enabled);
153                    nodeMap.put(id, n);
154                    TemplateParser.this.elements.add(n);
155                }
156                
157                if ("channel".equals(qname)) {
158                    String startVal = attributes.getValue("start");
159                    String endVal = attributes.getValue("end");
160                    String latencyVal = attributes.getValue("latency");
161                    String capacityVal = attributes.getValue("capacity");
162                    String enabledVal = attributes.getValue("enabled");
163                    
164                    int latency = new Integer(latencyVal).intValue();
165                    int capacity = new Integer(capacityVal).intValue();
166                    boolean enabled = new Boolean(enabledVal).booleanValue();
167                    
168                    startVal = startVal.replaceFirst("node", "");
169                    Integer startID = new Integer(startVal);
170                    Node start = (Node) nodeMap.get(startID);
171                    
172                    endVal = endVal.replaceFirst("node", "");
173                    Integer endID = new Integer(endVal);
174                    Node end = (Node) nodeMap.get(endID);
175                    
176                    Channel chan = null;
177                    try {
178                        chan = new Channel(start, end, enabled,
179                        latency, capacity);
180                    } catch (SameNodeException sne) {
181                        throw new SAXException(sne);
182                    }
183                    TemplateParser.this.elements.add(chan);
184                }
185                
186            }
187        }
188    }