/* * 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.driver.impl; import java.lang.reflect.Modifier; import java.util.Map; import org.drools.workbench.models.datamodel.oracle.ModelField; import org.drools.workbench.models.datamodel.oracle.ProjectDataModelOracle; import org.drools.workbench.models.datamodel.oracle.TypeSource; import org.kie.workbench.common.services.datamodel.backend.server.DataModelOracleUtilities; import org.kie.workbench.common.services.datamodeller.core.DataModel; import org.kie.workbench.common.services.datamodeller.core.DataObject; import org.kie.workbench.common.services.datamodeller.core.JavaEnum; import org.kie.workbench.common.services.datamodeller.core.ObjectSource; import org.kie.workbench.common.services.datamodeller.core.Visibility; import org.kie.workbench.common.services.datamodeller.core.impl.JavaEnumImpl; import org.kie.workbench.common.services.datamodeller.driver.ModelDriverException; import org.kie.workbench.common.services.datamodeller.util.DriverUtils; import org.kie.workbench.common.services.datamodeller.util.NamingUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class ProjectDataModelOracleUtils { private static final Logger logger = LoggerFactory.getLogger( ProjectDataModelOracleUtils.class ); public static void loadExternalDependencies( DataModel dataModel, ProjectDataModelOracle projectDataModelOracle, ClassLoader classLoader ) throws ModelDriverException { String[] factTypes = DataModelOracleUtilities.getFactTypes( projectDataModelOracle ); ObjectSource source; if ( factTypes != null ) { for ( int i = 0; i < factTypes.length; i++ ) { source = factSource( projectDataModelOracle, factTypes[ i ] ); if ( source != null && ObjectSource.DEPENDENCY.equals( source ) ) { addType( dataModel, projectDataModelOracle, factTypes[ i ], classLoader ); } } } } private static void addType( DataModel dataModel, ProjectDataModelOracle oracleDataModel, String factType, ClassLoader classLoader ) throws ModelDriverException { ClassMetadata classMetadata = readClassMetadata( factType, classLoader ); if ( classMetadata != null && !classMetadata.isMemberClass() && !classMetadata.isAnonymousClass() && !classMetadata.isLocalClass() ) { if ( classMetadata.isEnumClass() ) { addEnumType( dataModel, factType, classMetadata ); } else { addDataObjectType( dataModel, oracleDataModel, factType, classMetadata ); } } } private static void addDataObjectType( DataModel dataModel, ProjectDataModelOracle oracleDataModel, String factType, ClassMetadata classMetadata ) throws ModelDriverException { String superClass = DataModelOracleUtilities.getSuperType( oracleDataModel, factType ); Visibility visibility = DriverUtils.buildVisibility( classMetadata.getModifiers() ); DataObject dataObject; logger.debug( "Adding dataObjectType: " + factType + ", to dataModel: " + dataModel + ", from oracleDataModel: " + oracleDataModel ); dataObject = dataModel.addDataObject( factType, visibility, Modifier.isAbstract( classMetadata.getModifiers() ), Modifier.isFinal( classMetadata.getModifiers() ), ObjectSource.DEPENDENCY ); dataObject.setSuperClassName( superClass ); Map<String, ModelField[]> fields = oracleDataModel.getProjectModelFields(); if ( fields != null ) { ModelField[] factFields = fields.get( factType ); ModelField field; if ( factFields != null && factFields.length > 0 ) { for ( int j = 0; j < factFields.length; j++ ) { field = factFields[ j ]; if ( isLoadableField( field ) ) { if ( field.getType().equals( "Collection" ) ) { //read the correct bag and item classes. String bag = DataModelOracleUtilities.getFieldClassName( oracleDataModel, factType, field.getName() ); String itemsClass = DataModelOracleUtilities.getParametricFieldType( oracleDataModel, factType, field.getName() ); if ( itemsClass == null ) { //if we don't know the items class, the property will be managed as a simple property. dataObject.addProperty( field.getName(), bag ); } else { dataObject.addProperty( field.getName(), itemsClass, true, bag ); } } else { dataObject.addProperty( field.getName(), field.getClassName() ); } } } } } else { logger.debug( "No fields found for factTye: " + factType ); } } private static void addEnumType( DataModel dataModel, String factType, ClassMetadata classMetadata ) { String packageName = NamingUtils.extractPackageName( factType ); String className = NamingUtils.extractClassName( factType ); Visibility visibility = DriverUtils.buildVisibility( classMetadata.getModifiers() ); JavaEnum javaEnum = new JavaEnumImpl( packageName, className, visibility ); dataModel.addJavaEnum( javaEnum, ObjectSource.DEPENDENCY ); } private static ClassMetadata readClassMetadata( String factType, ClassLoader classLoader ) { try { Class _class = classLoader.loadClass( factType ); return new ClassMetadata( _class.getModifiers(), _class.isMemberClass(), _class.isLocalClass(), _class.isAnonymousClass(), _class.isEnum() ); } catch ( ClassNotFoundException e ) { logger.error( "It was not possible to read class metadata for class: " + factType ); } return null; } private static ObjectSource factSource( ProjectDataModelOracle oracleDataModel, String factType ) { TypeSource oracleType = DataModelOracleUtilities.getTypeSource( oracleDataModel, factType ); if ( TypeSource.JAVA_PROJECT.equals( oracleType ) ) { return ObjectSource.INTERNAL; } else if ( TypeSource.JAVA_DEPENDENCY.equals( oracleType ) ) { return ObjectSource.DEPENDENCY; } return null; } /** * Indicates if this field should be loaded or not. * Some fields like a filed with name "this" shouldn't be loaded. */ private static boolean isLoadableField( ModelField field ) { return ( field.getOrigin().equals( ModelField.FIELD_ORIGIN.DECLARED ) ); } static class ClassMetadata { int modifiers; boolean memberClass; boolean localClass; boolean anonymousClass; boolean enumClass; public ClassMetadata( int modifiers, boolean memberClass, boolean localClass, boolean anonymousClass, boolean enumClass ) { this.modifiers = modifiers; this.memberClass = memberClass; this.localClass = localClass; this.anonymousClass = anonymousClass; this.enumClass = enumClass; } public int getModifiers() { return modifiers; } public void setModifiers( int modifiers ) { this.modifiers = modifiers; } public boolean isMemberClass() { return memberClass; } public void setMemberClass( boolean memberClass ) { this.memberClass = memberClass; } public boolean isLocalClass() { return localClass; } public void setLocalClass( boolean localClass ) { this.localClass = localClass; } public boolean isAnonymousClass() { return anonymousClass; } public void setAnonymousClass( boolean anonymousClass ) { this.anonymousClass = anonymousClass; } public boolean isEnumClass() { return enumClass; } public void setEnumClass( boolean enumClass ) { this.enumClass = enumClass; } } }