001: /*
002: * JacORB - a free Java ORB
003: *
004: * Copyright (C) 1997-2004 Gerald Brose.
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Library General Public
008: * License as published by the Free Software Foundation; either
009: * version 2 of the License, or (at your option) any later version.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Library General Public License for more details.
015: *
016: * You should have received a copy of the GNU Library General Public
017: * License along with this library; if not, write to the Free
018: * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
019: */
020:
021: package org.jacorb.idl;
022:
023: /**
024: * IDL scoped names
025: *
026: * @author Gerald Brose
027: * @version $Id: ScopedName.java,v 1.37 2006/06/20 12:14:35 alphonse.bendt Exp $
028: *
029: */
030:
031: import java.io.PrintWriter;
032: import java.util.*;
033:
034: public class ScopedName extends SimpleTypeSpec implements
035: SwitchTypeSpec {
036: private static Hashtable pseudoScopes = new Hashtable();
037:
038: private static Hashtable enumMap = new Hashtable();
039:
040: private static Stack recursionStack = new Stack();
041:
042: /**
043: * Interfaces define a new scope, but since we can't do that
044: * in Java, this kind of scope is called a 'pseudo scope' and
045: * is just prepended to the interface name
046: */
047:
048: public static void definePseudoScope(String name) {
049: pseudoScopes.put(name, "");
050: }
051:
052: public static boolean isPseudoScope(String name) {
053: return (pseudoScopes.containsKey(name));
054: }
055:
056: /**
057: * unPseudo transforms scoped names like
058: * module.Interface1.Interface2.Type_name to
059: * module.Interface1Package.Interface2Package.Type_name
060: */
061:
062: public static String unPseudoName(String name) {
063: String n = unPseudo(name);
064: if (n.endsWith("PackagePackage") || !n.startsWith("_")
065: && n.endsWith("Package")) {
066: n = n.substring(0, n.lastIndexOf("Package"));
067: }
068: return n;
069: }
070:
071: private static String unPseudo(String name) {
072: if (name.length() > 0 && name.charAt(0) == '.') {
073: name = name.substring(1);
074: }
075:
076: String head = name;
077: String tail = null;
078: int lastDot = name.lastIndexOf('.');
079:
080: if (lastDot < 0)
081: return name;
082:
083: while (!isPseudoScope(head)) {
084: // search for longest tail in scope name which
085: // does not contain a pseudo scope
086:
087: lastDot = head.lastIndexOf('.');
088: if (lastDot < 0)
089: return name;
090: head = name.substring(0, lastDot);
091: tail = name.substring(lastDot + 1);
092: }
093:
094: java.util.StringTokenizer strtok = new java.util.StringTokenizer(
095: head, ".");
096: String scopes[] = new String[strtok.countTokens()];
097:
098: for (int i = 0; strtok.hasMoreTokens(); scopes[i++] = strtok
099: .nextToken())
100: ;
101:
102: StringBuffer newHead = new StringBuffer();
103: int j = 1;
104:
105: newHead.append(scopes[0]);
106:
107: while (!isPseudoScope(newHead.toString())) {
108: if (j == scopes.length)
109: return (name);
110: newHead.append(".");
111: newHead.append(scopes[j++]);
112: }
113:
114: StringBuffer copy = new StringBuffer(newHead.toString());
115: // we have to remember this...
116:
117: newHead.append("Package");
118:
119: while (j < scopes.length) {
120: newHead.append("." + scopes[j]);
121: copy.append("." + scopes[j]);
122: if (isPseudoScope(copy.toString()))
123: newHead.append("Package");
124: j++;
125: }
126:
127: if (tail != null)
128: newHead.append("." + tail);
129: return newHead.toString();
130:
131: }
132:
133: /**
134: * enumerations don't define new scopes in IDL, but their
135: * mapping to Java introduces a new scope by generating
136: * a new class for the enum's type. Thus, enumeration values
137: * have to be additionally scoped in Java.
138: */
139:
140: public static void enumMap(String n, String m) {
141: enumMap.put(n, m);
142: }
143:
144: private static String unEnum(String _name) {
145: String n = (String) enumMap.get(_name);
146: if (n != null)
147: return n;
148: else
149: return _name;
150: }
151:
152: /* end of static part */
153:
154: /* instance part */
155:
156: private TypeSpec resolvedSpec = null;
157: private String resolvedName = null;
158: private boolean resolved = false;
159: private Interface resolvedInterface = null;
160: boolean set = false;
161: public String typeName = null;
162:
163: public ScopedName(int num) {
164: super (num);
165: }
166:
167: public Object clone() {
168: ScopedName sn = new ScopedName(new_num());
169: sn.resolvedSpec = this .resolvedSpec;
170: sn.resolvedName = this .resolvedName;
171: sn.resolved = this .resolved;
172: sn.typeName = this .typeName;
173: sn.token = this .token;
174: sn.set = this .set;
175:
176: /* superclass instance vars */
177: sn.pack_name = this .pack_name;
178: sn.name = this .name;
179: sn.is_pseudo = this .is_pseudo;
180: sn.included = this .included;
181: sn.inhibitionFlag = this .inhibitionFlag;
182: return sn;
183: }
184:
185: public void setId(String _id) {
186: if (logger.isInfoEnabled())
187: logger.info("ScopedName.setId " + _id);
188:
189: typeName = _id;
190: escapeName();
191: }
192:
193: /**
194: */
195:
196: public void escapeName() {
197: if (!isEscaped(typeName)) {
198: // if the type name is not a simple name, then insert the escape
199: // char after the last dot
200: if (typeName.indexOf('.') > -1) {
201: if (lexer.strictJavaEscapeCheck(typeName
202: .substring(typeName.lastIndexOf('.') + 1))) {
203: typeName = typeName.substring(0, typeName
204: .lastIndexOf('.') + 1)
205: + "_"
206: + typeName.substring(typeName
207: .lastIndexOf('.') + 1);
208: }
209: } else {
210: if (lexer.strictJavaEscapeCheck(typeName))
211: typeName = "_" + typeName;
212: }
213: }
214:
215: if (logger.isInfoEnabled())
216: logger.info("ScopedName.escapeName " + typeName);
217: }
218:
219: public void setEnclosingSymbol(IdlSymbol s) {
220: if (enclosing_symbol != null && enclosing_symbol != s)
221: throw new RuntimeException(
222: "Compiler Error: trying to reassign container for "
223: + name);
224: enclosing_symbol = s;
225: }
226:
227: public void parse() {
228: }
229:
230: public boolean resolved() {
231: return resolved;
232: }
233:
234: public boolean basic() {
235: TypeSpec t = resolvedTypeSpec();
236: return t.basic();
237: }
238:
239: public boolean is_pseudo() {
240: return NameTable.isDefined(resolvedName(), "pseudo interface");
241: }
242:
243: public TypeSpec resolvedTypeSpec() {
244: if (!resolved)
245: resolvedName = resolvedName();
246: if (resolvedSpec == null)
247: parser.fatal_error("Not a type: " + resolvedName, token);
248: return resolvedSpec;
249: }
250:
251: public boolean isEscaped(String name) {
252: String last = null;
253: if (name.indexOf('.') > -1)
254: last = name.substring(name.lastIndexOf('.') + 1);
255: else
256: last = name;
257: return last.startsWith("_");
258: }
259:
260: public String resolvedName() {
261: if (!resolved)
262: resolvedName = resolvedName(pack_name, typeName);
263:
264: ConstDecl constDecl = ConstDecl.getDeclaration(resolvedName);
265:
266: if (constDecl != null) {
267: if (!constDecl.contained()) {
268: resolvedName += ".value";
269: }
270: }
271: resolved = true;
272: return resolvedName;
273: }
274:
275: /**
276: * This is the main name resolution algorithm. It resolves a qualified name
277: * s by replacing it by a fully qualified one, (watch out for typedef'd
278: * names!)
279: *
280: * @param name
281: * the name that is to be resolved. This may be a simple name,
282: * a partially qualified name, or even a fully qualifed name.
283: * @param scopeOfOrigin
284: * the scope from within which the resolution starts
285: * @return a fully qualified IDL identifier
286: */
287:
288: private String resolvedName(String scopeOfOrigin, String name) {
289: if (logger.isInfoEnabled())
290: logger.info("Resolve " + scopeOfOrigin + ":" + name);
291:
292: if (name == null)
293: throw new RuntimeException(
294: "Parser Error: null string in ScopedName (pack_name: "
295: + scopeOfOrigin + ") !");
296:
297: String result = null;
298:
299: // a fully qualified name starts with a '.'
300: boolean global = false;
301: if (name.charAt(0) == '.') {
302: // strip the dot
303: name = name.substring(1);
304: global = true;
305: }
306:
307: // strip any "[]" but remember them for later
308: String bracketSuffix = "";
309: if (name.endsWith("[]")) {
310: result = name.substring(0, name.indexOf("["));
311: bracketSuffix = "[]";
312: } else
313: result = name;
314:
315: // see if "scope.name" is a defined name. If so, return that
316: // definition. First, try to form a combined name
317: if (!global
318: && NameTable.isDefined(scopeOfOrigin + "." + result)) {
319: String unmappedResult = unMap(scopeOfOrigin + "." + result);
320:
321: if (logger.isInfoEnabled())
322: logger.info("resolve, " + scopeOfOrigin + "." + result
323: + " was in name table, returning "
324: + unmappedResult + " suffix: " + bracketSuffix);
325:
326: return unmappedResult + bracketSuffix;
327: }
328:
329: // now, check if name is known by itself (either because it is global
330: // or it is a qualified name)
331: if ((global || result.indexOf('.') > -1)
332: && NameTable.isDefined(result)) {
333: String unmappedResult = unMap(result);
334:
335: if (logger.isInfoEnabled())
336: logger.info("resolve, found " + result
337: + " in name table, returning " + unmappedResult
338: + " suffix: " + bracketSuffix);
339:
340: return unmappedResult + bracketSuffix;
341: }
342:
343: // split up all scopes contained in the name
344: java.util.StringTokenizer strtok = new java.util.StringTokenizer(
345: name, ".");
346: String nameScopes[] = new String[strtok.countTokens()];
347: for (int i = 0; strtok.hasMoreTokens(); i++) {
348: nameScopes[i] = strtok.nextToken();
349: }
350:
351: // if there are scopes in the name itself...
352: if (nameScopes.length > 0) {
353: // see if the compiler has registerd replacement names for
354: // our scopes
355: String replacedPackageName = parser
356: .pack_replace(nameScopes[0]);
357: if (!replacedPackageName.equals(nameScopes[0])) {
358: // okay, it has, so rebuild the fully scoped name
359: StringBuffer tmpString = new StringBuffer();
360: tmpString.append(replacedPackageName);
361: for (int i = 1; i < nameScopes.length; ++i) {
362: tmpString.append(".");
363: tmpString.append(nameScopes[i]);
364: }
365:
366: // check if this is a defined name now
367: result = tmpString.toString();
368: if (NameTable.isDefined(result)) {
369: String unmappedResult = unMap(result);
370:
371: if (logger.isInfoEnabled())
372: logger.info("resolve b, " + result
373: + " was in name table, returning "
374: + unmappedResult + " suffix: "
375: + bracketSuffix);
376: return unmappedResult + bracketSuffix;
377: }
378: }
379: }
380:
381: // split up the individual scopes in the scopeOfOrigin
382: java.util.StringTokenizer p_strtok = new java.util.StringTokenizer(
383: scopeOfOrigin, ".");
384: String packageScopes[] = new String[p_strtok.countTokens()];
385: for (int i = 0; p_strtok.hasMoreTokens(); i++) {
386: packageScopes[i] = p_strtok.nextToken();
387: }
388:
389: // If the simple name was not known and we have no scopes at
390: // all, try the global scope.
391: if (nameScopes.length == 0 || packageScopes.length == 0) {
392: if (NameTable.isDefined(result)) {
393: return unMap(result) + bracketSuffix;
394: }
395: // else: the name is not found, emit an error message
396: parser.fatal_error("Undefined name: " + name + " .", token);
397: }
398:
399: // if package name and the name which is to be resolved begin
400: // with the same scoping qualifiers, strip these from name
401: if (nameScopes[0].equals(packageScopes[0])) {
402: StringBuffer tmpString = new StringBuffer();
403: int minScopesLength = nameScopes.length < packageScopes.length ? nameScopes.length
404: : packageScopes.length;
405:
406: if (minScopesLength > 1) {
407: int i;
408: for (i = 1; i < minScopesLength - 1; i++) {
409: if (!(nameScopes[i].equals(packageScopes[i])))
410: break;
411: }
412: tmpString.append(nameScopes[i]);
413:
414: for (int k = i + 1; k < nameScopes.length; k++) {
415: tmpString.append(".");
416: tmpString.append(nameScopes[k]);
417: }
418: name = tmpString.toString();
419: }
420: }
421:
422: String prefix = "";
423: int start_index = 0;
424:
425: if (parser.package_prefix != null) {
426: prefix = parser.package_prefix + ".";
427: java.util.StringTokenizer prefix_strtok = new java.util.StringTokenizer(
428: prefix, ".");
429: String prefix_scopes[] = new String[prefix_strtok
430: .countTokens()];
431:
432: for (int i = 0; prefix_strtok.hasMoreTokens(); i++)
433: prefix_scopes[i] = prefix_strtok.nextToken();
434:
435: while (start_index < prefix_scopes.length
436: && prefix_scopes[start_index]
437: .equals(packageScopes[start_index]))
438: start_index++;
439: }
440:
441: StringBuffer buf = new StringBuffer();
442: int k = packageScopes.length - start_index;
443:
444: if (k > 0)
445: buf.append(packageScopes[start_index] + ".");
446:
447: for (int j = start_index + 1; j < packageScopes.length; j++) {
448: buf.append(packageScopes[j]);
449: buf.append(".");
450: }
451:
452: buf.append(name);
453:
454: int sub = start_index + 1;
455:
456: while (!NameTable.isDefined(prefix + buf.toString())) {
457: if (sub > packageScopes.length) {
458: parser.fatal_error("Undefined name: " + scopeOfOrigin
459: + "." + name, token);
460: return "/* unresolved name */";
461: }
462: buf = new StringBuffer();
463: k = packageScopes.length - sub++;
464: if (k > 0) {
465: buf.append(packageScopes[start_index] + ".");
466: for (int j = start_index + 1; j < k + start_index; j++) {
467: buf.append(packageScopes[j]);
468: buf.append(".");
469:
470: }
471: }
472: buf.append(name);
473: }
474: String res = unMap(prefix + buf.toString()) + bracketSuffix;
475: if (logger.isDebugEnabled())
476: logger.debug("ScopedName.resolve (at end) returns: " + res);
477: return res;
478: }
479:
480: public TypeSpec typeSpec() {
481: return this ;
482: }
483:
484: public void setPackage(String s) {
485: s = parser.pack_replace(s);
486: set = true;
487: if (pack_name.length() > 0)
488: pack_name = s + "." + pack_name;
489: else
490: pack_name = s;
491: }
492:
493: private String qualify(String str) {
494: if (str.charAt(0) == '.') {
495: return (str.substring(1));
496: } else {
497: if (!pack_name.equals(""))
498: return (pack_name + "." + str);
499: else
500: return str;
501: }
502: }
503:
504: /**
505: * replace _name by the type name it stands for (through
506: * as many levels of typedef's as necessary) As a side effect,
507: * set resolvedSpec to point to type spec object if the name
508: * resolved was defined as a type name
509: */
510:
511: private String unMap(String _name) {
512: if (logger.isDebugEnabled())
513: logger.debug("ScopedName.unmap: " + _name);
514:
515: TypeSpec y = TypeMap.map(_name);
516:
517: if (logger.isDebugEnabled())
518: logger.debug("ScopedName.unmap: " + _name + ", Type.map( "
519: + _name + " ) is : " + y);
520:
521: TypeSpec x = null;
522:
523: while (y != null && !(y instanceof ScopedName)
524: && !(y instanceof ConstrTypeSpec)) {
525: x = y;
526: y = y.typeSpec();
527: if (x.equals(y))
528: break; // necessary?
529: }
530:
531: if (y == null) {
532: if (x != null) {
533: resolvedSpec = x;
534: return x.typeName();
535: }
536: resolvedSpec = y;
537: return unEnum(_name);
538: }
539:
540: if (y instanceof ConstrTypeSpec) {
541: resolvedSpec = y;
542: return y.typeName();
543: }
544:
545: if (y instanceof ScopedName && y != null && x != y) {
546: return unMap(y.typeName());
547: }
548:
549: // If this is an alias of a sequence return the actual type.
550: if (y instanceof AliasTypeSpec
551: && ((AliasTypeSpec) y).originalType().typeSpec() instanceof SequenceType) {
552: resolvedSpec = y;
553: return y.typeName();
554: }
555:
556: if (y == null) {
557: resolvedSpec = x;
558: return x.typeName();
559: }
560:
561: resolvedSpec = y;
562: return _name;
563: }
564:
565: /**
566: * @return the fully qualified and resolved name in an intermediate
567: * format, i.e. with "Package" suffixes but without potential "omg.org"
568: * scopes
569: */
570:
571: public String typeName() {
572: String n = unPseudo(resolvedName(pack_name, typeName));
573:
574: // !n.startsWith( "_" )
575: if (n.endsWith("PackagePackage") || !isEscaped(n)
576: && n.endsWith("Package"))
577: n = n.substring(0, n.lastIndexOf("Package"));
578:
579: return n;
580: }
581:
582: public String holderName() {
583: return resolvedTypeSpec().holderName();
584: }
585:
586: public String printReadExpression(String streamname) {
587: return resolvedTypeSpec().printReadExpression(streamname);
588: }
589:
590: public String printWriteStatement(String var_name, String streamname) {
591: return resolvedTypeSpec().printWriteStatement(var_name,
592: streamname);
593: }
594:
595: public String printInsertExpression() {
596: return resolvedTypeSpec().printInsertExpression();
597: }
598:
599: public String printExtractExpression() {
600: return resolvedTypeSpec().printExtractExpression();
601: }
602:
603: /**
604: * @return a string for an expression of type TypeCode that describes this type
605: */
606:
607: public String getTypeCodeExpression() {
608: return resolvedTypeSpec().getTypeCodeExpression();
609: }
610:
611: public String id() {
612: return resolvedTypeSpec().id();
613: }
614:
615: public String toString() {
616: String n = typeName();
617: if (resolvedTypeSpec() != null
618: && (!n.startsWith("org.omg") && !n
619: .startsWith("java.lang"))) {
620: n = resolvedTypeSpec().omgPrefix() + n;
621: }
622: return n;
623: }
624:
625: public void print(PrintWriter ps) {
626: }
627:
628: public String IDLName() {
629: String n = toString();
630: StringBuffer sb = new StringBuffer();
631: int from = 0;
632: while (n.substring(from).indexOf('.') > 0) {
633: int to = from + n.substring(from).indexOf('.');
634: sb.append(n.substring(from, to) + "::");
635: from = to + 1;
636: }
637: sb.append(n.substring(from));
638:
639: return sb.toString();
640: }
641:
642: public static void addRecursionScope(String typeName) {
643: recursionStack.push(typeName);
644: }
645:
646: public static void removeRecursionScope(String typeName) {
647: String check = (String) recursionStack.pop();
648: if (typeName != null
649: && (check == null || !check.equals(typeName))) {
650: throw new RuntimeException(
651: "RecursionScope Error, expected " + typeName
652: + ", got " + check);
653: }
654: }
655:
656: public static boolean isRecursionScope(String typeName) {
657: return (recursionStack.search(typeName) != -1);
658: }
659:
660: public boolean isSwitchable() {
661: TypeSpec t = resolvedTypeSpec();
662: return ((t instanceof SwitchTypeSpec) && ((SwitchTypeSpec) t)
663: .isSwitchable());
664: }
665: }
|