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