Frames | No Frames |
1: /* NameTransformer.java -- 2: Copyright (C) 2005, 2006 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: // Create the buffer array, reserving the last element for null. 79: String[] n = new String[ st.countTokens() + 1 ]; 80: 81: int pp = 0; 82: while (st.hasMoreTokens()) 83: n [ pp++ ] = st.nextToken(); 84: 85: IntHolder p = new IntHolder(); 86: 87: NameComponent node = readNode(p, n); 88: 89: while (node != null) 90: { 91: components.add(node); 92: node = readNode(p, n); 93: } 94: 95: NameComponent[] name = new NameComponent[ components.size() ]; 96: for (int i = 0; i < name.length; i++) 97: { 98: name [ i ] = (NameComponent) components.get(i); 99: } 100: 101: NameValidator.check(name); 102: 103: return name; 104: } 105: 106: /** 107: * Converts the name into its string representation, as defined in 108: * the specification CORBA naming service. 109: * 110: * A string representation for the name consists of the name components, 111: * separated by a slash '/' character (for example, 'a/b/c'). If the 112: * {@link NameComponent#kind} field is not empty, it is given after 113: * period ('.'), for example 'a.b/c.d/.' . 114: * The period alone represents node where part where both 115: * {@link NameComponent#kind} and {@link NameComponent#id} are empty strings. 116: * 117: * If slash or dot are part of the name, they are escaped by backslash ('\'). 118: * If the backslash itself is part of the name, it is doubled. 119: * 120: * @param a_name a name to convert. 121: * @return a string representation. 122: */ 123: public String toString(NameComponent[] a_name) 124: throws InvalidName 125: { 126: NameValidator.check(a_name); 127: 128: StringBuffer b = new StringBuffer(); 129: 130: NameComponent n; 131: 132: for (int ni = 0; ni < a_name.length; ni++) 133: { 134: n = a_name [ ni ]; 135: appEscaping(b, n.id); 136: if (n.kind.length() > 0) 137: { 138: b.append('.'); 139: appEscaping(b, n.kind); 140: } 141: 142: if (ni < a_name.length - 1) 143: b.append('/'); 144: } 145: return b.toString(); 146: } 147: 148: /** 149: * Append the contents of the string to this 150: * string buffer, inserting the escape sequences, where required. 151: * 152: * @param b a buffer to append the contents to. 153: * @param s a string to append. 154: */ 155: private void appEscaping(StringBuffer b, String s) 156: { 157: char c; 158: for (int i = 0; i < s.length(); i++) 159: { 160: c = s.charAt(i); 161: switch (c) 162: { 163: case '.' : 164: case '/' : 165: case '\\' : 166: b.append('\\'); 167: b.append(c); 168: break; 169: 170: default : 171: b.append(c); 172: break; 173: } 174: } 175: } 176: 177: /** 178: * Assert the end of the current name component. 179: */ 180: private void assertEndOfNode(IntHolder p, String[] t) 181: throws InvalidName 182: { 183: if (t [ p.value ] != null) 184: if (!t [ p.value ].equals("/")) 185: throw new InvalidName("End of node expected at token " + p.value); 186: } 187: 188: /** 189: * Read the named component node. After reading the current positon 190: * advances to the beginning of the next node in an array. 191: * 192: * @param p the current position being wrapped inside the passed 193: * IntHolder. 194: * 195: * @param t the text buffer. 196: * 197: * @return the created node. 198: */ 199: private NameComponent readNode(IntHolder p, String[] t) 200: throws InvalidName 201: { 202: // End of stream has been reached. 203: if (t [ p.value ] == null) 204: return null; 205: 206: NameComponent n = new NameComponent(); 207: 208: if (t [ p.value ].equals(".")) 209: { 210: // The 'id' is missing, but the 'kind' may follow. 211: n.id = ""; 212: p.value++; 213: n.kind = readPart(p, t); 214: assertEndOfNode(p, t); 215: if (t [ p.value ] != null) 216: p.value++; 217: } 218: else if (t [ p.value ].equals("/")) 219: { 220: // This is not allowed here and may happen only 221: // on two subsequent slashes. 222: throw new InvalidName("Unexpected '/' token " + p.value); 223: } 224: else 225: { 226: n.id = readPart(p, t); 227: 228: // If some chars follow the id. 229: if (t [ p.value ] != null) 230: { 231: // Dot means that the kind part follows 232: if (t [ p.value ].equals(".")) 233: { 234: p.value++; 235: n.kind = readPart(p, t); 236: assertEndOfNode(p, t); 237: if (t [ p.value ] != null) 238: p.value++; 239: } 240: 241: // The next name component follows - advance to 242: // the beginning of the next name component. 243: else if (t [ p.value ].equals("/")) 244: { 245: n.kind = ""; 246: p.value++; 247: } 248: else 249: throw new InvalidName("Unexpected '" + t [ p.value ] + 250: "' at token " + p.value 251: ); 252: } 253: else 254: 255: // Id, and then end of sequence. 256: n.kind = ""; 257: } 258: 259: return n; 260: } 261: 262: /** 263: * Read the name part (id or kind). 264: * 265: * @param p the current position. After reading, advances 266: * to the beginning of the next name fragment. 267: * 268: * @param t the string buffer. 269: * 270: * @return the name part with resolved escape sequences. 271: */ 272: private String readPart(IntHolder p, String[] t) 273: { 274: StringBuffer part = new StringBuffer(); 275: 276: while (t [ p.value ] != null && !t [ p.value ].equals(".") && 277: !t [ p.value ].equals("/") 278: ) 279: { 280: if (t [ p.value ].equals(ESCAPE)) 281: { 282: p.value++; 283: part.append(t [ p.value ]); 284: } 285: else 286: part.append(t [ p.value ]); 287: 288: p.value++; 289: } 290: 291: return part.toString(); 292: } 293: 294: public static void main(String[] args) 295: { 296: NameComponent a = new NameComponent("a", "ak"); 297: NameComponent b = new NameComponent("b/z", "b.k"); 298: NameComponent c = new NameComponent("c", ""); 299: 300: NameTransformer sn = new NameTransformer(); 301: 302: try 303: { 304: String s = sn.toString(new NameComponent[] { a, b, c }); 305: System.out.println(s); 306: 307: //NameComponent[] k = toName("a.k/b.k2/c/d/."); 308: //NameComponent[] k = toName("a.bc/.b/c.x"); 309: 310: NameComponent[] k = sn.toName(s); 311: System.out.println("ToString"); 312: 313: for (int i = 0; i < k.length; i++) 314: { 315: System.out.println(k [ i ].id + ":" + k [ i ].kind); 316: } 317: } 318: catch (InvalidName ex) 319: { 320: ex.printStackTrace(); 321: } 322: } 323: 324: }