Project

General

Profile

1
/*
2
 * ClientViewHelper.java
3
 *
4
 * Created on June 25, 2007, 9:57 AM
5
 *
6
 * To change this template, choose Tools | Template Manager
7
 * and open the template in the editor.
8
 */
9

    
10
package edu.ucsb.nceas.metacat.clientview;
11

    
12
import com.oreilly.servlet.multipart.FilePart;
13
import com.oreilly.servlet.multipart.MultipartParser;
14
import com.oreilly.servlet.multipart.ParamPart;
15
import com.oreilly.servlet.multipart.Part;
16
import edu.ucsb.nceas.metacat.client.InsufficientKarmaException;
17
import edu.ucsb.nceas.metacat.client.MetacatClient;
18
import edu.ucsb.nceas.metacat.client.MetacatException;
19
import edu.ucsb.nceas.metacat.client.MetacatFactory;
20
import edu.ucsb.nceas.metacat.client.MetacatInaccessibleException;
21
import edu.ucsb.nceas.metacat.properties.PropertyService;
22
import edu.ucsb.nceas.utilities.XMLUtilities;
23
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
24
import java.io.BufferedReader;
25
import java.io.ByteArrayOutputStream;
26
import java.io.IOException;
27
import java.io.InputStream;
28
import java.io.InputStreamReader;
29
import java.io.Reader;
30
import java.io.StringReader;
31
import java.util.HashMap;
32
import java.util.Iterator;
33
import java.util.Properties;
34
import java.util.Stack;
35
import java.util.TreeMap;
36
import java.util.Vector;
37
import javax.servlet.http.HttpServletRequest;
38
import javax.servlet.http.HttpServletResponse;
39
import javax.servlet.http.HttpSession;
40
import javax.xml.xpath.XPath;
41
import javax.xml.xpath.XPathConstants;
42
import javax.xml.xpath.XPathExpressionException;
43
import javax.xml.xpath.XPathFactory;
44
import org.w3c.dom.DOMException;
45
import org.w3c.dom.Document;
46
import org.w3c.dom.Node;
47
import org.w3c.dom.NodeList;
48
import org.w3c.dom.Text;
49

    
50
/**
51
 *
52
 * @author barteau
53
 */
54
public class ClientViewHelper {
55
    private XPath                                       xpath = XPathFactory.newInstance().newXPath();
56
    private HttpSession                                 clientSession;
57
    private ClientView                                  clientViewBean = null;
58
    private MetacatClient                               metacatClient = null;
59
    private boolean                                     loggedIn = false;
60
    private Document                                    metadataDoc = null;
61
    private int                                         sizeLimit;
62
    private String                                      contactName = "";
63
    
64
    private static final String                         LDAP_TEMPLATE = "uid=%1s,o=%2s,dc=ecoinformatics,dc=org";
65
    
66
    public static final String                          DOWNLOAD_ACTION = "Download";
67
    
68
    public static final String                          PERMISSION_TYPE_ALLOW = "allow";
69
    
70
    public static final String                          PERMISSION_TYPE_DISALLOW = "deny";
71
    
72
    /**
73
     * Creates a new instance of ClientViewHelper, using info in an HttpServletRequest
74
     * for initializing.
75
     * @param request HttpServletRequest, sent from the client browser.
76
     * @throws edu.ucsb.nceas.metacat.client.MetacatInaccessibleException Thrown
77
     */
78
    public ClientViewHelper(HttpServletRequest request) throws MetacatInaccessibleException {
79
        String                              host, context;
80
        
81
        clientSession = request.getSession();
82
        host = request.getHeader("host");
83
        context = request.getContextPath();
84
        init(host, context);
85
    }
86
    
87
    /**
88
     * Creates a new instance of ClientViewHelper, using parameter values
89
     * for initializing.  This constructor is plain java code so it's the portal of
90
     * choice for JUnit testing.
91
     * @param host The host with port (if needed), such as "localhost:8084".
92
     * @param context The application root context.
93
     * @param bean ClientView instance, with pre-populated values.
94
     * @throws edu.ucsb.nceas.metacat.client.MetacatInaccessibleException thrown
95
     */
96
    public ClientViewHelper(String host, String context, ClientView bean) throws MetacatInaccessibleException {
97
        clientViewBean = bean;
98
        init(host, context);
99
    }
100
    
101
    private void init(String host, String context) throws MetacatInaccessibleException {
102
        String                              metacatPath = "http://%1s%2s/metacat";
103
        String                              tmp;
104
        
105
        tmp = metacatPath.replaceFirst("%1s", host);
106
        metacatPath = tmp.replaceFirst("%2s", context);
107
        metacatClient = (MetacatClient) MetacatFactory.createMetacatConnection(metacatPath);
108
        try {
109
        	sizeLimit = 
110
        		(new Integer(PropertyService.getProperty("replication.datafilesizelimit"))).intValue();
111
        } catch (PropertyNotFoundException pnfe) {
112
        	throw new MetacatInaccessibleException(pnfe.getMessage());
113
        }
114
    }
115
    
116
    /**
117
     * Main web API method for handling various actions.
118
     * @param request HttpServletRequest
119
     * @param response HttpServletResponse
120
     * @return String message
121
     */
122
    public String clientRequest(HttpServletRequest request, HttpServletResponse response)  {
123
        String                              result = null, action, contentType;
124
        MultipartParser                     multipartParser;
125
        HashMap                             responseMap;
126
        
127
        if (clientViewBean == null) {
128
            clientViewBean = (ClientView) clientSession.getAttribute(ClientView.CLIENT_VIEW_BEAN);
129
            
130
            if (clientViewBean == null) {
131
            	//make a new one and shove it in the session
132
            	clientViewBean = new ClientView();
133
            	clientSession.setAttribute(ClientView.CLIENT_VIEW_BEAN, clientViewBean);
134
            }
135
        }
136
        
137
        if (clientViewBean != null) {
138
            action = clientViewBean.getAction();
139
            contentType = request.getContentType();
140
            
141
            //*** BEGIN: manual bind params to bean (if we arrived here via the ClientViewHelper.jspx).
142
            if (action == null || action.equals("")) {
143
                if (contentType != null && contentType.indexOf("multipart/form-data") > -1) {
144
                    action = "Upload";
145
                } else {
146
                    action = request.getParameter("action");
147
                    clientViewBean.setDocId(request.getParameter("docid"));
148
                    clientViewBean.setMetaFileDocId(request.getParameter("metadataDocId"));
149
                    clientViewBean.setQformat(request.getParameter("qformat"));
150
                    clientViewBean.setPublicAccess(request.getParameter("publicAccess") != null);
151
                    clientViewBean.setContentStandard(request.getParameter("contentStandard"));
152
                }
153
                clientViewBean.setAction(action);
154
            }
155
            //*** END: manual bind params to bean.
156
            
157
            if (action != null) {
158
                if (action.equals("Login")) {
159
                    responseMap = handleClientRequest(null);
160
                    //*** Now that the action has been processed, clear it.
161
                    clientViewBean.setAction("");
162
                } else if (action.equals("Logout")) {
163
                    responseMap = handleClientRequest(null);
164
                    clientViewBean.setAction("");
165
                } else if (action.equals("Upload")) {
166
                    try {
167
                        //*** Init the MultipartParser.
168
                        multipartParser = new MultipartParser(request, sizeLimit * 1024 * 1024);
169
                        responseMap = handleClientRequest(multipartParser);
170
                    } catch (IOException ex) {
171
                        responseMap = new HashMap();
172
                        responseMap.put("message", ex.getMessage());
173
                    }
174
                    clientViewBean.setAction("");
175
                } else if (action.equals("Download")) {
176
                    responseMap = handleClientRequest(null);
177
                    try {
178
                        handleDownloadResponse(responseMap, response);
179
                    } catch (IOException ex) {
180
                        responseMap = new HashMap();
181
                        responseMap.put("message", ex.getMessage());
182
                    }
183
                    
184
                } else if (action.equals("Set Access")) {
185
                    responseMap = handleClientRequest(null);
186
                    clientViewBean.setAction("");
187
                } else {
188
                    responseMap = handleClientRequest(null);
189
                }
190
                result = (String) responseMap.get("message");
191
            }
192
        } else {
193
            result = "ClientViewHelper.clientRequest: ClientView bean is not instantiated.";
194
        }
195
        return(result);
196
    }
197
    
198
    /**
199
     * Main method for handling various actions.
200
     *
201
     * Note: This is mostly plain java code so it is JUnit friendly
202
     * (pass null as the MulipartParser).
203
     *
204
     * @param multipartParser Only needed if the action is "Upload".
205
     * @return HashMap containing "message", and possibly several other values.  If
206
     * the action is Download, than this will contain all needed values
207
     * to pass to handleDownloadResponse.
208
     */
209
    public HashMap handleClientRequest(MultipartParser multipartParser)  {
210
        String                              result = "", serverResponse;
211
        String                              button, posted_ldapUserName, tmp, action;
212
        HashMap                             responseMap = new HashMap();
213
        int                                 fileIdx;
214
        
215
        
216
        if (clientViewBean != null) {
217
            action = clientViewBean.getAction();
218
            if (action != null) {
219
                try {
220
                    if (action.equals("Login")) {
221
                        tmp = LDAP_TEMPLATE.replaceFirst("%1s", clientViewBean.getUsername());
222
                        posted_ldapUserName = tmp.replaceFirst("%2s", clientViewBean.getOrganization());
223
                        
224
                        serverResponse = metacatClient.login(posted_ldapUserName, clientViewBean.getPassword());
225
                        setLoggedIn(serverResponse);
226
                        result = parseXml("message", serverResponse);
227
                        contactName = parseXml("name", serverResponse);
228
                        clientViewBean.setMessage(ClientView.LOGIN_MESSAGE, result);
229
                        clientViewBean.setMessage(ClientView.UPLOAD_MESSAGE, "");
230
                        if (isLoggedIn()) {
231
                            clientViewBean.setSessionid(metacatClient.getSessionId());
232
                        }
233
                    } else if (action.equals("Logout")) {
234
                        result = metacatClient.logout();
235
                        setLoggedIn(result);
236
                        result = parseXml("message", result);
237
                        clientViewBean.setMessage(ClientView.LOGIN_MESSAGE, result);
238
                        clientViewBean.setMessage(ClientView.UPLOAD_MESSAGE, "");
239
                        if (!isLoggedIn()) {
240
                            clientViewBean.setUsername("");
241
                            clientViewBean.setPassword("");
242
                            clientViewBean.setOrganization("");
243
                            clientViewBean.setSessionid(null);
244
                        }
245
                    } else if (action.equals("Delete")) {
246
                        ClientFgdcHelper.clientDeleteRequest(clientViewBean, this);
247
                        clientViewBean.setAction("read"); //*** Set for re-query.
248
                        //*** Note: the clientViewBean will already have the updated Meta Doc Id.
249
                        
250
                    } else if (action.equals("Upload")) {
251
                        //*** Only process request if logged in.
252
                        if (isLoggedIn()) {
253
                            if (multipartParser == null)
254
                                result = "ClientViewHelper.handleClientRequest: MultipartParser is not instantiated.";
255
                            else
256
                                result = handlePackageUpload(clientViewBean, multipartParser);
257
                        } else {
258
                            result = "You must be logged in to perform an upload.";
259
                        }
260
                        clientViewBean.setMessage(ClientView.UPLOAD_MESSAGE, result);
261
                    } else if (action.equals("Update")) {
262
                        result = "This is not implemented here.  Call ClientViewHelper.jspx";
263
                    } else if (action.equals("Scope")) {
264
                        result = handleDocIdSelect();
265
                        clientViewBean.setMessage(ClientView.SELECT_MESSAGE, result);
266
                    } else if (action.equals("Download")) {
267
                        responseMap = download(clientViewBean);
268
                    } else if (action.equals("Set Access")) {
269
                        result = handleChangeAccess(clientViewBean.getMetaFileDocId(),
270
                                (clientViewBean.isPublicAccess()? PERMISSION_TYPE_ALLOW: PERMISSION_TYPE_DISALLOW));
271
                        clientViewBean.setMessage(ClientView.UPDATE_MESSAGE, result);
272
                    } else {
273
                        result = action + " action not recognized.";
274
                    }
275
                } catch (Exception ex) {
276
                    result = ex.getMessage();
277
                    clientViewBean.setMessage(ClientView.ERROR_MESSAGE, result);
278
                    ex.printStackTrace();
279
                }
280
            }
281
        } else {
282
            result = "ClientViewHelper.clientRequest: ClientView bean is not instantiated.";
283
        }
284
        responseMap.put("message", result);
285
        return(responseMap);
286
    }
287
    
288
    /**
289
     * This is a convenience method to reduce the amount of code in a Metacat Client.
290
     * It handles creating/reusing (per session) an instance of a ClientViewHelper.
291
     * @param request Since this is intended to be used by an Http client, it is passed the
292
     * available "request" variable (the HttpServletRequest).
293
     * @throws edu.ucsb.nceas.metacat.client.MetacatInaccessibleException Received by MetacatFactory.
294
     * @return ClientViewHelper instance.
295
     */
296
    public static ClientViewHelper clientViewHelperInstance(HttpServletRequest request) {
297
        ClientViewHelper                        result;
298
        
299
        result = (ClientViewHelper) request.getSession().getAttribute("ClientViewHelper");
300
        if (result == null) {
301
            try {
302
                result = new ClientViewHelper(request);
303
                request.getSession().setAttribute("ClientViewHelper", result);
304
            } catch (MetacatInaccessibleException ex) {
305
                ex.printStackTrace();
306
            }
307
        }
308
        
309
        return(result);
310
    }
311
    
312
    /**
313
     * A convenience method to be used by client code that requires
314
     * the user to be logged in.  NOTE: setUser() must have been called first,
315
     * otherwise it will always return false.
316
     * @return boolean  true if user has logged in for this session, false otherwise.
317
     */
318
    public boolean isLoggedIn() {
319
        return(loggedIn);
320
    }
321
    
322
    /**
323
     * After calling "login(ldapUserName, pwd)", call this with the username
324
     * and servers response message.  You can than use isLoggedIn() to determine if
325
     * the user is logged in, getLoginResponseElement(), etc.  The user name will also
326
     * used by calls to doMetadataUpload() for Document Id creation (scope).
327
     * @param userName User name
328
     * @param serverResponse XML login response sent from Metacat.
329
     */
330
    public void setLoggedIn(String serverResponse) {
331
        loggedIn = (serverResponse != null && serverResponse.indexOf("login") > -1);
332
    }
333
    
334
    public String parseXml(String elementName, String xml) {
335
        String                      result = null;
336
        Document                    doc;
337
        
338
        try {
339
            doc = XMLUtilities.getXMLReaderAsDOMDocument(new StringReader(xml));
340
            result = (String) xpath.evaluate(elementName, doc.getDocumentElement(), XPathConstants.STRING);
341
            if (result != null)
342
                result = result.trim();
343
        } catch (IOException ex) {
344
            ex.printStackTrace();
345
        } catch (XPathExpressionException ex) {
346
            ex.printStackTrace();
347
        }
348
        return(result);
349
    }
350
    
351
    public String handleDocIdSelect() {
352
        String                              result = "";
353
        TreeMap                             allDocIds;
354
        
355
        if (!clientViewBean.getPathValue().equals("")) {
356
            allDocIds = getSelectQueryMap();
357
            result = ClientHtmlHelper.mapToHtmlSelect(allDocIds, "docId", "width: 240", 10);
358
        }
359
        return(result);
360
    }
361
    
362
    /**
363
     * Handles metadata file and data file uploads for inserting new
364
     * Metacat data packages.  Note: if content type is not "multipart/form-data",
365
     * nothing will happen.
366
     * @param request HTTP request.
367
     * @return A 1-line status message for the user.
368
     */
369
    public String handlePackageUpload(ClientView clientViewBean, MultipartParser multipartParser) throws Exception {
370
        String                      result = "", contentType, formatType;
371
        String                      lastDocId, nextDocId, metaDocId, metaFileName;
372
        String                      fileInfo[];
373
        Reader                      reader;
374
        int                         sizeLimit, idx;
375
        InputStream                 inputStream;
376
        HashMap                     paramsMap, dataDocIDs;
377
        StringBuffer                fileName;
378
        boolean                     sendIt;
379
        Iterator                    iterIt;
380
        Stack                       docIdStack;
381
        
382
        //*** Get the First file, which should be the metadata file.
383
        paramsMap = new HashMap();
384
        fileName = new StringBuffer();
385
        inputStream = getNextInputStream(multipartParser, fileName, paramsMap);
386
        metaFileName = fileName.toString();
387
        if (metaFileName.toLowerCase().endsWith(".xml")) {
388
            //*** Keep it here for updating.
389
            setMetadataDoc(inputStream);
390
            //*** Get the Metadata File's DOC ID.
391
            lastDocId = getMetacatClient().getLastDocid(clientViewBean.getUsername());
392
            metaDocId = lastDocId = nextDocId(lastDocId, clientViewBean.getUsername());
393
            
394
            //*** Loop thru all of the data files, get fileName and inputStream.
395
            dataDocIDs = new HashMap();
396
            fileName = new StringBuffer();
397
            while ((inputStream = getNextInputStream(multipartParser, fileName, paramsMap)) != null) {
398
                //*** Get the data file's DOC ID.
399
                nextDocId = nextDocId(lastDocId, clientViewBean.getUsername());
400
                
401
                fileInfo = parseFileInfo(fileName.toString());
402
                dataDocIDs.put(nextDocId, fileInfo);
403
                
404
                //*** Upload the data file to metacat.
405
                getMetacatClient().upload(nextDocId, fileName.toString(), inputStream, Integer.MAX_VALUE);
406
                
407
                lastDocId = nextDocId;
408
                fileName = new StringBuffer();
409
            }
410
            
411
            if (ClientFgdcHelper.isFGDC(getMetadataDoc())) {
412
                sendIt = ClientFgdcHelper.handlePackageUpload(metaDocId, dataDocIDs, contactName, metaFileName, getMetadataDoc());
413
            } else {
414
                //TODO add other types of metadata grammars here...
415
                System.out.println("ClientViewHelper.handlePackageUpload: not an FGDC file = " + fileName);
416
                result = fileName + " is not an FGDC file.  Files not uploaded.";
417
                sendIt = false;
418
            }
419
            
420
            if (sendIt) {
421
                //*** Upload the metadata file to metacat.
422
                reader = XMLUtilities.getDOMTreeAsReader(metadataDoc.getDocumentElement(), false);
423
                getMetacatClient().insert(metaDocId, reader, null);
424
                
425
                result = "MetaCat Package Inserted:  the Document Identifier is " + metaDocId;
426
                reader.close();
427
                //*** Grant the public read access to the meta file.
428
                if (paramsMap.containsKey("publicAccess")) {
429
                    docIdStack = new Stack();
430
                    docIdStack.addAll(dataDocIDs.keySet());
431
                    setPublicAccess(this.PERMISSION_TYPE_ALLOW, metaDocId, docIdStack);
432
                }
433
            }
434
        } else {
435
            result = "The first file must be an XML Metadata file.  Files not uploaded.";
436
        }
437
        if (inputStream != null)
438
            inputStream.close();
439
        return(result);
440
    }
441
    
442
    private String setPublicAccess(String permissionType, String metaDocId, Stack docIdStack)
443
    throws InsufficientKarmaException, MetacatException, MetacatInaccessibleException {
444
        String                      result = " for Documents ";
445
        String                      docId, lst = metaDocId, permOrder;
446
        
447
        if (permissionType.equals("allow"))
448
            permOrder = "denyFirst";
449
        else
450
            permOrder = "allowFirst";
451
        
452
        getMetacatClient().setAccess(metaDocId, "public", "read", permissionType, permOrder);
453
        //*** Grant the public read access to the data files.
454
        while(!docIdStack.isEmpty()) {
455
            docId = (String) docIdStack.pop();
456
            getMetacatClient().setAccess(docId, "public", "read", permissionType, permOrder);
457
            lst += ", " + docId;
458
        }
459
        result = "Changed public read access to '" + permissionType + "' for " + result + lst;
460
        return(result);
461
    }
462
    
463
    private String handleChangeAccess(String metaDocId, String permissionType) throws Exception {
464
        Stack                       dataDocIDs;
465
        String                      result = "", xpathExpr = null;
466
        
467
        setMetadataDoc(metaDocId);
468
        //*** Build list of sub-documents.
469
        if (clientViewBean.getContentStandard().equals(ClientView.FEDERAL_GEOGRAPHIC_DATA_COMMITTEE)) {
470
            xpathExpr = ClientFgdcHelper.SUB_DOCS_PATH;
471
        } else if (clientViewBean.getContentStandard().equals(ClientView.ECOLOGICAL_METADATA_LANGUAGE)) {
472
            xpathExpr = null; //TODO  - EML
473
        }
474
        if (xpathExpr != null) {
475
            dataDocIDs = getNodeTextStack(xpath, xpathExpr, getMetadataDoc().getDocumentElement());
476
            result = setPublicAccess(permissionType, metaDocId, dataDocIDs);
477
        }
478
        return(result);
479
    }
480
    
481
    public String handleFileUpdate(MultipartParser multipartParser) throws Exception {
482
        String                      result = "", fNm, action, lastDocId, newDocId, xPathQuery, qFrmt;
483
        InputStream                 inputStream;
484
        HashMap                     paramsMap;
485
        StringBuffer                fileName;
486
        Iterator                    iterIt;
487
        boolean                     sendIt;
488
        String                      metadataDocId, fileInfo[];
489
        
490
        paramsMap = new HashMap();
491
        fileName = new StringBuffer();
492
        if ((inputStream = getNextInputStream(multipartParser, fileName, paramsMap)) != null) {
493
            action = (String) paramsMap.get("action");
494
            //*** Get the Doc Id.
495
            lastDocId = (String) paramsMap.get("docid");
496
            
497
            //*** Get the metadata Doc Id.
498
            metadataDocId = (String) paramsMap.get("metadataDocId");
499
            clientViewBean.setMetaFileDocId(metadataDocId);
500
            
501
            //*** Get the qformat.
502
            qFrmt = (String) paramsMap.get("qformat");
503
            clientViewBean.setQformat(qFrmt);
504
            
505
            fNm = fileName.toString();
506
            
507
            try {
508
                if (lastDocId.equals(metadataDocId)) { //*** This is the metadata file.
509
                    //*** Keep it here for updating.
510
                    setMetadataDoc(inputStream);
511
                    if (ClientFgdcHelper.isFGDC(getMetadataDoc())) {
512
                        clientViewBean.setContentStandard(ClientView.FEDERAL_GEOGRAPHIC_DATA_COMMITTEE);
513
                        if (!ClientFgdcHelper.hasMetacatInfo(lastDocId, getMetadataDoc())) {
514
                            
515
                            //*** Save the Doc Id for re-query.
516
                            clientViewBean.setMetaFileDocId(lastDocId);
517
                            clientViewBean.setAction("read"); //*** Set for re-query.
518
                            result = "Update not performed: the Metadata file has no prior Metacat info in it.";
519
                        } else {
520
                            xPathQuery = ClientFgdcHelper.XPATH_QUERY_TEMPLATE.replaceFirst("%1s", lastDocId);
521
                            newDocId = updateMetadataDoc(lastDocId, xPathQuery, fNm);
522
                            
523
                            //*** Save the Doc Id for re-query.
524
                            clientViewBean.setMetaFileDocId(newDocId);
525
                            clientViewBean.setAction("read"); //*** Set for re-query.
526
                            result = "Updated to new document (from " + lastDocId + " to " + newDocId + ")";
527
                        }
528
                    } else {
529
                        //***TODO This is EML.
530
                        clientViewBean.setContentStandard(ClientView.ECOLOGICAL_METADATA_LANGUAGE);
531
                        
532
                        //*** Save the Doc Id for re-query.
533
                        clientViewBean.setMetaFileDocId(lastDocId);
534
                        clientViewBean.setAction("read"); //*** Set for re-query.
535
                        result = "Currently this functionality only supports FGDC metadata.";
536
                    }
537
                } else {
538
                    //*** This is a data file.
539
                    //*** Query for the metadata, we need to update it with the new data file doc id.
540
                    setMetadataDoc(metadataDocId);
541
                    
542
                    if (ClientFgdcHelper.isFGDC(getMetadataDoc())) {
543
                        clientViewBean.setContentStandard(ClientView.FEDERAL_GEOGRAPHIC_DATA_COMMITTEE);
544
                        fileInfo = parseFileInfo(fNm);
545
                        
546
                        xPathQuery = ClientFgdcHelper.FGDC_DATA_FILE_QUERY_XPATH.replaceFirst("%1s", lastDocId);
547
                        newDocId = nextVersion(lastDocId, xPathQuery);
548
                        ClientFgdcHelper.updateFileNameAndType(getMetadataDoc().getDocumentElement(), newDocId, fileInfo);
549
                        //*** Upload the data file to metacat.
550
                        getMetacatClient().upload(newDocId, fNm, inputStream, Integer.MAX_VALUE);
551
                        result = "Updated to new document (from " + lastDocId + " to " + newDocId + ")";
552
                        
553
                        //*** Upload the metadata file to metacat.
554
                        xPathQuery = ClientFgdcHelper.XPATH_QUERY_TEMPLATE.replaceFirst("%1s", metadataDocId);
555
                        newDocId = updateMetadataDoc(metadataDocId, xPathQuery, null);
556
                        
557
                        //*** Save the new meta Doc Id for re-query.
558
                        clientViewBean.setMetaFileDocId(newDocId);
559
                        clientViewBean.setAction("read"); //*** Set for re-query.
560
                        
561
                    } else {
562
                        //***TODO This is EML.
563
                        clientViewBean.setContentStandard(ClientView.ECOLOGICAL_METADATA_LANGUAGE);
564
                        
565
                        //*** Save the old meta Doc Id for re-query.
566
                        clientViewBean.setMetaFileDocId(metadataDocId);
567
                        clientViewBean.setAction("read"); //*** Set for re-query.
568
                        result = "Currently this functionality only supports FGDC metadata.";
569
                    }
570
                }
571
            } catch (java.io.IOException ex) {
572
                ex.printStackTrace();
573
            }
574
        } else {
575
            result = "Please enter the updated file path/name.";
576
        }
577
        clientViewBean.setMessage(ClientView.UPDATE_MESSAGE, result);
578
        return(result);
579
    }
580
    
581
    private String updateMetadataDoc(String lastDocId, String docIdPath, String origFileName) {
582
        String                      newDocId = null;
583
        Reader                      reader;
584
        
585
        //*** Update the metadata with the new Doc Id version.
586
        try {
587
            newDocId = nextVersion(lastDocId, docIdPath);
588
            if (origFileName != null) {
589
                if (clientViewBean.getContentStandard().equals(ClientView.FEDERAL_GEOGRAPHIC_DATA_COMMITTEE))
590
                    ClientFgdcHelper.updateMetadataFileName(getMetadataDoc().getDocumentElement(), newDocId, origFileName);
591
                else
592
                    ; //TODO EML, etc.
593
            }
594
            //*** Upload the metadata file to metacat.
595
            reader = XMLUtilities.getDOMTreeAsReader(getMetadataDoc().getDocumentElement(), false);
596
            getMetacatClient().update(newDocId, reader, null);
597
            reader.close();
598
        } catch (Exception ex) {
599
            ex.printStackTrace();
600
        }
601
        return(newDocId);
602
    }
603
    
604
    private InputStream getNextInputStream(MultipartParser multipartParser, StringBuffer fileName, HashMap paramsMap)
605
    throws IOException {
606
        InputStream                     result = null;
607
        Part                            part;
608
        String                          parmName = null, value = null, fnam;
609
        
610
        while ((part = multipartParser.readNextPart()) != null) {
611
            if (part.isParam()) {
612
                parmName = part.getName();
613
                value = ((ParamPart) part).getStringValue();
614
                paramsMap.put(parmName, value);
615
                
616
            } else if (part.isFile()) {
617
                fnam = ((FilePart) part).getFileName();
618
                if (fnam != null && !fnam.equals("")) {
619
                    //*** File name is passed back via StringBuffer fileName param.
620
                    fileName.append(fnam);
621
                    result = ((FilePart) part).getInputStream();
622
                    break;
623
                }
624
            }
625
        }
626
        return(result);
627
    }
628
    
629
    private void getRemainingParameters(MultipartParser multipartParser, HashMap paramsMap)
630
    throws IOException {
631
        InputStream                     result = null;
632
        Part                            part;
633
        String                          parmName = null, value = null, fnam;
634
        
635
        while ((part = multipartParser.readNextPart()) != null) {
636
            if (part.isParam()) {
637
                parmName = part.getName();
638
                value = ((ParamPart) part).getStringValue();
639
                paramsMap.put(parmName, value);
640
            }
641
        }
642
    }
643
    
644
    /**
645
     * Queries Metacat for document listings, and returns the results in a TreeMap,
646
     * where the key is the Doc Id, and the value is the Create Date.  If the document
647
     * contains the specified 'returnfield', an addtional entry will be created with
648
     * the value being a Vector of sub-DocId's.  The key of this entry will be the
649
     * original DocId with some addtional text added.
650
     * Reads bean properties 'pathExpr' (String[]), 'pathValue' (String)
651
     * and 'returnfield' (String).
652
     * @return TreeMap
653
     */
654
    public TreeMap getSelectQueryMap() {
655
        TreeMap                         result;
656
        Document                        doc;
657
        NodeList                        nodeLst, subNodeLst;
658
        Node                            node, subNode;
659
        String                          key, val, paramExpr, paramVal;
660
        String                          value, returnFld;
661
        String                          path;
662
        Vector                          optGroup;
663
        final String                    DOCID_EXPR = "./docid";
664
        final String                    DOCNAME_EXPR = "./createdate";
665
        final String                    PARAM_EXPR = "./param[@name='%1s']";
666
        
667
        path = clientViewBean.getPathExpr();
668
        returnFld = clientViewBean.getReturnfield();
669
        value = clientViewBean.getPathValue();
670
        
671
        result = new TreeMap();
672
        //paramExpr = String.format(PARAM_EXPR, returnFld);
673
        paramExpr = PARAM_EXPR.replaceFirst("%1s", returnFld);
674
        //*** Query the database ***
675
        doc = query(path, value, returnFld);
676
        //*** Build the TreeMap to return ***
677
        try {
678
            nodeLst = (NodeList) xpath.evaluate("/resultset/document", doc, XPathConstants.NODESET);
679
            for (int i = 0; i < nodeLst.getLength(); i++) {
680
                node = nodeLst.item(i);
681
                key = xpath.evaluate(DOCID_EXPR, node);
682
                val = xpath.evaluate(DOCNAME_EXPR, node);
683
                result.put(key, key + " (" + val + ")");
684
                
685
                //*** returnfield values ***
686
                subNodeLst = (NodeList) xpath.evaluate(paramExpr, node, XPathConstants.NODESET);
687
                if (subNodeLst.getLength() > 0) {
688
                    optGroup = new Vector();
689
                    for (int k = 0; k < subNodeLst.getLength(); k++) {
690
                        subNode =  subNodeLst.item(k);
691
                        paramVal = xpath.evaluate("text()", subNode);
692
                        optGroup.add(paramVal);
693
                    }
694
                    result.put(key + " Data Files", optGroup);
695
                }
696
                
697
            }
698
        } catch (XPathExpressionException ex) {
699
            ex.printStackTrace();
700
        }
701
        return(result);
702
    }
703
    
704
    /**
705
     * Query metacat for documents that 'CONTAINS' the value at the specified XPath
706
     * expression.  Additionally, returns another non-standard field value.
707
     * Standard info contains: DocId, DocName, DocType, CreateDate, and UpdateDate.
708
     * @param pathExpr String contianing an XPath expression.
709
     * @param pathValue String containing a comparison value at the XPath expression.
710
     * @param returnFld String containing an XPath expression to a field which will be returned
711
     * in addition to the standard info.
712
     * @return DOM Document containing the results.
713
     */
714
    public Document query(String pathExpr, String pathValue, String returnFld) {
715
        Document                        result = null;
716
        InputStream                     response;
717
        BufferedReader                  buffy;
718
        Properties                      prop;
719
        
720
        try {
721
            prop = new Properties();
722
            prop.put("action", "query");
723
            prop.put("qformat", "xml");
724
            prop.put(pathExpr, pathValue);
725
            if (returnFld != null) {
726
                prop.put("returnfield", returnFld);
727
            }
728
            
729
            response = metacatClient.sendData(prop, null, null, 0);
730
            if (response != null) {
731
                buffy = new BufferedReader(new InputStreamReader(response));
732
                result = XMLUtilities.getXMLReaderAsDOMDocument(buffy);
733
            }
734
        } catch (IOException ex) {
735
            ex.printStackTrace();
736
        } catch (Exception ex) {
737
            ex.printStackTrace();
738
        }
739
        return(result);
740
    }
741
    
742
    public void setMetadataDoc(Document doc) {
743
        metadataDoc = doc;
744
    }
745
    
746
    public void setMetadataDoc(String docId) throws Exception {
747
        Document                        doc = null;
748
        BufferedReader                  buffy;
749
        Properties                      prop;
750
        InputStream                     response;
751
        
752
        //*** MetaCatServlet Properties: action, qformat and docid. ***
753
        prop = new Properties();
754
        prop.put("action", "read");
755
        prop.put("qformat", "xml");
756
        prop.put("docid", docId);
757
        response = metacatClient.sendData(prop, null, null, 0);
758
        if (response != null) {
759
            buffy = new BufferedReader(new InputStreamReader(response));
760
            doc = XMLUtilities.getXMLReaderAsDOMDocument(buffy);
761
            response.close();
762
        }
763
        setMetadataDoc(doc);
764
    }
765
    
766
    public void setMetadataDoc(InputStream ioStream) throws IOException {
767
        BufferedReader                          buffy;
768
        
769
        if (ioStream != null) {
770
            buffy = new BufferedReader(new InputStreamReader(ioStream));
771
            metadataDoc = XMLUtilities.getXMLReaderAsDOMDocument(buffy);
772
        }
773
    }
774
    
775
    public Document getMetadataDoc() {
776
        return(metadataDoc);
777
    }
778
    
779
    public String nextVersion(String lastDocId, String xPathQuery) throws XPathExpressionException {
780
        String                      result = null, tokens[], scope, ready2Split, tmp;
781
        int                         vers, docNum;
782
        final int                   LAST_TOKEN = 2;
783
        final String                TEMPLATE = "%1s.%2d.%3d";
784
        Node                        node;
785
        
786
        //*** Parse the last Doc Id, and increment the version number.
787
        if(lastDocId != null && lastDocId.indexOf(".") > -1) {
788
            ready2Split = lastDocId.replace('.','~'); //*** This is necessary for the split to work.
789
            tokens = ready2Split.split("~");
790
            if(tokens.length > LAST_TOKEN && !tokens[LAST_TOKEN].equals("")) {
791
                scope = tokens[LAST_TOKEN - 2];
792
                docNum = Integer.parseInt(tokens[LAST_TOKEN - 1]);
793
                try {
794
                    vers = Integer.parseInt(tokens[LAST_TOKEN]);
795
                    //result = String.format(TEMPLATE, scope, docNum, 1 + vers);
796
                    tmp = TEMPLATE.replaceFirst("%1s", scope);
797
                    tmp = tmp.replaceFirst("%2d", String.valueOf(docNum));
798
                    result = tmp.replaceFirst("%3d", String.valueOf(vers + 1));
799
                    
800
                } catch (NumberFormatException ex) {
801
                    //*** In case the lastDocId has something other than a number.
802
                    //result = String.format(TEMPLATE, scope, docNum, 1);
803
                    tmp = TEMPLATE.replaceFirst("%1s", scope);
804
                    tmp = tmp.replaceFirst("%2d", String.valueOf(docNum));
805
                    result = tmp.replaceFirst("%3d", "1");
806
                }
807
            } else {
808
                //*** In case the lastDocId ends with a '.'
809
                result = lastDocId + "1";
810
            }
811
        } else {
812
            //*** In case of missing doc Id.
813
            result = null;
814
        }
815
        //*** Update the Doc Id in the metadata file.
816
        if (getMetadataDoc() != null) {
817
            node = (Node) xpath.evaluate(xPathQuery, getMetadataDoc().getDocumentElement(), XPathConstants.NODE);
818
            setTextContent(xpath, node, result);
819
        }
820
        return(result);
821
    }
822
    
823
    private String nextDocId(String lastDocId, String scope) {
824
        String                      result = null, tokens[], tmp;
825
        int                         vers;
826
        String                      template = scope.toLowerCase() + ".%1d.%2d";
827
        
828
        if(lastDocId != null && lastDocId.indexOf(".") > -1) {
829
            lastDocId = lastDocId.replace('.','~'); //*** This is necessary for the split to work.
830
            tokens = lastDocId.split("~");
831
            if(tokens.length > 1 && !tokens[1].equals("")) {
832
                try {
833
                    vers = Integer.parseInt(tokens[1]);
834
                    //result = String.format(template, 1 + vers, 1);
835
                    tmp = template.replaceFirst("%1d", String.valueOf(1 + vers));
836
                    result = tmp.replaceFirst("%2d", "1");
837
                } catch (NumberFormatException ex) {
838
                    //*** In case the lastDocId has something other than a number.
839
                    //result = String.format(template, 1, 1);
840
                    tmp = template.replaceFirst("%1d", "1");
841
                    result = tmp.replaceFirst("%2d", "1");
842
                }
843
            } else {
844
                //*** In case the lastDocId ends with a '.'
845
                //result = String.format(template, 1, 1);
846
                tmp = template.replaceFirst("%1d", "1");
847
                result = tmp.replaceFirst("%2d", "1");
848
            }
849
        } else {
850
            //*** In case there isn't any doc Id's with the user name.
851
            //result = String.format(template, 1, 1);
852
            tmp = template.replaceFirst("%1d", "1");
853
            result = tmp.replaceFirst("%2d", "1");
854
        }
855
        return(result);
856
    }
857
    
858
    public MetacatClient getMetacatClient() {
859
        return(metacatClient);
860
    }
861
    
862
    //*** BEGIN: Static utility methods ***
863
    
864
    public static String[] parseFileInfo(String fileName) {
865
        String[]                        result = new String[2];
866
        int                             idx;
867
        String                          formatType;
868
        
869
        //*** Set the file format (just using file extension for now).
870
        idx = fileName.lastIndexOf(".");
871
        if (idx > 1)
872
            formatType = fileName.substring(idx+1).toUpperCase();
873
        else
874
            formatType = "";
875
        
876
        result[ClientView.FORMAT_TYPE] = formatType;
877
        result[ClientView.FILE_NAME] = fileName.toString();
878
        return(result);
879
    }
880
    
881
    public static void updateNodeText(Node root, XPath xPath, String expression, String text) {
882
        Node                    targetNode;
883
        
884
        if (text != null && !text.equals("")) {
885
            try {
886
                targetNode = (Node) xPath.evaluate(expression, root, XPathConstants.NODE);
887
                setTextContent(xPath, targetNode, text);
888
                //targetNode.setTextContent(text);
889
            } catch (XPathExpressionException ex) {
890
                ex.printStackTrace();
891
            }
892
        }
893
    }
894
    
895
    
896
    public static Node getNode(XPath xPath, String expression, Node root) {
897
        Node                        result = null;
898
        
899
        try {
900
            result = (Node) xPath.evaluate(expression, root, XPathConstants.NODE);
901
        } catch (XPathExpressionException ex) {
902
            ex.printStackTrace();
903
        }
904
        return(result);
905
        
906
    }
907
    
908
    public static String getNodeText(XPath xPath, String expression, Node root) {
909
        Node                        node;
910
        String                      result = null;
911
        
912
        node = getNode(xPath, expression, root);
913
        if (node != null && !node.equals(""))
914
            result = getTextContent(xPath, node);
915
        //result = node.getTextContent(); Not in java 1.4
916
        return(result);
917
    }
918
    
919
    public static String[] getNodeTextList(XPath xPath, String expression, Node root) {
920
        NodeList                    nodes;
921
        String                      result[] = new String[0];
922
        int                         size;
923
        
924
        try {
925
            nodes = (NodeList) xPath.evaluate(expression, root, XPathConstants.NODESET);
926
            if (nodes != null && (size = nodes.getLength()) > 0) {
927
                result = new String[size];
928
                for(int i = 0; i < size; i++)
929
                    result[i] = getTextContent(xPath, nodes.item(i));
930
                //result[i] = nodes.item(i).getTextContent(); Not in java 1.4
931
            }
932
        } catch (XPathExpressionException ex) {
933
            ex.printStackTrace();
934
        }
935
        return(result);
936
    }
937
    
938
    public static Stack getNodeTextStack(XPath xpathInstance, String xpathExpr, Node parentNode) {
939
        String                      nodeLst[];
940
        Stack                       result = new Stack();
941
        
942
        nodeLst = getNodeTextList(xpathInstance, xpathExpr, parentNode);
943
        for(int i = 0; i < nodeLst.length; i++)
944
            result.push(nodeLst[i]);
945
        return(result);
946
    }
947
    
948
    public static String getStringFromInputStream(InputStream input) {
949
        StringBuffer result = new StringBuffer();
950
        BufferedReader in = new BufferedReader(new InputStreamReader(input));
951
        String line;
952
        try {
953
            while ((line = in.readLine()) != null) {
954
                result.append(line);
955
            }
956
        } catch (IOException e) {
957
            System.out.println("ClientViewHelper.getStringFromInputStream: " + e);
958
        }
959
        return result.toString();
960
    }
961
    
962
    //*** END: Static utility methods ***
963
    
964
    public String makeRedirectUrl() {
965
        String                      result, docId, message;
966
        
967
        docId = clientViewBean.getMetaFileDocId();
968
        if (clientViewBean.getAction().equals(DOWNLOAD_ACTION)) {
969
            result = null;
970
        } else if (docId != null && !docId.equals("")) {
971
            message = clientViewBean.getMessage(ClientView.UPDATE_MESSAGE);
972
            result = "metacat?action=read&qformat=" +clientViewBean.getQformat()
973
            + "&docid=" + docId + "&sessionid=" + clientViewBean.getSessionid() + "&message=" + message;
974
        } else {
975
            result = "style/skins/" + clientViewBean.getQformat() + "/confirm.jsp";
976
        }
977
        //*** Reset bean action property.
978
        clientViewBean.setAction("");
979
        return(result);
980
    }
981
    
982
    private HashMap download(ClientView bean) {
983
        Properties                      args;
984
        InputStream                     inStream;
985
        String                          docId, metaId, fNm = null, pth, txtLst[];
986
        String                          msg = "File '~' (~) downloaded";
987
        Node                            branchRoot, metaRoot;
988
        ByteArrayOutputStream           outStream;
989
        int                             intMe;
990
        HashMap                         responseMap = new HashMap();
991
        
992
        docId = bean.getDocId();
993
        metaId = bean.getMetaFileDocId();
994
        if (docId != null && metaId != null && !docId.equals("") && !metaId.equals("")) {
995
            //*** Properties args: key=param_value, value=param_name.
996
            args = new Properties();
997
            args.put("read", "action");
998
            try {
999
                //*** First, retrieve the metadata and get the original filename.
1000
                //*** Also, if this is the metadata, get a list of docId's for the package.
1001
                setMetadataDoc(metaId);
1002
                metaRoot = getMetadataDoc().getDocumentElement();
1003
                if (ClientFgdcHelper.isFGDC(getMetadataDoc())) {
1004
                    //*** FGDC
1005
                    if (docId.equals(metaId)) { //*** This is the metadata file.
1006
                        pth = ClientFgdcHelper.FGDC_DOCID_ROOT_XPATH.replaceFirst("%1s", docId);
1007
                        branchRoot = getNode(xpath, pth, getMetadataDoc());
1008
                        fNm = getNodeText(xpath, ClientFgdcHelper.FGDC_FILE_NAME_XPATH, branchRoot);
1009
                        //include the filename for the docid
1010
                        args.put(fNm, docId);
1011
                        fNm = toZipFileName(fNm);
1012
                        responseMap.put("contentType", "application/zip");
1013
                        //*** Get the list of docId's for the entire package.
1014
                        args.put(metaId, "docid");
1015
                        txtLst = getNodeTextList(xpath, ClientFgdcHelper.FGDC_DATA_FILE_NODES_XPATH, branchRoot);
1016
                        for (int i = 0; i < txtLst.length; i++) {
1017
                        	String additionalDocId = txtLst[i];
1018
                        	if (additionalDocId != null && additionalDocId.length() > 1) {
1019
                        		//look up the filename from the metadata
1020
                        		String tempPath = ClientFgdcHelper.PATH4ANCESTOR.replaceFirst("%1s", additionalDocId);
1021
                        		tempPath = tempPath.replaceFirst("%2s", "digform");
1022
                                Node tempBranchRoot = getNode(xpath, tempPath, getMetadataDoc());
1023
                                String tempFileName = getNodeText(xpath, ClientFgdcHelper.FGDC_DATA_FILE_NAME_XPATH, tempBranchRoot);
1024
                                //include the docid
1025
                        		args.put(additionalDocId, "docid");
1026
                        		//include the filename for the docid
1027
                        		args.put(tempFileName, additionalDocId);
1028
                        	}
1029
                        }
1030
                        args.put("zip", "qformat");
1031
                    } else { //*** This is a data file.
1032
                        pth = ClientFgdcHelper.PATH4ANCESTOR.replaceFirst("%1s", docId);
1033
                        pth = pth.replaceFirst("%2s", "digform");
1034
                        branchRoot = getNode(xpath, pth, getMetadataDoc());
1035
                        fNm = getNodeText(xpath, ClientFgdcHelper.FGDC_DATA_FILE_NAME_XPATH, branchRoot);
1036
                        responseMap.put("contentType", "application/octet-stream");
1037
                        args.put(docId, "docid");
1038
                        args.put("xml", "qformat");
1039
                    }
1040
                } else {
1041
                    //*** TODO: EML -  this is just some basic code to start with.
1042
                    if (docId.equals(metaId)) {
1043
                        fNm = "emlMetadata.xml";
1044
                        txtLst = new String[] {docId};
1045
                        args.put(txtLst[0], "docid");
1046
                        args.put("zip", "qformat");
1047
                        responseMap.put("contentType", "application/zip");
1048
                    } else {
1049
                        fNm = "emlData.dat";
1050
                        args.put("xml", "qformat");
1051
                        args.put(docId, "docid");
1052
                        responseMap.put("contentType", "application/octet-stream");
1053
                    }
1054
                }
1055
                
1056
                //*** Set the filename in the response.
1057
                responseMap.put("Content-Disposition", "attachment; filename=" + fNm);
1058
                
1059
                //*** Next, read the file from metacat.
1060
                inStream = metacatClient.sendParameters(args);
1061
                
1062
                //*** Then, convert the input stream into an output stream.
1063
                outStream = new ByteArrayOutputStream();
1064
                while ((intMe = inStream.read()) != -1) {
1065
                    outStream.write(intMe);
1066
                }
1067
                
1068
                //*** Now, write the output stream to the response.
1069
                responseMap.put("outputStream", outStream);
1070
                
1071
                //*** Finally, set the message for the user interface to display.
1072
                msg = msg.replaceFirst("~", fNm);
1073
                msg = msg.replaceFirst("~", docId);
1074
                bean.setMessage(ClientView.SELECT_MESSAGE, msg);
1075
            } catch (Exception ex) {
1076
                ex.printStackTrace();
1077
                bean.setMessage(ClientView.SELECT_MESSAGE, ex.getMessage());
1078
            }
1079
        }
1080
        responseMap.put("message", bean.getMessage(ClientView.SELECT_MESSAGE));
1081
        return(responseMap);
1082
    }
1083
    
1084
    private void handleDownloadResponse(HashMap responseMap, HttpServletResponse response) throws IOException {
1085
        ByteArrayOutputStream                       outStream;
1086
        String                                      contentDisposition, contentType;
1087
        
1088
        contentType = (String) responseMap.get("contentType");
1089
        contentDisposition = (String) responseMap.get("Content-Disposition");
1090
        outStream = (ByteArrayOutputStream) responseMap.get("outputStream");
1091
        
1092
        response.setContentType(contentType);
1093
        response.setHeader("Content-Disposition", contentDisposition);
1094
        response.setContentLength(outStream.size());
1095
        outStream.writeTo(response.getOutputStream());
1096
        response.flushBuffer();
1097
    }
1098
    
1099
    public static String toZipFileName(String fileName) {
1100
        String                      result = "metacat";
1101
        int                         idx;
1102
        
1103
        if (fileName != null && !fileName.equals("") && !fileName.equals(".")) {
1104
            idx = fileName.indexOf('.');
1105
            if (idx > -1)
1106
                result = fileName.substring(0, idx);
1107
            else
1108
                result = fileName;
1109
        }
1110
        result += ".zip";
1111
        return(result);
1112
    }
1113
    
1114
    public static void setTextContent(XPath xPath, Node elementNode, String content) throws DOMException {
1115
        Text                        textNode, newTxtNode;
1116
        Document                    document;
1117
        
1118
        textNode = (Text) getNode(xPath, "text()", elementNode);
1119
        if (textNode != null) {
1120
            if (isElementContentWhitespace(textNode)) {
1121
                //*** If there is an existing text node, and it's whitespace,
1122
                //*** create a new text node and insert it before whitespace.
1123
                document = elementNode.getOwnerDocument();
1124
                newTxtNode = document.createTextNode(content);
1125
                elementNode.insertBefore(newTxtNode, textNode);
1126
            } else {
1127
                //*** If there is an existing text node, and it has content,
1128
                //*** overwrite the existing text.
1129
                textNode.setNodeValue(content);
1130
            }
1131
        } else {
1132
            //*** If there isn't an existing text node,
1133
            //*** create a new text node and append it to the elementNode.
1134
            document = elementNode.getOwnerDocument();
1135
            newTxtNode = document.createTextNode(content);
1136
            elementNode.appendChild(newTxtNode);
1137
        }
1138
    }
1139
    
1140
    public static String getTextContent(XPath xPath, Node elementNode) throws DOMException {
1141
        String                      result = "";
1142
        Text                        textNode;
1143
        
1144
        if (elementNode.getNodeType() != Node.TEXT_NODE)
1145
            textNode = (Text) getNode(xPath, "text()", elementNode);
1146
        else
1147
            textNode = (Text) elementNode;
1148
        if (textNode != null)
1149
            result = textNode.getNodeValue();
1150
        return(result);
1151
    }
1152
    
1153
    public static boolean isElementContentWhitespace(Text textNode) {
1154
        boolean                     result = false;
1155
        String                      val;
1156
        
1157
        if ((val = textNode.getNodeValue()) != null) {
1158
            if (val != null) {
1159
                val = val.trim();
1160
                result = (val.length() == 0);
1161
            }
1162
        }
1163
        return(result);
1164
    }
1165
    
1166
}
(5-5/5)