/*
* Copyright 2015 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*
* 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.kie.workbench.common.services.datamodeller.parser.util;
import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.drools.core.base.ClassTypeResolver;
import org.kie.workbench.common.services.datamodeller.driver.ModelDriverException;
import org.kie.workbench.common.services.datamodeller.parser.descr.ClassOrInterfaceTypeDescr;
import org.kie.workbench.common.services.datamodeller.parser.descr.FileDescr;
import org.kie.workbench.common.services.datamodeller.parser.descr.IdentifierWithTypeArgumentsDescr;
import org.kie.workbench.common.services.datamodeller.parser.descr.ImportDescr;
import org.kie.workbench.common.services.datamodeller.parser.descr.ModifierDescr;
import org.kie.workbench.common.services.datamodeller.parser.descr.TypeArgumentDescr;
import org.kie.workbench.common.services.datamodeller.parser.descr.TypeArgumentListDescr;
import org.kie.workbench.common.services.datamodeller.parser.descr.TypeDescr;
public class JavaDriverUtils {
public static ClassTypeResolver createClassTypeResolver( FileDescr fileDescr, ClassLoader classLoader ) {
String packageName;
Set<String> classImports = new HashSet<String>();
List<ImportDescr> fileImports = fileDescr.getImports();
if ( fileImports != null ) {
for ( ImportDescr importDescr : fileDescr.getImports() ) {
classImports.add( importDescr.getName( true ) );
}
}
if ( fileDescr.getPackageDescr() != null ) {
packageName = fileDescr.getPackageDescr().getPackageName();
} else {
packageName = null;
}
//add current package too, if not added, the class type resolver don't resolve current package classes.
if ( packageName != null && !"".equals( packageName ) ) {
classImports.add( packageName + ".*" );
}
return new ClassTypeResolver( classImports, classLoader );
}
public static boolean isPrimitiveType( TypeDescr typeDescr ) {
return typeDescr.isPrimitiveType();
}
public static boolean isSimpleClass( TypeDescr typeDescr ) {
if ( !typeDescr.isClassOrInterfaceType() ) {
return false;
}
ClassOrInterfaceTypeDescr classOrInterfaceTypeDescr = typeDescr.getClassOrInterfaceType();
List<IdentifierWithTypeArgumentsDescr> identifierWithTypeArgumentsList = classOrInterfaceTypeDescr.getIdentifierWithTypeArguments();
if ( identifierWithTypeArgumentsList == null || identifierWithTypeArgumentsList.size() == 0 ) {
return false;
}
for ( IdentifierWithTypeArgumentsDescr identifierWithTypeArguments : identifierWithTypeArgumentsList ) {
if ( identifierWithTypeArguments.getArguments() != null ) {
return false;
}
}
return true;
}
public static Object[] isSimpleGeneric( TypeDescr typeDescr ) {
Object[] result = new Object[ 3 ];
result[ 0 ] = false;
result[ 1 ] = null;
result[ 2 ] = null;
if ( !typeDescr.isClassOrInterfaceType() ) {
return result;
}
ClassOrInterfaceTypeDescr classOrInterfaceTypeDescr = typeDescr.getClassOrInterfaceType();
List<IdentifierWithTypeArgumentsDescr> identifierWithTypeArgumentsList = classOrInterfaceTypeDescr.getIdentifierWithTypeArguments();
if ( identifierWithTypeArgumentsList == null || identifierWithTypeArgumentsList.size() == 0 ) {
return result;
}
int i = 0;
StringBuilder outerClassName = new StringBuilder();
for ( IdentifierWithTypeArgumentsDescr identifierWithTypeArguments : identifierWithTypeArgumentsList ) {
i++;
if ( i > 1 ) {
outerClassName.append( "." );
}
outerClassName.append( identifierWithTypeArguments.getIdentifier().getIdentifier() );
if ( identifierWithTypeArguments.getArguments() != null ) {
if ( identifierWithTypeArgumentsList.size() > i ) {
return result;
}
TypeArgumentListDescr typeArgumentList = identifierWithTypeArguments.getArguments();
List<TypeArgumentDescr> typeArguments = typeArgumentList != null ? typeArgumentList.getArguments() : null;
if ( typeArguments == null || typeArguments.size() != 1 ) {
return result;
}
TypeDescr type;
if ( ( type = typeArguments.get( 0 ).getType() ) != null && isSimpleClass( type ) ) {
result[ 0 ] = true;
result[ 1 ] = outerClassName.toString();
result[ 2 ] = type;
return result;
}
}
}
return result;
}
public static boolean isArray( TypeDescr typeDescr ) {
return typeDescr.getDimensionsCount() > 0;
}
/**
* @return Return true if the given type can be managed by the driver, and subsequently by the UI.
* <p/>
* E.g. of managed types are:
* int, Integer, java.lang.Integer, org.kie.SomeClass, List<Integer>, java.util.List<org.kie.SomeClass>
* <p/>
* e.g. of not manged types are:
* int[], java.util.List<List<String>>, List<Map<String, org.kie.SomeClass>>
*/
public static boolean isManagedType( TypeDescr typeDescr, ClassTypeResolver classTypeResolver ) throws ModelDriverException {
if ( isArray( typeDescr ) ) {
return false;
}
if ( isPrimitiveType( typeDescr ) || isSimpleClass( typeDescr ) ) {
return true;
}
Object[] simpleGenerics = isSimpleGeneric( typeDescr );
if ( Boolean.FALSE.equals( simpleGenerics[ 0 ] ) ) {
return false;
} else {
//try to guess if we have something in the form Collection<SomeClass>
String collectionCandidate = simpleGenerics[ 1 ].toString();
try {
Class collectionCandidateClass = classTypeResolver.resolveType( collectionCandidate );
return Collection.class.isAssignableFrom( collectionCandidateClass );
} catch ( ClassNotFoundException e ) {
throw new ModelDriverException( "Class could not be resolved for name: " + collectionCandidate + ". " + e.getMessage(), e );
}
}
}
public static boolean equalsType( TypeDescr type, String fullClassName, boolean multiple, String fullBagClassName, ClassTypeResolver classTypeResolver ) throws ClassNotFoundException {
String currentClassName;
String currentBag;
if ( isArray( type ) ) {
return false;
}
if ( type.isPrimitiveType() ) {
return !multiple && fullClassName.equals( type.getPrimitiveType().getName() );
}
if ( isSimpleClass( type ) ) {
currentClassName = classTypeResolver.getFullTypeName( type.getClassOrInterfaceType().getClassName() );
return !multiple && fullClassName.equals( currentClassName );
}
Object[] simpleGenerics = isSimpleGeneric( type );
if ( Boolean.TRUE.equals( simpleGenerics[ 0 ] ) && multiple ) {
currentBag = ( String ) simpleGenerics[ 1 ];
currentBag = classTypeResolver.getFullTypeName( currentBag );
currentClassName = ( ( TypeDescr ) simpleGenerics[ 2 ] ).getClassOrInterfaceType().getClassName();
currentClassName = classTypeResolver.getFullTypeName( currentClassName );
return fullBagClassName.equals( currentBag ) && fullClassName.equals( currentClassName );
}
return false;
}
public static int buildModifierRepresentation( List<ModifierDescr> modifiers ) {
int result = 0x0;
if ( modifiers != null ) {
for ( ModifierDescr modifier : modifiers ) {
if ( "public".equals( modifier.getName() ) ) {
result = result | Modifier.PUBLIC;
}
if ( "protected".equals( modifier.getName() ) ) {
result = result | Modifier.PROTECTED;
}
if ( "private".equals( modifier.getName() ) ) {
result = result | Modifier.PRIVATE;
}
if ( "abstract".equals( modifier.getName() ) ) {
result = result | Modifier.ABSTRACT;
}
if ( "static".equals( modifier.getName() ) ) {
result = result | Modifier.STATIC;
}
if ( "final".equals( modifier.getName() ) ) {
result = result | Modifier.FINAL;
}
if ( "transient".equals( modifier.getName() ) ) {
result = result | Modifier.TRANSIENT;
}
if ( "volatile".equals( modifier.getName() ) ) {
result = result | Modifier.VOLATILE;
}
if ( "synchronized".equals( modifier.getName() ) ) {
result = result | Modifier.SYNCHRONIZED;
}
if ( "native".equals( modifier.getName() ) ) {
result = result | Modifier.NATIVE;
}
if ( "strictfp".equals( modifier.getName() ) ) {
result = result | Modifier.STRICT;
}
if ( "interface".equals( modifier.getName() ) ) {
result = result | Modifier.INTERFACE;
}
}
}
return result;
}
}