<commit_before>/**
 * Copyright (C) 2009-2012 the original author or authors.
 * See the notice.md file distributed with this work for additional
 * information regarding copyright ownership.
 *
 * 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 org.fusesource.restygwt.rebind;

import java.io.PrintWriter;
import java.util.HashSet;

import com.google.gwt.core.ext.BadPropertyValueException;
import com.google.gwt.core.ext.GeneratorContext;
import com.google.gwt.core.ext.PropertyOracle;
import com.google.gwt.core.ext.SelectionProperty;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JParameterizedType;
import com.google.gwt.user.rebind.AbstractSourceCreator;
import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
import com.google.gwt.user.rebind.SourceWriter;

/**
 * provides additional helper methods for generating source..
 *
 * @author <a href="http://hiramchirino.com"><NAME></a>
 */
public abstract class BaseSourceCreator extends AbstractSourceCreator {

    public static final TreeLogger.Type ERROR = TreeLogger.ERROR;
    public static final TreeLogger.Type WARN = TreeLogger.WARN;
    public static final TreeLogger.Type INFO = TreeLogger.INFO;
    public static final TreeLogger.Type TRACE = TreeLogger.TRACE;
    public static final TreeLogger.Type DEBUG = TreeLogger.DEBUG;
    public static final TreeLogger.Type SPAM = TreeLogger.SPAM;
    public static final TreeLogger.Type ALL = TreeLogger.ALL;

    protected final GeneratorContext context;
    protected final JClassType source;
    protected final String packageName;
    protected final String shortName;
    protected final String name;
    protected SourceWriter sourceWriter;
    private TreeLogger logger;
    private PrintWriter writer;

    static final private ThreadLocal<HashSet<String>> GENERATED_CLASSES = new ThreadLocal<HashSet<String>>();

    static public HashSet<String> getGeneratedClasses() {
        HashSet<String> rc = GENERATED_CLASSES.get();
        if (rc == null) {
            rc = new HashSet<String>();
            GENERATED_CLASSES.set(rc);
        }
        return rc;
    }

    static public void clearGeneratedClasses() {
        GENERATED_CLASSES.set(null);
    }

    public static JClassType find(Class<?> type, TreeLogger logger, GeneratorContext context) throws UnableToCompleteException {
        return RestServiceGenerator.find(logger, context, type.getName().replace('$', '.'));
    }

    public BaseSourceCreator(final TreeLogger logger, GeneratorContext context, JClassType source, String suffix) {
        this.logger = logger;
        this.context = context;
        this.source = source;
        this.packageName = getOpenPackageName( source.getPackage().getName() );
        
        if(source instanceof JParameterizedType)
        {
    		JParameterizedType ptype = (JParameterizedType)source;
			StringBuilder builder = new StringBuilder();
			for(JClassType type : ptype.getTypeArgs())
			{
				builder.append("__");
				builder.append(type.getParameterizedQualifiedSourceName().replace('.', '_').replace("<", "__").replace(">", "__").replace(",", "_").replace(" ", "_"));
			}
			this.shortName = getName( source ) + builder.toString() + suffix;
        }
        else
        {
        	this.shortName = getName( source ) + suffix;
        }

        this.name = packageName + "." + shortName;
    }

    protected String getName( JClassType source ){
        if( source.getEnclosingType() != null ){
            return getName( source.getEnclosingType() ) + "_" + source.getSimpleSourceName();
        }
        return source.getSimpleSourceName();
    }
    
    /**
     * Some packages are protected such that any type we generate in that package can't subsequently be loaded
     * because of a {@link SecurityException}, for example <code>java.</code> and <code>javax.</code> packages. 
     * <p>
     * To workaround this issue we add a prefix onto such packages so that the generated code can be loaded
     * later. The prefix added is <code>open.</code>
     * 
     * @param name
     * @return
     */
    private String getOpenPackageName(String name) {
      if (name.startsWith("java.") || name.startsWith("javax.")) {
        name = "open."+name;
      }
      return name;
    }
    
    protected PrintWriter writer() {
        HashSet<String> classes = getGeneratedClasses();
        if (classes.contains(name)) {
            return null;
        }
        classes.add(name);<commit_msg>Change name generation to avoid class names larger than 255 characters<commit_after>/**
 * Copyright (C) 2009-2012 the original author or authors.
 * See the notice.md file distributed with this work for additional
 * information regarding copyright ownership.
 *
 * 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 org.fusesource.restygwt.rebind;

import java.io.PrintWriter;
import java.util.HashSet;

import com.google.gwt.core.ext.BadPropertyValueException;
import com.google.gwt.core.ext.GeneratorContext;
import com.google.gwt.core.ext.PropertyOracle;
import com.google.gwt.core.ext.SelectionProperty;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JParameterizedType;
import com.google.gwt.user.rebind.AbstractSourceCreator;
import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
import com.google.gwt.user.rebind.SourceWriter;

/**
 * provides additional helper methods for generating source..
 *
 * @author <a href="http://hiramchirino.com"><NAME></a>
 */
public abstract class BaseSourceCreator extends AbstractSourceCreator {

    public static final TreeLogger.Type ERROR = TreeLogger.ERROR;
    public static final TreeLogger.Type WARN = TreeLogger.WARN;
    public static final TreeLogger.Type INFO = TreeLogger.INFO;
    public static final TreeLogger.Type TRACE = TreeLogger.TRACE;
    public static final TreeLogger.Type DEBUG = TreeLogger.DEBUG;
    public static final TreeLogger.Type SPAM = TreeLogger.SPAM;
    public static final TreeLogger.Type ALL = TreeLogger.ALL;

    protected final GeneratorContext context;
    protected final JClassType source;
    protected final String packageName;
    protected final String shortName;
    protected final String name;
    protected SourceWriter sourceWriter;
    private TreeLogger logger;
    private PrintWriter writer;

    static final private ThreadLocal<HashSet<String>> GENERATED_CLASSES = new ThreadLocal<HashSet<String>>();

    static public HashSet<String> getGeneratedClasses() {
        HashSet<String> rc = GENERATED_CLASSES.get();
        if (rc == null) {
            rc = new HashSet<String>();
            GENERATED_CLASSES.set(rc);
        }
        return rc;
    }

    static public void clearGeneratedClasses() {
        GENERATED_CLASSES.set(null);
    }

    public static JClassType find(Class<?> type, TreeLogger logger, GeneratorContext context) throws UnableToCompleteException {
        return RestServiceGenerator.find(logger, context, type.getName().replace('$', '.'));
    }

    public BaseSourceCreator(final TreeLogger logger, GeneratorContext context, JClassType source, String suffix) {
        this.logger = logger;
        this.context = context;
        this.source = source;
        this.packageName = getOpenPackageName( source.getPackage().getName() );
        
        if(source instanceof JParameterizedType)
        {
    		JParameterizedType ptype = (JParameterizedType)source;
			StringBuilder builder = new StringBuilder();
			for(JClassType type : ptype.getTypeArgs())
			{
				builder.append("__");
				builder.append(parametersName2ClassName(type.getParameterizedQualifiedSourceName()));
			}
			this.shortName = reduceName(getName( source ) + builder.toString() + suffix,suffix);
        }
        else
        {
        	this.shortName = reduceName(getName( source ) + suffix,suffix);
        }

        this.name = packageName + "." + shortName;
    }
    

    //Many filesystems prevent files with names larger than 256 characters.
    //Lets have class name less than 200 to allow new generators safelly to add more sufixes there if needed
    private String reduceName(String newClassName,String suffix) {
        if(newClassName.length()<200){
        	return newClassName;
        }
//        String sufx = "_Gen_GwtJackEncDec_";
        //Lets first try to reduce the package name of the parametrized types
        // according to parametersName2ClassName parametrized types
        //Lets find if there are parametrized types
        
        String noSufix  =  newClassName.substring(0,newClassName.length()-suffix.length());
        if(newClassName.indexOf("__")>0){
        	//has generic
        	String primaryName = noSufix.substring(0,noSufix.indexOf("__"));
        	String genericPart = noSufix.substring(noSufix.indexOf("__")+2);
        	StringBuffer genericBuff = new StringBuffer();
        	String[] eachGeneric = genericPart.split("__");
        	for(String genericType:eachGeneric){
        		genericBuff.append("__");
        		genericBuff.append(reduceType(genericType));
        	}
        	return primaryName+genericBuff.toString()+suffix;
        }
        //If there is no generic type lets give an error and force the client to reduce className
		return newClassName;
	}

	private String reduceType(String genericType) {
		if(genericType==null || genericType.indexOf("_")<0){
			return genericType;
		}
		String pack = genericType.substring(0,genericType.lastIndexOf("_"));
		String finalName = genericType.substring(genericType.lastIndexOf("_")+1);
		int packSize = pack.length();
		if(packSize>7){
			pack = pack.subSequence(0, 2)+Integer.toString((packSize-5))+pack.substring(packSize-3);
			return pack+"_"+finalName;
		}
		return genericType;
	}

	public static final String parametersName2ClassName(String parametrizedQualifiedSourceName){
    	return parametrizedQualifiedSourceName.replace('.', '_').replace("<", "__").replace(">", "__");
    }
    
  

    protected String getName( JClassType source ){
        if( source.getEnclosingType() != null ){
            return getName( source.getEnclosingType() ) + "_" + source.getSimpleSourceName();
        }
        return source.getSimpleSourceName();
    }
    
    /**
     * Some packages are protected such that any type we generate in that package can't subsequently be loaded
     * because of a {@link SecurityException}, for example <code>java.</code> and <code>javax.</code> packages. 
     * <p>
     * To workaround this issue we add a prefix onto such packages so that the generated code can be loaded
     * later. The prefix added is <code>open.</code>
     * 
     * @param name
     * @return
     */
    private String getOpenPackageName(String name) {
      if (name.startsWith("java.") || name.startsWith("javax.")) {
        name = "open."+name;
      }
      return name;
    }
    
    protected PrintWriter writer() {
        HashSet<String> classes = getGeneratedClasses();
        if (classes.contains(name)) {
            return null;
        }
        classes.add(name);
{'fraction_non_alphanumeric': 0.10031704739452077, 'fraction_numerical': 0.004146004389887001, 'mean_word_length': 3.3393298059964724, 'pattern_counts': {'":': 0, '<': 45, '<?xml version=': 0, '>': 45, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6442606', 'n_tokens_mistral': 3446, 'n_tokens_neox': 3306, 'n_words': 954}