Project

General

Profile

1
/**
2
 *  '$RCSfile$'
3
 *    Purpose: A Class that implements utility methods for a metadata catalog
4
 *  Copyright: 2000 Regents of the University of California and the
5
 *             National Center for Ecological Analysis and Synthesis
6
 *    Authors: Matt Jones, Jivka Bojilova
7
 *    Release: @release@
8
 *
9
 *   '$Author: jones $'
10
 *     '$Date: 2004-03-26 17:40:45 -0800 (Fri, 26 Mar 2004) $'
11
 * '$Revision: 2068 $'
12
 *
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
 */
27

    
28
package edu.ucsb.nceas.metacat;
29

    
30
import java.io.File;
31
import java.net.MalformedURLException;
32
import java.net.URL;
33
import java.util.Hashtable;
34
import java.util.Stack;
35
import java.util.Vector;
36

    
37
import edu.ucsb.nceas.dbadapter.AbstractDatabase;
38
import edu.ucsb.nceas.utilities.Options;
39

    
40
/**
41
 * A suite of utility classes for the metadata catalog server
42
 */
43
public class MetaCatUtil
44
{
45

    
46
    public static AbstractDatabase dbAdapter;
47

    
48
    private static Options options = null;
49

    
50
    private static boolean debug = true;
51

    
52
    /**
53
     * Determine our db adapter class and create an instance of that class
54
     */
55
    static {
56
        try {
57
            dbAdapter = (AbstractDatabase) createObject(getOption("dbAdapter"));
58
        } catch (Exception e) {
59
            System.err.println("Error in MetaCatUtil static block:"
60
                    + e.getMessage());
61
        }
62
    }
63

    
64
    /**
65
     * Instantiate a class using the name of the class at runtime
66
     * 
67
     * @param className the fully qualified name of the class to instantiate
68
     */
69
    public static Object createObject(String className) throws Exception
70
    {
71

    
72
        Object object = null;
73
        try {
74
            Class classDefinition = Class.forName(className);
75
            object = classDefinition.newInstance();
76
        } catch (InstantiationException e) {
77
            throw e;
78
        } catch (IllegalAccessException e) {
79
            throw e;
80
        } catch (ClassNotFoundException e) {
81
            throw e;
82
        }
83
        return object;
84
    }
85

    
86
    /**
87
     * Utility method to get an option value from the properties file
88
     * 
89
     * @param optionName the name of the option requested
90
     * @return the String value for the option, or null if not set
91
     */
92
    public static String getOption(String optionName)
93
    {
94
        if (options == null) {
95
            options = Options.getInstance();
96
        }
97
        String value = options.getOption(optionName);
98
        return value;
99
    }
100

    
101
    /** Utility method to convert a file handle into a URL */
102
    public static URL fileToURL(File file)
103
    {
104
        String path = file.getAbsolutePath();
105
        String fSep = System.getProperty("file.separator");
106
        if (fSep != null && fSep.length() == 1)
107
                path = path.replace(fSep.charAt(0), '/');
108
        if (path.length() > 0 && path.charAt(0) != '/') path = '/' + path;
109
        try {
110
            return new URL("file", null, path);
111
        } catch (java.net.MalformedURLException e) {
112
            /*
113
             * According to the spec this could only happen if the file
114
             */
115
            throw new Error("unexpected MalformedURLException");
116
        }
117
    }
118

    
119
    /**
120
     * Utility method to parse the query part of a URL into parameters. This
121
     * method assumes the format of the query par tof the url is an ampersand
122
     * separated list of name/value pairs, with equal signs separating the name
123
     * from the value (e.g., name=tom&zip=99801 ). Returns a has of the name
124
     * value pairs, hashed on name.
125
     */
126
    public static Hashtable parseQuery(String query)
127
            throws MalformedURLException
128
    {
129
        String[][] params = new String[200][2];
130
        Hashtable parameters = new Hashtable();
131

    
132
        String temp = "";
133
        boolean ampflag = true;
134
        boolean poundflag = false;
135
        int arrcount = 0;
136

    
137
        if (query != null) {
138
            for (int i = 0; i < query.length(); i++) {
139

    
140
                // go throught the remainder of the query one character at a
141
                // time.
142
                if (query.charAt(i) == '=') {
143
                    // if the current char is a # then the preceding should be
144
                    // a name
145
                    if (!poundflag && ampflag) {
146
                        params[arrcount][0] = temp.trim();
147
                        temp = "";
148
                    } else {
149
                        //if there are two #s or &s in a row throw an
150
                        // exception.
151
                        throw new MalformedURLException(
152
                                "metacatURL: Two parameter names "
153
                                        + "not allowed in sequence");
154
                    }
155
                    poundflag = true;
156
                    ampflag = false;
157
                } else if (query.charAt(i) == '&' || i == query.length() - 1) {
158
                    //the text preceding the & should be the param value.
159
                    if (i == query.length() - 1) {
160
                        //if at the end of the string grab the last value and
161
                        // append it.
162
                        if (query.charAt(i) != '=') {
163
                            //ignore an extra & on the end of the string
164
                            temp += query.charAt(i);
165
                        }
166
                    }
167

    
168
                    if (!ampflag && poundflag) {
169
                        params[arrcount][1] = temp.trim();
170
                        parameters
171
                                .put(params[arrcount][0], params[arrcount][1]);
172
                        temp = "";
173
                        arrcount++; //increment the array to the next row.
174
                    } else {
175
                        //if there are two =s or &s in a row through an
176
                        // exception
177
                        throw new MalformedURLException(
178
                                "metacatURL: Two parameter values "
179
                                        + "not allowed in sequence");
180
                    }
181
                    poundflag = false;
182
                    ampflag = true;
183
                } else {
184
                    //get the next character in the string
185
                    temp += query.charAt(i);
186
                }
187
            }
188
        }
189
        return parameters;
190
    }
191

    
192
    /**
193
     * Utility method to print debugging messages. User can set debug level for
194
     * this message. The number is fewer, the message is more important
195
     * 
196
     * @param msg, the content of the message
197
     * @param debugLevel, an integer indicating the message debug leve
198
     */
199
    public static void debugMessage(String msg, int debugLevel)
200
    {
201
        if (debug) {
202
            int limit = 1;
203
            try {
204
                limit = Integer.parseInt(getOption("debuglevel"));
205

    
206
            } catch (Exception e) {
207
                System.out.println(e.getMessage());
208
            }
209
            //don't allow the user set debugLevel less than or equals 0
210
            if (debugLevel <= 0) {
211
                debugLevel = 1;
212
            }
213

    
214
            if (debugLevel < limit) {
215
                System.err.println("@debugprefix@ " + msg);
216
            }
217
        }
218
    }
219

    
220
    public static Vector getOptionList(String optiontext)
221
    {
222
        Vector optionsVector = new Vector();
223
        if (optiontext.indexOf(",") == -1) {
224
            optionsVector.addElement(optiontext);
225
            return optionsVector;
226
        }
227

    
228
        while (optiontext.indexOf(",") != -1) {
229
            String s = optiontext.substring(0, optiontext.indexOf(","));
230
            optionsVector.addElement(s.trim());
231
            optiontext = optiontext.substring(optiontext.indexOf(",") + 1,
232
                    optiontext.length());
233
            if (optiontext.indexOf(",") == -1) { //catch the last list entry
234
                optionsVector.addElement(optiontext.trim());
235
            }
236
        }
237
        return optionsVector;
238
    }
239

    
240
    /** Normalizes the given string. Taken from configXML.java */
241
    public static String normalize(String s)
242
    {
243
        StringBuffer str = new StringBuffer();
244

    
245
        int len = (s != null) ? s.length() : 0;
246
        for (int i = 0; i < len; i++) {
247
            char ch = s.charAt(i);
248
            switch (ch) {
249
            case '<':
250
                {
251
                    str.append("&lt;");
252
                    break;
253
                }
254
            case '>':
255
                {
256
                    str.append("&gt;");
257
                    break;
258
                }
259
            case '&':
260
                {
261
                    str.append("&amp;");
262
                    break;
263
                }
264
            case '"':
265
                {
266
                    str.append("&quot;");
267
                    break;
268
                }
269
            case '\r':
270
            case '\n':
271
                {
272
                    // else, default append char
273
                }
274
            default:
275
                {
276
                    str.append(ch);
277
                }
278
            }
279
        }
280
        return (str.toString());
281
    }
282

    
283
    /**
284
     * Get docid from online/url string
285
     */
286
    public static String getDocIdWithRevFromOnlineURL(String url)
287
    {
288
        String docid = null;
289
        String DOCID = "docid";
290
        boolean find = false;
291
        char limited = '&';
292
        int count = 0; //keep track how many & was found
293
        Vector list = new Vector();// keep index number for &
294
        if (url == null) {
295
            MetaCatUtil.debugMessage("url is null and null will be returned",
296
                    30);
297
            return docid;
298
        }
299
        // the first element in list is 0
300
        list.add(new Integer(0));
301
        for (int i = 0; i < url.length(); i++) {
302
            if (url.charAt(i) == limited) {
303
                // count plus 1
304
                count++;
305
                list.add(new Integer(i));
306
                // get substring beween two &
307
                String str = url.substring(
308
                        ((Integer) list.elementAt(count - 1)).intValue(), i);
309
                MetaCatUtil.debugMessage("substring between two & is: " + str,
310
                        30);
311
                //if the subString contains docid, we got it
312
                if (str.indexOf(DOCID) != -1) {
313
                    //get index of '="
314
                    int start = getIndexForGivenChar(str, '=') + 1;
315
                    int end = str.length();
316
                    docid = str.substring(start, end);
317
                    find = true;
318
                }//if
319
            }//if
320
        }//for
321
        //if not find, we need check the subtring between the index of last &
322
        // and
323
        // the end of string
324
        if (!find) {
325
            MetaCatUtil.debugMessage("Checking the last substring", 35);
326
            String str = url.substring(((Integer) list.elementAt(count))
327
                    .intValue() + 1, url.length());
328
            MetaCatUtil.debugMessage("Last substring is: " + str, 30);
329
            if (str.indexOf(DOCID) != -1) {
330
                //get index of '="
331
                int start = getIndexForGivenChar(str, '=') + 1;
332
                int end = str.length();
333
                docid = str.substring(start, end);
334
                find = true;
335
            }//if
336
        }//if
337
        MetaCatUtil.debugMessage("The docid from online url is:" + docid, 30);
338
        return docid.trim();
339
    }
340

    
341
    private static int getIndexForGivenChar(String str, char character)
342
    {
343
        int index = -1;
344
        // make sure str is not null
345
        if (str == null) {
346
            MetaCatUtil.debugMessage(
347
                    "The given str is null and -1 will be returned", 30);
348
            return index;
349
        }
350
        // got though the string
351
        for (int i = 0; i < str.length(); i++) {
352
            // find the first one then break the loop
353
            if (str.charAt(i) == character) {
354
                index = i;
355
                break;
356
            }//if
357
        }//for
358
        MetaCatUtil.debugMessage("the index for char " + character + " is: "
359
                + index, 30);
360
        return index;
361
    }
362

    
363
    /**
364
     * Utility method to get docid from a given string
365
     * 
366
     * @param string, the given string should be these two format: 1) str1.str2
367
     *            in this case docid= str1.str2 2) str1.str2.str3, in this case
368
     *            docid =str1.str2
369
     * @param the sperator char
370
     */
371
    public static String getDocIdFromString(String str)
372
    {
373
        String docId = null;
374
        if (str == null) {
375
            MetaCatUtil.debugMessage(
376
                    "The given str is null and null will be returned"
377
                            + " in getDocIdfromString", 30);
378
            return docId;
379
        } //make sure docid is not null
380
        int dotNumber = 0;//count how many dots in given string
381
        int indexOfLastDot = 0;
382

    
383
        //assume that seperator is one charactor string
384
        char seperator = getOption("accNumSeparator").charAt(0);
385

    
386
        for (int i = 0; i < str.length(); i++) {
387
            if (str.charAt(i) == seperator) {
388
                dotNumber++;//count how many dots
389
                indexOfLastDot = i;//keep the last dot postion
390
            }
391
        }//for
392

    
393
        //The string formatt is wrong, because it has more than two or less
394
        // than
395
        //one seperator
396
        if (dotNumber > 2 || dotNumber < 1) {
397
            docId = null;
398
        } else if (dotNumber == 2) //the case for str1.str2.str3
399
        {
400
            docId = str.substring(0, indexOfLastDot);
401
        } else if (dotNumber == 1) //the case for str1.str2
402
        {
403
            docId = str;
404
        }
405

    
406
        return docId;
407
    }//getDocIdFromString
408

    
409
    /**
410
     * Utility method to get version number from a given string
411
     * 
412
     * @param string, the given string should be these two format: 1)
413
     *            str1.str2(no version) version =-1; 2) str1.str2.str3, in this
414
     *            case version = str3; 3) other, vresion =-2
415
     */
416
    public static int getVersionFromString(String str)
417
            throws NumberFormatException
418
    {
419
        int version = -1;
420
        String versionString = null;
421
        int dotNumber = 0;//count how many dots in given string
422
        int indexOfLastDot = 0;
423

    
424
        //assume that seperator is one charactor string
425
        char seperator = getOption("accNumSeparator").charAt(0);
426

    
427
        for (int i = 0; i < str.length(); i++) {
428
            if (str.charAt(i) == seperator) {
429
                dotNumber++;//count how many dots
430
                indexOfLastDot = i;//keep the last dot postion
431
            }
432
        }//for
433

    
434
        //The string formatt is wrong, because it has more than two or less
435
        // than
436
        //one seperator
437
        if (dotNumber > 2 || dotNumber < 1) {
438
            version = -2;
439
        } else if (dotNumber == 2 && (indexOfLastDot != (str.length() - 1)))
440
        //the case for str1.str2.str3
441
        {
442
            versionString = str.substring((indexOfLastDot + 1), str.length());
443
            version = Integer.parseInt(versionString);
444
        } else if (dotNumber == 1) //the case for str1.str2
445
        {
446
            version = -1;
447
        }
448

    
449
        return version;
450
    }//getVersionFromString
451

    
452
    /**
453
     * Utility method to get version string from a given string
454
     * 
455
     * @param string, the given string should be these two format: 1)
456
     *            str1.str2(no version) version=null; 2) str1.str2.str3, in
457
     *            this case version = str3; 3) other, vresion =null;
458
     */
459
    public static String getRevisionStringFromString(String str)
460
            throws NumberFormatException
461
    {
462
        // String to store the version
463
        String versionString = null;
464
        int dotNumber = 0;//count how many dots in given string
465
        int indexOfLastDot = 0;
466

    
467
        //assume that seperator is one charactor string
468
        char seperator = getOption("accNumSeparator").charAt(0);
469

    
470
        for (int i = 0; i < str.length(); i++) {
471
            if (str.charAt(i) == seperator) {
472
                dotNumber++;//count how many dots
473
                indexOfLastDot = i;//keep the last dot postion
474
            }
475
        }//for
476

    
477
        //The string formatt is wrong, because it has more than two or less
478
        // than
479
        //one seperator
480
        if (dotNumber > 2 || dotNumber < 1) {
481
            versionString = null;
482
        } else if (dotNumber == 2 && (indexOfLastDot != (str.length() - 1))) {
483
            //the case for str1.str2.str3
484
            // indexOfLastDot != (str.length() -1) means get rid of str1.str2.
485
            versionString = str.substring((indexOfLastDot + 1), str.length());
486
        } else if (dotNumber == 1) //the case for str1.str2 or str1.str2.
487
        {
488
            versionString = null;
489
        }
490

    
491
        return versionString;
492
    }//getVersionFromString
493

    
494
    /**
495
     * This method will get docid from an AccessionNumber. There is no
496
     * assumption the accessnumber will be str1.str2.str3. It can be more. So
497
     * we think the docid will be get rid of last part
498
     */
499
    public static String getDocIdFromAccessionNumber(String accessionNumber)
500
    {
501
        String docid = null;
502
        if (accessionNumber == null) { return docid; }
503
        String seperator = getOption("accNumSeparator");
504
        int indexOfLastSeperator = accessionNumber.lastIndexOf(seperator);
505
        docid = accessionNumber.substring(0, indexOfLastSeperator);
506
        MetaCatUtil.debugMessage("after parsing accessionnumber, docid is "
507
                + docid, 30);
508
        return docid;
509
    }
510

    
511
    /**
512
     * This method will call both getDocIdFromString and
513
     * getDocIdFromAccessionNumber. So first, if the string looks str1.str2,
514
     * the docid will be str1.str2. If the string is str1.str2.str3, the docid
515
     * will be str1.str2. If the string is str1.str2.str3.str4 or more, the
516
     * docid will be str1.str2.str3. If the string look like str1, null will be
517
     * returned
518
     *  
519
     */
520
    public static String getSmartDocId(String str)
521
    {
522
        String docid = null;
523
        //call geDocIdFromString first.
524
        docid = getDocIdFromString(str);
525
        // If docid is null, try to call getDocIdFromAccessionNumber
526
        // it will handle the seperator more than2
527
        if (docid == null) {
528
            docid = getDocIdFromAccessionNumber(str);
529
        }
530
        MetaCatUtil.debugMessage("The docid get from smart docid getor is "
531
                + docid, 30);
532
        return docid;
533
    }
534

    
535
    /**
536
     * This method will get revision from an AccessionNumber. There is no
537
     * assumption the accessnumber will be str1.str2.str3. It can be more. So
538
     * we think the docid will be get rid of last part
539
     */
540
    public static int getRevisionFromAccessionNumber(String accessionNumber)
541
            throws NumberFormatException
542
    {
543
        String rev = null;
544
        int revNumber = -1;
545
        if (accessionNumber == null) { return revNumber; }
546
        String seperator = getOption("accNumSeparator");
547
        int indexOfLastSeperator = accessionNumber.lastIndexOf(seperator);
548
        rev = accessionNumber.substring(indexOfLastSeperator + 1,
549
                accessionNumber.length());
550
        revNumber = Integer.parseInt(rev);
551
        MetaCatUtil.debugMessage("after parsing accessionnumber, rev is "
552
                + revNumber, 30);
553
        return revNumber;
554
    }
555

    
556
    /**
557
     * Method to get the name of local replication server
558
     */
559
    public static String getLocalReplicationServerName()
560
    {
561
        String replicationServerName = null;
562
        String serverHost = null;
563
        serverHost = getOption("server");
564
        // append "context/servelet/replication" to the host name
565
        replicationServerName = serverHost + getOption("replicationpath");
566
        return replicationServerName;
567

    
568
    }
569

    
570
    /**
571
     * Method to get docidwithrev from eml2 inline data id The eml inline data
572
     * id would look like eml.200.2.3
573
     */
574
    public static String getDocIdWithoutRevFromInlineDataID(String inlineDataID)
575
    {
576
        String docidWithoutRev = null;
577
        if (inlineDataID == null) { return docidWithoutRev; }
578
        String seperator = MetaCatUtil.getOption("accNumSeparator");
579
        char charSeperator = seperator.charAt(0);
580
        int targetNumberOfSeperator = 2;// we want to know his index
581
        int numberOfSeperator = 0;
582
        for (int i = 0; i < inlineDataID.length(); i++) {
583
            // meet seperator, increase number of seperator
584
            if (inlineDataID.charAt(i) == charSeperator) {
585
                numberOfSeperator++;
586
            }
587
            // if number of seperator reach the target one, record the index(i)
588
            // and get substring and terminate the loop
589
            if (numberOfSeperator == targetNumberOfSeperator) {
590
                docidWithoutRev = inlineDataID.substring(0, i);
591
                break;
592
            }
593
        }
594

    
595
        MetaCatUtil.debugMessage("Docid without rev from inlinedata id: "
596
                + docidWithoutRev, 35);
597
        return docidWithoutRev;
598

    
599
    }
600

    
601
    /**
602
     * Revise stack change a stack to opposite order
603
     */
604
    public static Stack reviseStack(Stack stack)
605
    {
606
        Stack result = new Stack();
607
        // make sure the parameter is correct
608
        if (stack == null || stack.isEmpty()) {
609
            result = stack;
610
            return result;
611
        }
612

    
613
        while (!stack.isEmpty()) {
614
            Object obj = stack.pop();
615
            result.push(obj);
616
        }
617
        return result;
618
    }
619

    
620
    /** A method to replace whitespace in url */
621
    public static String replaceWhiteSpaceForURL(String urlHasWhiteSpace)
622
    {
623
        StringBuffer newUrl = new StringBuffer();
624
        String whiteSpaceReplace = "%20";
625
        if (urlHasWhiteSpace == null || urlHasWhiteSpace.trim().equals("")) { return null; }
626

    
627
        for (int i = 0; i < urlHasWhiteSpace.length(); i++) {
628
            char ch = urlHasWhiteSpace.charAt(i);
629
            if (!Character.isWhitespace(ch)) {
630
                newUrl.append(ch);
631
            } else {
632
                //it is white sapce, replace it by %20
633
                newUrl = newUrl.append(whiteSpaceReplace);
634
            }
635

    
636
        }//for
637
        MetaCatUtil.debugMessage("The new string without space is:"
638
                + newUrl.toString(), 35);
639
        return newUrl.toString();
640

    
641
    }// replaceWhiteSpaceForUR
642

    
643
}
(42-42/61)