Package org.drools.workbench.screens.dtablexls.backend.server.conversion

Source Code of org.drools.workbench.screens.dtablexls.backend.server.conversion.DecisionTableXLSToDecisionTableGuidedConverter

/*
* Copyright 2012 JBoss Inc
*
* 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.drools.workbench.screens.dtablexls.backend.server.conversion;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import javax.annotation.PostConstruct;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.inject.Named;

import org.drools.core.util.DateUtils;
import org.drools.decisiontable.parser.xls.ExcelParser;
import org.drools.template.model.Global;
import org.drools.template.model.Import;
import org.drools.template.parser.DataListener;
import org.drools.workbench.models.guided.dtable.shared.conversion.ConversionMessageType;
import org.drools.workbench.models.guided.dtable.shared.conversion.ConversionResult;
import org.drools.workbench.models.guided.dtable.shared.model.GuidedDecisionTable52;
import org.drools.workbench.screens.drltext.service.DRLTextEditorService;
import org.drools.workbench.screens.drltext.type.DRLResourceTypeDefinition;
import org.drools.workbench.screens.dtablexls.service.DecisionTableXLSConversionService;
import org.drools.workbench.screens.dtablexls.type.DecisionTableXLSResourceTypeDefinition;
import org.drools.workbench.screens.factmodel.backend.server.util.FactModelPersistence;
import org.drools.workbench.screens.factmodel.model.AnnotationMetaModel;
import org.drools.workbench.screens.factmodel.model.FactMetaModel;
import org.drools.workbench.screens.factmodel.model.FactModels;
import org.drools.workbench.screens.factmodel.model.FieldMetaModel;
import org.drools.workbench.screens.globals.model.GlobalsModel;
import org.drools.workbench.screens.globals.service.GlobalsEditorService;
import org.drools.workbench.screens.globals.type.GlobalResourceTypeDefinition;
import org.drools.workbench.screens.guided.dtable.service.GuidedDecisionTableEditorService;
import org.drools.workbench.screens.guided.dtable.type.GuidedDTableResourceTypeDefinition;
import org.guvnor.common.services.project.model.Project;
import org.guvnor.common.services.project.model.ProjectImports;
import org.guvnor.common.services.project.service.ProjectService;
import org.guvnor.common.services.shared.metadata.MetadataService;
import org.guvnor.common.services.shared.metadata.model.Metadata;
import org.uberfire.io.IOService;
import org.uberfire.java.nio.file.Files;
import org.kie.workbench.common.screens.datamodeller.model.AnnotationDefinitionTO;
import org.kie.workbench.common.screens.datamodeller.model.DataModelTO;
import org.kie.workbench.common.screens.datamodeller.model.DataObjectTO;
import org.kie.workbench.common.screens.datamodeller.model.ObjectPropertyTO;
import org.kie.workbench.common.screens.datamodeller.model.PropertyTypeTO;
import org.kie.workbench.common.screens.datamodeller.service.DataModelerService;
import org.uberfire.backend.server.util.Paths;
import org.uberfire.backend.vfs.Path;
import org.uberfire.security.Identity;
import org.uberfire.workbench.type.ResourceTypeDefinition;

/**
* Converter from a XLS Decision Table to a Guided Decision Table
*/
@ApplicationScoped
public class DecisionTableXLSToDecisionTableGuidedConverter implements DecisionTableXLSConversionService {

    @Inject
    private Identity identity;

    @Inject
    @Named("ioStrategy")
    private IOService ioService;

    @Inject
    private DRLTextEditorService drlService;

    @Inject
    private GuidedDecisionTableEditorService guidedDecisionTableService;

    @Inject
    private GlobalsEditorService globalsService;

    @Inject
    private ProjectService projectService;

    @Inject
    private MetadataService metadataService;

    @Inject
    //Type Definition to ensure new files have correct extension
    private DecisionTableXLSResourceTypeDefinition xlsDTableType;

    @Inject
    //Type Definition to ensure new files have correct extension
    private GuidedDTableResourceTypeDefinition guidedDTableType;

    @Inject
    //Type Definition to ensure new files have correct extension
    private DRLResourceTypeDefinition drlType;

    @Inject
    private DataModelerService modellerService;

    @Inject
    //Type Definition to ensure new files have correct extension
    private GlobalResourceTypeDefinition globalsType;

    private Map<String, String> orderedBaseTypes = new TreeMap<String, String>();
    private Map<String, AnnotationDefinitionTO> annotationDefinitions;

    @PostConstruct
    public void initialiseTypeConversionMetaData() {
        final List<PropertyTypeTO> baseTypes = modellerService.getBasePropertyTypes();
        if ( baseTypes != null ) {
            for ( PropertyTypeTO type : baseTypes ) {
                orderedBaseTypes.put( type.getName(), type.getClassName() );
            }
        }

        annotationDefinitions = modellerService.getAnnotationDefinitions();
    }

    @Override
    public ConversionResult convert( final Path path ) {

        ConversionResult result = new ConversionResult();

        //Check Asset is of the correct format
        if ( !xlsDTableType.accept( path ) ) {
            result.addMessage( "Source Asset is not an XLS Decision Table.",
                               ConversionMessageType.ERROR );
            return result;
        }

        //Perform conversion!
        final GuidedDecisionTableGeneratorListener listener = parseAssets( path,
                                                                           result );

        //Root path for new resources is the same folder as the XLS file
        final Path context = Paths.convert( Paths.convert( path ).getParent() );

        //Add Ancillary resources
        createNewImports( context,
                          listener.getImports(),
                          result );
        createNewFunctions( context,
                            listener.getImports(),
                            listener.getFunctions(),
                            result );
        createNewQueries( context,
                          listener.getImports(),
                          listener.getQueries(),
                          result );
        makeNewJavaTypes( context,
                          listener.getTypeDeclarations(),
                          result );
        createNewGlobals( context,
                          listener.getGlobals(),
                          result );

        //Add Web Guided Decision Tables
        createNewDecisionTables( context,
                                 listener.getImports(),
                                 listener.getGuidedDecisionTables(),
                                 result );

        return result;
    }

    private GuidedDecisionTableGeneratorListener parseAssets( final Path path,
                                                              final ConversionResult result ) {

        final List<DataListener> listeners = new ArrayList<DataListener>();
        final GuidedDecisionTableGeneratorListener listener = new GuidedDecisionTableGeneratorListener( result );
        listeners.add( listener );

        final ExcelParser parser = new ExcelParser( listeners );
        final InputStream stream = ioService.newInputStream( Paths.convert( path ) );

        try {
            parser.parseFile( stream );
        } finally {
            try {
                stream.close();
            } catch ( IOException ioe ) {
                result.addMessage( ioe.getMessage(),
                                   ConversionMessageType.ERROR );
            }
        }
        return listener;
    }

    private void createNewFunctions( final Path context,
                                     final List<Import> imports,
                                     final List<String> functions,
                                     final ConversionResult result ) {
        if ( functions == null || functions.isEmpty() ) {
            return;
        }

        //Create new assets for Functions
        for ( int iCounter = 0; iCounter < functions.size(); iCounter++ ) {

            final String assetName = makeNewAssetName( "Function " + ( iCounter + 1 ),
                                                       drlType );
            final String drl = makeDRL( imports,
                                        functions.get( iCounter ) );
            drlService.create( context,
                               assetName,
                               drl,
                               "Converted from XLS Decision Table" );

            result.addMessage( "Created Function '" + assetName + "'",
                               ConversionMessageType.INFO );
        }
    }

    private void createNewQueries( final Path context,
                                   final List<Import> imports,
                                   final List<String> queries,
                                   final ConversionResult result ) {
        if ( queries == null || queries.isEmpty() ) {
            return;
        }

        //Create new assets for Queries
        for ( int iCounter = 0; iCounter < queries.size(); iCounter++ ) {

            final String assetName = makeNewAssetName( "Query " + ( iCounter + 1 ),
                                                       drlType );
            final String drl = makeDRL( imports,
                                        queries.get( iCounter ) );
            drlService.create( context,
                               assetName,
                               drl,
                               "Converted from XLS Decision Table" );

            result.addMessage( "Created Query '" + assetName + "'",
                               ConversionMessageType.INFO );
        }
    }

    private void makeNewJavaTypes( final Path context,
                                   final List<String> declaredTypes,
                                   final ConversionResult result ) {
        if ( declaredTypes == null || declaredTypes.isEmpty() ) {
            return;
        }

        final Project project = projectService.resolveProject( context );

        for ( String declaredType : declaredTypes ) {
            final FactModels factModels = FactModelPersistence.unmarshal( declaredType );
            final String packageName = factModels.getPackageName();
            final DataModelTO dataModelTO = new DataModelTO();

            for ( FactMetaModel factMetaModel : factModels.getModels() ) {
                final DataObjectTO dataObjectTO = new DataObjectTO( factMetaModel.getName(),
                                                                    packageName,
                                                                    factMetaModel.getSuperType() );
                final List<AnnotationMetaModel> annotationMetaModel = factMetaModel.getAnnotations();
                addAnnotations( dataObjectTO,
                                annotationMetaModel );

                final List<FieldMetaModel> fields = factMetaModel.getFields();

                for ( FieldMetaModel fieldMetaModel : fields ) {
                    final String fieldName = fieldMetaModel.name;
                    final String fieldType = fieldMetaModel.type;
                    //Guvnor 5.5 (and earlier) does not have MultipleType
                    boolean isMultiple = false;
                    boolean isBaseType = orderedBaseTypes.containsValue( fieldType );
                    ObjectPropertyTO property = new ObjectPropertyTO( fieldName,
                                                                      fieldType,
                                                                      isMultiple,
                                                                      isBaseType );
                    //field has no annotation in Guvnor 5.5 (and earlier)
                    dataObjectTO.getProperties().add( property );

                    result.addMessage( "Created Java Type " + getJavaTypeFQCN( dataObjectTO ),
                                       ConversionMessageType.INFO );
                }

                dataModelTO.getDataObjects().add( dataObjectTO );
            }

            modellerService.saveModel( dataModelTO,
                                       project );
        }
    }

    private String getJavaTypeFQCN( final DataObjectTO dataObjectTO ) {
        final String packageName = dataObjectTO.getPackageName();
        final String className = dataObjectTO.getClassName();
        if ( packageName == null || packageName.equals( "" ) ) {
            return className;
        }
        return packageName + "." + className;
    }

    private void addAnnotations( final DataObjectTO dataObject,
                                 final List<AnnotationMetaModel> annotationMetaModelList ) {
        for ( AnnotationMetaModel annotationMetaModel : annotationMetaModelList ) {
            final String name = annotationMetaModel.name;
            final Map<String, String> values = annotationMetaModel.values;

            String key = AnnotationDefinitionTO.VALUE_PARAM;
            String value = "";

            if ( values.size() > 0 ) {
                key = values.keySet().iterator().next();
                value = values.values().iterator().next();
            }

            if ( "Role".equals( name ) ) {
                dataObject.addAnnotation( annotationDefinitions.get( AnnotationDefinitionTO.ROLE_ANNOTATION ),
                                          key,
                                          value );
            } else if ( "Position".equals( name ) ) {
                dataObject.addAnnotation( annotationDefinitions.get( AnnotationDefinitionTO.POSITION_ANNOTATON ),
                                          key,
                                          value );
            } else if ( "Equals".equals( name ) ) {
                dataObject.addAnnotation( annotationDefinitions.get( AnnotationDefinitionTO.KEY_ANNOTATION ),
                                          key,
                                          value );
            }
        }
    }

    private String makeDRL( final List<Import> imports,
                            final String baseDRL ) {
        final StringBuilder sb = new StringBuilder();
        if ( !( imports == null || imports.isEmpty() ) ) {
            for ( Import item : imports ) {
                sb.append( "import " ).append( item.getClassName() ).append( ";\n" );
            }
            sb.append( "\n" );
        }
        sb.append( baseDRL ).append( "\n" );
        return sb.toString();
    }

    private void createNewGlobals( final Path context,
                                   final List<Global> globals,
                                   final ConversionResult result ) {
        if ( globals == null || globals.isEmpty() ) {
            return;
        }

        //Create new asset for Globals. All Globals can be in one file.
        final String assetName = makeNewAssetName( "Global",
                                                   globalsType );
        final GlobalsModel model = makeGlobalsModel( globals );
        globalsService.create( context,
                               assetName,
                               model,
                               "Converted from XLS Decision Table" );

        result.addMessage( "Created Globals '" + assetName + "'",
                           ConversionMessageType.INFO );
    }

    private GlobalsModel makeGlobalsModel( final List<Global> globals ) {
        final GlobalsModel model = new GlobalsModel();
        for ( Global global : globals ) {
            model.getGlobals().add( new org.drools.workbench.screens.globals.model.Global( global.getIdentifier(),
                                                                                           global.getClassName() ) );
        }
        return model;
    }

    private void createNewImports( final Path context,
                                   final List<Import> imports,
                                   final ConversionResult result ) {

        if ( imports == null || imports.isEmpty() ) {
            return;
        }

        //Load existing PackageImports
        ProjectImports projectImports = new ProjectImports();
        final org.uberfire.java.nio.file.Path nioExternalImportsPath = Paths.convert( context ).resolve( "project.imports" );
        final Path externalImportsPath = Paths.convert( nioExternalImportsPath );
        if ( Files.exists( nioExternalImportsPath ) ) {
            projectImports = projectService.load( externalImportsPath );
        }

        //Make collections of existing Imports so we don't duplicate them when adding the new
        List<String> existingImports = new ArrayList<String>();
        for ( org.drools.workbench.models.datamodel.imports.Import item : projectImports.getImports().getImports() ) {
            existingImports.add( item.getType() );
        }

        //Add imports
        boolean isModified = false;
        for ( Import item : imports ) {
            if ( !existingImports.contains( item.getClassName() ) ) {
                isModified = true;
                result.addMessage( "Created Import for '" + item.getClassName() + "'.",
                                   ConversionMessageType.INFO );
                projectImports.getImports().addImport( new org.drools.workbench.models.datamodel.imports.Import( item.getClassName() ) );
            }
        }

        //Save update
        if ( isModified ) {
            final Metadata metadata = metadataService.getMetadata( context );
            projectService.save( externalImportsPath,
                                 projectImports,
                                 metadata,
                                 "Imports added during XLS conversion" );
        }
    }

    private void createNewDecisionTables( final Path context,
                                          final List<Import> imports,
                                          final List<GuidedDecisionTable52> dtables,
                                          final ConversionResult result ) {
        if ( dtables == null || dtables.isEmpty() ) {
            return;
        }

        //Create new assets for Guided Decision Tables
        for ( int iCounter = 0; iCounter < dtables.size(); iCounter++ ) {

            //Add imports
            final GuidedDecisionTable52 dtable = dtables.get( iCounter );
            for ( Import item : imports ) {
                dtable.getImports().addImport( new org.drools.workbench.models.datamodel.imports.Import( item.getClassName() ) );
            }

            //Make new resource
            final String assetName = makeNewAssetName( dtable.getTableName(),
                                                       guidedDTableType );
            guidedDecisionTableService.create( context,
                                               assetName,
                                               dtable,
                                               "Converted from XLS Decision Table" );

            result.addMessage( "Created Guided Decision Table '" + assetName + "'",
                               ConversionMessageType.INFO );
        }
    }

    private String makeNewAssetName( final String baseName,
                                     final ResourceTypeDefinition type ) {
        Calendar now = Calendar.getInstance();
        StringBuilder sb = new StringBuilder( baseName );
        sb.append( " (converted on " );
        sb.append( DateUtils.format( now.getTime() ) );
        sb.append( " " );
        sb.append( now.get( Calendar.HOUR_OF_DAY ) );
        sb.append( ":" );
        sb.append( now.get( Calendar.MINUTE ) );
        sb.append( ":" );
        sb.append( now.get( Calendar.SECOND ) );
        sb.append( ")" );
        sb.append( "." ).append( type.getSuffix() );
        return sb.toString();
    }

}
TOP

Related Classes of org.drools.workbench.screens.dtablexls.backend.server.conversion.DecisionTableXLSToDecisionTableGuidedConverter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.