/* * Copyright 2013 Guidewire Software, Inc. */ package gw.lang.reflect; import gw.lang.reflect.gs.IGenericTypeVariable; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.RandomAccess; import java.util.Set; public class TypeInfoUtil { public static <S extends CharSequence, T extends IFeatureInfo> List<T> makeSortedUnmodifiableRandomAccessListFromFeatures( Map<S, T> map ) { if( map.isEmpty() ) { return Collections.emptyList(); } Collection<T> values = map.values(); return makeSortedUnmodifiableRandomAccessList( values ); } public static <T extends IFeatureInfo> List<T> makeSortedUnmodifiableRandomAccessList( Collection<T> collection ) { if( collection.isEmpty() ) { return Collections.emptyList(); } List<T> list = collection instanceof List && collection instanceof RandomAccess ? (List<T>)collection : new ArrayList<T>( collection ); sortByName( list ); return Collections.unmodifiableList( list ); } public static MethodList makeSortedUnmodifiableRandomAccessList( MethodList collection ) { if( collection.isEmpty() ) { return MethodList.EMPTY; } List<IMethodInfo> list = new ArrayList<IMethodInfo>(collection); sortByName( list ); return new MethodList(list); } public static <T extends IFeatureInfo> void sortByName( List<T> featureInfos ) { if( featureInfos.isEmpty() ) { return; } Collections.sort( featureInfos, new Comparator<IFeatureInfo>() { public int compare( IFeatureInfo o1, IFeatureInfo o2 ) { return o1.getName().compareToIgnoreCase( o2.getName() ); } } ); } public static String getMethodSignature( IMethodInfo mi ) { IFunctionType type = TypeSystem.getOrCreateFunctionType( mi ); return mi.getDisplayName() + getParameterDisplay( mi ) + " : " + getTypeName( type.getReturnType() ); } public static String getConstructorSignature( IConstructorInfo constructorInfo ) { return constructorInfo.getDisplayName() + getParameterDisplay( constructorInfo ); } public static String getParameterDisplay( IMethodInfo mi ) { IParameterInfo[] pd = mi.getParameters(); return getParameterDisplay( pd ); } public static String getParameterDisplay( IConstructorInfo ci ) { IParameterInfo[] pd = ci.getParameters(); return getParameterDisplay( pd ); } private static String getParameterDisplay( IParameterInfo[] pds ) { if( pds == null || pds.length == 0 ) { return "()"; } String strParams = "("; for( int i = 0; i < pds.length; i++ ) { strParams += (i == 0 ? "" : ", ") + pds[i].getFeatureType().getName(); } strParams += ")"; return strParams; } public static String getTypeVarList( IFeatureInfo fi ) { return getTypeVarList( fi, false ); } public static String getTypeVarList( IFeatureInfo fi, boolean bRelative ) { if( fi instanceof IGenericMethodInfo ) { StringBuilder vars = new StringBuilder(); int i = 0; for( IGenericTypeVariable tv : ((IGenericMethodInfo)fi).getTypeVariables() ) { vars.append( i++ > 0 ? ',' : '<' ); vars.append( tv.getNameWithBounds( bRelative ) ); } if( i > 0 ) { return vars.append( '>' ).toString(); } } return ""; } public static String getTypeVarListNoBounds( IFeatureInfo fi ) { if( fi instanceof IGenericMethodInfo ) { StringBuilder vars = new StringBuilder(); int i = 0; for( IGenericTypeVariable tv : ((IGenericMethodInfo)fi).getTypeVariables() ) { vars.append( i++ > 0 ? ',' : '<' ); vars.append( tv.getName() ); } if( i > 0 ) { return vars.append( '>' ).toString(); } } return ""; } public static String getTypeName( IType type ) { String strType; if( type.isArray() ) { strType = getTypeName( type.getComponentType() ) + "[]"; } else { strType = type.getRelativeName(); } return strType; } public static String normalizePackageName( String packageName ) { StringBuilder sb = new StringBuilder(); String[] parts = packageName.split( "\\." ); for ( String part : parts ) { if ( sb.length() > 0 ) { sb.append( '.' ); } sb.append( normalizeGosuIdentifier( part ) ); } return sb.toString(); } public static String normalizeGosuIdentifier( String propertyName, Set<String> usedPropertyNames, boolean caseSensitive ) { propertyName = normalizeGosuIdentifier( propertyName ); int suffix = 2; String newPropertyName = propertyName; while ( ! usedPropertyNames.add( caseSensitive ? newPropertyName : newPropertyName.toLowerCase() ) ) { newPropertyName = propertyName + suffix++; } return newPropertyName; } public static String normalizeGosuIdentifier( String name ) { StringBuilder sb = new StringBuilder(); for ( int i = 0; i < name.length(); i++ ) { char ch = name.charAt( i ); if ( i == 0 ) { // some existing properties are composed solely of numbers, added isDigit() since they don't seem to be // syntactically invalid in Gosu, and are actively being used by CC. if ( Character.isJavaIdentifierStart( ch ) || Character.isDigit( ch ) ) { // use as-is sb.append( ch ); } else if ( Character.isJavaIdentifierPart( ch ) ) { // prefix with "_" sb.append( '_' ); sb.append( ch ); } else { // replace with "_" sb.append( '_' ); } } else if ( Character.isJavaIdentifierPart( ch ) ) { // use as-is sb.append( ch ); } else { // replace with "_" sb.append( '_' ); } } name = sb.toString(); if ( name.length() == 0 ) { name = "_"; } return name; } }