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: tao $'
10
 *     '$Date: 2004-05-11 18:00:52 -0700 (Tue, 11 May 2004) $'
11
 * '$Revision: 2165 $'
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
    /**
54
     * Determine our db adapter class and create an instance of that class
55
     */
56
    static {
57
        try {
58
            dbAdapter = (AbstractDatabase) createObject(getOption("dbAdapter"));
59
        } catch (Exception e) {
60
            System.err.println("Error in MetaCatUtil static block:"
61
                    + e.getMessage());
62
        }
63
    }
64

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
342

    
343
    /**
344
     * Eocgorid identifier will look like: ecogrid://knb/tao.1.1
345
     * The AccessionNumber tao.1.1 will be returned. If the given doesn't
346
     * contains ecogrid, null will be returned.
347
     * @param identifier String
348
     * @return String
349
     */
350
    public static String getAccessionNumberFromEcogridIdentifier(String identifier)
351
    {
352
      String accessionNumber = null;
353
      if (identifier != null && identifier.startsWith(DBSAXHandler.ECOGRID))
354
      {
355
        // find the last "/" in identifier
356
        int indexOfLastSlash = identifier.lastIndexOf("/");
357
        int start = indexOfLastSlash+1;
358
        int end   = identifier.length();
359
        accessionNumber = identifier.substring(start, end);
360
      }
361
      MetaCatUtil.debugMessage("The accession number from url is " +
362
                                 accessionNumber, 10);
363
      return accessionNumber;
364
    }
365

    
366
    private static int getIndexForGivenChar(String str, char character)
367
    {
368
        int index = -1;
369
        // make sure str is not null
370
        if (str == null) {
371
            MetaCatUtil.debugMessage(
372
                    "The given str is null and -1 will be returned", 30);
373
            return index;
374
        }
375
        // got though the string
376
        for (int i = 0; i < str.length(); i++) {
377
            // find the first one then break the loop
378
            if (str.charAt(i) == character) {
379
                index = i;
380
                break;
381
            }//if
382
        }//for
383
        MetaCatUtil.debugMessage("the index for char " + character + " is: "
384
                + index, 30);
385
        return index;
386
    }
387

    
388
    /**
389
     * Utility method to get docid from a given string
390
     *
391
     * @param string, the given string should be these two format: 1) str1.str2
392
     *            in this case docid= str1.str2 2) str1.str2.str3, in this case
393
     *            docid =str1.str2
394
     * @param the sperator char
395
     */
396
    public static String getDocIdFromString(String str)
397
    {
398
        String docId = null;
399
        if (str == null) {
400
            MetaCatUtil.debugMessage(
401
                    "The given str is null and null will be returned"
402
                            + " in getDocIdfromString", 30);
403
            return docId;
404
        } //make sure docid is not null
405
        int dotNumber = 0;//count how many dots in given string
406
        int indexOfLastDot = 0;
407

    
408
        //assume that seperator is one charactor string
409
        char seperator = getOption("accNumSeparator").charAt(0);
410

    
411
        for (int i = 0; i < str.length(); i++) {
412
            if (str.charAt(i) == seperator) {
413
                dotNumber++;//count how many dots
414
                indexOfLastDot = i;//keep the last dot postion
415
            }
416
        }//for
417

    
418
        //The string formatt is wrong, because it has more than two or less
419
        // than
420
        //one seperator
421
        if (dotNumber > 2 || dotNumber < 1) {
422
            docId = null;
423
        } else if (dotNumber == 2) //the case for str1.str2.str3
424
        {
425
            docId = str.substring(0, indexOfLastDot);
426
        } else if (dotNumber == 1) //the case for str1.str2
427
        {
428
            docId = str;
429
        }
430

    
431
        return docId;
432
    }//getDocIdFromString
433

    
434
    /**
435
     * Utility method to get version number from a given string
436
     *
437
     * @param string, the given string should be these two format: 1)
438
     *            str1.str2(no version) version =-1; 2) str1.str2.str3, in this
439
     *            case version = str3; 3) other, vresion =-2
440
     */
441
    public static int getVersionFromString(String str)
442
            throws NumberFormatException
443
    {
444
        int version = -1;
445
        String versionString = null;
446
        int dotNumber = 0;//count how many dots in given string
447
        int indexOfLastDot = 0;
448

    
449
        //assume that seperator is one charactor string
450
        char seperator = getOption("accNumSeparator").charAt(0);
451

    
452
        for (int i = 0; i < str.length(); i++) {
453
            if (str.charAt(i) == seperator) {
454
                dotNumber++;//count how many dots
455
                indexOfLastDot = i;//keep the last dot postion
456
            }
457
        }//for
458

    
459
        //The string formatt is wrong, because it has more than two or less
460
        // than
461
        //one seperator
462
        if (dotNumber > 2 || dotNumber < 1) {
463
            version = -2;
464
        } else if (dotNumber == 2 && (indexOfLastDot != (str.length() - 1)))
465
        //the case for str1.str2.str3
466
        {
467
            versionString = str.substring((indexOfLastDot + 1), str.length());
468
            version = Integer.parseInt(versionString);
469
        } else if (dotNumber == 1) //the case for str1.str2
470
        {
471
            version = -1;
472
        }
473

    
474
        return version;
475
    }//getVersionFromString
476

    
477
    /**
478
     * Utility method to get version string from a given string
479
     *
480
     * @param string, the given string should be these two format: 1)
481
     *            str1.str2(no version) version=null; 2) str1.str2.str3, in
482
     *            this case version = str3; 3) other, vresion =null;
483
     */
484
    public static String getRevisionStringFromString(String str)
485
            throws NumberFormatException
486
    {
487
        // String to store the version
488
        String versionString = null;
489
        int dotNumber = 0;//count how many dots in given string
490
        int indexOfLastDot = 0;
491

    
492
        //assume that seperator is one charactor string
493
        char seperator = getOption("accNumSeparator").charAt(0);
494

    
495
        for (int i = 0; i < str.length(); i++) {
496
            if (str.charAt(i) == seperator) {
497
                dotNumber++;//count how many dots
498
                indexOfLastDot = i;//keep the last dot postion
499
            }
500
        }//for
501

    
502
        //The string formatt is wrong, because it has more than two or less
503
        // than
504
        //one seperator
505
        if (dotNumber > 2 || dotNumber < 1) {
506
            versionString = null;
507
        } else if (dotNumber == 2 && (indexOfLastDot != (str.length() - 1))) {
508
            //the case for str1.str2.str3
509
            // indexOfLastDot != (str.length() -1) means get rid of str1.str2.
510
            versionString = str.substring((indexOfLastDot + 1), str.length());
511
        } else if (dotNumber == 1) //the case for str1.str2 or str1.str2.
512
        {
513
            versionString = null;
514
        }
515

    
516
        return versionString;
517
    }//getVersionFromString
518

    
519
    /**
520
     * This method will get docid from an AccessionNumber. There is no
521
     * assumption the accessnumber will be str1.str2.str3. It can be more. So
522
     * we think the docid will be get rid of last part
523
     */
524
    public static String getDocIdFromAccessionNumber(String accessionNumber)
525
    {
526
        String docid = null;
527
        if (accessionNumber == null) { return docid; }
528
        String seperator = getOption("accNumSeparator");
529
        int indexOfLastSeperator = accessionNumber.lastIndexOf(seperator);
530
        docid = accessionNumber.substring(0, indexOfLastSeperator);
531
        MetaCatUtil.debugMessage("after parsing accessionnumber, docid is "
532
                + docid, 30);
533
        return docid;
534
    }
535

    
536
    /**
537
     * This method will call both getDocIdFromString and
538
     * getDocIdFromAccessionNumber. So first, if the string looks str1.str2,
539
     * the docid will be str1.str2. If the string is str1.str2.str3, the docid
540
     * will be str1.str2. If the string is str1.str2.str3.str4 or more, the
541
     * docid will be str1.str2.str3. If the string look like str1, null will be
542
     * returned
543
     *
544
     */
545
    public static String getSmartDocId(String str)
546
    {
547
        String docid = null;
548
        //call geDocIdFromString first.
549
        docid = getDocIdFromString(str);
550
        // If docid is null, try to call getDocIdFromAccessionNumber
551
        // it will handle the seperator more than2
552
        if (docid == null) {
553
            docid = getDocIdFromAccessionNumber(str);
554
        }
555
        MetaCatUtil.debugMessage("The docid get from smart docid getor is "
556
                + docid, 30);
557
        return docid;
558
    }
559

    
560
    /**
561
     * This method will get revision from an AccessionNumber. There is no
562
     * assumption the accessnumber will be str1.str2.str3. It can be more. So
563
     * we think the docid will be get rid of last part
564
     */
565
    public static int getRevisionFromAccessionNumber(String accessionNumber)
566
            throws NumberFormatException
567
    {
568
        String rev = null;
569
        int revNumber = -1;
570
        if (accessionNumber == null) { return revNumber; }
571
        String seperator = getOption("accNumSeparator");
572
        int indexOfLastSeperator = accessionNumber.lastIndexOf(seperator);
573
        rev = accessionNumber.substring(indexOfLastSeperator + 1,
574
                accessionNumber.length());
575
        revNumber = Integer.parseInt(rev);
576
        MetaCatUtil.debugMessage("after parsing accessionnumber, rev is "
577
                + revNumber, 30);
578
        return revNumber;
579
    }
580

    
581
    /**
582
     * Method to get the name of local replication server
583
     */
584
    public static String getLocalReplicationServerName()
585
    {
586
        String replicationServerName = null;
587
        String serverHost = null;
588
        serverHost = getOption("server");
589
        // append "context/servelet/replication" to the host name
590
        replicationServerName = serverHost + getOption("replicationpath");
591
        return replicationServerName;
592

    
593
    }
594

    
595
    /**
596
     * Method to get docidwithrev from eml2 inline data id The eml inline data
597
     * id would look like eml.200.2.3
598
     */
599
    public static String getDocIdWithoutRevFromInlineDataID(String inlineDataID)
600
    {
601
        String docidWithoutRev = null;
602
        if (inlineDataID == null) { return docidWithoutRev; }
603
        String seperator = MetaCatUtil.getOption("accNumSeparator");
604
        char charSeperator = seperator.charAt(0);
605
        int targetNumberOfSeperator = 2;// we want to know his index
606
        int numberOfSeperator = 0;
607
        for (int i = 0; i < inlineDataID.length(); i++) {
608
            // meet seperator, increase number of seperator
609
            if (inlineDataID.charAt(i) == charSeperator) {
610
                numberOfSeperator++;
611
            }
612
            // if number of seperator reach the target one, record the index(i)
613
            // and get substring and terminate the loop
614
            if (numberOfSeperator == targetNumberOfSeperator) {
615
                docidWithoutRev = inlineDataID.substring(0, i);
616
                break;
617
            }
618
        }
619

    
620
        MetaCatUtil.debugMessage("Docid without rev from inlinedata id: "
621
                + docidWithoutRev, 35);
622
        return docidWithoutRev;
623

    
624
    }
625

    
626
    /**
627
     * Revise stack change a stack to opposite order
628
     */
629
    public static Stack reviseStack(Stack stack)
630
    {
631
        Stack result = new Stack();
632
        // make sure the parameter is correct
633
        if (stack == null || stack.isEmpty()) {
634
            result = stack;
635
            return result;
636
        }
637

    
638
        while (!stack.isEmpty()) {
639
            Object obj = stack.pop();
640
            result.push(obj);
641
        }
642
        return result;
643
    }
644

    
645
    /** A method to replace whitespace in url */
646
    public static String replaceWhiteSpaceForURL(String urlHasWhiteSpace)
647
    {
648
        StringBuffer newUrl = new StringBuffer();
649
        String whiteSpaceReplace = "%20";
650
        if (urlHasWhiteSpace == null || urlHasWhiteSpace.trim().equals("")) { return null; }
651

    
652
        for (int i = 0; i < urlHasWhiteSpace.length(); i++) {
653
            char ch = urlHasWhiteSpace.charAt(i);
654
            if (!Character.isWhitespace(ch)) {
655
                newUrl.append(ch);
656
            } else {
657
                //it is white sapce, replace it by %20
658
                newUrl = newUrl.append(whiteSpaceReplace);
659
            }
660

    
661
        }//for
662
        MetaCatUtil.debugMessage("The new string without space is:"
663
                + newUrl.toString(), 35);
664
        return newUrl.toString();
665

    
666
    }// replaceWhiteSpaceForUR
667

    
668
}
(43-43/62)