1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package net.sourceforge.schemaspy.view;
20
21 import java.io.BufferedReader;
22 import java.io.File;
23 import java.io.FileReader;
24 import java.io.IOException;
25 import java.io.InputStream;
26 import java.io.InputStreamReader;
27 import java.io.Reader;
28 import java.util.ArrayList;
29 import java.util.HashMap;
30 import java.util.List;
31 import java.util.Map;
32 import java.util.NoSuchElementException;
33 import java.util.StringTokenizer;
34 import net.sourceforge.schemaspy.Config;
35 import net.sourceforge.schemaspy.model.InvalidConfigurationException;
36 import net.sourceforge.schemaspy.util.LineWriter;
37
38
39
40
41
42
43
44
45
46 public class StyleSheet {
47 private static StyleSheet instance;
48 private final String css;
49 private String bodyBackgroundColor;
50 private String tableHeadBackgroundColor;
51 private String tableBackgroundColor;
52 private String linkColor;
53 private String linkVisitedColor;
54 private String primaryKeyBackgroundColor;
55 private String indexedColumnBackgroundColor;
56 private String selectedTableBackgroundColor;
57 private String excludedColumnBackgroundColor;
58 private final List<String> ids = new ArrayList<String>();
59
60 private StyleSheet(BufferedReader cssReader) throws IOException {
61 String lineSeparator = System.getProperty("line.separator");
62 StringBuilder data = new StringBuilder();
63 String line;
64
65 while ((line = cssReader.readLine()) != null) {
66 data.append(line);
67 data.append(lineSeparator);
68 }
69
70 css = data.toString();
71
72 int startComment = data.indexOf("/*");
73 while (startComment != -1) {
74 int endComment = data.indexOf("*/");
75 data.replace(startComment, endComment + 2, "");
76 startComment = data.indexOf("/*");
77 }
78
79 StringTokenizer tokenizer = new StringTokenizer(data.toString(), "{}");
80 String id = null;
81 while (tokenizer.hasMoreTokens()) {
82 String token = tokenizer.nextToken().trim();
83 if (id == null) {
84 id = token.toLowerCase();
85 ids.add(id);
86 } else {
87 Map<String, String> attribs = parseAttributes(token);
88 if (id.equals(".content"))
89 bodyBackgroundColor = attribs.get("background");
90 else if (id.equals("th"))
91 tableHeadBackgroundColor = attribs.get("background-color");
92 else if (id.equals("td"))
93 tableBackgroundColor = attribs.get("background-color");
94 else if (id.equals(".primarykey"))
95 primaryKeyBackgroundColor = attribs.get("background");
96 else if (id.equals(".indexedcolumn"))
97 indexedColumnBackgroundColor = attribs.get("background");
98 else if (id.equals(".selectedtable"))
99 selectedTableBackgroundColor = attribs.get("background");
100 else if (id.equals(".excludedcolumn"))
101 excludedColumnBackgroundColor = attribs.get("background");
102 else if (id.equals("a:link"))
103 linkColor = attribs.get("color");
104 else if (id.equals("a:visited"))
105 linkVisitedColor = attribs.get("color");
106 id = null;
107 }
108 }
109 }
110
111
112
113
114
115
116
117 public static StyleSheet getInstance() throws ParseException {
118 if (instance == null) {
119 try {
120 instance = new StyleSheet(new BufferedReader(getReader(Config.getInstance().getCss())));
121 } catch (IOException exc) {
122 throw new ParseException(exc);
123 }
124 }
125
126 return instance;
127 }
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143 private static Reader getReader(String cssName) throws IOException {
144 File cssFile = new File(cssName);
145 if (cssFile.exists())
146 return new FileReader(cssFile);
147 cssFile = new File(System.getProperty("user.dir"), cssName);
148 if (cssFile.exists())
149 return new FileReader(cssFile);
150
151 InputStream cssStream = StyleSheet.class.getClassLoader().getResourceAsStream(cssName);
152 if (cssStream == null)
153 throw new ParseException("Unable to find requested style sheet: " + cssName);
154
155 return new InputStreamReader(cssStream);
156 }
157
158 private Map<String, String> parseAttributes(String data) {
159 Map<String, String> attribs = new HashMap<String, String>();
160
161 try {
162 StringTokenizer attrTokenizer = new StringTokenizer(data, ";");
163 while (attrTokenizer.hasMoreTokens()) {
164 StringTokenizer pairTokenizer = new StringTokenizer(attrTokenizer.nextToken(), ":");
165 String attribute = pairTokenizer.nextToken().trim().toLowerCase();
166 String value = pairTokenizer.nextToken().trim().toLowerCase();
167 attribs.put(attribute, value);
168 }
169 } catch (NoSuchElementException badToken) {
170 System.err.println("Failed to extract attributes from '" + data + "'");
171 throw badToken;
172 }
173
174 return attribs;
175 }
176
177
178
179
180
181
182
183 public void write(LineWriter out) throws IOException {
184 out.write(css);
185 }
186
187 public String getBodyBackground() {
188 if (bodyBackgroundColor == null)
189 throw new MissingCssPropertyException(".content", "background");
190
191 return bodyBackgroundColor;
192 }
193
194 public String getTableBackground() {
195 if (tableBackgroundColor == null)
196 throw new MissingCssPropertyException("td", "background-color");
197
198 return tableBackgroundColor;
199 }
200
201 public String getTableHeadBackground() {
202 if (tableHeadBackgroundColor == null)
203 throw new MissingCssPropertyException("th", "background-color");
204
205 return tableHeadBackgroundColor;
206 }
207
208 public String getPrimaryKeyBackground() {
209 if (primaryKeyBackgroundColor == null)
210 throw new MissingCssPropertyException(".primaryKey", "background");
211
212 return primaryKeyBackgroundColor;
213 }
214
215 public String getIndexedColumnBackground() {
216 if (indexedColumnBackgroundColor == null)
217 throw new MissingCssPropertyException(".indexedColumn", "background");
218
219 return indexedColumnBackgroundColor;
220 }
221
222 public String getSelectedTableBackground() {
223 if (selectedTableBackgroundColor == null)
224 throw new MissingCssPropertyException(".selectedTable", "background");
225
226 return selectedTableBackgroundColor;
227 }
228
229 public String getExcludedColumnBackgroundColor() {
230 if (excludedColumnBackgroundColor == null)
231 throw new MissingCssPropertyException(".excludedColumn", "background");
232
233 return excludedColumnBackgroundColor;
234 }
235
236 public String getLinkColor() {
237 if (linkColor == null)
238 throw new MissingCssPropertyException("a:link", "color");
239
240 return linkColor;
241 }
242
243 public String getLinkVisitedColor() {
244 if (linkVisitedColor == null)
245 throw new MissingCssPropertyException("a:visited", "color");
246
247 return linkVisitedColor;
248 }
249
250
251
252
253 public static class MissingCssPropertyException extends InvalidConfigurationException {
254 private static final long serialVersionUID = 1L;
255
256
257
258
259
260 public MissingCssPropertyException(String cssSection, String propName) {
261 super("Required property '" + propName + "' was not found for the definition of '" + cssSection + "' in " + Config.getInstance().getCss());
262 }
263 }
264
265
266
267
268 public static class ParseException extends InvalidConfigurationException {
269 private static final long serialVersionUID = 1L;
270
271
272
273
274 public ParseException(Exception cause) {
275 super(cause);
276 }
277
278
279
280
281 public ParseException(String msg) {
282 super(msg);
283 }
284 }
285 }