1
2
3 package net.sourceforge.sql2java;
4
5 import java.io.BufferedReader;
6 import java.io.File;
7 import java.io.FileReader;
8 import java.util.Enumeration;
9 import java.util.Hashtable;
10
11 /**
12 * Parses an existing source file for special sql2code comment blocks.
13 * <br>
14 * Stores the source code that it finds in between those blocks in a
15 * hashtable. This allows CodeWriter classes to rewrite existing files
16 * while preserving code written by the user.
17 *
18 * @author James Cooper <pixel@bitmechanic.com>
19 * @version $Id: UserCodeParser.java,v 1.3 2007/07/13 13:18:29 kameleono Exp $
20 */
21 public class UserCodeParser {
22
23 private static final String START = "// ";
24 private static final String BLOCK_BEGIN = "+";
25 private static final String BLOCK_END = "-";
26
27 private String LINE_SEP = System.getProperty("line.separator");
28 private Hashtable codeHash;
29 private String filename;
30 private boolean isNew;
31
32 /**
33 * Constructs a new parser, and tells the parser to try to load the
34 * given filename.
35 * <br>
36 * If the file does not exist, the parser will simply initialize a
37 * new hashtable internally, and the get methods on the parser will
38 * return new comment blocks (with nothing in between them).
39 *
40 * @param filename Full path to the existing file to parse.
41 * @throws Exception if the existing file exists, but cannot be read,
42 * or if there is an error while reading the file
43 */
44 public UserCodeParser(String filename) throws Exception {
45 parse(filename);
46 }
47
48 /**
49 * Returns the filename associated with this parser.
50 */
51 public String getFilename() { return filename; }
52
53 /**
54 * Returns true if the file to parse did not exist.
55 */
56 public boolean isNew() { return isNew; }
57
58 /**
59 * Parses the file passed in.
60 */
61 public void parse(String parsedFileName) throws Exception {
62 codeHash = new Hashtable();
63 boolean inBlock = false;
64 String blockName = null;
65 StringBuffer code = new StringBuffer();
66 isNew = true;
67
68 File file = new File(parsedFileName);
69 if(file.exists()) {
70 filename = parsedFileName;
71 isNew = false;
72 BufferedReader reader = new BufferedReader(new FileReader(file));
73 String line = reader.readLine();
74 while(line != null) {
75 if(inBlock) code.append(line).append(LINE_SEP);
76
77 if(line.indexOf(START) != -1) {
78 if(inBlock) {
79 if(line.equals(START + blockName + BLOCK_END)) {
80
81
82 codeHash.put(blockName, code.toString());
83 inBlock = false;
84 }
85 }
86 else {
87 blockName = parseName(line);
88 if(!blockName.equals("")) {
89 inBlock = true;
90 code.setLength(0);
91 code.append(line).append(LINE_SEP);
92 }
93 }
94 }
95
96 line = reader.readLine();
97 }
98 reader.close();
99 }
100 }
101
102 private String parseName(String line) {
103 int startPos = line.indexOf(START);
104 if(startPos == -1) return "";
105 startPos += START.length();
106
107 if(startPos >= (line.length() + 1)) return "";
108
109 int endPos = line.lastIndexOf(BLOCK_BEGIN, startPos);
110 if(endPos != line.length()-BLOCK_BEGIN.length()) return "";
111 else {
112 String name = line.substring(startPos, endPos);
113 return name.trim();
114 }
115 }
116
117 /**
118 * Returns true if there is a block with the given name in the
119 * existing file that was parsed, otherwise returns false.
120 *
121 * @param name Name of the code block to check for.
122 */
123 public boolean hasBlock(String name) {
124 return codeHash.get(name) != null;
125 }
126
127 /**
128 * Returns the comment+code block associated with this name.
129 * <br>
130 * If the name is not found in the parsed file, this returns a new
131 * comment block with no code inside it.
132 *
133 * @param name Name of the code block to return.
134 */
135 public String getBlock(String name) {
136 String code = null;
137 if (name != null) code = (String)codeHash.get(name);
138 if(code == null) {
139 code = generateNewBlock(name);
140 codeHash.put(name, code);
141 }
142 return code;
143 }
144
145 /**
146 * Returns an array of the block names parsed in the existing file.
147 * <br>
148 * If the file did not exist, or if there are no blocks in the file,
149 * a zero length array is returned.
150 */
151 public String[] getBlockNames() {
152 String list[] = new String[codeHash.size()];
153 int i = 0;
154 for(Enumeration e = codeHash.keys(); e.hasMoreElements(); ) {
155 list[i++] = (String)e.nextElement();
156 }
157
158 return list;
159 }
160
161 /**
162 * Generates a new code block with this name.
163 */
164 private String generateNewBlock(String name) {
165 StringBuffer str = new StringBuffer(512);
166 str.append(START);
167 str.append(name);
168 str.append(BLOCK_BEGIN);
169 str.append(LINE_SEP).append(LINE_SEP);
170 str.append(START);
171 str.append(name);
172 str.append(BLOCK_END);
173
174 return str.toString();
175 }
176 }