/*
* JacORB - a free Java ORB
*
* Copyright (C) 1997-2014 Gerald Brose / The JacORB Team.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
package org.jacorb.idl;
import java.io.File;
import java.io.PrintWriter;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
/**
* @author Gerald Brose
*/
public class EnumType
extends TypeDeclaration
implements SwitchTypeSpec
{
public SymbolList enumlist;
int const_counter = 0;
private boolean written = false;
private boolean parsed = false;
public EnumType(int num)
{
super(num);
pack_name = "";
}
public Object clone()
{
EnumType et = new EnumType(new_num());
et.enumlist = this.enumlist;
et.typeName = this.typeName;
et.pack_name = this.pack_name;
et.name = this.name;
et.token = this.token;
et.included = this.included;
et.enclosing_symbol = this.enclosing_symbol;
et.parsed = this.parsed;
return et;
}
public TypeDeclaration declaration()
{
return this;
}
public int size()
{
return enumlist.v.size();
}
/**
*/
public void set_included(boolean i)
{
included = i;
}
public String typeName()
{
if (typeName == null)
{
setPrintPhaseNames();
}
return typeName;
}
public boolean basic()
{
return true;
}
public void setPackage(String s)
{
s = parser.pack_replace(s);
if (pack_name.length() > 0)
pack_name = s + "." + pack_name;
else
pack_name = s;
}
public void setEnclosingSymbol(IdlSymbol s)
{
if (enclosing_symbol != null && enclosing_symbol != s)
throw new RuntimeException("Compiler Error: trying to reassign container for " + name);
enclosing_symbol = s;
}
public void parse()
{
if (parsed)
{
return ;
}
parsed = true;
escapeName();
try
{
ConstrTypeSpec ctspec = new ConstrTypeSpec(new_num());
ctspec.c_type_spec = this;
NameTable.define(full_name(), IDLTypes.TYPE);
TypeMap.typedef(full_name(), ctspec);
String enum_ident = null;
// we have to get the scoping right: enums do not
// define scopes, but their element identifiers are scoped.
// for the Java mapping, we need to get the enum type name
// back as it defines the class name where the constants
// are defined. Therefore, an additional mapping in
// ScopedName is required.
String prefix = (pack_name.length() > 0 ?
full_name().substring(0, full_name().lastIndexOf('.') + 1) :
"");
for (Enumeration e = enumlist.v.elements(); e.hasMoreElements();)
{
enum_ident = (String) e.nextElement();
try
{
NameTable.define(prefix + enum_ident, IDLTypes.ENUM_LABEL);
ScopedName.enumMap(prefix + enum_ident, full_name() +
"." + enum_ident);
}
catch (NameAlreadyDefined p)
{
parser.error("Identifier " + enum_ident +
" already defined in immediate scope", token);
}
}
}
catch (NameAlreadyDefined p)
{
parser.error("Enum " + full_name() + " already defined", token);
}
}
public String className()
{
String fullName = typeName();
if (fullName.indexOf('.') > 0)
{
return fullName.substring(fullName.lastIndexOf('.') + 1);
}
return fullName;
}
public String printReadExpression(String streamname)
{
return toString() + "Helper.read(" + streamname + ")";
}
public String printWriteStatement(String var_name, String streamname)
{
return toString() + "Helper.write(" + streamname + "," + var_name + ");";
}
public String holderName()
{
return typeName() + "Holder";
}
public String helperName()
{
return typeName() + "Helper";
}
public String getTypeCodeExpression()
{
return getTypeCodeExpression(new HashSet());
}
public String getTypeCodeExpression(Set knownTypes)
{
if (knownTypes.contains(this))
{
return this.getRecursiveTypeCodeExpression();
}
StringBuffer sb = new StringBuffer();
sb.append("org.omg.CORBA.ORB.init().create_enum_tc(" +
typeName() + "Helper.id(),\"" + className() + "\",");
sb.append("new String[]{");
for (Enumeration e = enumlist.v.elements(); e.hasMoreElements();)
{
sb.append("\"" + (String) e.nextElement() + "\"");
if (e.hasMoreElements())
sb.append(",");
}
sb.append("})");
return sb.toString();
}
private void printHolderClass(String className, PrintWriter ps)
{
if (!pack_name.equals(""))
ps.println("package " + pack_name + ";");
printClassComment("enum", className, ps);
ps.println("public" + parser.getFinalString() + " class " + className + "Holder");
ps.println("\timplements org.omg.CORBA.portable.Streamable");
ps.println("{");
ps.println("\tpublic " + className + " value;" + Environment.NL);
ps.println("\tpublic " + className + "Holder ()");
ps.println("\t{");
ps.println("\t}");
ps.println("\tpublic " + className + "Holder (final " + className + " initial)");
ps.println("\t{");
ps.println("\t\tvalue = initial;");
ps.println("\t}");
ps.println("\tpublic org.omg.CORBA.TypeCode _type ()");
ps.println("\t{");
ps.println("\t\treturn " + className + "Helper.type ();");
ps.println("\t}");
ps.println("\tpublic void _read (final org.omg.CORBA.portable.InputStream in)");
ps.println("\t{");
ps.println("\t\tvalue = " + className + "Helper.read (in);");
ps.println("\t}");
ps.println("\tpublic void _write (final org.omg.CORBA.portable.OutputStream out)");
ps.println("\t{");
ps.println("\t\t" + className + "Helper.write (out,value);");
ps.println("\t}");
ps.println("}");
}
private void printHelperClass(String className, PrintWriter ps)
{
if (!pack_name.equals(""))
ps.println("package " + pack_name + ";");
printClassComment("enum", className, ps);
ps.println("public abstract class " + className + "Helper");
ps.println("{");
ps.println("\tprivate volatile static org.omg.CORBA.TypeCode _type;");
/* type() method */
ps.println("\tpublic static org.omg.CORBA.TypeCode type ()");
ps.println("\t{");
ps.println("\t\tif (_type == null)");
ps.println("\t\t{");
ps.println("\t\t\tsynchronized(" + className + "Helper.class)");
ps.println("\t\t\t{");
ps.println("\t\t\t\tif (_type == null)");
ps.println("\t\t\t\t{");
ps.println("\t\t\t\t\t_type = " + getTypeCodeExpression() + ";");
ps.println("\t\t\t\t}");
ps.println("\t\t\t}");
ps.println("\t\t}");
ps.println("\t\treturn _type;");
ps.println("\t}" + Environment.NL);
String type = typeName();
TypeSpec.printInsertExtractMethods(ps, type);
printIdMethod(ps);
ps.println("\tpublic static " + className + " read (final org.omg.CORBA.portable.InputStream in)");
ps.println("\t{");
ps.println("\t\treturn " + className + ".from_int(in.read_long());");
ps.println("\t}" + Environment.NL);
ps.println("\tpublic static void write (final org.omg.CORBA.portable.OutputStream out, final " + className + " s)");
ps.println("\t{");
ps.println("\t\tout.write_long(s.value());");
ps.println("\t}");
ps.println("}");
}
/** print the class that maps the enum */
private void printEnumClass(String className, PrintWriter pw)
{
if (!pack_name.equals(""))
pw.println("package " + pack_name + ";");
printClassComment("enum", className, pw);
pw.println("public" + parser.getFinalString() + " class " + className);
pw.println("\timplements org.omg.CORBA.portable.IDLEntity" + Environment.NL + "{");
printSerialVersionUID(pw);
pw.println("\tprivate int value = -1;");
for (Enumeration e = enumlist.v.elements(); e.hasMoreElements();)
{
String label = (String) e.nextElement();
pw.println("\tpublic static final int _" + label + " = " + (const_counter++) + ";");
pw.println("\tpublic static final " + name + " " + label + " = new " + name + "(_" + label + ");");
}
pw.println("\tpublic int value()");
pw.println("\t{");
pw.println("\t\treturn value;");
pw.println("\t}");
pw.println("\tpublic static " + name + " from_int(int value)");
pw.println("\t{");
pw.println("\t\tswitch (value) {");
for (Enumeration e = enumlist.v.elements(); e.hasMoreElements();)
{
String label = (String) e.nextElement();
pw.println("\t\t\tcase _" + label + ": return " + label + ";");
}
pw.println("\t\t\tdefault: throw new org.omg.CORBA.BAD_PARAM();");
pw.println("\t\t}");
pw.println("\t}");
pw.println("\tpublic String toString()");
pw.println("\t{");
pw.println("\t\tswitch (value) {");
for (Enumeration e = enumlist.v.elements(); e.hasMoreElements();)
{
String label = (String) e.nextElement();
pw.println("\t\t\tcase _" + label + ": return \"" + label + "\";");
}
pw.println("\t\t\tdefault: throw new org.omg.CORBA.BAD_PARAM();");
pw.println("\t\t}");
pw.println("\t}");
pw.println("\tprotected " + name + "(int i)");
pw.println("\t{");
pw.println("\t\tvalue = i;");
pw.println("\t}");
pw.println("\t/**");
pw.println("\t * Designate replacement object when deserialized from stream. See");
pw.println("\t * http://www.omg.org/docs/ptc/02-01-03.htm#Issue4271");
pw.println("\t *");
pw.println("\t * @throws java.io.ObjectStreamException");
pw.println("\t */");
pw.println("\tjava.lang.Object readResolve()");
if (!parser.cldc10 )
pw.println("\tthrows java.io.ObjectStreamException");
pw.println("\t{");
pw.println("\t\treturn from_int(value());");
pw.println("\t}");
pw.println("}");
}
/** generate required classes */
public void print(PrintWriter ps)
{
setPrintPhaseNames();
// no code generation for included definitions
if (included && !generateIncluded())
{
return ;
}
// only write once
if (!written)
{
try
{
String className = className();
String path =
parser.out_dir + fileSeparator +
pack_name.replace('.', fileSeparator);
File dir = new File(path);
if (!dir.exists())
{
if (!dir.mkdirs())
{
org.jacorb.idl.parser.fatal_error("Unable to create " + path, null);
}
}
String fname = className + ".java";
File f = new File(dir, fname);
if (GlobalInputStream.isMoreRecentThan(f))
{
// print the mapped java class
PrintWriter printWriter = new PrintWriter(new java.io.FileWriter(f));
printEnumClass(className, printWriter);
printWriter.close();
}
fname = className + "Holder.java";
f = new File(dir, fname);
if (GlobalInputStream.isMoreRecentThan(f))
{
// print the holder class
PrintWriter printWriter = new PrintWriter(new java.io.FileWriter(f));
printHolderClass(className, printWriter);
printWriter.close();
}
fname = className + "Helper.java";
f = new File(dir, fname);
if (GlobalInputStream.isMoreRecentThan(f))
{
// print the helper class
PrintWriter printWriter = new PrintWriter(new java.io.FileWriter(f));
printHelperClass(className, printWriter);
printWriter.close();
}
written = true;
}
catch (java.io.IOException i)
{
throw new RuntimeException("File IO error" + i);
}
}
}
public String toString()
{
return typeName();
}
public boolean isSwitchable()
{
return true;
}
public void printInsertIntoAny(PrintWriter ps,
String anyname,
String varname)
{
ps.println("\t\t" + pack_name + "." + className() + "Helper.insert(" + anyname + ", " + varname + ");");
}
public void printExtractResult(PrintWriter ps,
String resultname,
String anyname,
String resulttype)
{
ps.println("\t\t" + resultname + " = " + pack_name + "." + className() + "Helper.extract(" + anyname + ");");
}
/**
*/
public void accept(IDLTreeVisitor visitor)
{
visitor.visitEnum(this);
}
}