KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > derby > iapi > util > IdUtil


1 /*
2
3    Derby - Class com.ihost.cs.IdUtil
4
5    Licensed to the Apache Software Foundation (ASF) under one or more
6    contributor license agreements. See the NOTICE file distributed with
7    this work for additional information regarding copyright ownership.
8    The ASF licenses this file to you under the Apache License, Version 2.0
9    (the "License"); you may not use this file except in compliance with
10    the License. You may obtain a copy of the License at
11
12       http://www.apache.org/licenses/LICENSE-2.0
13
14    Unless required by applicable law or agreed to in writing, software
15    distributed under the License is distributed on an "AS IS" BASIS,
16    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17    See the License for the specific language governing permissions and
18    limitations under the License.
19
20  */

21
22 package org.apache.derby.iapi.util;
23
24 import org.apache.derby.iapi.reference.Attribute;
25 import org.apache.derby.iapi.reference.SQLState;
26 import org.apache.derby.iapi.reference.Property;
27 import org.apache.derby.iapi.error.StandardException;
28 import java.io.IOException JavaDoc;
29 import java.io.StringReader JavaDoc;
30 import java.util.Vector JavaDoc;
31 import java.util.HashSet JavaDoc;
32 import java.util.Properties JavaDoc;
33
34 /**
35   Utility class for parsing and producing string representations of
36   ids. This class supports both delimited and un-delimited ids.
37
38   <P>The syntax for an id follows.
39   <PRE>
40       id := delim-id | unDelim-id
41
42       delim-id := "[""|[any char but quote]]+"
43       undelim-id := (a-z|A-Z|anyunicodeletter)[a-z|A-Z|_|0-9|anyunicodeletter|anyunicodedigit]*
44
45       In the syntax braces show grouping. '*' means repeat 0 or more times.
46       '|' means or. '+' means repeat 1 or more times.
47   </PRE>
48
49   <P>In addition this class provides support for qualified names. A qualified name
50   is a dot (.) separated list of ids.
51
52   <P>Limitations:
53   <OL>
54   <LI>Unicode escape sequences in ids are not supported.
55   <LI>Escape sequences (\n...) are not supported.
56   </OL>
57   */

58 public abstract class IdUtil
59 {
60     /**
61       Delimit the identifier provided.
62       @return the delimited identifier.
63       */

64     public static String JavaDoc delimitId(String JavaDoc id)
65     {
66         StringBuffer JavaDoc quotedBuffer = new StringBuffer JavaDoc();
67         quotedBuffer.append('\"');
68         char[] charArray = id.toCharArray();
69
70         for (int ix = 0; ix < charArray.length; ix++){
71             char currentChar = charArray[ix];
72             quotedBuffer.append(currentChar);
73             if (currentChar == '\"')
74                 quotedBuffer.append('\"');
75         }
76         quotedBuffer.append('\"');
77         
78         return quotedBuffer.toString();
79     }
80
81     /**
82       Produce a delimited two part qualified name from two
83       un-delimited identifiers.
84       @return the result.
85       */

86     public static String JavaDoc mkQualifiedName(String JavaDoc id1,
87                                          String JavaDoc id2)
88     {
89         if( null == id1)
90             return delimitId(id2);
91         return
92             delimitId(id1) +
93             "." +
94             delimitId(id2);
95     }
96
97     /**
98       Make a string form of a qualified name from the array of ids provided.
99       */

100     public static String JavaDoc mkQualifiedName(String JavaDoc[] ids)
101     {
102         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
103         for (int ix=0; ix < ids.length; ix++)
104         {
105             if (ix!=0) sb.append(".");
106             sb.append(delimitId(ids[ix]));
107         }
108         return sb.toString();
109     }
110
111     /**
112       Scan a qualified name from the String provided. Raise an excepion
113       if the string does not contain a qualified name.
114       
115       @param s The string to be parsed
116       @param normalizeToUpper If true then undelimited names are converted to upper case (the ANSI standard). If false then undelimited names are converted to lower case (used when the source database is Informix Foundation).
117       @return An array of strings made by breaking the input string at its dots, '.'.
118       @exception StandardException Oops
119       */

120     public static String JavaDoc[] parseQualifiedName(String JavaDoc s, boolean normalizeToUpper)
121          throws StandardException
122     {
123         StringReader JavaDoc r = new StringReader JavaDoc(s);
124         String JavaDoc[] qName = parseQualifiedName(r, normalizeToUpper);
125         verifyEmpty(r);
126         return qName;
127     }
128
129     /**
130       Scan a qualified name from a StringReader. Return an array
131       of Strings with 1 entry per name scanned. Raise an exception
132       if the StringReader does not contain a valid qualified name.
133
134       @param r A StringReader for the string to be parsed
135       @param normalizeToUpper If true then undelimited names are converted to upper case (the ANSI standard). If false then undelimited names are converted to lower case (used when the source database is Informix Foundation).
136       @return An array of strings made by breaking the input string at its dots, '.'.
137       @exception StandardException Oops
138       */

139     public static String JavaDoc[] parseQualifiedName(StringReader JavaDoc r, boolean normalizeToUpper)
140          throws StandardException
141     {
142         Vector JavaDoc v = new Vector JavaDoc();
143         while (true)
144         {
145             String JavaDoc thisId = parseId(r,true, normalizeToUpper);
146             v.addElement(thisId);
147             int dot;
148
149             try {
150                 r.mark(0);
151                 dot = r.read();
152                 if (dot != '.')
153                 {
154                     if (dot!=-1) r.reset();
155                     break;
156                 }
157             }
158
159             catch (IOException JavaDoc ioe){
160                 throw StandardException.newException(SQLState.ID_PARSE_ERROR,ioe);
161             }
162         }
163         String JavaDoc[] result = new String JavaDoc[v.size()];
164         v.copyInto(result);
165         return result;
166     }
167     
168     /**
169       Convert the String provided to an ID. Throw an exception
170       iff the string does not contain only a valid external form
171       for an id. This is a convenience routine that simply
172       uses getId(StringReader) to do the work.
173       
174       <P> See the header for getId below for restrictions.
175       
176       @exception StandardException Oops
177       */

178     public static String JavaDoc parseId(String JavaDoc s)
179          throws StandardException
180     {
181         StringReader JavaDoc r = new StringReader JavaDoc(s);
182         String JavaDoc id = parseId(r,true, true);
183         verifyEmpty(r);
184         return id;
185     }
186
187     /**
188       Read an id from the StringReader provided.
189
190
191       @param normalize true means return ids in nomral form, false means
192             return them as they were entered.
193
194       <P>
195       Raise an exception if the first thing in the StringReader
196       is not a valid id.
197
198       @exception StandardException Ooops.
199       */

200     public static String JavaDoc parseId(StringReader JavaDoc r, boolean normalize, boolean normalizeToUpper)
201          throws StandardException
202     {
203         try {
204             r.mark(0);
205             int c = r.read();
206             if (c == -1) //id can't be 0-length
207
throw StandardException.newException(SQLState.ID_PARSE_ERROR);
208             r.reset();
209             if (c == '"')
210                 return parseQId(r,normalize);
211             else
212                 return parseUnQId(r,normalize, normalizeToUpper);
213         }
214
215         catch (IOException JavaDoc ioe){
216             throw StandardException.newException(SQLState.ID_PARSE_ERROR,ioe);
217         }
218     }
219
220     private static String JavaDoc parseUnQId(StringReader JavaDoc r, boolean normalize, boolean normalizeToUpper)
221          throws IOException JavaDoc,StandardException
222     {
223         StringBuffer JavaDoc b = new StringBuffer JavaDoc();
224         int c;
225         boolean first;
226         //
227
for(first = true; ; first=false)
228         {
229             r.mark(0);
230             if (idChar(first,c=r.read()))
231                 b.append((char)c);
232             else
233                 break;
234         }
235         if (c != -1) r.reset();
236
237         if (normalize)
238             return normalizeToUpper ? StringUtil.SQLToUpperCase(b.toString()) : StringUtil.SQLToLowerCase(b.toString());
239         else
240             return b.toString();
241     }
242
243
244     private static boolean idChar(boolean first,int c)
245     {
246         if (((c>='a' && c<='z') || (c>='A' && c<='Z')) ||
247             (!first &&(c>='0' && c<='9')) || (!first &&c =='_') )
248             return true;
249         else if (Character.isLetter((char) c))
250             return true;
251         else if (!first && Character.isDigit((char) c))
252             return true;
253         return false;
254     }
255     private static String JavaDoc parseQId(StringReader JavaDoc r,boolean normalize)
256          throws IOException JavaDoc,StandardException
257     {
258         StringBuffer JavaDoc b = new StringBuffer JavaDoc();
259         int c = r.read();
260         if (c != '"') throw StandardException.newException(SQLState.ID_PARSE_ERROR);
261         while (true)
262         {
263             c=r.read();
264             if (c == '"')
265             {
266                 r.mark(0);
267                 int c2 = r.read();
268                 if (c2 != '"')
269                 {
270                     if (c2!=-1)r.reset();
271                     break;
272                 }
273             }
274             else if (c == -1)
275                 throw StandardException.newException(SQLState.ID_PARSE_ERROR);
276             
277             b.append((char)c);
278         }
279
280         if (b.length() == 0) //id can't be 0-length
281
throw StandardException.newException(SQLState.ID_PARSE_ERROR);
282
283         if (normalize)
284             return b.toString();
285         else
286             return delimitId(b.toString()); //Put the quotes back.
287
}
288
289     private static void verifyEmpty(java.io.Reader JavaDoc r)
290          throws StandardException
291     {
292         try {
293             if (r.read() != -1)
294                 throw StandardException.newException(SQLState.ID_PARSE_ERROR);
295         }
296
297         catch (IOException JavaDoc ioe){
298             throw StandardException.newException(SQLState.ID_PARSE_ERROR,ioe);
299         }
300     }
301     /**Index of the schema name in a jar name on a db classpath*/
302     public static final int DBCP_SCHEMA_NAME = 0;
303     /**Index of the sql jar name in a jar name on a db classpath*/
304     public static final int DBCP_SQL_JAR_NAME = 1;
305     
306     /**
307       Scan a database classpath from the string provided. This returns
308       an array with one qualified name per entry on the classpath. The
309       constants above describe the content of the returned names. This
310       raises an an exception if the string does not contain a valid database
311       class path.
312   <PRE>
313       classpath := item[:item]*
314       item := id.id
315       
316       In the syntax braces ([]) show grouping. '*' means repeat 0 or more times.
317       The syntax for id is defined in IdUtil.
318   </PRE>
319       <BR>
320       Classpath returned is a two part name. <BR>
321       If the class path is empty then this returns an array
322       of zero length.
323
324       @exception StandardException Oops
325       */

326     public static String JavaDoc[][] parseDbClassPath(String JavaDoc input, boolean normalizeToUpper)
327          throws StandardException
328     {
329         //As a special case we accept a zero length dbclasspath.
330
if (input.length() == 0)
331             return new String JavaDoc[0][];
332
333         Vector JavaDoc v = new Vector JavaDoc();
334         java.io.StringReader JavaDoc r = new java.io.StringReader JavaDoc(input);
335         //
336
while (true)
337         {
338             try {
339                 String JavaDoc[] thisQName = IdUtil.parseQualifiedName(r, normalizeToUpper);
340                 if (thisQName.length != 2)
341                     throw StandardException.newException(SQLState.DB_CLASS_PATH_PARSE_ERROR,input);
342
343                 v.addElement(thisQName);
344                 int delim = r.read();
345                 if (delim != ':')
346                 {
347                     if (delim!=-1)
348                         throw StandardException.newException(SQLState.DB_CLASS_PATH_PARSE_ERROR,input);
349                     break;
350                 }
351             }
352             
353             catch (StandardException se){
354                 if (se.getMessageId().equals(SQLState.ID_PARSE_ERROR))
355                     throw StandardException.newException(SQLState.DB_CLASS_PATH_PARSE_ERROR,
356                                                          se,input);
357                 else
358                     throw se;
359             }
360             
361             catch (IOException JavaDoc ioe){
362                 throw StandardException.newException(SQLState.DB_CLASS_PATH_PARSE_ERROR,ioe,input);
363             }
364         }
365         String JavaDoc[][] result = new String JavaDoc[v.size()][];
366         v.copyInto(result);
367         return result;
368     }
369
370
371     /*
372     ** Methods that operate on lists of identifiers.
373     */

374
375
376     /**
377       Scan a list of ids from the string provided. This returns
378       an array with id per entry. This raises an an exception if
379       the string does not contain a valid list of names.
380
381       @exception StandardException Oops
382       */

383     public static String JavaDoc[] parseIdList(String JavaDoc p)
384          throws StandardException
385     {
386         if (p==null) return null;
387         StringReader JavaDoc r = new StringReader JavaDoc(p);
388         String JavaDoc[] result = parseIdList(r, true);
389         verifyListEmpty(r);
390         return result;
391     }
392     
393     
394     /**
395       Parse an idList.
396
397       @param normalize true means return ids in nomral form, false means
398             return them as they were entered.
399
400       @exception StandardException Oops
401       */

402     private static String JavaDoc[] parseIdList(StringReader JavaDoc r, boolean normalize)
403          throws StandardException
404     {
405         Vector JavaDoc v = new Vector JavaDoc();
406         while (true)
407         {
408             int delim;
409             try {
410                 String JavaDoc thisId = IdUtil.parseId(r,normalize, true);
411                 v.addElement(thisId);
412                 r.mark(0);
413                 delim = r.read();
414                 if (delim != ',')
415                 {
416                     if (delim!=-1) r.reset();
417                     break;
418                 }
419             }
420             
421             catch (StandardException se){
422                 if (se.getMessageId().equals(SQLState.ID_LIST_PARSE_ERROR))
423                     throw StandardException.newException(SQLState.ID_LIST_PARSE_ERROR,se);
424                 else
425                     throw se;
426             }
427             
428             catch (IOException JavaDoc ioe){
429                 throw StandardException.newException(SQLState.ID_LIST_PARSE_ERROR,ioe);
430             }
431         }
432         if (v.size() == 0) return null;
433         String JavaDoc[] result = new String JavaDoc[v.size()];
434         v.copyInto(result);
435         return result;
436     }
437
438     /**
439       Return an IdList with all the ids that in l1 and l2
440       or null if not ids are on both lists.
441
442       @param l1 An array of ids in normal form
443       @param l2 An array of ids in nomral form
444       */

445     public static String JavaDoc intersect(String JavaDoc[] l1, String JavaDoc[] l2)
446     {
447         if (l1 == null || l2 == null) return null;
448         HashSet JavaDoc h = new HashSet JavaDoc();
449         for(int ix=0;ix<l2.length;ix++) h.add(l2[ix]);
450         Vector JavaDoc v = new Vector JavaDoc();
451         for(int ix=0;ix<l1.length;ix++) if (h.contains(l1[ix])) v.addElement(l1[ix]);
452         return vectorToIdList(v,true);
453     }
454
455     /**
456       Return an idList in external form with one id for every
457       element of v. If v has no elements, return null.
458
459       @param normal True means the ids in v are in normal form
460              and false means they are in external form.
461       */

462     private static String JavaDoc vectorToIdList(Vector JavaDoc v,boolean normal)
463     {
464         if (v.size() == 0) return null;
465         String JavaDoc[] a = new String JavaDoc[v.size()];
466         v.copyInto(a);
467         if (normal)
468             return mkIdList(a);
469         else
470             return mkIdListAsEntered(a);
471     }
472
473     /**
474      * Map userName to authorizationId
475      *
476      * @exception StandardException on error
477      */

478     public static String JavaDoc getUserAuthorizationId(String JavaDoc userName) throws StandardException
479     {
480         try {
481             return parseId(userName);
482         }
483         catch (StandardException se) {
484             throw StandardException.newException(SQLState.AUTH_INVALID_USER_NAME, userName);
485         }
486     }
487
488     /**
489      * Get user name from URL properties. Handles the case of "" user.
490      *
491      * @exception StandardException on error
492      */

493     public static String JavaDoc getUserNameFromURLProps(Properties JavaDoc params)
494     {
495         String JavaDoc userName = params.getProperty(Attribute.USERNAME_ATTR,
496                             Property.DEFAULT_USER_NAME);
497         if (userName.equals(""))
498             userName = Property.DEFAULT_USER_NAME;
499
500         return userName;
501     }
502
503     /**
504       Return an IdList with all the ids that are repeated
505       in l.
506
507       @param l a list of ids in normal form.
508       */

509     public static String JavaDoc dups(String JavaDoc[] l)
510     {
511         if (l == null) return null;
512         HashSet JavaDoc h = new HashSet JavaDoc();
513         Vector JavaDoc v = new Vector JavaDoc();
514         for(int ix=0;ix<l.length;ix++)
515         {
516             if (!h.contains(l[ix]))
517                 h.add(l[ix]);
518             else
519                 v.addElement(l[ix]);
520         }
521         return vectorToIdList(v,true);
522     }
523     
524     /**
525       Return an IdList with all the duplicate ids removed
526       @param l a list of ids in external form.
527       @exception StandardException Oops.
528       */

529     public static String JavaDoc pruneDups(String JavaDoc l) throws StandardException
530     {
531         if (l == null) return null;
532         String JavaDoc[] normal_a = parseIdList(l);
533         StringReader JavaDoc r = new StringReader JavaDoc(l);
534         String JavaDoc[] external_a = parseIdList(r,false);
535         HashSet JavaDoc h = new HashSet JavaDoc();
536         Vector JavaDoc v = new Vector JavaDoc();
537         for(int ix=0;ix<normal_a.length;ix++)
538         {
539             if (!h.contains(normal_a[ix]))
540             {
541                 h.add(normal_a[ix]);
542                 v.addElement(external_a[ix]);
543             }
544         }
545         return vectorToIdList(v,false);
546     }
547
548     /**
549       Produce a string form of an idList from an array of
550       normalized ids.
551       */

552     public static String JavaDoc mkIdList(String JavaDoc[] ids)
553     {
554         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
555         for (int ix=0;ix<ids.length; ix++)
556         {
557             if (ix != 0) sb.append(",");
558             sb.append(IdUtil.delimitId(ids[ix]));
559         }
560         return sb.toString();
561     }
562
563     /**
564       Produce an id list from an array of ids in external form
565       */

566     private static String JavaDoc mkIdListAsEntered(String JavaDoc[] externalIds )
567     {
568         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
569         for (int ix=0;ix<externalIds.length; ix++)
570         {
571             if (ix != 0) sb.append(",");
572             sb.append(externalIds[ix]);
573         }
574         return sb.toString();
575     }
576
577     private static void verifyListEmpty(StringReader JavaDoc r)
578          throws StandardException
579     {
580         try {
581             if (r.read() != -1)
582                 throw StandardException.newException(SQLState.ID_LIST_PARSE_ERROR);
583         }
584
585         catch (IOException JavaDoc ioe){
586             throw StandardException.newException(SQLState.ID_LIST_PARSE_ERROR,ioe);
587         }
588         
589
590     }
591
592     /**
593       Return true if the id provided is on the list provided.
594       @param id an id in normal form
595       @param list a list of ids in external form.
596       @exception StandardException oops.
597       */

598     public static boolean idOnList(String JavaDoc id, String JavaDoc list)
599          throws StandardException
600     {
601         if (list==null) return false;
602         String JavaDoc[] list_a = parseIdList(list);
603         for (int ix=0; ix < list_a.length; ix++)
604             if (id.equals(list_a[ix])) return true;
605         return false;
606     }
607
608     /**
609       Delete an id from a list of ids.
610       @param id an id in normal form (quotes removed, upshifted)
611       @param list a comma separated list of ids in external
612              form (possibly delmited or not upshifted).
613       @return the list with the id deleted or null if the
614         resulting list has no ids. If 'id' is not on 'list'
615         this returns list unchanged.
616                  
617       @exception StandardException oops.
618       */

619     public static String JavaDoc deleteId(String JavaDoc id, String JavaDoc list)
620          throws StandardException
621     {
622         if (list==null) return null;
623         Vector JavaDoc v = new Vector JavaDoc();
624         StringReader JavaDoc r = new StringReader JavaDoc(list);
625         String JavaDoc[] enteredList_a = parseIdList(r,false);
626         //
627
//Loop through enteredList element by element
628
//removing elements that match id. Before we
629
//compare we parse each id in list to convert
630
//to normal form.
631
for (int ix=0; ix < enteredList_a.length; ix++)
632             if (!id.equals(IdUtil.parseId(enteredList_a[ix])))
633                 v.addElement(enteredList_a[ix]);
634         if (v.size() == 0)
635             return null;
636         else
637             return vectorToIdList(v,false);
638     }
639
640
641     /**
642       Append an id in external form.
643       @return the list with the id appended.
644       @exception StandardException oops
645       */

646     public static String JavaDoc appendId(String JavaDoc id, String JavaDoc list)
647          throws StandardException
648     {
649         if (list==null)
650             return id;
651         else
652             return list+","+id;
653     }
654 }
655
Popular Tags