1 |
17
|
jones
|
/**
|
2 |
203
|
jones
|
* '$RCSfile$'
|
3 |
|
|
* Purpose: A Class that handles the SAX XML events as they
|
4 |
|
|
* are generated from XML documents
|
5 |
|
|
* Copyright: 2000 Regents of the University of California and the
|
6 |
|
|
* National Center for Ecological Analysis and Synthesis
|
7 |
|
|
* Authors: Matt Jones, Jivka Bojilova
|
8 |
17
|
jones
|
*
|
9 |
203
|
jones
|
* '$Author$'
|
10 |
|
|
* '$Date$'
|
11 |
|
|
* '$Revision$'
|
12 |
669
|
jones
|
*
|
13 |
|
|
* This program is free software; you can redistribute it and/or modify
|
14 |
|
|
* it under the terms of the GNU General Public License as published by
|
15 |
|
|
* the Free Software Foundation; either version 2 of the License, or
|
16 |
|
|
* (at your option) any later version.
|
17 |
|
|
*
|
18 |
|
|
* This program is distributed in the hope that it will be useful,
|
19 |
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
20 |
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
21 |
|
|
* GNU General Public License for more details.
|
22 |
|
|
*
|
23 |
|
|
* You should have received a copy of the GNU General Public License
|
24 |
|
|
* along with this program; if not, write to the Free Software
|
25 |
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
26 |
17
|
jones
|
*/
|
27 |
|
|
|
28 |
75
|
jones
|
package edu.ucsb.nceas.metacat;
|
29 |
51
|
jones
|
|
30 |
6606
|
leinfelder
|
import java.sql.PreparedStatement;
|
31 |
2076
|
jones
|
import java.sql.ResultSet;
|
32 |
|
|
import java.sql.Statement;
|
33 |
6595
|
leinfelder
|
import java.util.Date;
|
34 |
2076
|
jones
|
import java.util.EmptyStackException;
|
35 |
|
|
import java.util.Enumeration;
|
36 |
|
|
import java.util.Hashtable;
|
37 |
|
|
import java.util.Stack;
|
38 |
|
|
import java.util.Vector;
|
39 |
|
|
|
40 |
5015
|
daigle
|
import edu.ucsb.nceas.metacat.database.DBConnection;
|
41 |
|
|
import edu.ucsb.nceas.metacat.database.DBConnectionPool;
|
42 |
5030
|
daigle
|
import edu.ucsb.nceas.metacat.properties.PropertyService;
|
43 |
4425
|
daigle
|
import edu.ucsb.nceas.metacat.service.XMLSchema;
|
44 |
4698
|
daigle
|
import edu.ucsb.nceas.metacat.util.MetacatUtil;
|
45 |
7403
|
leinfelder
|
import edu.ucsb.nceas.utilities.triple.Triple;
|
46 |
|
|
import edu.ucsb.nceas.utilities.triple.TripleCollection;
|
47 |
4080
|
daigle
|
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
|
48 |
4425
|
daigle
|
import edu.ucsb.nceas.utilities.StringUtil;
|
49 |
1590
|
tao
|
|
50 |
2663
|
sgarg
|
import org.apache.log4j.Logger;
|
51 |
185
|
jones
|
import org.xml.sax.Attributes;
|
52 |
|
|
import org.xml.sax.SAXException;
|
53 |
204
|
jones
|
import org.xml.sax.SAXParseException;
|
54 |
186
|
jones
|
import org.xml.sax.ext.DeclHandler;
|
55 |
185
|
jones
|
import org.xml.sax.ext.LexicalHandler;
|
56 |
|
|
import org.xml.sax.helpers.DefaultHandler;
|
57 |
17
|
jones
|
|
58 |
1359
|
tao
|
/**
|
59 |
31
|
jones
|
* A database aware Class implementing callback bethods for the SAX parser to
|
60 |
2076
|
jones
|
* call when processing the XML stream and generating events.
|
61 |
31
|
jones
|
*/
|
62 |
2076
|
jones
|
public class DBSAXHandler extends DefaultHandler implements LexicalHandler,
|
63 |
2730
|
sgarg
|
DeclHandler
|
64 |
2076
|
jones
|
{
|
65 |
17
|
jones
|
|
66 |
2076
|
jones
|
protected boolean atFirstElement;
|
67 |
17
|
jones
|
|
68 |
2076
|
jones
|
protected boolean processingDTD;
|
69 |
220
|
jones
|
|
70 |
2076
|
jones
|
protected String docname = null;
|
71 |
17
|
jones
|
|
72 |
2076
|
jones
|
protected String doctype;
|
73 |
2620
|
tao
|
|
74 |
|
|
protected String catalogid = null;
|
75 |
1359
|
tao
|
|
76 |
2076
|
jones
|
protected String systemid;
|
77 |
1359
|
tao
|
|
78 |
2076
|
jones
|
private boolean stackCreated = false;
|
79 |
1359
|
tao
|
|
80 |
4470
|
daigle
|
protected Stack<DBSAXNode> nodeStack;
|
81 |
203
|
jones
|
|
82 |
4470
|
daigle
|
protected Vector<DBSAXNode> nodeIndex;
|
83 |
72
|
bojilova
|
|
84 |
2076
|
jones
|
protected DBConnection connection = null;
|
85 |
|
|
|
86 |
|
|
protected DocumentImpl currentDocument;
|
87 |
2620
|
tao
|
|
88 |
6595
|
leinfelder
|
protected Date createDate = null;
|
89 |
2620
|
tao
|
|
90 |
6595
|
leinfelder
|
protected Date updateDate = null;
|
91 |
2076
|
jones
|
|
92 |
|
|
protected DBSAXNode rootNode;
|
93 |
|
|
|
94 |
|
|
protected String action = null;
|
95 |
|
|
|
96 |
|
|
protected String docid = null;
|
97 |
|
|
|
98 |
|
|
protected String revision = null;
|
99 |
|
|
|
100 |
|
|
protected String user = null;
|
101 |
|
|
|
102 |
|
|
protected String[] groups = null;
|
103 |
|
|
|
104 |
|
|
protected String pub = null;
|
105 |
5752
|
leinfelder
|
|
106 |
|
|
protected String encoding = null;
|
107 |
2076
|
jones
|
|
108 |
4470
|
daigle
|
// private boolean endDocument = false;
|
109 |
2076
|
jones
|
|
110 |
|
|
protected int serverCode = 1;
|
111 |
|
|
|
112 |
4470
|
daigle
|
protected Hashtable<String,String> namespaces = new Hashtable<String,String>();
|
113 |
2076
|
jones
|
|
114 |
|
|
protected boolean hitTextNode = false; // a flag to hit text node
|
115 |
|
|
|
116 |
|
|
// a buffer to keep all text nodes for same element
|
117 |
4470
|
daigle
|
// it is for if element was split
|
118 |
2076
|
jones
|
protected StringBuffer textBuffer = new StringBuffer();
|
119 |
|
|
|
120 |
4470
|
daigle
|
// protected Stack textBufferStack = new Stack();
|
121 |
2076
|
jones
|
|
122 |
5208
|
daigle
|
public static final int MAXDATACHARS = 4000;
|
123 |
2076
|
jones
|
|
124 |
|
|
//protected static final int MAXDATACHARS = 50;
|
125 |
|
|
|
126 |
|
|
// methods writeChildNodeToDB, setAttribute, setNamespace,
|
127 |
|
|
// writeTextForDBSAXNode will increase endNodeId.
|
128 |
|
|
protected long endNodeId = -1; // The end node id for a substree
|
129 |
|
|
// DOCTITLE attr cleared from the db
|
130 |
|
|
// private static final int MAXTITLELEN = 1000;
|
131 |
2590
|
tao
|
|
132 |
|
|
private boolean isRevisionDoc = false;
|
133 |
4425
|
daigle
|
|
134 |
|
|
protected Vector<XMLSchema> schemaList = new Vector<XMLSchema>();
|
135 |
2076
|
jones
|
|
136 |
|
|
//HandlerTriple stuff
|
137 |
|
|
TripleCollection tripleList = new TripleCollection();
|
138 |
|
|
|
139 |
|
|
Triple currentTriple = new Triple();
|
140 |
|
|
|
141 |
|
|
boolean startParseTriple = false;
|
142 |
|
|
|
143 |
|
|
boolean hasTriple = false;
|
144 |
7128
|
leinfelder
|
|
145 |
7137
|
leinfelder
|
protected boolean writeAccessRules = true;
|
146 |
|
|
|
147 |
|
|
protected boolean ignoreDenyFirst = true;
|
148 |
2076
|
jones
|
|
149 |
2165
|
tao
|
public static final String ECOGRID = "ecogrid://";
|
150 |
|
|
|
151 |
2663
|
sgarg
|
private Logger logMetacat = Logger.getLogger(DBSAXHandler.class);
|
152 |
|
|
|
153 |
2076
|
jones
|
/**
|
154 |
|
|
* Construct an instance of the handler class
|
155 |
2165
|
tao
|
*
|
156 |
2076
|
jones
|
* @param conn the JDBC connection to which information is written
|
157 |
|
|
*/
|
158 |
6595
|
leinfelder
|
private DBSAXHandler(DBConnection conn, Date createDate, Date updateDate)
|
159 |
2076
|
jones
|
{
|
160 |
|
|
this.connection = conn;
|
161 |
|
|
this.atFirstElement = true;
|
162 |
|
|
this.processingDTD = false;
|
163 |
2620
|
tao
|
this.createDate = createDate;
|
164 |
|
|
this.updateDate = updateDate;
|
165 |
2076
|
jones
|
|
166 |
|
|
// Create the stack for keeping track of node context
|
167 |
|
|
// if it doesn't already exist
|
168 |
|
|
if (!stackCreated) {
|
169 |
4470
|
daigle
|
nodeStack = new Stack<DBSAXNode>();
|
170 |
|
|
nodeIndex = new Vector<DBSAXNode>();
|
171 |
2076
|
jones
|
stackCreated = true;
|
172 |
1590
|
tao
|
}
|
173 |
2076
|
jones
|
}
|
174 |
|
|
|
175 |
|
|
/**
|
176 |
|
|
* Construct an instance of the handler class
|
177 |
2165
|
tao
|
*
|
178 |
2076
|
jones
|
* @param conn the JDBC connection to which information is written
|
179 |
|
|
* @param action - "INSERT" or "UPDATE"
|
180 |
|
|
* @param docid to be inserted or updated into JDBC connection
|
181 |
|
|
* @param user the user connected to MetaCat servlet and owns the document
|
182 |
|
|
* @param groups the groups to which user belongs
|
183 |
|
|
* @param pub flag for public "read" access on document
|
184 |
|
|
* @param serverCode the serverid from xml_replication on which this
|
185 |
|
|
* document resides.
|
186 |
2165
|
tao
|
*
|
187 |
2076
|
jones
|
*/
|
188 |
2165
|
tao
|
/* TODO excise this constructor because not used anywhere in project
|
189 |
2076
|
jones
|
public DBSAXHandler(DBConnection conn, String action, String docid,
|
190 |
|
|
String user, String[] groups, String pub, int serverCode)
|
191 |
|
|
{
|
192 |
|
|
this(conn);
|
193 |
|
|
this.action = action;
|
194 |
|
|
this.docid = docid;
|
195 |
|
|
this.user = user;
|
196 |
|
|
this.groups = groups;
|
197 |
|
|
this.pub = pub;
|
198 |
|
|
this.serverCode = serverCode;
|
199 |
|
|
this.xmlIndex = new Thread(this);
|
200 |
|
|
}
|
201 |
|
|
*/
|
202 |
|
|
/**
|
203 |
|
|
* Construct an instance of the handler class In this constructor, user can
|
204 |
|
|
* specify the version need to upadate
|
205 |
2165
|
tao
|
*
|
206 |
2076
|
jones
|
* @param conn the JDBC connection to which information is written
|
207 |
|
|
* @param action - "INSERT" or "UPDATE"
|
208 |
|
|
* @param docid to be inserted or updated into JDBC connection
|
209 |
|
|
* @param revision, the user specified the revision need to be update
|
210 |
|
|
* @param user the user connected to MetaCat servlet and owns the document
|
211 |
|
|
* @param groups the groups to which user belongs
|
212 |
|
|
* @param pub flag for public "read" access on document
|
213 |
|
|
* @param serverCode the serverid from xml_replication on which this
|
214 |
|
|
* document resides.
|
215 |
2165
|
tao
|
*
|
216 |
2076
|
jones
|
*/
|
217 |
|
|
public DBSAXHandler(DBConnection conn, String action, String docid,
|
218 |
|
|
String revision, String user, String[] groups, String pub,
|
219 |
7128
|
leinfelder
|
int serverCode, Date createDate, Date updateDate, boolean writeAccessRules)
|
220 |
2076
|
jones
|
{
|
221 |
2620
|
tao
|
this(conn, createDate, updateDate);
|
222 |
2076
|
jones
|
this.action = action;
|
223 |
|
|
this.docid = docid;
|
224 |
|
|
this.revision = revision;
|
225 |
|
|
this.user = user;
|
226 |
|
|
this.groups = groups;
|
227 |
|
|
this.pub = pub;
|
228 |
|
|
this.serverCode = serverCode;
|
229 |
7128
|
leinfelder
|
this.writeAccessRules = writeAccessRules;
|
230 |
2076
|
jones
|
}
|
231 |
|
|
|
232 |
|
|
/** SAX Handler that receives notification of beginning of the document */
|
233 |
|
|
public void startDocument() throws SAXException
|
234 |
|
|
{
|
235 |
5208
|
daigle
|
logMetacat.debug("DBSaxHandler.startDocument - starting document");
|
236 |
2076
|
jones
|
|
237 |
|
|
// Create the document node representation as root
|
238 |
|
|
rootNode = new DBSAXNode(connection, this.docid);
|
239 |
|
|
// Add the node to the stack, so that any text data can be
|
240 |
|
|
// added as it is encountered
|
241 |
|
|
nodeStack.push(rootNode);
|
242 |
|
|
}
|
243 |
|
|
|
244 |
|
|
/** SAX Handler that receives notification of end of the document */
|
245 |
4080
|
daigle
|
public void endDocument() throws SAXException {
|
246 |
5208
|
daigle
|
logMetacat.debug("DBSaxHandler.endDocument - ending document");
|
247 |
4080
|
daigle
|
// Starting new thread for writing XML Index.
|
248 |
|
|
// It calls the run method of the thread.
|
249 |
2076
|
jones
|
|
250 |
4080
|
daigle
|
try {
|
251 |
4470
|
daigle
|
// if it is data package insert triple into relation table;
|
252 |
4080
|
daigle
|
if (doctype != null
|
253 |
4698
|
daigle
|
&& MetacatUtil.getOptionList(
|
254 |
4213
|
daigle
|
PropertyService.getProperty("xml.packagedoctype")).contains(
|
255 |
4080
|
daigle
|
doctype) && hasTriple && !isRevisionDoc) {
|
256 |
72
|
bojilova
|
|
257 |
4470
|
daigle
|
// initial handler and write into relation db only for
|
258 |
4080
|
daigle
|
// xml-documents
|
259 |
|
|
if (!isRevisionDoc) {
|
260 |
|
|
RelationHandler handler = new RelationHandler(docid, doctype,
|
261 |
|
|
connection, tripleList);
|
262 |
|
|
}
|
263 |
|
|
}
|
264 |
|
|
} catch (Exception e) {
|
265 |
5208
|
daigle
|
logMetacat.error("DBSaxHandler.endDocument - Failed to write triples into relation table"
|
266 |
4080
|
daigle
|
+ e.getMessage());
|
267 |
|
|
throw new SAXException("Failed to write triples into relation table "
|
268 |
|
|
+ e.getMessage());
|
269 |
|
|
}
|
270 |
4425
|
daigle
|
|
271 |
|
|
// If we get here, the document and schema parsed okay. If there are
|
272 |
|
|
// any schemas in the schema list, they are new and need to be registered.
|
273 |
|
|
for (XMLSchema xmlSchema : schemaList) {
|
274 |
|
|
String externalFileUri = xmlSchema.getExternalFileUri();
|
275 |
|
|
String fileNamespace = xmlSchema.getFileNamespace();
|
276 |
|
|
SchemaLocationResolver resolver =
|
277 |
|
|
new SchemaLocationResolver(fileNamespace, externalFileUri);
|
278 |
|
|
resolver.resolveNameSpace();
|
279 |
|
|
}
|
280 |
4080
|
daigle
|
}
|
281 |
|
|
|
282 |
2076
|
jones
|
/** SAX Handler that is called at the start of Namespace */
|
283 |
|
|
public void startPrefixMapping(String prefix, String uri)
|
284 |
|
|
throws SAXException
|
285 |
|
|
{
|
286 |
5208
|
daigle
|
logMetacat.debug("DBSaxHandler.startPrefixMapping - Starting namespace");
|
287 |
821
|
bojilova
|
|
288 |
2076
|
jones
|
namespaces.put(prefix, uri);
|
289 |
|
|
}
|
290 |
1359
|
tao
|
|
291 |
2076
|
jones
|
/** SAX Handler that is called at the start of each XML element */
|
292 |
|
|
public void startElement(String uri, String localName, String qName,
|
293 |
|
|
Attributes atts) throws SAXException
|
294 |
|
|
{
|
295 |
|
|
// for element <eml:eml...> qname is "eml:eml", local name is "eml"
|
296 |
|
|
// for element <acl....> both qname and local name is "eml"
|
297 |
4470
|
daigle
|
// uri is namespace
|
298 |
5208
|
daigle
|
logMetacat.debug("DBSaxHandler.startElement - Start ELEMENT(qName) " + qName);
|
299 |
|
|
logMetacat.debug("DBSaxHandler.startElement - Start ELEMENT(localName) " + localName);
|
300 |
|
|
logMetacat.debug("DBSaxHandler.startElement - Start ELEMENT(uri) " + uri);
|
301 |
17
|
jones
|
|
302 |
2076
|
jones
|
DBSAXNode parentNode = null;
|
303 |
|
|
DBSAXNode currentNode = null;
|
304 |
18
|
jones
|
|
305 |
2076
|
jones
|
// Get a reference to the parent node for the id
|
306 |
|
|
try {
|
307 |
2605
|
tao
|
|
308 |
2076
|
jones
|
parentNode = (DBSAXNode) nodeStack.peek();
|
309 |
|
|
} catch (EmptyStackException e) {
|
310 |
|
|
parentNode = null;
|
311 |
|
|
}
|
312 |
1359
|
tao
|
|
313 |
2076
|
jones
|
// If hit a text node, we need write this text for current's parent
|
314 |
4470
|
daigle
|
// node This will happen if the element is mixed
|
315 |
2076
|
jones
|
if (hitTextNode && parentNode != null) {
|
316 |
|
|
// write the textbuffer into db for parent node.
|
317 |
|
|
endNodeId = writeTextForDBSAXNode(endNodeId, textBuffer, parentNode);
|
318 |
|
|
// rest hitTextNode
|
319 |
|
|
hitTextNode = false;
|
320 |
|
|
// reset textbuffer
|
321 |
|
|
textBuffer = null;
|
322 |
|
|
textBuffer = new StringBuffer();
|
323 |
2605
|
tao
|
|
324 |
2076
|
jones
|
}
|
325 |
2605
|
tao
|
|
326 |
2076
|
jones
|
// Document representation that points to the root document node
|
327 |
|
|
if (atFirstElement) {
|
328 |
|
|
atFirstElement = false;
|
329 |
|
|
// If no DOCTYPE declaration: docname = root element
|
330 |
|
|
// doctype = root element name or name space
|
331 |
|
|
if (docname == null) {
|
332 |
|
|
docname = localName;
|
333 |
|
|
// if uri isn't null doctype = uri(namespace)
|
334 |
4470
|
daigle
|
// otherwise root element
|
335 |
2076
|
jones
|
if (uri != null && !(uri.trim()).equals("")) {
|
336 |
|
|
doctype = uri;
|
337 |
|
|
} else {
|
338 |
|
|
doctype = docname;
|
339 |
|
|
}
|
340 |
5208
|
daigle
|
logMetacat.debug("DBSaxHandler.startElement - DOCNAME-a: " + docname);
|
341 |
|
|
logMetacat.debug("DBSaxHandler.startElement - DOCTYPE-a: " + doctype);
|
342 |
2076
|
jones
|
} else if (doctype == null) {
|
343 |
|
|
// because docname is not null and it is declared in dtd
|
344 |
|
|
// so could not be in schema, no namespace
|
345 |
|
|
doctype = docname;
|
346 |
5208
|
daigle
|
logMetacat.debug("DBSaxHandler.startElement - DOCTYPE-b: " + doctype);
|
347 |
1217
|
tao
|
}
|
348 |
2605
|
tao
|
|
349 |
2076
|
jones
|
rootNode.writeNodename(docname);
|
350 |
2605
|
tao
|
|
351 |
2076
|
jones
|
try {
|
352 |
|
|
// for validated XML Documents store a reference to XML DB
|
353 |
|
|
// Catalog
|
354 |
|
|
// Because this is select statement and it needn't to roll back
|
355 |
|
|
// if
|
356 |
4470
|
daigle
|
// insert document action failed.
|
357 |
2076
|
jones
|
// In order to decrease DBConnection usage count, we get a new
|
358 |
|
|
// dbconnection from pool
|
359 |
2620
|
tao
|
|
360 |
2076
|
jones
|
DBConnection dbConn = null;
|
361 |
|
|
int serialNumber = -1;
|
362 |
2605
|
tao
|
|
363 |
2076
|
jones
|
if (systemid != null) {
|
364 |
|
|
try {
|
365 |
|
|
// Get dbconnection
|
366 |
|
|
dbConn = DBConnectionPool
|
367 |
|
|
.getDBConnection("DBSAXHandler.startElement");
|
368 |
|
|
serialNumber = dbConn.getCheckOutSerialNumber();
|
369 |
1359
|
tao
|
|
370 |
6606
|
leinfelder
|
String sql = "SELECT catalog_id FROM xml_catalog "
|
371 |
|
|
+ "WHERE entry_type = 'DTD' "
|
372 |
|
|
+ "AND public_id = ?";
|
373 |
|
|
|
374 |
|
|
PreparedStatement pstmt = dbConn.prepareStatement(sql);
|
375 |
|
|
pstmt.setString(1, doctype);
|
376 |
|
|
ResultSet rs = pstmt.executeQuery();
|
377 |
2076
|
jones
|
boolean hasRow = rs.next();
|
378 |
|
|
if (hasRow) {
|
379 |
|
|
catalogid = rs.getString(1);
|
380 |
|
|
}
|
381 |
6606
|
leinfelder
|
pstmt.close();
|
382 |
2076
|
jones
|
}//try
|
383 |
|
|
finally {
|
384 |
|
|
// Return dbconnection
|
385 |
6606
|
leinfelder
|
DBConnectionPool.returnDBConnection(dbConn, serialNumber);
|
386 |
2076
|
jones
|
}//finally
|
387 |
|
|
}
|
388 |
1359
|
tao
|
|
389 |
2076
|
jones
|
//create documentImpl object by the constructor which can
|
390 |
|
|
// specify
|
391 |
|
|
//the revision
|
392 |
2605
|
tao
|
|
393 |
|
|
if (!isRevisionDoc)
|
394 |
|
|
{
|
395 |
|
|
currentDocument = new DocumentImpl(connection, rootNode
|
396 |
2076
|
jones
|
.getNodeID(), docname, doctype, docid, revision,
|
397 |
2620
|
tao
|
action, user, this.pub, catalogid, this.serverCode,
|
398 |
|
|
createDate, updateDate);
|
399 |
3221
|
berkley
|
}
|
400 |
2076
|
jones
|
} catch (Exception ane) {
|
401 |
5454
|
berkley
|
ane.printStackTrace(System.out);
|
402 |
|
|
ane.printStackTrace(System.err);
|
403 |
|
|
throw (new SAXException("Error in DBSaxHandler.startElement for action "
|
404 |
|
|
+ action + " : " + ane.getMessage(), ane));
|
405 |
2076
|
jones
|
}
|
406 |
|
|
}
|
407 |
1359
|
tao
|
|
408 |
2076
|
jones
|
// Create the current node representation
|
409 |
2627
|
tao
|
currentNode = new DBSAXNode(connection, qName, localName,
|
410 |
|
|
parentNode, rootNode.getNodeID(), docid, doctype);
|
411 |
821
|
bojilova
|
|
412 |
2076
|
jones
|
// Add all of the namespaces
|
413 |
|
|
String prefix;
|
414 |
|
|
String nsuri;
|
415 |
4470
|
daigle
|
Enumeration<String> prefixes = namespaces.keys();
|
416 |
2076
|
jones
|
while (prefixes.hasMoreElements()) {
|
417 |
|
|
prefix = (String) prefixes.nextElement();
|
418 |
|
|
nsuri = (String) namespaces.get(prefix);
|
419 |
|
|
currentNode.setNamespace(prefix, nsuri, docid);
|
420 |
|
|
}
|
421 |
|
|
namespaces = null;
|
422 |
4470
|
daigle
|
namespaces = new Hashtable<String,String>();
|
423 |
17
|
jones
|
|
424 |
2076
|
jones
|
// Add all of the attributes
|
425 |
|
|
for (int i = 0; i < atts.getLength(); i++) {
|
426 |
|
|
String attributeName = atts.getQName(i);
|
427 |
|
|
String attributeValue = atts.getValue(i);
|
428 |
|
|
endNodeId = currentNode.setAttribute(attributeName, attributeValue,
|
429 |
|
|
docid);
|
430 |
1359
|
tao
|
|
431 |
2076
|
jones
|
// To handle name space and schema location if the attribute name
|
432 |
4425
|
daigle
|
// is xsi:schemaLocation. If the name space is in not in catalog
|
433 |
|
|
// table it will be registered.
|
434 |
2076
|
jones
|
if (attributeName != null
|
435 |
|
|
&& attributeName
|
436 |
|
|
.indexOf(MetaCatServlet.SCHEMALOCATIONKEYWORD) != -1) {
|
437 |
4425
|
daigle
|
// These schemas will be registered in the end endDocument() method
|
438 |
|
|
// assuming parsing is successful.
|
439 |
|
|
// each namespace could have several schema locations. parsedUri will
|
440 |
|
|
// hold a list of uri and files.
|
441 |
|
|
attributeValue = StringUtil.replaceTabsNewLines(attributeValue);
|
442 |
|
|
attributeValue = StringUtil.replaceDuplicateSpaces(attributeValue);
|
443 |
|
|
Vector<String> parsedUri = StringUtil.toVector(attributeValue, ' ');
|
444 |
|
|
for (int j = 0; j < parsedUri.size(); j = j + 2 ) {
|
445 |
|
|
if (j + 1 >= parsedUri.size()) {
|
446 |
|
|
throw new SAXException("Odd number of elements found when parsing schema location: " +
|
447 |
|
|
attributeValue + ". There should be an even number of uri/files in location.");
|
448 |
|
|
}
|
449 |
|
|
XMLSchema xmlSchema =
|
450 |
|
|
new XMLSchema(parsedUri.get(j), parsedUri.get(j + 1));
|
451 |
|
|
schemaList.add(xmlSchema);
|
452 |
|
|
}
|
453 |
2076
|
jones
|
}
|
454 |
|
|
}
|
455 |
|
|
|
456 |
|
|
// Add the node to the stack, so that any text data can be
|
457 |
4080
|
daigle
|
// added as it is encountered
|
458 |
|
|
nodeStack.push(currentNode);
|
459 |
|
|
// Add the node to the vector used by thread for writing XML Index
|
460 |
|
|
nodeIndex.addElement(currentNode);
|
461 |
|
|
// start parsing triple
|
462 |
|
|
try {
|
463 |
|
|
if (doctype != null
|
464 |
4698
|
daigle
|
&& MetacatUtil.getOptionList(
|
465 |
4213
|
daigle
|
PropertyService.getProperty("xml.packagedoctype")).contains(doctype)
|
466 |
4080
|
daigle
|
&& localName.equals("triple")) {
|
467 |
|
|
startParseTriple = true;
|
468 |
|
|
hasTriple = true;
|
469 |
|
|
currentTriple = new Triple();
|
470 |
|
|
}
|
471 |
|
|
} catch (PropertyNotFoundException pnfe) {
|
472 |
5454
|
berkley
|
pnfe.printStackTrace(System.out);
|
473 |
|
|
pnfe.printStackTrace(System.err);
|
474 |
|
|
throw (new SAXException("Error in DBSaxHandler.startElement for action " + action +
|
475 |
|
|
" : " + pnfe.getMessage(), pnfe));
|
476 |
4080
|
daigle
|
}
|
477 |
|
|
}
|
478 |
|
|
|
479 |
2076
|
jones
|
|
480 |
|
|
/** SAX Handler that is called for each XML text node */
|
481 |
|
|
public void characters(char[] cbuf, int start, int len) throws SAXException
|
482 |
1841
|
tao
|
{
|
483 |
5208
|
daigle
|
logMetacat.debug("DBSaxHandler.characters - starting characters");
|
484 |
4470
|
daigle
|
// buffer all text nodes for same element. This is for if text was split
|
485 |
2076
|
jones
|
// into different nodes
|
486 |
|
|
textBuffer.append(new String(cbuf, start, len));
|
487 |
|
|
// set hittextnode true
|
488 |
|
|
hitTextNode = true;
|
489 |
|
|
// if text buffer .size is greater than max, write it to db.
|
490 |
|
|
// so we can save memory
|
491 |
|
|
if (textBuffer.length() > MAXDATACHARS) {
|
492 |
5208
|
daigle
|
logMetacat.debug("DBSaxHandler.characters - Write text into DB in charaters"
|
493 |
2663
|
sgarg
|
+ " when text buffer size is greater than maxmum number");
|
494 |
2076
|
jones
|
DBSAXNode currentNode = (DBSAXNode) nodeStack.peek();
|
495 |
|
|
endNodeId = writeTextForDBSAXNode(endNodeId, textBuffer,
|
496 |
|
|
currentNode);
|
497 |
|
|
textBuffer = null;
|
498 |
|
|
textBuffer = new StringBuffer();
|
499 |
899
|
berkley
|
}
|
500 |
2076
|
jones
|
}
|
501 |
|
|
|
502 |
|
|
/**
|
503 |
|
|
* SAX Handler that is called for each XML text node that is Ignorable
|
504 |
|
|
* white space
|
505 |
|
|
*/
|
506 |
|
|
public void ignorableWhitespace(char[] cbuf, int start, int len)
|
507 |
|
|
throws SAXException
|
508 |
1841
|
tao
|
{
|
509 |
2076
|
jones
|
// When validation is turned "on", white spaces are reported here
|
510 |
|
|
// When validation is turned "off" white spaces are not reported here,
|
511 |
|
|
// but through characters() callback
|
512 |
5208
|
daigle
|
logMetacat.debug("DBSaxHandler.ignorableWhitespace - in ignorableWhitespace");
|
513 |
2076
|
jones
|
|
514 |
|
|
DBSAXNode currentNode = (DBSAXNode) nodeStack.peek();
|
515 |
|
|
|
516 |
|
|
// Write the content of the node to the database
|
517 |
5208
|
daigle
|
endNodeId = currentNode.writeChildNodeToDB("TEXT", null, new String(cbuf, start, len),
|
518 |
2076
|
jones
|
docid);
|
519 |
1217
|
tao
|
}
|
520 |
2076
|
jones
|
|
521 |
|
|
/**
|
522 |
|
|
* SAX Handler called once for each processing instruction found: node that
|
523 |
|
|
* PI may occur before or after the root element.
|
524 |
|
|
*/
|
525 |
|
|
public void processingInstruction(String target, String data)
|
526 |
|
|
throws SAXException
|
527 |
1217
|
tao
|
{
|
528 |
5208
|
daigle
|
logMetacat.debug("DBSaxHandler.processingInstruction - in processing instructions");
|
529 |
2076
|
jones
|
DBSAXNode currentNode = (DBSAXNode) nodeStack.peek();
|
530 |
|
|
endNodeId = currentNode.writeChildNodeToDB("PI", target, data, docid);
|
531 |
|
|
}
|
532 |
1359
|
tao
|
|
533 |
2076
|
jones
|
/** SAX Handler that is called at the end of each XML element */
|
534 |
|
|
public void endElement(String uri, String localName, String qName)
|
535 |
|
|
throws SAXException
|
536 |
|
|
{
|
537 |
5208
|
daigle
|
logMetacat.debug("DBSaxHandler.endElement - End element " + qName);
|
538 |
660
|
bojilova
|
|
539 |
2076
|
jones
|
// write buffered text nodes into db (so no splited)
|
540 |
|
|
DBSAXNode currentNode = (DBSAXNode) nodeStack.peek();
|
541 |
1359
|
tao
|
|
542 |
2076
|
jones
|
// If before the end element, the parser hit text nodes and store them
|
543 |
|
|
// into the buffer, write the buffer to data base. The reason we put
|
544 |
|
|
// write database here is for xerces some time split text node
|
545 |
|
|
if (hitTextNode) {
|
546 |
5208
|
daigle
|
logMetacat.debug("DBSaxHandler.endElement - Write text into DB in End Element");
|
547 |
2076
|
jones
|
endNodeId = writeTextForDBSAXNode(endNodeId, textBuffer,
|
548 |
|
|
currentNode);
|
549 |
1359
|
tao
|
|
550 |
2076
|
jones
|
//if it is triple parsing process
|
551 |
|
|
if (startParseTriple) {
|
552 |
660
|
bojilova
|
|
553 |
2076
|
jones
|
String content = textBuffer.toString().trim();
|
554 |
|
|
if (localName.equals("subject")) { //get the subject content
|
555 |
|
|
currentTriple.setSubject(content);
|
556 |
|
|
} else if (localName.equals("relationship")) { //get the
|
557 |
|
|
// relationship
|
558 |
|
|
// content
|
559 |
|
|
currentTriple.setRelationship(content);
|
560 |
|
|
} else if (localName.equals("object")) { //get the object
|
561 |
|
|
// content
|
562 |
|
|
currentTriple.setObject(content);
|
563 |
|
|
}
|
564 |
|
|
}
|
565 |
17
|
jones
|
|
566 |
2076
|
jones
|
}//if
|
567 |
72
|
bojilova
|
|
568 |
2076
|
jones
|
//set hitText false
|
569 |
|
|
hitTextNode = false;
|
570 |
|
|
// reset textbuff
|
571 |
|
|
textBuffer = null;
|
572 |
|
|
textBuffer = new StringBuffer();
|
573 |
17
|
jones
|
|
574 |
2076
|
jones
|
// Get the node from the stack
|
575 |
|
|
currentNode = (DBSAXNode) nodeStack.pop();
|
576 |
|
|
//finishing parsing single triple
|
577 |
|
|
if (startParseTriple && localName.equals("triple")) {
|
578 |
|
|
// add trip to triple collection
|
579 |
|
|
tripleList.addTriple(currentTriple);
|
580 |
|
|
//rest variable
|
581 |
|
|
currentTriple = null;
|
582 |
|
|
startParseTriple = false;
|
583 |
|
|
}
|
584 |
|
|
}
|
585 |
17
|
jones
|
|
586 |
2076
|
jones
|
//
|
587 |
|
|
// the next section implements the LexicalHandler interface
|
588 |
|
|
//
|
589 |
185
|
jones
|
|
590 |
2076
|
jones
|
/** SAX Handler that receives notification of DOCTYPE. Sets the DTD */
|
591 |
|
|
public void startDTD(String name, String publicId, String systemId)
|
592 |
|
|
throws SAXException
|
593 |
|
|
{
|
594 |
|
|
docname = name;
|
595 |
|
|
doctype = publicId;
|
596 |
|
|
systemid = systemId;
|
597 |
185
|
jones
|
|
598 |
2076
|
jones
|
processingDTD = true;
|
599 |
|
|
DBSAXNode currentNode = (DBSAXNode) nodeStack.peek();
|
600 |
|
|
//create a DTD node and write docname,publicid and system id into db
|
601 |
|
|
// we don't put the dtd node into node stack
|
602 |
|
|
DBSAXNode dtdNode = new DBSAXNode(connection, name, publicId, systemId,
|
603 |
|
|
currentNode, currentNode.getRootNodeID(), docid);
|
604 |
5208
|
daigle
|
logMetacat.debug("DBSaxHandler.startDTD - Start DTD");
|
605 |
|
|
logMetacat.debug("DBSaxHandler.startDTD - Setting processingDTD to true");
|
606 |
|
|
logMetacat.debug("DBSaxHandler.startDTD - DOCNAME: " + docname);
|
607 |
|
|
logMetacat.debug("DBSaxHandler.startDTD - DOCTYPE: " + doctype);
|
608 |
|
|
logMetacat.debug("DBSaxHandler.startDTD - SYSID: " + systemid);
|
609 |
2076
|
jones
|
}
|
610 |
185
|
jones
|
|
611 |
2076
|
jones
|
/**
|
612 |
|
|
* SAX Handler that receives notification of end of DTD
|
613 |
|
|
*/
|
614 |
|
|
public void endDTD() throws SAXException
|
615 |
|
|
{
|
616 |
1359
|
tao
|
|
617 |
2076
|
jones
|
processingDTD = false;
|
618 |
5208
|
daigle
|
logMetacat.debug("DBSaxHandler.endDTD - Setting processingDTD to false");
|
619 |
|
|
logMetacat.debug("DBSaxHandler.endDTD - end DTD");
|
620 |
2076
|
jones
|
}
|
621 |
185
|
jones
|
|
622 |
2076
|
jones
|
/**
|
623 |
|
|
* SAX Handler that receives notification of comments in the DTD
|
624 |
|
|
*/
|
625 |
|
|
public void comment(char[] ch, int start, int length) throws SAXException
|
626 |
|
|
{
|
627 |
5208
|
daigle
|
logMetacat.debug("DBSaxHandler.comment - starting comment");
|
628 |
2076
|
jones
|
if (!processingDTD) {
|
629 |
|
|
DBSAXNode currentNode = (DBSAXNode) nodeStack.peek();
|
630 |
|
|
endNodeId = currentNode.writeChildNodeToDB("COMMENT", null,
|
631 |
|
|
new String(ch, start, length), docid);
|
632 |
|
|
}
|
633 |
|
|
}
|
634 |
185
|
jones
|
|
635 |
2076
|
jones
|
/**
|
636 |
|
|
* SAX Handler that receives notification of the start of CDATA sections
|
637 |
|
|
*/
|
638 |
|
|
public void startCDATA() throws SAXException
|
639 |
|
|
{
|
640 |
5208
|
daigle
|
logMetacat.debug("DBSaxHandler.startCDATA - starting CDATA");
|
641 |
2076
|
jones
|
}
|
642 |
185
|
jones
|
|
643 |
2076
|
jones
|
/**
|
644 |
|
|
* SAX Handler that receives notification of the end of CDATA sections
|
645 |
|
|
*/
|
646 |
|
|
public void endCDATA() throws SAXException
|
647 |
|
|
{
|
648 |
5208
|
daigle
|
logMetacat.debug("DBSaxHandler.endCDATA - end CDATA");
|
649 |
2076
|
jones
|
}
|
650 |
185
|
jones
|
|
651 |
2076
|
jones
|
/**
|
652 |
|
|
* SAX Handler that receives notification of the start of entities
|
653 |
|
|
*/
|
654 |
|
|
public void startEntity(String name) throws SAXException
|
655 |
|
|
{
|
656 |
5208
|
daigle
|
logMetacat.debug("DBSaxHandler.startEntity - starting entity: " + name);
|
657 |
2076
|
jones
|
//System.out.println("start ENTITY: " + name);
|
658 |
|
|
if (name.equals("[dtd]")) {
|
659 |
|
|
processingDTD = true;
|
660 |
|
|
}
|
661 |
|
|
}
|
662 |
185
|
jones
|
|
663 |
2076
|
jones
|
/**
|
664 |
|
|
* SAX Handler that receives notification of the end of entities
|
665 |
|
|
*/
|
666 |
|
|
public void endEntity(String name) throws SAXException
|
667 |
|
|
{
|
668 |
5208
|
daigle
|
logMetacat.debug("DBSaxHandler.endEntity - ending entity: " + name);
|
669 |
2076
|
jones
|
//System.out.println("end ENTITY: " + name);
|
670 |
|
|
if (name.equals("[dtd]")) {
|
671 |
|
|
processingDTD = false;
|
672 |
|
|
}
|
673 |
|
|
}
|
674 |
186
|
jones
|
|
675 |
2076
|
jones
|
/**
|
676 |
|
|
* SAX Handler that receives notification of element declarations
|
677 |
|
|
*/
|
678 |
|
|
public void elementDecl(String name, String model)
|
679 |
|
|
throws org.xml.sax.SAXException
|
680 |
|
|
{
|
681 |
|
|
//System.out.println("ELEMENTDECL: " + name + " " + model);
|
682 |
5208
|
daigle
|
logMetacat.debug("DBSaxHandler.elementDecl - element declaration: " + name + " " + model);
|
683 |
2076
|
jones
|
}
|
684 |
186
|
jones
|
|
685 |
2076
|
jones
|
/**
|
686 |
|
|
* SAX Handler that receives notification of attribute declarations
|
687 |
|
|
*/
|
688 |
|
|
public void attributeDecl(String eName, String aName, String type,
|
689 |
|
|
String valueDefault, String value) throws org.xml.sax.SAXException
|
690 |
|
|
{
|
691 |
821
|
bojilova
|
|
692 |
2076
|
jones
|
//System.out.println("ATTRIBUTEDECL: " + eName + " "
|
693 |
|
|
// + aName + " " + type + " " + valueDefault + " "
|
694 |
|
|
// + value);
|
695 |
5208
|
daigle
|
logMetacat.debug("DBSaxHandler.attributeDecl - attribute declaration: " + eName + " " + aName + " "
|
696 |
2663
|
sgarg
|
+ type + " " + valueDefault + " " + value);
|
697 |
2076
|
jones
|
}
|
698 |
186
|
jones
|
|
699 |
2076
|
jones
|
/**
|
700 |
|
|
* SAX Handler that receives notification of internal entity declarations
|
701 |
|
|
*/
|
702 |
|
|
public void internalEntityDecl(String name, String value)
|
703 |
|
|
throws org.xml.sax.SAXException
|
704 |
|
|
{
|
705 |
|
|
//System.out.println("INTERNENTITYDECL: " + name + " " + value);
|
706 |
5208
|
daigle
|
logMetacat.debug("DBSaxHandler.internalEntityDecl - internal entity declaration: " + name + " " + value);
|
707 |
2076
|
jones
|
}
|
708 |
186
|
jones
|
|
709 |
2076
|
jones
|
/**
|
710 |
|
|
* SAX Handler that receives notification of external entity declarations
|
711 |
|
|
*/
|
712 |
|
|
public void externalEntityDecl(String name, String publicId, String systemId)
|
713 |
|
|
throws org.xml.sax.SAXException
|
714 |
|
|
{
|
715 |
|
|
//System.out.println("EXTERNENTITYDECL: " + name + " " + publicId
|
716 |
|
|
// + " " + systemId);
|
717 |
5208
|
daigle
|
logMetacat.debug("DBSaxHandler.externalEntityDecl - external entity declaration: " + name + " " + publicId
|
718 |
2663
|
sgarg
|
+ " " + systemId);
|
719 |
2076
|
jones
|
// it processes other external entity, not the DTD;
|
720 |
|
|
// it doesn't signal for the DTD here
|
721 |
|
|
processingDTD = false;
|
722 |
|
|
}
|
723 |
186
|
jones
|
|
724 |
2076
|
jones
|
//
|
725 |
|
|
// the next section implements the ErrorHandler interface
|
726 |
|
|
//
|
727 |
186
|
jones
|
|
728 |
2076
|
jones
|
/**
|
729 |
|
|
* SAX Handler that receives notification of fatal parsing errors
|
730 |
|
|
*/
|
731 |
|
|
public void fatalError(SAXParseException exception) throws SAXException
|
732 |
|
|
{
|
733 |
5208
|
daigle
|
logMetacat.fatal("DBSaxHandler.fatalError - " + exception.getMessage());
|
734 |
2076
|
jones
|
throw (new SAXException("Fatal processing error.", exception));
|
735 |
|
|
}
|
736 |
204
|
jones
|
|
737 |
2076
|
jones
|
/**
|
738 |
|
|
* SAX Handler that receives notification of recoverable parsing errors
|
739 |
|
|
*/
|
740 |
|
|
public void error(SAXParseException exception) throws SAXException
|
741 |
|
|
{
|
742 |
5208
|
daigle
|
logMetacat.error("DBSaxHandler.error - " + exception.getMessage());
|
743 |
5888
|
leinfelder
|
throw (new SAXException(exception.getMessage(), exception));
|
744 |
2076
|
jones
|
}
|
745 |
204
|
jones
|
|
746 |
2076
|
jones
|
/**
|
747 |
|
|
* SAX Handler that receives notification of warnings
|
748 |
|
|
*/
|
749 |
|
|
public void warning(SAXParseException exception) throws SAXException
|
750 |
|
|
{
|
751 |
5208
|
daigle
|
logMetacat.warn("DBSaxHandler.warning - " + exception.getMessage());
|
752 |
5888
|
leinfelder
|
throw (new SAXException(exception.getMessage(), exception));
|
753 |
2076
|
jones
|
}
|
754 |
204
|
jones
|
|
755 |
2076
|
jones
|
//
|
756 |
|
|
// Helper, getter and setter methods
|
757 |
|
|
//
|
758 |
1359
|
tao
|
|
759 |
2076
|
jones
|
/**
|
760 |
|
|
* get the document name
|
761 |
|
|
*/
|
762 |
|
|
public String getDocname()
|
763 |
|
|
{
|
764 |
|
|
return docname;
|
765 |
|
|
}
|
766 |
204
|
jones
|
|
767 |
2076
|
jones
|
/**
|
768 |
|
|
* get the document processing state
|
769 |
|
|
*/
|
770 |
|
|
public boolean processingDTD()
|
771 |
|
|
{
|
772 |
|
|
return processingDTD;
|
773 |
|
|
}
|
774 |
2590
|
tao
|
|
775 |
|
|
|
776 |
|
|
/**
|
777 |
|
|
* get the the is revision doc
|
778 |
|
|
* @return
|
779 |
|
|
*/
|
780 |
|
|
public boolean getIsRevisionDoc()
|
781 |
|
|
{
|
782 |
|
|
return isRevisionDoc;
|
783 |
|
|
}
|
784 |
|
|
|
785 |
|
|
/**
|
786 |
|
|
* Set the the handler is for revisionDoc
|
787 |
|
|
* @param isRevisionDoc
|
788 |
|
|
*/
|
789 |
|
|
public void setIsRevisionDoc(boolean isRevisionDoc)
|
790 |
|
|
{
|
791 |
|
|
this.isRevisionDoc = isRevisionDoc;
|
792 |
|
|
}
|
793 |
2076
|
jones
|
|
794 |
5752
|
leinfelder
|
public String getEncoding() {
|
795 |
|
|
return encoding;
|
796 |
|
|
}
|
797 |
|
|
|
798 |
|
|
public void setEncoding(String encoding) {
|
799 |
|
|
this.encoding = encoding;
|
800 |
|
|
}
|
801 |
|
|
|
802 |
|
|
/* Method to write a text buffer for DBSAXNode */
|
803 |
2076
|
jones
|
protected long writeTextForDBSAXNode(long previousEndNodeId,
|
804 |
|
|
StringBuffer strBuffer, DBSAXNode node) throws SAXException
|
805 |
|
|
{
|
806 |
|
|
long nodeId = previousEndNodeId;
|
807 |
|
|
// Check parameter
|
808 |
|
|
if (strBuffer == null || node == null) { return nodeId; }
|
809 |
|
|
boolean moredata = true;
|
810 |
2352
|
sgarg
|
|
811 |
|
|
String normalizedData = strBuffer.toString();
|
812 |
5208
|
daigle
|
logMetacat.debug("DBSAXHandler.writeTextForDBSAXNode - Before normalize in write process: " + normalizedData);
|
813 |
4698
|
daigle
|
String afterNormalize = MetacatUtil.normalize(normalizedData);
|
814 |
5208
|
daigle
|
logMetacat.debug("DBSAXHandler.writeTextForDBSAXNode - After normalize in write process: " + afterNormalize);
|
815 |
3731
|
tao
|
strBuffer = new StringBuffer(afterNormalize);;
|
816 |
2352
|
sgarg
|
|
817 |
2076
|
jones
|
int bufferSize = strBuffer.length();
|
818 |
|
|
int start = 0;
|
819 |
|
|
|
820 |
|
|
// if there are some cotent in buffer, write it
|
821 |
|
|
if (bufferSize > 0) {
|
822 |
5208
|
daigle
|
logMetacat.debug("DBSAXHandler.writeTextForDBSAXNode - Write text into DB");
|
823 |
2076
|
jones
|
|
824 |
|
|
// Write the content of the node to the database
|
825 |
5208
|
daigle
|
nodeId = node.writeChildNodeToDB("TEXT", null, new String(strBuffer), docid);
|
826 |
2076
|
jones
|
}//if
|
827 |
|
|
return nodeId;
|
828 |
|
|
}
|
829 |
2605
|
tao
|
|
830 |
|
|
public long getRootNodeId()
|
831 |
|
|
{
|
832 |
|
|
return rootNode.getNodeID();
|
833 |
|
|
}
|
834 |
2620
|
tao
|
|
835 |
|
|
public String getDocumentType()
|
836 |
|
|
{
|
837 |
|
|
return doctype;
|
838 |
|
|
}
|
839 |
|
|
|
840 |
|
|
public String getDocumentName()
|
841 |
|
|
{
|
842 |
|
|
return docname;
|
843 |
|
|
}
|
844 |
|
|
|
845 |
|
|
public String getCatalogId()
|
846 |
|
|
{
|
847 |
|
|
return catalogid;
|
848 |
|
|
}
|
849 |
17
|
jones
|
}
|