All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.dyuproject.protostuff.compiler.STCodeGenerator Maven / Gradle / Ivy

//========================================================================
//Copyright 2007-2010 David Yu [email protected]
//------------------------------------------------------------------------
//Licensed 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 com.dyuproject.protostuff.compiler;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Pattern;

import org.antlr.stringtemplate.AttributeRenderer;
import org.antlr.stringtemplate.CommonGroupLoader;
import org.antlr.stringtemplate.StringTemplate;
import org.antlr.stringtemplate.StringTemplateErrorListener;
import org.antlr.stringtemplate.StringTemplateGroup;
import org.antlr.stringtemplate.StringTemplateGroupLoader;

import com.dyuproject.protostuff.parser.Formatter;
import com.dyuproject.protostuff.parser.Proto;
import com.dyuproject.protostuff.parser.ProtoUtil;

/**
 * Base class for code generators using StringTemplate.
 *
 * @author David Yu
 * @created Jan 5, 2010
 */
public abstract class STCodeGenerator implements ProtoCompiler
{
    
    public static final String TEMPLATE_BASE = "com/dyuproject/protostuff/compiler";
    
    public static final Pattern FORMAT_DELIM = Pattern.compile("&&");
    
    static final ConcurrentHashMap, AttributeRenderer> DEFAULT_RENDERERS = 
            new ConcurrentHashMap, AttributeRenderer>();
    
    static final ConcurrentHashMap DEFAULT_FORMATTERS = 
            new ConcurrentHashMap();
    
    public static final StringTemplateErrorListener ERROR_LISTENER = 
            new StringTemplateErrorListener()
    {
        public void error(String msg, Throwable e)
        {
            System.err.println("error: " + msg);
        }
        public void warning(String msg)
        {
            System.err.println("warning: " + msg);
        }
    };
    
    public static final CommonGroupLoader GROUP_LOADER = 
            new CommonGroupLoader(TEMPLATE_BASE, ERROR_LISTENER);
    
    public static final AttributeRenderer STRING_ATTRIBUTE_RENDERER = 
            new AttributeRenderer()
    {
        public String toString(Object o)
        {
            return (String)o;
        }

        public String toString(Object o, String formatName)
        {
            String str = (String)o;
            if(formatName==null)
                return str;
            
            String[] formats = FORMAT_DELIM.split(formatName);
            
            return formats.length == 0 ? format(str, formatName) : 
                chainedFormat(str, formats);
        }
    };
    
    static
    {
        StringTemplateGroup.registerGroupLoader(GROUP_LOADER);
        
        // attribute renderers
        
        setAttributeRenderer(String.class, STRING_ATTRIBUTE_RENDERER);
        
        GROUP_LOADER.loadGroup("base").setAttributeRenderers(DEFAULT_RENDERERS);
        
        Formatter.BUILTIN.addAllTo(DEFAULT_FORMATTERS);
    }
    
    /**
     * Formats the string n times.
     * 
     * 
     * For example:
     * input = "some_foo"
     * formatters = ["PCS", "UPPER"]
     * 
     * Output:
     * 1st pass: "Some Foo"
     * 2nd pass: "SOME FOO"
     * 
*/ public static String chainedFormat(String str, String[] formats) { // chained formatting String formatted = str; for(String f : formats) formatted = format(formatted, f); return formatted; } /** * Formats the string {@code str} using the format {@code formatName}. * * If the formatter with the name does not exist, the input string will be * appended with the formatName. */ public static String format(String str, String formatName) { final Formatter formatter = DEFAULT_FORMATTERS.get(formatName); if(formatter != null) return formatter.format(str); // regex replace int eq = formatName.indexOf("=="); if(eq > 0) { String toReplace = formatName.substring(0, eq); String replacement = formatName.substring(eq+2); if(toReplace.length()==1 && replacement.length()==1) return str.replace(toReplace.charAt(0), replacement.charAt(0)); return str.replaceAll(toReplace, replacement); } return str + formatName; } /** * Returns true if there was no previous attribute renderer with the same class. */ public static boolean setAttributeRenderer(Class typeClass, AttributeRenderer ar) { return null == DEFAULT_RENDERERS.put(typeClass, ar); } /** * Returns true if there was no previous formatter with the same name. */ public static boolean setFormatter(String name, Formatter f) { return null == DEFAULT_FORMATTERS.put(name, f); } public static StringTemplateGroup getSTG(String groupName) { return __loader.loadGroup(groupName); } public static StringTemplate getST(String groupName, String name) { return getSTG(groupName).getInstanceOf(name); } public static void setGroupLoader(StringTemplateGroupLoader loader) { if(loader != null) { __loader = loader; StringTemplateGroup.registerGroupLoader(loader); } } private static StringTemplateGroupLoader __loader = GROUP_LOADER; protected final String id; public STCodeGenerator(String id) { this.id = id; } public String getOutputId() { return id; } public void compile(ProtoModule module) throws IOException { String ci = module.getOption("compile_imports"); boolean compileImports = ci != null && !"false".equalsIgnoreCase(ci); boolean recursive = "recursive".equalsIgnoreCase(ci); File source = module.getSource(); if(source.isDirectory()) { for(File f : CompilerUtil.getProtoFiles(source)) compile(module, parseProto(f, module), compileImports, recursive); } else compile(module, parseProto(source, module), compileImports, recursive); } protected static Proto parseProto(File file, ProtoModule module) { CachingProtoLoader loader = module.getCachingProtoLoader(); if(loader == null) return ProtoUtil.parseProto(file); try { return loader.loadFrom(file, null); } catch(Exception e) { throw new RuntimeException(e); } } protected void compile(ProtoModule module, Proto proto, boolean compileImports, boolean recursive) throws IOException { final List overridden = new ArrayList(); try { collect(module, proto, overridden, recursive); if(!recursive) { compile(module, proto); if(compileImports) { for(Proto p : proto.getImportedProtos()) compile(module, p); } } } finally { for(Proto p : overridden) postCompile(module, p); } } protected void collect(ProtoModule module, Proto proto, List overridden, boolean compile) throws IOException { for(Proto p : proto.getImportedProtos()) collect(module, p, overridden, compile); if(override(module, proto)) overridden.add(proto); if(compile) compile(module, proto); } protected static boolean override(ProtoModule module, Proto proto) { String pkg = proto.getPackageName(); String jpkg = proto.getJavaPackageName(); String opkg = module.getOption(pkg); String ojpkg = module.getOption(jpkg); boolean override = false; if(opkg != null && opkg.length() != 0) { proto.getMutablePackageName().override(opkg); override = true; } if(ojpkg != null && ojpkg.length() != 0) { proto.getMutableJavaPackageName().override(ojpkg); override = true; } return override; } protected static void postCompile(ProtoModule module, Proto proto) { proto.getMutableJavaPackageName().reset(); proto.getMutablePackageName().reset(); } protected abstract void compile(ProtoModule module, Proto proto) throws IOException; }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy