mlang@286
|
1 |
/*
|
mlang@286
|
2 |
* Created on Jun 24, 2003
|
mlang@286
|
3 |
*
|
mlang@286
|
4 |
*/
|
mlang@286
|
5 |
package isac.util.genhtml;
|
mlang@286
|
6 |
|
mlang@286
|
7 |
import isac.util.InformationProcessor;
|
mlang@286
|
8 |
|
mlang@286
|
9 |
import java.io.FileWriter;
|
mlang@286
|
10 |
import java.io.IOException;
|
mlang@286
|
11 |
import java.io.InputStream;
|
mlang@286
|
12 |
import java.io.StringReader;
|
mlang@286
|
13 |
import java.util.HashSet;
|
mlang@286
|
14 |
import java.util.Iterator;
|
mlang@286
|
15 |
import java.util.Set;
|
mlang@286
|
16 |
import java.util.StringTokenizer;
|
mlang@286
|
17 |
import java.util.Vector;
|
mlang@286
|
18 |
|
mlang@286
|
19 |
import javax.xml.parsers.DocumentBuilder;
|
mlang@286
|
20 |
import javax.xml.parsers.DocumentBuilderFactory;
|
mlang@286
|
21 |
import javax.xml.parsers.ParserConfigurationException;
|
mlang@286
|
22 |
import javax.xml.transform.Source;
|
mlang@286
|
23 |
import javax.xml.transform.stream.StreamSource;
|
mlang@286
|
24 |
|
mlang@286
|
25 |
import org.w3c.dom.Document;
|
mlang@286
|
26 |
import org.w3c.dom.Element;
|
mlang@286
|
27 |
import org.w3c.dom.NodeList;
|
mlang@286
|
28 |
import org.xml.sax.InputSource;
|
mlang@286
|
29 |
import org.xml.sax.SAXException;
|
mlang@286
|
30 |
|
mlang@286
|
31 |
/**
|
mlang@286
|
32 |
* @author Andreas Griesmayer
|
mlang@286
|
33 |
*
|
mlang@286
|
34 |
*/
|
mlang@286
|
35 |
public class GenHTML {
|
mlang@286
|
36 |
|
mlang@286
|
37 |
static final int PBLTREE_XSL = 1;
|
mlang@286
|
38 |
|
mlang@286
|
39 |
static final int METTREE_XSL = 2;
|
mlang@286
|
40 |
|
mlang@286
|
41 |
static final int EXPTREE_XSL = 3;
|
mlang@286
|
42 |
|
mlang@286
|
43 |
static final int SIMPLE_HIERARCHY_XSL = 4;
|
mlang@286
|
44 |
|
mlang@286
|
45 |
static final int SIMPLE_PBL_NODE = 5;
|
mlang@286
|
46 |
|
mlang@291
|
47 |
static String destination_ = "/home/neuper/proto2/www/kbase/";
|
mlang@286
|
48 |
|
mlang@291
|
49 |
public static void main(String[] argv) {
|
mlang@286
|
50 |
if (argv.length > 0) destination_ = argv[0];
|
mlang@286
|
51 |
GenHTML genhtml = new GenHTML();
|
mlang@286
|
52 |
genhtml.buildHierarchy("met/code.html");
|
mlang@286
|
53 |
genhtml.buildHierarchy("met/index.html");
|
mlang@286
|
54 |
genhtml.buildHierarchy("met/heading.html");
|
mlang@286
|
55 |
genhtml.buildHierarchy("met/menu_empty.html");
|
mlang@286
|
56 |
genhtml.buildHierarchy("met/main.html");
|
mlang@286
|
57 |
|
mlang@286
|
58 |
genhtml.buildHierarchy("pbl/code.html");
|
mlang@286
|
59 |
genhtml.buildHierarchy("pbl/index.html");
|
mlang@286
|
60 |
genhtml.buildHierarchy("pbl/heading.html");
|
mlang@286
|
61 |
genhtml.buildHierarchy("pbl/menu_empty.html");
|
mlang@286
|
62 |
genhtml.buildHierarchy("pbl/main.html");
|
mlang@286
|
63 |
|
mlang@286
|
64 |
genhtml.buildHierarchy("exp/code.html");
|
mlang@286
|
65 |
genhtml.buildHierarchy("exp/index.html");
|
mlang@286
|
66 |
genhtml.buildHierarchy("exp/heading.html");
|
mlang@286
|
67 |
genhtml.buildHierarchy("exp/menu_empty.html");
|
mlang@286
|
68 |
genhtml.buildHierarchy("exp/main.html");
|
mlang@286
|
69 |
|
mlang@286
|
70 |
Set exp_set = genhtml.loadFileList("exp");
|
mlang@286
|
71 |
Iterator exp_it = exp_set.iterator();
|
mlang@286
|
72 |
int index = exp_set.size();
|
mlang@286
|
73 |
while (exp_it.hasNext()) {
|
mlang@286
|
74 |
System.out.println("exp to generate:" + (index--));
|
mlang@286
|
75 |
genhtml.loadContent("exp/" + exp_it.next());
|
mlang@286
|
76 |
}
|
mlang@286
|
77 |
|
mlang@286
|
78 |
Set pbl_set = genhtml.loadFileList("pbl");
|
mlang@286
|
79 |
index = pbl_set.size();
|
mlang@286
|
80 |
Iterator pbl_it = pbl_set.iterator();
|
mlang@286
|
81 |
while (pbl_it.hasNext()) {
|
mlang@286
|
82 |
System.out.println("pbl to generate:" + (index--));
|
mlang@286
|
83 |
genhtml.loadContent("pbl/" + pbl_it.next());
|
mlang@286
|
84 |
}
|
mlang@286
|
85 |
|
mlang@286
|
86 |
Set met_set = genhtml.loadFileList("met");
|
mlang@286
|
87 |
index = met_set.size();
|
mlang@286
|
88 |
Iterator met_it = met_set.iterator();
|
mlang@286
|
89 |
while (met_it.hasNext()) {
|
mlang@286
|
90 |
System.out.println("met to generate:" + (index--));
|
mlang@286
|
91 |
genhtml.loadContent("met/" + met_it.next());
|
mlang@286
|
92 |
}
|
mlang@286
|
93 |
|
mlang@286
|
94 |
}
|
mlang@286
|
95 |
|
mlang@286
|
96 |
Set loadFileList(String type) {
|
mlang@286
|
97 |
Set return_set = new HashSet();
|
mlang@286
|
98 |
try {
|
mlang@286
|
99 |
|
mlang@286
|
100 |
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
mlang@286
|
101 |
DocumentBuilder db = dbf.newDocumentBuilder();
|
mlang@286
|
102 |
String h_xml = InformationProcessor.loadHierarchy("", type);
|
mlang@286
|
103 |
InputSource inputsource = new InputSource(new StringReader(h_xml));
|
mlang@286
|
104 |
Document document = db.parse(inputsource);
|
mlang@286
|
105 |
|
mlang@286
|
106 |
Element doc_elem = document.getDocumentElement();
|
mlang@286
|
107 |
NodeList nodelist = doc_elem.getElementsByTagName("CONTENTREF");
|
mlang@286
|
108 |
for (int index = 0; index < nodelist.getLength(); index++) {
|
mlang@286
|
109 |
return_set.add(nodelist.item(index).getFirstChild()
|
mlang@286
|
110 |
.getNodeValue().trim());
|
mlang@286
|
111 |
}
|
mlang@286
|
112 |
|
mlang@286
|
113 |
nodelist = doc_elem.getElementsByTagName("EXAMPLE");
|
mlang@286
|
114 |
for (int index = 0; index < nodelist.getLength(); index++) {
|
mlang@286
|
115 |
return_set.add(nodelist.item(index).getFirstChild()
|
mlang@286
|
116 |
.getNodeValue().trim());
|
mlang@286
|
117 |
}
|
mlang@286
|
118 |
} catch (ParserConfigurationException e) {
|
mlang@286
|
119 |
e.printStackTrace();
|
mlang@286
|
120 |
} catch (SAXException e) {
|
mlang@286
|
121 |
e.printStackTrace();
|
mlang@286
|
122 |
} catch (IOException e) {
|
mlang@286
|
123 |
e.printStackTrace();
|
mlang@286
|
124 |
}
|
mlang@286
|
125 |
return return_set;
|
mlang@286
|
126 |
}
|
mlang@286
|
127 |
|
mlang@286
|
128 |
/**
|
mlang@286
|
129 |
* Loads all hierarchies which are displayed on the web-browser
|
mlang@286
|
130 |
*/
|
mlang@286
|
131 |
protected void buildHierarchy(String path) {
|
mlang@286
|
132 |
String session = "";
|
mlang@286
|
133 |
StringTokenizer tokens = new StringTokenizer(path, "/");
|
mlang@286
|
134 |
// (String)request.getSession().getAttribute("session_id");
|
mlang@286
|
135 |
// if(session==null)
|
mlang@286
|
136 |
// session="";
|
mlang@286
|
137 |
path = "";
|
mlang@286
|
138 |
String type = tokens.nextToken();
|
mlang@286
|
139 |
|
mlang@286
|
140 |
if (!tokens.hasMoreTokens())
|
mlang@286
|
141 |
path = "/index.html";
|
mlang@286
|
142 |
else
|
mlang@286
|
143 |
while (tokens.hasMoreTokens())
|
mlang@286
|
144 |
path += "/" + tokens.nextToken();
|
mlang@286
|
145 |
try {
|
mlang@286
|
146 |
if (path.endsWith("code.html")) {
|
mlang@286
|
147 |
Vector parameter = new Vector();
|
mlang@286
|
148 |
parameter.add(session);
|
mlang@286
|
149 |
parameter.add(type);
|
mlang@286
|
150 |
Vector result;
|
mlang@286
|
151 |
Source xslSource = null;
|
mlang@286
|
152 |
Source xmlSource = new StreamSource(new StringReader(
|
mlang@286
|
153 |
InformationProcessor.loadHierarchy(session, type)));
|
mlang@286
|
154 |
if (type.equals("pbl"))
|
mlang@286
|
155 |
xslSource = new StreamSource(
|
mlang@286
|
156 |
getClass()
|
mlang@286
|
157 |
.getResourceAsStream(
|
mlang@286
|
158 |
"/isac/util/genhtml/templates/pbl_hierarchy_jmenu.xsl"));
|
mlang@286
|
159 |
else if (type.equals("met"))
|
mlang@286
|
160 |
xslSource = new StreamSource(
|
mlang@286
|
161 |
getClass()
|
mlang@286
|
162 |
.getResourceAsStream(
|
mlang@286
|
163 |
"/isac/util/genhtml/templates/met_hierarchy_jmenu.xsl"));
|
mlang@286
|
164 |
else
|
mlang@286
|
165 |
xslSource = new StreamSource(
|
mlang@286
|
166 |
getClass()
|
mlang@286
|
167 |
.getResourceAsStream(
|
mlang@286
|
168 |
"/isac/util/genhtml/templates/exp_hierarchy_jmenu.xsl"));
|
mlang@286
|
169 |
String header = toString(getClass().getResourceAsStream(
|
mlang@286
|
170 |
"/isac/util/genhtml/templates/codeheader.html"));
|
mlang@286
|
171 |
String footer = toString(getClass().getResourceAsStream(
|
mlang@286
|
172 |
"/isac/util/genhtml/templates/codefooter.html"));
|
mlang@286
|
173 |
|
mlang@286
|
174 |
// Perform the transformation, sending the output to the
|
mlang@286
|
175 |
// response.
|
mlang@286
|
176 |
//java.io.PrintWriter out = response.getWriter();
|
mlang@286
|
177 |
FileWriter out = new FileWriter(destination_ + type + "/"
|
mlang@286
|
178 |
+ path);
|
mlang@286
|
179 |
out.write(header);
|
mlang@286
|
180 |
Encoder.encodeInformation(xslSource, xmlSource, out);
|
mlang@286
|
181 |
out.write(footer);
|
mlang@286
|
182 |
out.close();
|
mlang@286
|
183 |
} else {
|
mlang@286
|
184 |
if (path.trim().endsWith("index.html")) {
|
mlang@286
|
185 |
if (type.equals("pbl")) {
|
mlang@286
|
186 |
path = "index_pbl.html";
|
mlang@286
|
187 |
} else if (type.equals("met"))
|
mlang@286
|
188 |
path = "index_met.html";
|
mlang@286
|
189 |
else
|
mlang@286
|
190 |
path = "index_exp.html";
|
mlang@286
|
191 |
}
|
mlang@286
|
192 |
System.out.println(path);
|
mlang@286
|
193 |
InputStream istream = getClass().getResourceAsStream(
|
mlang@286
|
194 |
"/isac/util/genhtml/jscript/" + path);
|
mlang@286
|
195 |
FileWriter out = new FileWriter(destination_ + type + "/"
|
mlang@286
|
196 |
+ path);
|
mlang@286
|
197 |
int input;
|
mlang@286
|
198 |
while ((input = istream.read()) != -1) {
|
mlang@286
|
199 |
out.write(input);
|
mlang@286
|
200 |
}
|
mlang@286
|
201 |
out.close();
|
mlang@286
|
202 |
}
|
mlang@286
|
203 |
|
mlang@286
|
204 |
} catch (IOException exc) {
|
mlang@286
|
205 |
System.out.println("IOException:" + exc.getMessage());
|
mlang@286
|
206 |
}
|
mlang@286
|
207 |
}
|
mlang@286
|
208 |
|
mlang@286
|
209 |
private String toString(InputStream istream) {
|
mlang@286
|
210 |
StringBuffer buf = new StringBuffer(10000);
|
mlang@286
|
211 |
int input;
|
mlang@286
|
212 |
try {
|
mlang@286
|
213 |
while ((input = istream.read()) != -1) {
|
mlang@286
|
214 |
buf.append((char) input);
|
mlang@286
|
215 |
}
|
mlang@286
|
216 |
} catch (IOException e) {
|
mlang@286
|
217 |
return getErrorXML("Sorry, IOException while accessing the InputStream "
|
mlang@286
|
218 |
+ e.getMessage());
|
mlang@286
|
219 |
}
|
mlang@286
|
220 |
return buf.toString();
|
mlang@286
|
221 |
}
|
mlang@286
|
222 |
|
mlang@286
|
223 |
private static String getErrorXML(String string) {
|
mlang@286
|
224 |
return "<ERROR><DESCRIPTION> <h1> Error in file LoadHierarchy.java </h1>"
|
mlang@286
|
225 |
+ string + "</DESCRIPTION></ERROR>";
|
mlang@286
|
226 |
}
|
mlang@286
|
227 |
|
mlang@286
|
228 |
protected void loadFile(String path) {
|
mlang@286
|
229 |
StringTokenizer tokens = new StringTokenizer(path, "/");
|
mlang@286
|
230 |
// (String)request.getSession().getAttribute("session_id");
|
mlang@286
|
231 |
// if(session==null)
|
mlang@286
|
232 |
// session="";
|
mlang@286
|
233 |
String session_id = "";
|
mlang@286
|
234 |
path = "";
|
mlang@286
|
235 |
String type = (String) tokens.nextToken();
|
mlang@286
|
236 |
|
mlang@286
|
237 |
if (!tokens.hasMoreTokens())
|
mlang@286
|
238 |
path = "/index.html";
|
mlang@286
|
239 |
else
|
mlang@286
|
240 |
while (tokens.hasMoreTokens())
|
mlang@286
|
241 |
path += "/" + tokens.nextToken();
|
mlang@286
|
242 |
try {
|
mlang@286
|
243 |
if (path.endsWith("code.html")) {
|
mlang@286
|
244 |
Vector parameter = new Vector();
|
mlang@286
|
245 |
parameter.add(session_id);
|
mlang@286
|
246 |
parameter.add(type);
|
mlang@286
|
247 |
Vector result;
|
mlang@286
|
248 |
Source xmlSource = new StreamSource(new StringReader(
|
mlang@286
|
249 |
InformationProcessor.loadHierarchy(session_id, type)));
|
mlang@286
|
250 |
|
mlang@286
|
251 |
// Perform the transformation, sending the output to the
|
mlang@286
|
252 |
// response.
|
mlang@286
|
253 |
java.io.FileWriter out = new FileWriter(destination_ + type
|
mlang@286
|
254 |
+ "/" + path);
|
mlang@286
|
255 |
Encoder.encodeHierarchy(type, xmlSource, out);
|
mlang@286
|
256 |
return;
|
mlang@286
|
257 |
} else if (path.trim().endsWith("heading.html")) {
|
mlang@286
|
258 |
java.io.FileWriter out = new FileWriter(destination_ + type
|
mlang@286
|
259 |
+ "/" + path);
|
mlang@286
|
260 |
out.write(getHeader(session_id));
|
mlang@286
|
261 |
return;
|
mlang@286
|
262 |
} else if (path.trim().endsWith("treecontent.html")) {
|
mlang@286
|
263 |
Vector parameter = new Vector();
|
mlang@286
|
264 |
parameter.add(session_id);
|
mlang@286
|
265 |
parameter.add(type);
|
mlang@286
|
266 |
Vector result;
|
mlang@286
|
267 |
Source xmlSource = new StreamSource(new StringReader(
|
mlang@286
|
268 |
InformationProcessor.loadHierarchy(session_id, type)));
|
mlang@286
|
269 |
|
mlang@286
|
270 |
// Perform the transformation, sending the output to the
|
mlang@286
|
271 |
// response.
|
mlang@286
|
272 |
java.io.FileWriter out = new FileWriter(destination_ + type
|
mlang@286
|
273 |
+ "/" + path);
|
mlang@286
|
274 |
|
mlang@286
|
275 |
Encoder.encodeHContent(type, xmlSource, out);
|
mlang@286
|
276 |
return;
|
mlang@286
|
277 |
}
|
mlang@286
|
278 |
//TODO this type should not result in different files but in an
|
mlang@286
|
279 |
// autogeneration of a fitting file
|
mlang@286
|
280 |
if (path.trim().endsWith("index.html")) {
|
mlang@286
|
281 |
if (type.equals("pbl")) {
|
mlang@286
|
282 |
path = "index_pbl.html";
|
mlang@286
|
283 |
} else if (type.equals("met"))
|
mlang@286
|
284 |
path = "index_met.html";
|
mlang@286
|
285 |
else
|
mlang@286
|
286 |
path = "index_exp.html";
|
mlang@286
|
287 |
}
|
mlang@286
|
288 |
InputStream istream = getClass().getResourceAsStream(
|
mlang@286
|
289 |
"/isac/BrowserServlet/jscript/" + path);
|
mlang@286
|
290 |
java.io.FileWriter out = new FileWriter(destination_ + type + "/"
|
mlang@286
|
291 |
+ path);
|
mlang@286
|
292 |
int input;
|
mlang@286
|
293 |
while ((input = istream.read()) != -1) {
|
mlang@286
|
294 |
out.write(input);
|
mlang@286
|
295 |
}
|
mlang@286
|
296 |
|
mlang@286
|
297 |
} catch (IOException exc) {
|
mlang@286
|
298 |
System.out.println("bla");
|
mlang@286
|
299 |
}
|
mlang@286
|
300 |
}
|
mlang@286
|
301 |
|
mlang@286
|
302 |
private String getHeader(String session_id) {
|
mlang@286
|
303 |
String headercontent = "<html>"
|
mlang@286
|
304 |
+ "<body>"
|
mlang@286
|
305 |
+ "<a href=\"../../isac.BrowserServlet.Login\" target=\"text\">"
|
mlang@286
|
306 |
+ " login </a>"
|
mlang@286
|
307 |
+ " "
|
mlang@286
|
308 |
+ "<a href=\"../../isac.BrowserServlet.Logout\" target=\"text\">"
|
mlang@286
|
309 |
+ " logout </a>"
|
mlang@286
|
310 |
+ "<br> <a href=\"../../isac.BrowserServlet.LoadFile/pbl/index.html\" target=\"_top\">PBLHierarchy</a>"
|
mlang@286
|
311 |
+ " <a href=\"../../isac.BrowserServlet.LoadFile/met/index.html\" target=\"_top\">METHierarchy</a>"
|
mlang@286
|
312 |
+ " <a href=\"../../isac.BrowserServlet.LoadFile/exp/index.html\" target=\"_top\">ExampleHierarchy</a>"
|
mlang@286
|
313 |
+ " ";
|
mlang@286
|
314 |
|
mlang@286
|
315 |
String username;
|
mlang@286
|
316 |
if ((username = InformationProcessor.getUsername(session_id)) == null)
|
mlang@286
|
317 |
headercontent += "not logged in";
|
mlang@286
|
318 |
else
|
mlang@286
|
319 |
headercontent += " welcome <b>" + username + "</b>";
|
mlang@286
|
320 |
headercontent += "</body> </html>";
|
mlang@286
|
321 |
return headercontent;
|
mlang@286
|
322 |
}
|
mlang@286
|
323 |
|
mlang@286
|
324 |
protected void loadContent(String path) {
|
mlang@286
|
325 |
StringTokenizer tokens = new StringTokenizer(path, "/");
|
mlang@286
|
326 |
|
mlang@286
|
327 |
String session = "";
|
mlang@286
|
328 |
|
mlang@286
|
329 |
Vector parameter = new Vector();
|
mlang@286
|
330 |
parameter.add(session);
|
mlang@286
|
331 |
try {
|
mlang@286
|
332 |
Source xslSource = null;
|
mlang@286
|
333 |
Source xmlSource = null;
|
mlang@286
|
334 |
|
mlang@286
|
335 |
String command = tokens.nextToken();
|
mlang@286
|
336 |
String header = "<?xml version=\"1.0\"?> \n"
|
mlang@286
|
337 |
+ "<?xml-stylesheet href=\"http://pear.math.pitt.edu/mathzilla/Examples/mml.css\" type=\"text/css\"?>\n"
|
mlang@286
|
338 |
+ "<!DOCTYPE html SYSTEM \"mathml.dtd_\">\n" +
|
mlang@286
|
339 |
//"<?xml-stylesheet type=\"text/xsl\"
|
mlang@286
|
340 |
// href=\"http://www.w3.org/Math/XSL/pmathml.xsl\"?>\n"+
|
mlang@286
|
341 |
//" <HTML xmlns=\"http://www.w3.org/1999/xhtml\">\n"+
|
mlang@286
|
342 |
"<HTML xmlns=\"http://www.w3.org/1999/xhtml\"\n"
|
mlang@286
|
343 |
+ "xmlns:math=\"http://www.w3.org/1998/Math/MathML\"\n"
|
mlang@286
|
344 |
+ "xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n"
|
mlang@286
|
345 |
+ "<BODY>";
|
mlang@286
|
346 |
|
mlang@286
|
347 |
String footer = "</BODY>\n</HTML>";
|
mlang@286
|
348 |
// if(command.equals("pbl-node")){
|
mlang@286
|
349 |
FileWriter out;
|
mlang@286
|
350 |
parameter.add(command);
|
mlang@286
|
351 |
if (!tokens.hasMoreElements()) {
|
mlang@286
|
352 |
out = new FileWriter(destination_ + path + ".html");
|
mlang@286
|
353 |
out.write(header);
|
mlang@286
|
354 |
out.write("no details");
|
mlang@286
|
355 |
out.write(footer);
|
mlang@286
|
356 |
return;
|
mlang@286
|
357 |
}
|
mlang@286
|
358 |
String contentfile = tokens.nextToken();
|
mlang@286
|
359 |
parameter.add(contentfile);
|
mlang@286
|
360 |
|
mlang@286
|
361 |
if (!contentfile.trim().endsWith(".xml")) { return; }
|
mlang@286
|
362 |
out = new FileWriter(destination_ + path + ".html");
|
mlang@291
|
363 |
xmlSource = new StreamSource(new StringReader(InformationProcessor
|
mlang@291
|
364 |
.loadXML(session, command, contentfile)));
|
mlang@286
|
365 |
xslSource = new StreamSource(getClass().getResourceAsStream(
|
mlang@286
|
366 |
"/isac/util/genhtml/templates/pbl_node_content.xsl"));
|
mlang@286
|
367 |
// }
|
mlang@286
|
368 |
// Perform the transformation, sending the output to the response.
|
mlang@286
|
369 |
out.write(header);
|
mlang@286
|
370 |
Encoder.encodeInformation(xslSource, xmlSource, out);
|
mlang@286
|
371 |
out.write(footer);
|
mlang@286
|
372 |
} catch (IOException exc) {
|
mlang@286
|
373 |
exc.printStackTrace();
|
mlang@286
|
374 |
}
|
mlang@286
|
375 |
// arg1.getWriter().print("pathinfo: "+arg0.getPathInfo()+"\n
|
mlang@286
|
376 |
// transl:"+arg0.getPathTranslated());
|
mlang@286
|
377 |
}
|
mlang@286
|
378 |
|
mlang@286
|
379 |
} |