Frames | No Frames |
1: /* NameTransformer.java -- 2: Copyright (C) 2005 Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: 39: package gnu.CORBA.NamingService; 40: 41: import org.omg.CORBA.IntHolder; 42: import org.omg.CosNaming.NameComponent; 43: import org.omg.CosNaming.NamingContextPackage.InvalidName; 44: 45: import java.util.ArrayList; 46: import java.util.StringTokenizer; 47: 48: /** 49: * This class converts between string and array representations of the 50: * multi component object names. 51: * 52: * @author Audrius Meskauskas, Lithuania (AudriusA@Bioinformatics.org) 53: */ 54: public class NameTransformer 55: { 56: /** 57: * A string, indicating the escape character. 58: */ 59: public static final String ESCAPE = "\\"; 60: 61: /** 62: * Convert the string name representation into the array name 63: * representation. See {@link #toString(NameComponent)} for the 64: * description of this format. 65: * 66: * @param name the string form of the name. 67: * 68: * @return the array form of the name. 69: * 70: * @throws InvalidName if the name cannot be parsed. 71: */ 72: public NameComponent[] toName(String a_name) 73: throws InvalidName 74: { 75: ArrayList components = new ArrayList(); 76: StringTokenizer st = new StringTokenizer(a_name, "./\\", true); 77: 78: String id; 79: String kind; 80: String next; 81: 82: // Create the buffer array, reserving the last element for null. 83: String[] n = new String[ st.countTokens() + 1 ]; 84: 85: int pp = 0; 86: while (st.hasMoreTokens()) 87: n [ pp++ ] = st.nextToken(); 88: 89: IntHolder p = new IntHolder(); 90: 91: NameComponent node = readNode(p, n); 92: 93: while (node != null) 94: { 95: components.add(node); 96: node = readNode(p, n); 97: } 98: 99: NameComponent[] name = new NameComponent[ components.size() ]; 100: for (int i = 0; i < name.length; i++) 101: { 102: name [ i ] = (NameComponent) components.get(i); 103: } 104: 105: NameValidator.check(name); 106: 107: return name; 108: } 109: 110: /** 111: * Converts the name into its string representation, as defined in 112: * the specification CORBA naming service. 113: * 114: * A string representation for the name consists of the name components, 115: * separated by a slash '/' character (for example, 'a/b/c'). If the 116: * {@link NameComponent#kind} field is not empty, it is given after 117: * period ('.'), for example 'a.b/c.d/.' . 118: * The period alone represents node where part where both 119: * {@link NameComponent#kind} and {@link NameComponent#id} are empty strings. 120: * 121: * If slash or dot are part of the name, they are escaped by backslash ('\'). 122: * If the backslash itself is part of the name, it is doubled. 123: * 124: * @param a_name a name to convert. 125: * @return a string representation. 126: */ 127: public String toString(NameComponent[] a_name) 128: throws InvalidName 129: { 130: NameValidator.check(a_name); 131: 132: StringBuffer b = new StringBuffer(); 133: 134: NameComponent n; 135: 136: for (int ni = 0; ni < a_name.length; ni++) 137: { 138: n = a_name [ ni ]; 139: appEscaping(b, n.id); 140: if (n.kind.length() > 0) 141: { 142: b.append('.'); 143: appEscaping(b, n.kind); 144: } 145: 146: if (ni < a_name.length - 1) 147: b.append('/'); 148: } 149: return b.toString(); 150: } 151: 152: /** 153: * Append the contents of the string to this 154: * string buffer, inserting the escape sequences, where required. 155: * 156: * @param b a buffer to append the contents to. 157: * @param s a string to append. 158: */ 159: private void appEscaping(StringBuffer b, String s) 160: { 161: char c; 162: for (int i = 0; i < s.length(); i++) 163: { 164: c = s.charAt(i); 165: switch (c) 166: { 167: case '.' : 168: case '/' : 169: case '\\' : 170: b.append('\\'); 171: b.append(c); 172: break; 173: 174: default : 175: b.append(c); 176: break; 177: } 178: } 179: } 180: 181: /** 182: * Assert the end of the current name component. 183: */ 184: private void assertEndOfNode(IntHolder p, String[] t) 185: throws InvalidName 186: { 187: if (t [ p.value ] != null) 188: if (!t [ p.value ].equals("/")) 189: throw new InvalidName("End of node expected at token " + p.value); 190: } 191: 192: /** 193: * Read the named component node. After reading the current positon 194: * advances to the beginning of the next node in an array. 195: * 196: * @param p the current position being wrapped inside the passed 197: * IntHolder. 198: * 199: * @param t the text buffer. 200: * 201: * @return the created node. 202: */ 203: private NameComponent readNode(IntHolder p, String[] t) 204: throws InvalidName 205: { 206: // End of stream has been reached. 207: if (t [ p.value ] == null) 208: return null; 209: 210: NameComponent n = new NameComponent(); 211: 212: if (t [ p.value ].equals(".")) 213: { 214: // The 'id' is missing, but the 'kind' may follow. 215: n.id = ""; 216: p.value++; 217: n.kind = readPart(p, t); 218: assertEndOfNode(p, t); 219: if (t [ p.value ] != null) 220: p.value++; 221: } 222: else if (t [ p.value ].equals("/")) 223: { 224: // This is not allowed here and may happen only 225: // on two subsequent slashes. 226: throw new InvalidName("Unexpected '/' token " + p.value); 227: } 228: else 229: { 230: n.id = readPart(p, t); 231: 232: // If some chars follow the id. 233: if (t [ p.value ] != null) 234: { 235: // Dot means that the kind part follows 236: if (t [ p.value ].equals(".")) 237: { 238: p.value++; 239: n.kind = readPart(p, t); 240: assertEndOfNode(p, t); 241: if (t [ p.value ] != null) 242: p.value++; 243: } 244: 245: // The next name component follows - advance to 246: // the beginning of the next name component. 247: else if (t [ p.value ].equals("/")) 248: { 249: n.kind = ""; 250: p.value++; 251: } 252: else 253: throw new InvalidName("Unexpected '" + t [ p.value ] + 254: "' at token " + p.value 255: ); 256: } 257: else 258: 259: // Id, and then end of sequence. 260: n.kind = ""; 261: } 262: 263: return n; 264: } 265: 266: /** 267: * Read the name part (id or kind). 268: * 269: * @param p the current position. After reading, advances 270: * to the beginning of the next name fragment. 271: * 272: * @param t the string buffer. 273: * 274: * @return the name part with resolved escape sequences. 275: */ 276: private String readPart(IntHolder p, String[] t) 277: { 278: StringBuffer part = new StringBuffer(); 279: 280: while (t [ p.value ] != null && !t [ p.value ].equals(".") && 281: !t [ p.value ].equals("/") 282: ) 283: { 284: if (t [ p.value ].equals(ESCAPE)) 285: { 286: p.value++; 287: part.append(t [ p.value ]); 288: } 289: else 290: part.append(t [ p.value ]); 291: 292: p.value++; 293: } 294: 295: return part.toString(); 296: } 297: 298: public static void main(String[] args) 299: { 300: NameComponent a = new NameComponent("a", "ak"); 301: NameComponent b = new NameComponent("b/z", "b.k"); 302: NameComponent c = new NameComponent("c", ""); 303: 304: NameTransformer sn = new NameTransformer(); 305: 306: try 307: { 308: String s = sn.toString(new NameComponent[] { a, b, c }); 309: System.out.println(s); 310: 311: //NameComponent[] k = toName("a.k/b.k2/c/d/."); 312: //NameComponent[] k = toName("a.bc/.b/c.x"); 313: 314: NameComponent[] k = sn.toName(s); 315: System.out.println("ToString"); 316: 317: for (int i = 0; i < k.length; i++) 318: { 319: System.out.println(k [ i ].id + ":" + k [ i ].kind); 320: } 321: } 322: catch (InvalidName ex) 323: { 324: ex.printStackTrace(); 325: } 326: } 327: 328: }