blob: c8d347aec7abf8b831112dee8c2a2550b835c37a [file] [log] [blame]
/* $Id$
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.etch.bindings.cpp.compiler;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.etch.compiler.Backend;
import org.apache.etch.compiler.CmdLineOptions;
import org.apache.etch.compiler.EtchGrammarConstants;
import org.apache.etch.compiler.LogHandler;
import org.apache.etch.compiler.Output;
import org.apache.etch.compiler.ParseException;
import org.apache.etch.compiler.Token;
import org.apache.etch.compiler.Version;
import org.apache.etch.compiler.ast.Builtin;
import org.apache.etch.compiler.ast.Enumx;
import org.apache.etch.compiler.ast.Except;
import org.apache.etch.compiler.ast.Item;
import org.apache.etch.compiler.ast.Message;
import org.apache.etch.compiler.ast.MessageDirection;
import org.apache.etch.compiler.ast.Module;
import org.apache.etch.compiler.ast.MsgDirHelper;
import org.apache.etch.compiler.ast.Name;
import org.apache.etch.compiler.ast.Named;
import org.apache.etch.compiler.ast.ParamList;
import org.apache.etch.compiler.ast.Parameter;
import org.apache.etch.compiler.ast.ReservedWordChecker;
import org.apache.etch.compiler.ast.Service;
import org.apache.etch.compiler.ast.Struct;
import org.apache.etch.compiler.ast.Thrown;
import org.apache.etch.compiler.ast.TypeRef;
import org.apache.etch.compiler.opt.ToString;
import org.apache.etch.compiler.opt.ToString.FieldItem;
import org.apache.etch.compiler.opt.ToString.FmtItem;
import org.apache.etch.compiler.opt.ToString.StringItem;
import org.apache.etch.util.Assertion;
import org.apache.etch.util.Hash;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.exception.ResourceNotFoundException;
import org.apache.velocity.runtime.RuntimeServices;
import org.apache.velocity.runtime.log.LogChute;
/**
* Compiler is a helper class not only for Backend, but also for the templates.
* They call methods here to perform "hard" tasks.
*/
public class Compiler extends Backend {
private final static String tmplPath1 = "org/apache/etch/bindings/cpp/compiler/";
private final static String tmplPath2 = "resources/org/apache/etch/bindings/cpp/compiler/";
/**
* Filename suffix for Header and Implementation files
*/
private final static String fnSuffixH = ".h";
private final static String fnSuffixI = ".cpp";
/**
* Folder Name - Include and Source
*/
private final static String fnInclude = "include/";
private final static String fnSource = "src/";
private final static String VERSION = Version.VERSION + " / "
+ CompilerVersion.VERSION;
/**
* Constructs the Compiler. This is a helper class not only for Backend, but
* also for the templates. They call methods here to perform "hard" tasks. * @throws
* Exception
*/
public Compiler() throws Exception {
this.initVelocity();
String[] path = { tmplPath1, tmplPath2 };
// value factory templates
this.vf_h_vm = this.getTemplate(path, "vf_h.vm");
this.vf_cpp_vm = this.getTemplate(path, "vf_cpp.vm");
// interface templates
this.intf_h_vm = this.getTemplate(path, "intf_h.vm");
this.intf_cpp_vm = this.getTemplate(path, "intf_cpp.vm");
// interface remote templates
this.remote_h_vm = this.getTemplate(path, "remote_h.vm");
this.remote_cpp_vm = this.getTemplate(path, "remote_cpp.vm");
// interface stub templates
this.stub_h_vm = this.getTemplate(path, "stub_h.vm");
this.stub_cpp_vm = this.getTemplate(path, "stub_cpp.vm");
// helper templates
this.helper_h_vm = this.getTemplate(path, "helper_h.vm");
this.helper_cpp_vm = this.getTemplate(path, "helper_cpp.vm");
this.readme_vm = this.getTemplate(path, "readme.vm");
// Main template
this.main_h_vm = this.getTemplate(path, "main_h.vm");
this.main_cpp_vm = this.getTemplate(path, "main_cpp.vm");
// Base template
this.base_h_vm = this.getTemplate(path, "base_h.vm");
this.base_cpp_vm = this.getTemplate(path, "base_cpp.vm");
// Implementation template
this.impl_h_vm = this.getTemplate(path, "impl_h.vm");
this.impl_cpp_vm = this.getTemplate(path, "impl_cpp.vm");
// Wireshark
this.etch_wireshark_vm = this.getTemplate(path, "etch_wireshark.vm");
// Keyword list
this.local_kwd = this.getPath(path, "cppKeywords.kwd");
}
// interface templates
private final Template intf_h_vm;
private final Template intf_cpp_vm;
// Base template
private final Template base_h_vm;
private final Template base_cpp_vm;
// Value Factory
private final Template vf_h_vm;
private final Template vf_cpp_vm;
// remote interface templates
private final Template remote_h_vm;
private final Template remote_cpp_vm;
// interface stub templates
private final Template stub_h_vm;
private final Template stub_cpp_vm;
// helper templates
private final Template helper_h_vm;
private final Template helper_cpp_vm;
private final Template readme_vm;
// Main template
private final Template main_h_vm;
private final Template main_cpp_vm;
// Implementation template
private final Template impl_h_vm;
private final Template impl_cpp_vm;
private final Template etch_wireshark_vm;
private final String local_kwd;
private LogHandler lh;
/**
* Initializes use of velocity engine and sets up resource loaders. * @throws
* Exception
*/
private void initVelocity() throws Exception {
Velocity.setProperty(Velocity.RUNTIME_LOG_LOGSYSTEM, new MyLogger());
Velocity.setProperty(Velocity.RESOURCE_LOADER, "file, class");
Velocity.setProperty("file.resource.loader.description",
"Velocity File Resource Loader");
Velocity.setProperty("file.resource.loader.class",
"org.apache.velocity.runtime.resource.loader.FileResourceLoader");
Velocity.setProperty("file.resource.loader.path", ".");
Velocity.setProperty("class.resource.loader.description",
"Velocity Classpath Resource Loader");
Velocity.setProperty("class.resource.loader.class",
"org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
Velocity.init();
}
private static class MyLogger implements LogChute {
private final LogHandler lh = null;
@Override
public void init(RuntimeServices rts) throws Exception {
// ignore.
}
@Override
public boolean isLevelEnabled(int level) {
return level >= 2;
}
@Override
public void log(int level, String msg) {
if (level < 2)
return;
if (this.lh != null)
this.lh.report(level == 2 ? LogHandler.LEVEL_WARNING
: LogHandler.LEVEL_ERROR, null, msg);
else
System.out.printf("Velocity msg (%d): %s\n", level, msg);
}
@Override
public void log(int level, String msg, Throwable e) {
if (level < 2)
return;
if (this.lh != null)
this.lh.report(level == 2 ? LogHandler.LEVEL_WARNING
: LogHandler.LEVEL_ERROR, null, msg);
else
System.out.printf("Velocity msg (%d): %s: %s\n", level, msg, e);
}
}
/**
* @param path
* @param fn
* @return the velocity template
* @throws Exception
*/
private Template getTemplate(String[] path, String fn) throws Exception {
ResourceNotFoundException rnfe = null;
for (String p : path) {
if (p == null)
continue;
// System.out.println( "trying to load template "+(p+fn) );
try {
if (Velocity.resourceExists(p + fn))
return Velocity.getTemplate(p + fn);
} catch (ResourceNotFoundException e) {
rnfe = e;
} catch (Exception e) {
System.out.println("ignoring " + e);
}
}
if (rnfe != null)
throw rnfe;
throw new ResourceNotFoundException("could not find resource: " + fn);
}
@Override
public void generate(Module module, CmdLineOptions options) throws Exception {
// java always wants to not flatten packages:
options.noFlattenPackages = true;
this.lh = options.lh;
boolean ignoreGlobal = options.ignoreGlobalWordsList;
boolean ignoreLocal = options.ignoreLocalWordsList;
String userWords = options.userWordsList != null ? options.userWordsList
.getPath() : null;
Set<String> what = options.what;
// Load the reserved words lists if any have been provided.
Map<String, String> words = new HashMap<String, String>();
if (!ignoreGlobal)
this.mapWords(this.global_kwd, words);
if (!ignoreLocal)
this.mapWords(this.local_kwd, words);
if (userWords != null)
this.mapWords(userWords, words);
// check for collisions with the reserved word list.
ReservedWordChecker checker = new ReservedWordChecker(words, false, this.lh);
module.treewalk(checker);
if (!checker.ok()) {
this.lh.report(LogHandler.LEVEL_ERROR, null,
"Encountered errors during c generation.");
return;
}
// ok, we're ready to generate code. make sure the
// output directories exist.
Output dir = options.output;
Output templateDir = options.templateOutput;
// generate code for each service.
for (Service intf : module) {
this.generate(intf, what, dir, templateDir);
}
}
public boolean isGenerateImpl() {
return this.isGenerateImpl;
}
public boolean isGenerateMain() {
return this.isGenerateMain;
}
boolean isGenerateImpl;
boolean isGenerateMain;
private void generate(final Service intf, Set<String> what, Output dir,
Output templateDir) throws Exception {
what = this.populateWhat(what);
if (what.isEmpty()) {
// lh.logMessage( lh.LEVEL_ERROR, null, "User has selected NONE\n"
// );
return;
}
final MessageDirection msgDir = this.getMessageDirection(what);
if (what.contains(WHAT_INTF)) {
// Generate the value factory file.
this.generateVf(intf, dir, msgDir);
// Generate the interface, remote, and stub files.
this.generateIntfRemoteStub(intf, dir, msgDir, MessageDirection.BOTH,
false);
this.generateIntfRemoteStub(intf, dir, msgDir, MessageDirection.SERVER,
true);
this.generateIntfRemoteStub(intf, dir, msgDir, MessageDirection.CLIENT,
true);
// Generate helper file.
this.generateHelper(intf, dir, msgDir);
// Generate base file.
this.generateBase(intf, dir, msgDir);
// Generate readme file.
this.generateReadme(intf, dir, msgDir);
this.generateKeywordList(intf, dir, msgDir, MessageDirection.BOTH, true);
}
// Generate main template file.
if (what.contains(WHAT_MAIN))
this.generateMain(intf, templateDir, msgDir);
// Generate impl template file.
if (what.contains(WHAT_IMPL))
this.generateImpl(intf, templateDir, msgDir);
}
private void generateReadme(final Service intf, Output dir,
final MessageDirection msgDir) throws Exception {
this.doFile(dir, "readme-etch-cpp-files.txt", this.lh, new Gen() {
@Override
public void run(PrintWriter pw) throws Exception {
Compiler.this.generateReadme(pw, intf, msgDir);
}
});
}
private void generateKeywordList(final Service intf, Output dir,
final MessageDirection what, final MessageDirection mc,
final boolean hasBaseClass) throws Exception {
this.doFile(dir, this.getKeywordFilename(intf), this.lh, new Gen() {
@Override
public void run(PrintWriter pw) throws Exception {
Compiler.this.generateKeywords(pw, intf, mc, hasBaseClass);
}
});
}
void generateKeywords(PrintWriter pw, Service intf, MessageDirection mc,
boolean hasBaseClass) throws Exception {
VelocityContext context = new VelocityContext();
context.put("now", new Date());
context.put("version", VERSION);
context.put("helper", this);
context.put("intf", intf);
context.put("mc", mc);
context.put("suffix", MsgDirHelper.getSuffix(mc).toLowerCase());
context.put("hasBaseClass", hasBaseClass);
this.etch_wireshark_vm.merge(context, pw);
}
public String getKeywordForWireshark(String fieldname) {
int hash = Hash.hash(fieldname);
return String.format("0x%08x", hash) + "," + fieldname;
}
private void generateVf(final Service intf, Output dir,
final MessageDirection mc) throws Exception {
this.doFile(dir, fnSource + this.getVfName(intf) + fnSuffixI, this.lh,
new Gen() {
@Override
public void run(PrintWriter pw) throws Exception {
Compiler.this.generateVfI(pw, intf, mc);
}
});
this.doFile(dir, fnInclude + this.getVfName(intf) + fnSuffixH, this.lh,
new Gen() {
@Override
public void run(PrintWriter pw) throws Exception {
Compiler.this.generateVfH(pw, intf, mc);
}
});
}
private void generateHelper(final Service intf, Output dir,
final MessageDirection msgDir) throws Exception {
this.doFile(dir, fnSource + this.getHelperName(intf) + fnSuffixI, this.lh,
new Gen() {
@Override
public void run(PrintWriter pw) throws Exception {
Compiler.this.generateHelperI(pw, intf, msgDir);
}
});
this.doFile(dir, fnInclude + this.getHelperName(intf) + fnSuffixH, this.lh,
new Gen() {
@Override
public void run(PrintWriter pw) throws Exception {
Compiler.this.generateHelperH(pw, intf, msgDir);
}
});
}
private void generateMain(final Service intf, Output dir,
MessageDirection msgDir) throws Exception {
if (msgDir == MessageDirection.BOTH || msgDir == MessageDirection.CLIENT) {
this.doFile(dir, this.getMainName(intf, MessageDirection.CLIENT)
+ fnSuffixI, this.lh, new Gen() {
@Override
public void run(PrintWriter pw) throws Exception {
Compiler.this.generateMainI(pw, intf, MessageDirection.CLIENT, false);
}
});
this.doFile(dir, this.getMainName(intf, MessageDirection.CLIENT)
+ fnSuffixH, this.lh, new Gen() {
@Override
public void run(PrintWriter pw) throws Exception {
Compiler.this.generateMainH(pw, intf, MessageDirection.CLIENT, false);
}
});
}
if (msgDir == MessageDirection.BOTH || msgDir == MessageDirection.SERVER) {
this.doFile(dir, this.getMainName(intf, MessageDirection.SERVER)
+ fnSuffixI, this.lh, new Gen() {
@Override
public void run(PrintWriter pw) throws Exception {
Compiler.this.generateMainI(pw, intf, MessageDirection.SERVER, false);
}
});
this.doFile(dir, this.getMainName(intf, MessageDirection.SERVER)
+ fnSuffixH, this.lh, new Gen() {
@Override
public void run(PrintWriter pw) throws Exception {
Compiler.this.generateMainH(pw, intf, MessageDirection.SERVER, false);
}
});
}
}
private void generateBase(final Service intf, Output dir,
MessageDirection msgDir) throws Exception {
if (msgDir == MessageDirection.BOTH || msgDir == MessageDirection.CLIENT) {
this.doFile(dir,
fnSource + this.getBaseName(intf, MessageDirection.CLIENT)
+ fnSuffixI, this.lh, new Gen() {
@Override
public void run(PrintWriter pw) throws Exception {
Compiler.this.generateBaseI(pw, intf, MessageDirection.CLIENT,
false);
}
});
this.doFile(dir,
fnInclude + this.getBaseName(intf, MessageDirection.CLIENT)
+ fnSuffixH, this.lh, new Gen() {
@Override
public void run(PrintWriter pw) throws Exception {
Compiler.this.generateBaseH(pw, intf, MessageDirection.CLIENT,
false);
}
});
}
if (msgDir == MessageDirection.BOTH || msgDir == MessageDirection.SERVER) {
this.doFile(dir,
fnSource + this.getBaseName(intf, MessageDirection.SERVER)
+ fnSuffixI, this.lh, new Gen() {
@Override
public void run(PrintWriter pw) throws Exception {
Compiler.this.generateBaseI(pw, intf, MessageDirection.SERVER,
false);
}
});
this.doFile(dir,
fnInclude + this.getBaseName(intf, MessageDirection.SERVER)
+ fnSuffixH, this.lh, new Gen() {
@Override
public void run(PrintWriter pw) throws Exception {
Compiler.this.generateBaseH(pw, intf, MessageDirection.SERVER,
false);
}
});
}
}
private void generateImpl(final Service intf, Output dir,
MessageDirection msgDir) throws Exception {
if (msgDir == MessageDirection.BOTH || msgDir == MessageDirection.CLIENT) {
this.doFile(dir, this.getImplName(intf, MessageDirection.CLIENT)
+ fnSuffixI, this.lh, new Gen() {
@Override
public void run(PrintWriter pw) throws Exception {
Compiler.this.generateImplI(pw, intf, MessageDirection.CLIENT, false);
}
});
this.doFile(dir, this.getImplName(intf, MessageDirection.CLIENT)
+ fnSuffixH, this.lh, new Gen() {
@Override
public void run(PrintWriter pw) throws Exception {
Compiler.this.generateImplH(pw, intf, MessageDirection.CLIENT, false);
}
});
}
if (msgDir == MessageDirection.BOTH || msgDir == MessageDirection.SERVER) {
this.doFile(dir, this.getImplName(intf, MessageDirection.SERVER)
+ fnSuffixI, this.lh, new Gen() {
@Override
public void run(PrintWriter pw) throws Exception {
Compiler.this.generateImplI(pw, intf, MessageDirection.SERVER, false);
}
});
this.doFile(dir, this.getImplName(intf, MessageDirection.SERVER)
+ fnSuffixH, this.lh, new Gen() {
@Override
public void run(PrintWriter pw) throws Exception {
Compiler.this.generateImplH(pw, intf, MessageDirection.SERVER, false);
}
});
}
}
private void generateIntfRemoteStub(final Service intf, Output dir,
final MessageDirection what, final MessageDirection mc,
final boolean hasBaseClass) throws Exception {
// Generate interface file
this.doFile(dir, fnSource + this.getIntfName(intf, mc) + fnSuffixI,
this.lh, new Gen() {
@Override
public void run(PrintWriter pw) throws Exception {
Compiler.this.generateIntfI(pw, intf, mc, hasBaseClass);
}
});
this.doFile(dir, fnInclude + this.getIntfName(intf, mc) + fnSuffixH,
this.lh, new Gen() {
@Override
public void run(PrintWriter pw) throws Exception {
Compiler.this.generateIntfH(pw, intf, mc, hasBaseClass);
}
});
// Generate remote file
if (mc == MessageDirection.BOTH || what == MessageDirection.BOTH
|| mc != what) {
this.doFile(dir, fnSource + this.getRemoteName(intf, mc) + fnSuffixI,
this.lh, new Gen() {
@Override
public void run(PrintWriter pw) throws Exception {
Compiler.this.generateRemoteI(pw, intf, mc, hasBaseClass);
}
});
this.doFile(dir, fnInclude + this.getRemoteName(intf, mc) + fnSuffixH,
this.lh, new Gen() {
@Override
public void run(PrintWriter pw) throws Exception {
Compiler.this.generateRemoteH(pw, intf, mc, hasBaseClass);
}
});
}
// Generate stub file
if (mc == MessageDirection.BOTH || what == MessageDirection.BOTH
|| mc == what) {
this.doFile(dir, fnSource + this.getStubName(intf, mc) + fnSuffixI,
this.lh, new Gen() {
@Override
public void run(PrintWriter pw) throws Exception {
Compiler.this.generateStubI(pw, intf, mc, hasBaseClass);
}
});
this.doFile(dir, fnInclude + this.getStubName(intf, mc) + fnSuffixH,
this.lh, new Gen() {
@Override
public void run(PrintWriter pw) throws Exception {
Compiler.this.generateStubH(pw, intf, mc, hasBaseClass);
}
});
}
}
/**
* Generate the value factory Implementation for the service.
*
* @param pw
* @param intf
* @param mc
* @throws Exception
*/
void generateVfI(PrintWriter pw, Service intf, MessageDirection mc)
throws Exception {
// params keeps track of the total set of parameters
// named (for enums, structs, exceptions, and messages).
Set<String> params = new HashSet<String>();
VelocityContext context = new VelocityContext();
context.put("now", new Date());
context.put("version", VERSION);
context.put("helper", this);
context.put("intf", intf);
context.put("params", params);
context.put("inc", this.getVfName(intf) + fnSuffixH);
context.put("mc", mc);
context.put("namespace", this.cppNamespace(intf));
this.vf_cpp_vm.merge(context, pw);
}
/**
* Generate the value factory Header for the service.
*
* @param pw
* @param intf
* @param mc
* @throws Exception
*/
void generateVfH(PrintWriter pw, Service intf, MessageDirection mc)
throws Exception {
// params keeps track of the total set of parameters
// named (for enums, structs, exceptions, and messages).
Set<String> params = new HashSet<String>();
VelocityContext context = new VelocityContext();
context.put("now", new Date());
context.put("version", VERSION);
context.put("helper", this);
context.put("intf", intf);
context.put("params", params);
context.put("mc", mc);
context.put("namespace", this.cppNamespace(intf));
this.vf_h_vm.merge(context, pw);
}
/**
* Generate the interface Implementation for the service.
*
* @param pw
* @param intf
* @param mc
* @param hasBaseClass
* @throws Exception
*/
void generateIntfI(PrintWriter pw, Service intf, MessageDirection mc,
boolean hasBaseClass) throws Exception {
VelocityContext context = new VelocityContext();
context.put("now", new Date());
context.put("version", VERSION);
context.put("helper", this);
context.put("intf", intf);
context.put("mc", mc);
context.put("inc", this.getIntfName(intf, mc) + fnSuffixH);
context.put("suffix", MsgDirHelper.getSuffix(mc));
context.put("hasBaseClass", hasBaseClass);
context.put("namespace", this.cppNamespace(intf));
this.intf_cpp_vm.merge(context, pw);
}
/**
* Generate the interface Header for the service.
*
* @param pw
* @param intf
* @param mc
* @param hasBaseClass
* @throws Exception
*/
void generateIntfH(PrintWriter pw, Service intf, MessageDirection mc,
boolean hasBaseClass) throws Exception {
VelocityContext context = new VelocityContext();
context.put("now", new Date());
context.put("version", VERSION);
context.put("helper", this);
context.put("intf", intf);
context.put("mc", mc);
context.put("suffix", MsgDirHelper.getSuffix(mc));
context.put("hasBaseClass", hasBaseClass);
context.put("inc", intf.name() + fnSuffixH);
context.put("namespace", this.cppNamespace(intf));
this.intf_h_vm.merge(context, pw);
}
/**
* Generate the call to message implementation of the interface. This class
* turns calls on its methods into messages which are sent to the remote stub.
* For two-way calls, it then waits for a response message, returning the
* result therein to the caller.
*
* @param pw
* @param intf
* @param mc
* @param hasBaseClass
* @throws Exception
*/
void generateRemoteI(PrintWriter pw, Service intf, MessageDirection mc,
boolean hasBaseClass) throws Exception {
VelocityContext context = new VelocityContext();
context.put("now", new Date());
context.put("version", VERSION);
context.put("helper", this);
context.put("intf", intf);
context.put("mc", mc);
context.put("suffix", MsgDirHelper.getSuffix(mc));
context.put("hasBaseClass", hasBaseClass);
context.put("inc", this.getRemoteName(intf, mc) + fnSuffixH);
context.put("methodList", new ArrayList<String>());
context.put("namespace", this.cppNamespace(intf));
this.remote_cpp_vm.merge(context, pw);
}
/**
* Generate the call to message implementation Header of the interface. This
* class turns calls on its methods into messages which are sent to the remote
* stub. For two-way calls, it then waits for a response message, returning
* the result therein to the caller.
*
* @param pw
* @param intf
* @param mc
* @param hasBaseClass
* @throws Exception
*/
void generateRemoteH(PrintWriter pw, Service intf, MessageDirection mc,
boolean hasBaseClass) throws Exception {
VelocityContext context = new VelocityContext();
context.put("now", new Date());
context.put("version", VERSION);
context.put("helper", this);
context.put("intf", intf);
context.put("mc", mc);
context.put("suffix", MsgDirHelper.getSuffix(mc));
context.put("inc", this.getRemoteName(intf, mc) + fnSuffixH);
context.put("hasBaseClass", hasBaseClass);
context.put("methodList", new ArrayList<String>());
context.put("namespace", this.cppNamespace(intf));
this.remote_h_vm.merge(context, pw);
}
/**
* Generate the message to call implementation. This class accepts a message
* and turns it back into a call on the user's implementation. For two-way
* messages, the return value from the user's implementation method is turned
* into the appropriate response message and sent.
*
* @param pw
* @param intf
* @param mc
* @param hasBaseClass
* @throws Exception
*/
void generateStubI(PrintWriter pw, Service intf, MessageDirection mc,
boolean hasBaseClass) throws Exception {
VelocityContext context = new VelocityContext();
context.put("now", new Date());
context.put("version", VERSION);
context.put("helper", this);
context.put("intf", intf);
context.put("mc", mc);
context.put("suffix", MsgDirHelper.getSuffix(mc));
context.put("inc", this.getStubName(intf, mc) + fnSuffixH);
context.put("hasBaseClass", hasBaseClass);
context.put("namespace", this.cppNamespace(intf));
this.stub_cpp_vm.merge(context, pw);
}
/**
* Generate the message to call implementation. This class accepts a message
* and turns it back into a call on the user's implementation. For two-way
* messages, the return value from the user's implementation method is turned
* into the appropriate response message and sent.
*
* @param pw
* @param intf
* @param mc
* @param hasBaseClass
* @throws Exception
*/
void generateStubH(PrintWriter pw, Service intf, MessageDirection mc,
boolean hasBaseClass) throws Exception {
VelocityContext context = new VelocityContext();
context.put("now", new Date());
context.put("version", VERSION);
context.put("helper", this);
context.put("intf", intf);
context.put("mc", mc);
context.put("suffix", MsgDirHelper.getSuffix(mc));
context.put("inc", this.getIntfName(intf, mc) + fnSuffixH);
context.put("hasBaseClass", hasBaseClass);
context.put("namespace", this.cppNamespace(intf));
this.stub_h_vm.merge(context, pw);
}
/**
* Generate the transport plumbing helper Implementation.
*
* @param pw
* @param intf
* @param mc
* @throws Exception
*/
void generateHelperI(PrintWriter pw, Service intf, MessageDirection mc)
throws Exception {
VelocityContext context = new VelocityContext();
context.put("now", new Date());
context.put("version", VERSION);
context.put("helper", this);
context.put("intf", intf);
context.put("inc", this.getHelperName(intf) + fnSuffixH);
context.put("mc", mc);
context.put("namespace", this.cppNamespace(intf));
this.helper_cpp_vm.merge(context, pw);
}
/**
* Generate the transport plumbing helper Header.
*
* @param pw
* @param intf
* @param mc
* @throws Exception
*/
void generateHelperH(PrintWriter pw, Service intf, MessageDirection mc)
throws Exception {
VelocityContext context = new VelocityContext();
context.put("now", new Date());
context.put("version", VERSION);
context.put("helper", this);
context.put("intf", intf);
context.put("inc", this.getHelperName(intf) + fnSuffixH);
context.put("mc", mc);
context.put("namespace", this.cppNamespace(intf));
this.helper_h_vm.merge(context, pw);
}
/**
* Generate the readme.txt.
*
* @param pw
* @param intf
* @param mc
* @throws Exception
*/
void generateReadme(PrintWriter pw, Service intf, MessageDirection mc)
throws Exception {
VelocityContext context = new VelocityContext();
context.put("now", new Date());
context.put("version", VERSION);
context.put("helper", this);
context.put("intf", intf);
context.put("mc", mc);
context.put("namespace", this.cppNamespace(intf));
this.readme_vm.merge(context, pw);
}
/**
* Generate the template main program.
*
* @param pw
* @param intf
* @param mc
* @param hasBaseClass
* @throws Exception
*/
void generateMainI(PrintWriter pw, Service intf, MessageDirection mc,
boolean hasBaseClass) throws Exception {
VelocityContext context = new VelocityContext();
context.put("now", new Date());
context.put("version", VERSION);
context.put("helper", this);
context.put("intf", intf);
context.put("mc", mc);
context.put("suffix", MsgDirHelper.getSuffix(mc));
context.put("hasBaseClass", hasBaseClass);
context.put("namespace", this.cppNamespace(intf));
this.main_cpp_vm.merge(context, pw);
}
void generateMainH(PrintWriter pw, Service intf, MessageDirection mc,
boolean hasBaseClass) throws Exception {
VelocityContext context = new VelocityContext();
context.put("now", new Date());
context.put("version", VERSION);
context.put("helper", this);
context.put("intf", intf);
context.put("mc", mc);
context.put("suffix", MsgDirHelper.getSuffix(mc));
context.put("hasBaseClass", hasBaseClass);
context.put("namespace", this.cppNamespace(intf));
this.main_h_vm.merge(context, pw);
}
/**
* Generates the base implementation of the interfaces, with each method
* throwing an exception to the tune that it isn't implemented. User's impl
* will extend this base implementation.
*
* @param pw
* @param intf
* @param mc
* @param hasBaseClass
* @throws Exception
*/
void generateBaseI(PrintWriter pw, Service intf, MessageDirection mc,
boolean hasBaseClass) throws Exception {
VelocityContext context = new VelocityContext();
context.put("now", new Date());
context.put("version", VERSION);
context.put("helper", this);
context.put("intf", intf);
context.put("mc", mc);
context.put("suffix", MsgDirHelper.getSuffix(mc));
context.put("inc", this.getBaseName(intf, mc) + fnSuffixH);
context.put("hasBaseClass", hasBaseClass);
context.put("methodList", new ArrayList<String>());
context.put("namespace", this.cppNamespace(intf));
this.base_cpp_vm.merge(context, pw);
}
/**
* Generates the base implementation of the interfaces, with each method
* throwing an exception to the tune that it isn't implemented. User's impl
* will extend this base implementation.
*
* @param pw
* @param intf
* @param mc
* @param hasBaseClass
* @throws Exception
*/
void generateBaseH(PrintWriter pw, Service intf, MessageDirection mc,
boolean hasBaseClass) throws Exception {
VelocityContext context = new VelocityContext();
context.put("now", new Date());
context.put("version", VERSION);
context.put("helper", this);
context.put("intf", intf);
context.put("mc", mc);
context.put("inc", this.getIntfName(intf, mc) + fnSuffixH);
context.put("suffix", MsgDirHelper.getSuffix(mc));
context.put("hasBaseClass", hasBaseClass);
context.put("methodList", new ArrayList<String>());
context.put("namespace", this.cppNamespace(intf));
this.base_h_vm.merge(context, pw);
}
/**
* Generate the template user implemention class which extends the base
* implementation generated above. This class will only have the appropriate
* constructor and reference to the appropriate remote, and a comment inviting
* the user to override methods.
*
* @param pw
* @param intf
* @param mc
* @param hasBaseClass
* @throws Exception
*/
void generateImplI(PrintWriter pw, Service intf, MessageDirection mc,
boolean hasBaseClass) throws Exception {
VelocityContext context = new VelocityContext();
context.put("now", new Date());
context.put("version", VERSION);
context.put("helper", this);
context.put("intf", intf);
context.put("mc", mc);
context.put("suffix", MsgDirHelper.getSuffix(mc));
context.put("hasBaseClass", hasBaseClass);
context.put("namespace", this.cppNamespace(intf));
this.impl_cpp_vm.merge(context, pw);
}
/**
* Generate the template user implemention class which extends the base
* implementation generated above. This class will only have the appropriate
* constructor and reference to the appropriate remote, and a comment inviting
* the user to override methods.
*
* @param pw
* @param intf
* @param mc
* @param hasBaseClass
* @throws Exception
*/
void generateImplH(PrintWriter pw, Service intf, MessageDirection mc,
boolean hasBaseClass) throws Exception {
VelocityContext context = new VelocityContext();
context.put("now", new Date());
context.put("version", VERSION);
context.put("helper", this);
context.put("intf", intf);
context.put("mc", mc);
context.put("suffix", MsgDirHelper.getSuffix(mc));
context.put("hasBaseClass", hasBaseClass);
context.put("namespace", this.cppNamespace(intf));
this.impl_h_vm.merge(context, pw);
}
public MessageDirection getRemoteDirection(MessageDirection mc) {
if (mc == MessageDirection.SERVER) {
return MessageDirection.CLIENT;
}
if (mc == MessageDirection.BOTH) {
return MessageDirection.BOTH;
}
return MessageDirection.SERVER;
}
public String getRemoteDirectionName(MessageDirection mc) {
return this.getDirectionName(this.getRemoteDirection(mc));
}
public boolean hasMessageDirectionBoth(Service intf) {
return intf.hasMessageDirection(MessageDirection.BOTH);
}
@Override
public boolean isClient(MessageDirection mc) {
return mc == MessageDirection.CLIENT || mc == MessageDirection.BOTH;
}
@Override
public boolean isServer(MessageDirection mc) {
return mc == MessageDirection.SERVER || mc == MessageDirection.BOTH;
}
public String getDirectionName(MessageDirection mc) {
return MsgDirHelper.getSuffix(mc).toLowerCase();
}
public MessageDirection getMsgDirServer() {
return MessageDirection.SERVER;
}
public MessageDirection getMsgDirClient() {
return MessageDirection.CLIENT;
}
public String getServiceName(Service intf) {
return intf.name().name().toLowerCase();
}
public String getIntfName(Service intf) {
return this.getServiceName(intf);
}
public String getVfName(Service intf) {
return "ValueFactory" + this.getIntfName(intf, MessageDirection.BOTH);
}
public String getIntfName(Service intf, MessageDirection mc) {
String suffix = MsgDirHelper.getSuffix(mc);
return intf.name() + suffix;
}
public String getMainName(Service intf, MessageDirection mc) {
if (mc == MessageDirection.SERVER)
return "Main" + intf.name() + "Listener";
return "Main" + this.getIntfName(intf, mc);
}
public String getImplName(Service intf, MessageDirection mc) {
return "Impl" + this.getIntfName(intf, mc);
}
public String getRemoteName(Service intf, MessageDirection mc) {
return "Remote" + this.getIntfName(intf, mc);
}
public String getStubName(Service intf, MessageDirection mc) {
return "Stub" + this.getIntfName(intf, mc);
}
public String getHelperName(Service intf) {
return intf.name() + "Helper";
}
public String getBaseName(Service intf, MessageDirection mc) {
return "Base" + this.getIntfName(intf, mc);
}
public String getKeywordFilename(Service intf) {
return intf.name().name().toLowerCase() + "_wireshark.ewh";
}
@Override
public String asyncReceiverPoolName(Message msg) {
return msg.getAsyncReceiver().toString().toLowerCase();
}
@Override
public String getTypeValue(TypeRef type, Token value) {
Token t = type.type();
switch (t.kind) {
case EtchGrammarConstants.LONG:
return value.image + "LL";
case EtchGrammarConstants.FLOAT:
case EtchGrammarConstants.DOUBLE:
return value.image + (value.image.indexOf('.') > -1 ? "f" : "");
case EtchGrammarConstants.STRING:
return "L" + this.protectString(value.image);
case EtchGrammarConstants.BOOLEAN:
return value.image.toUpperCase();
default:
return value.image;
}
}
private String protectString(String s) {
StringBuffer sb = new StringBuffer();
sb.append("\"");
for (char c : s.toCharArray()) {
if (c == '\t') {
sb.append("\\t");
continue;
}
if (c == '\r') {
sb.append("\\r");
continue;
}
if (c == '\n') {
sb.append("\\n");
continue;
}
if (c == '\"') {
sb.append("\\\"");
continue;
}
if (c == '\\') {
sb.append("\\\\");
continue;
}
if (c >= 32 && c < 127) {
sb.append(c);
continue;
}
sb.append(String.format("\\u%04x", (int) c));
}
sb.append("\"");
return sb.toString();
}
private String getNativeArrayTypeName(TypeRef type) {
Token t = type.type();
String nativeArrayName = "EtchNativeArray";
switch (t.kind) {
case EtchGrammarConstants.BOOLEAN:
return nativeArrayName + "Bool";
case EtchGrammarConstants.BYTE:
return nativeArrayName + "Byte";
case EtchGrammarConstants.SHORT:
return nativeArrayName + "Short";
case EtchGrammarConstants.INT:
return nativeArrayName + "Int";
case EtchGrammarConstants.LONG:
return nativeArrayName + "Long";
case EtchGrammarConstants.FLOAT:
return nativeArrayName + "Float";
case EtchGrammarConstants.DOUBLE:
return nativeArrayName + "Double";
case EtchGrammarConstants.STRING:
return nativeArrayName + "String";
case EtchGrammarConstants.OBJECT:
return nativeArrayName + "Object";
default: {
// we have to use a fully qualified name here.
// find the actual type...
Named<?> n = type.intf().get(t.image);
// System.out.println("Token: " + t.image);
if (n == null)
throw new IllegalArgumentException(String.format(
"undefined or ambiguous name at line %d: %s", t.beginLine, t.image));
if (n.isBuiltin()) {
Builtin b = (Builtin) n;
return nativeArrayName + b.className().substring(4);
}
if (n.isEnumx()) {
return nativeArrayName + n.efqname(this);
} else {
return type.intf().name() + "::" + nativeArrayName + n.efqname(this);
}
}
}
}
@Override
public String getTypeName(TypeRef type) {
return " I A M NOT IMPLEMENTED";
//if (type.dim() > 0)
// return this.getPointerTypeName(type);
}
public String getNativeTypeNameForConstants(TypeRef type) {
if (type.type().kind == EtchGrammarConstants.STRING)
return "wchar_t*";
return this.getNativeTypeName(type, false);
}
/**
* @param type
* the etch type
* @return the fundamental native type for c so etch int -> c int, while etch
* string -> wchar* string.
*/
@Override
public String getNativeTypeName(TypeRef type) {
return this.getNativeTypeName(type, false);
}
public String getEtchTypeName(TypeRef type, boolean Pointer) {
if (type.dim() > 0) return this.getArrayTypeName(type, Pointer);
return Pointer ? this.getPointerTypeName(type) : this.getNativeTypeName(type, true);
}
private String getArrayTypeName(TypeRef type, boolean pointer) {
// TODO Auto-generated method stub
if(pointer)
return this.getNativeArrayTypeName( type ) + "Ptr";
if (type.type().kind == EtchGrammarConstants.BYTE) {
return "EtchNativeArray<" + this.getNativeTypeName( type, false ) + "> ";
} else {
return "EtchNativeArray<" + this.getNativeTypeName( type, true ) + "Ptr> ";
}
}
public String getNativeTypeName(TypeRef type, boolean etch_type) {
Token t = type.type();
switch (t.kind) {
case EtchGrammarConstants.VOID:
return "void";
case EtchGrammarConstants.BOOLEAN:
return (etch_type ? "EtchBool" : "capu::bool_t");
case EtchGrammarConstants.BYTE:
return (etch_type ? "EtchByte" : "capu::int8_t");
case EtchGrammarConstants.SHORT:
return (etch_type ? "EtchShort" : "capu::int16_t");
case EtchGrammarConstants.INT:
return (etch_type ? "EtchInt32" : "capu::int32_t");
case EtchGrammarConstants.LONG:
return (etch_type ? "EtchLong" : "capu::int64_t");
case EtchGrammarConstants.FLOAT:
return (etch_type ? "EtchFloat" : "capu::float_t");
case EtchGrammarConstants.DOUBLE:
return (etch_type ? "EtchDouble" : "capu::double_t");
case EtchGrammarConstants.STRING:
return (etch_type ? "EtchString" : "EtchString");
case EtchGrammarConstants.OBJECT:
return (etch_type ? "EtchObject" : "EtchObject");
default: {
// we have to use a fully qualified name here.
// find the actual type...
Named<?> n = type.intf().get(t.image);
// System.out.println("Token: " + t.image);
if (n == null)
throw new IllegalArgumentException(String.format(
"undefined or ambiguous name at line %d: %s", t.beginLine, t.image));
if (n.isBuiltin()) {
Builtin b = (Builtin) n;
if (n.efqname(this).equals("EtchDate")) return b.className();
if (n.efqname(this).equals("EtchList")) return b.className()+"<EtchObjectPtr> ";
if (n.efqname(this).equals("EtchHashTable")) return b.className()+"<EtchObjectPtr, EtchObjectPtr> ";
if (n.efqname(this).equals("EtchHashSet")) return b.className()+"<EtchObjectPtr> ";
throw new IllegalArgumentException(String.format(
"unable to find correct Etch data type for type at line %d: %s", t.beginLine, n.efqname(this)));
}
if (n.isEnumx()) {
return n.efqname(this);
} else {
return type.intf().name() + "::" + n.efqname(this);
}
}
}
}
/**
* @param type
* the etch type
* @return the fundamental native reference type for cpp.
*/
public String getPointerTypeName(TypeRef type) {
Token t = type.type();
switch (t.kind) {
case EtchGrammarConstants.VOID:
return "void";
case EtchGrammarConstants.BOOLEAN:
return "EtchBoolPtr";
case EtchGrammarConstants.BYTE:
return "EtchBytePtr";
case EtchGrammarConstants.SHORT:
return "EtchShortPtr";
case EtchGrammarConstants.INT:
return "EtchInt32Ptr";
case EtchGrammarConstants.LONG:
return "EtchLongPtr";
case EtchGrammarConstants.FLOAT:
return "EtchFloatPtr";
case EtchGrammarConstants.DOUBLE:
return "EtchDoublePtr";
case EtchGrammarConstants.STRING:
return "EtchStringPtr";
case EtchGrammarConstants.OBJECT:
return "EtchObjectPtr";
default: {
// we have to use a fully qualified name here.
// find the actual type...
Named<?> n = type.intf().get(t.image);
if (n == null)
throw new IllegalArgumentException(String.format(
"undefined or ambiguous name at line %d: %s", t.beginLine, t.image));
if (n.efqname(this).equals("EtchDate"))
return "EtchDatePtr";
if (n.isBuiltin()) {
return n.efqname(this) + "Ptr";
}
return type.intf().name() + "::" + n.efqname(this) + "Ptr";
}
}
}
@Override
public String mfvname(String vname) {
return "_mf_" + vname;
}
@Override
public String mtvname(String vname) {
return "_mt_" + vname;
}
@Override
public String getLang() {
return "cpp";
}
@Override
public String enum_efqname(String fqname, String moduleName,
String serviceName, String enumName) {
return enumName;
}
@Override
public String except_efqname(String fqname, String moduleName,
String serviceName, String exceptName) {
return serviceName.toLowerCase() + "_" + exceptName;
}
@Override
public String struct_efqname(String fqname, String moduleName,
String serviceName, String structName) {
return serviceName.toLowerCase() + "_" + structName;
}
@Override
public String qualifyParameterName(Token name) {
return name.image;
}
@Override
public String qualifyConstantName(Service intf, Token name) {
return intf.fqname() + '.' + name.image;
}
@Override
public String qualifyEnumName(Service intf, Token name) {
return intf.fqname() + '.' + name.image;
}
Set<String> history = new HashSet<String>();
public boolean resetHistory() {
this.history = new HashSet<String>();
return true;
}
public boolean addStringToHistory(String s) {
this.history.add(s);
return true;
}
public boolean historyContains(String s) {
return this.history.contains(s);
}
public String cppNamespace(Service svc) {
return (svc.fqname()).replace('.', '_');
}
// ///////////////////////////////////////////////
// /////////////////// WORKSPACE /////////////////
// ///////////////////////////////////////////////
@Override
public String formatString(ParamList<Service> n, boolean isExcept)
throws ParseException, IOException {
ToString ts = (ToString) n.getOpt("ToString");
List<FmtItem> list;
if (ts != null) {
list = ts.getFormat();
n.checkFormatList(ts.lineno(), list);
} else if (isExcept)
list = n.mkFormatList(true, ((Except) n).hasExtends());
else
list = n.mkFormatList(false, ((Struct) n).hasExtends());
if (list.size() == 1) {
return list.get(0).value();
}
StringBuffer sb = new StringBuffer();
sb.append("\"");
for (FmtItem i : list) {
if (i instanceof FieldItem) {
sb.append("%s");
} else {
this.escape(sb, ((StringItem) i).value());
}
}
sb.append("\"");
for (FmtItem i : list) {
if (i instanceof FieldItem) {
sb.append(", ");
sb.append(((FieldItem) i).value() + "->c_str()");
}
}
return sb.toString();
}
private void escape(StringBuffer sb, String s) throws IOException {
StringReader rdr = new StringReader(s);
int c;
while ((c = rdr.read()) >= 0) {
if (c == '"')
sb.append("\\\"");
else if (c == '\\')
sb.append("\\\\");
else if (c == '\t')
sb.append("\\t");
else if (c == '\r')
sb.append("\\r");
else if (c == '\n')
sb.append("\\n");
else
sb.append((char) c);
}
}
@Override
public String getValidator(Named<?> named) {
if (named instanceof Parameter) {
Parameter param = (Parameter) named;
TypeRef type = param.type();
if (type.isBuiltin())
return String.format("EtchValidator%s::Get(runtime, %d, tmpValue)",
this.getValidatorStringForParam(param), type.dim());
Named<?> n = type.getNamed(type.intf());
if (n.isBuiltin()) {
Builtin b = (Builtin) n;
String cn = b.className();
if (n.efqname(this).equals("EtchHashTable")) {
cn += "<EtchObjectPtr, EtchObjectPtr>";
}
if (n.efqname(this).equals("EtchHashSet")) {
cn += "<EtchObjectPtr>";
}
if (n.efqname(this).equals("EtchList")) {
cn += "<EtchObjectPtr>";
}
/*
* int i = cn.indexOf( '<' ); if (i >= 0) cn = cn.substring( 0, i );
*/
return String.format(
"EtchValidatorCustom::Get(runtime, %d, %s::TYPE(), %s, tmpValue);",
type.dim(), cn, b.allowSubclass());
}
// Allow subclassing for etch defined structs and externs.
if (n.isStruct() || n.isExcept()) {
if (n.isStruct()) {
Struct s = (Struct) n;
return String.format(
"EtchValidatorCustom::Get(runtime, %d, %s::TYPE(), true, tmpValue);",
type.dim(), s
.service().name() + "::" + n.efqname(this));
}
Except e = (Except) n;
return String.format(
"EtchValidatorCustom::Get(runtime, %d, %s::TYPE(), true, tmpValue);", type.dim(), e
.service().name() + "::" + n.efqname(this));
}
// Don't allow subclassing for externs or etch defined enums.
if (!(n.isExtern() || n.isEnumx()))
Assertion.check(n.isExtern() || n.isEnumx(),
"n.isExtern() || n.isEnumx(): " + n);
Enumx e = (Enumx) n;
return String.format(
"EtchValidatorCustom::Get(runtime, %d, %s::TYPE(), false, tmpValue);",
type.dim(), n.efqname(this));
}
if (named instanceof Thrown) {
Thrown thrown = (Thrown) named;
Except e = (Except) thrown.getNamed();
String efgName = this.getExcept(thrown).service().name() + "::"
+ e.efqname(this);
return String.format(
"EtchValidatorCustom::Get(runtime, 0, %s::TYPE(), true, tmpValue);"
, efgName);
}
if (named instanceof Item)
return "EtchValidatorBoolean::Get(runtime, 0, tmpValue)";
return "NULL";
}
/**
* @param name
* @return the appropriate name for a getter method.
*/
public String getGetterName(Name name) {
String s = name.name;
return "get" + s.substring(0, 1).toUpperCase() + s.substring(1);
}
/**
* @param name
* @return the appropriate name for a setter method.
*/
public String getSetterName(Name name) {
String s = name.name;
return "set" + s.substring(0, 1).toUpperCase() + s.substring(1);
}
@Override
public void addDefaults(Service service) throws ParseException {
this.addBuiltin(service, this.newName("List"), "EtchList", true);
this.addBuiltin(service, this.newName("Map"), "EtchHashTable", true);
this.addBuiltin(service, this.newName("Set"), "EtchHashSet", true);
this.addBuiltin(service, this.newName("Datetime"), "EtchDate", false);
}
public String getValidatorStringForParam(Parameter param) {
TypeRef type = param.type();
return this.getValidatorStringForParam(type);
}
public String getValidatorStringForParam(TypeRef type) {
switch (type.type().kind) {
case EtchGrammarConstants.BOOLEAN:
return "Boolean";
case EtchGrammarConstants.BYTE:
return "Byte";
case EtchGrammarConstants.INT:
return "Int";
case EtchGrammarConstants.SHORT:
return "Short";
case EtchGrammarConstants.DOUBLE:
return "Double";
case EtchGrammarConstants.FLOAT:
return "Float";
case EtchGrammarConstants.LONG:
return "Long";
case EtchGrammarConstants.STRING:
return "String";
}
// what should be the default here?
return "Object";
}
public String getValidatorStringForParam(Message param) {
return this.getValidatorStringForParam(param.type());
}
public boolean isEnumParam(Parameter p) {
if (p.type() == null)
return false;
if (p.type().intf() == null)
return false;
if (p.type().getNamed(p.type().intf()) == null)
return false;
return p.type().getNamed(p.type().intf()).isEnumx();
}
public boolean isCustomType(Parameter param) {
return this.isCustomType(param.type());
}
public boolean isRefType(TypeRef param) {
if (param == null)
return true;
switch (param.type().kind) {
case EtchGrammarConstants.BOOLEAN:
case EtchGrammarConstants.DOUBLE:
case EtchGrammarConstants.FLOAT:
case EtchGrammarConstants.INT:
case EtchGrammarConstants.LONG:
case EtchGrammarConstants.ENUM:
case EtchGrammarConstants.DECIMAL:
case EtchGrammarConstants.SHORT:
return false;
default:
return true;
}
}
public boolean isCustomType(TypeRef param) {
switch (param.type().kind) {
case EtchGrammarConstants.BOOLEAN:
case EtchGrammarConstants.DOUBLE:
case EtchGrammarConstants.FLOAT:
case EtchGrammarConstants.INTEGER:
case EtchGrammarConstants.STRING:
case EtchGrammarConstants.LONG:
return false;
default:
return true;
}
}
public String getTypeName(Parameter pa) {
return pa.type().type().image;
}
public String getTypeName(Message pa) {
return pa.type().type().image;
}
public List<String> getUsedServiceNames(Service s) {
final List<String> ret = new LinkedList<String>();
IncludeTreeWalker walker = new IncludeTreeWalker(ret, s);
try {
s.treewalk(walker);
} catch (ParseException e) {
e.printStackTrace();
}
return walker.getList();
}
public boolean containsStructsOrMessages(Service s) {
return s.messages(false).hasNext() || s.structs(false).hasNext();
}
public String getClassIdVarName(Parameter p) {
Named<?> n = p.type().getNamed(p.type().intf());
return n.efqname(this);
}
public String getClassIdVarName(Thrown t) {
Except p = (Except) t.getNamed();
return p.service().name() + "::" + p.name().toString();
}
public Except getExcept(Thrown t) {
Except e = (Except) t.getNamed();
return e;
}
public String getClassIdVarName(Message n) {
Named<?> na = n.type().getNamed(n.type().intf());
return na.efqname(this);
}
public String getDefiningServiceNameOf(TypeRef type) {
Named<?> na = type.getNamed(type.intf());
return na.parent().name().name.toLowerCase();
}
}