View Javadoc

1   package net.sf.quarrel.file;
2   
3   import org.apache.commons.lang.StringUtils;
4   import org.apache.commons.logging.Log;
5   import org.apache.commons.logging.LogFactory;
6   
7   import java.io.IOException;
8   import java.io.InputStream;
9   import java.io.InputStreamReader;
10  import java.io.LineNumberReader;
11  import java.util.Iterator;
12  
13  /***
14   * This class is responsible for parsing an InputStream and reporting all
15   * discovered elements to the ElementCollector.  The element collector will
16   * build a model from the values discovered.  This will sperate the knowledge
17   * of the file structure from the object model used to represent it.
18   * <p/>
19   * There are some potential problems with this class right now.
20   * <ul>
21   * <li>it has more knowldge about UML than it should.  Ideally, it would only
22   * know about idents and such.  But right now, I'm not sure how to make it work
23   * without checking for key words</li>
24   * <li>the code is checking for an indent of zero to link the case
25   * of two class header on adjacent line.  if I can fix the problem mentioned
26   * above, then this problem will probably be fixed as well.</li>
27   * </ul>
28   * </p>
29   */
30  public class StreamParser {
31  
32      private final static Log LOG = LogFactory.getLog(StreamParser.class);
33  
34      private final ElementCollector _elementCollector;
35      private InputStream _inputStream;
36  
37      /***
38       * Create a new StreamParse for the specified InputStream.  Call parse() to
39       * to perform the parsing and then call the elements() method to get the
40       * results.
41       *
42       * @param source the InputStream to parse
43       * @see #parse()
44       * @see #elements()
45       */
46      public StreamParser(final InputStream source) {
47          _elementCollector = new ElementCollector();
48          _inputStream = source;
49      }
50  
51      /***
52       * Parses the InputStream provided and reports all discovered data to the
53       * collector.
54       *
55       * @param inputStream the InputStream to parse
56       * @throws IOException      if there are any parsing errors
57       * @throws ParsingException if the file structure is not valid
58       * @deprecated use #parse() instead.  this method will be made private.
59       */
60      private void parse(final InputStream inputStream)
61              throws IOException, ParsingException {
62  
63          final InputStreamReader isr = new InputStreamReader(inputStream);
64          final LineNumberReader br = new LineNumberReader(isr);
65  
66          int indent = 0;
67  
68          String line;
69  
70          boolean firstLine = true;
71  
72          while ((line = br.readLine()) != null) {
73  
74              if (StringUtils.isEmpty(line.trim())) {
75                  continue;
76              }
77  
78              final int lineNumber = br.getLineNumber();
79  
80              LOG.debug("[" + lineNumber + "][" + determinIndent(line) + "]" + line);
81  
82              if (firstLine) {
83                  _elementCollector.push(line);
84                  firstLine = false;
85                  indent = determinIndent(line);
86              } else {
87  
88                  final int newIndent = determinIndent(line);
89  
90                  LOG.debug("newIndent = " + newIndent);
91                  String value = line.trim();
92  
93                  if (newIndent > indent) {
94  
95                      final FeatureType type = FeatureType.getEnum(value);
96                      if (type != null) {
97                          _elementCollector.push(value);
98                      } else {
99                          _elementCollector.add(value);
100                     }
101 
102                 } else if (newIndent == indent) {
103 
104                     if (indent == 0) {
105                         _elementCollector.pop();
106                         _elementCollector.push(value);
107                     } else {
108                         _elementCollector.add(value);
109                     }
110 
111                 } else { // newIndent < indent
112 
113                     _elementCollector.pop();
114 
115                     final FeatureType type = FeatureType.getEnum(value);
116 
117                     if (type != null) {
118                         _elementCollector.push(value);
119                     } else {
120                         _elementCollector.pop();
121                         _elementCollector.push(value);
122                     }
123 
124                 }
125 
126                 indent = newIndent;
127 
128             }
129 
130 //
131 
132 //
133 //            }
134 
135         }
136 
137         _elementCollector.finish();
138 
139     }
140 
141     private int determinIndent(final String line) {
142 
143         int i = 0;
144 
145         while ((line.charAt(i)) == ' ') {
146             i++;
147         }
148 
149         return i;
150     }
151 
152     public void parse() throws IOException, ParsingException {
153         parse(_inputStream);
154     }
155 
156     public Iterator elements() {
157         return _elementCollector.elements();
158     }
159 }