com.processpuzzle.application.domain.Application.java Source code

Java tutorial

Introduction

Here is the source code for com.processpuzzle.application.domain.Application.java

Source

/*
Name: 
- Application
    
Description: 
-  
    
Requires:
- 
    
Provides:
- 
    
Part of: ProcessPuzzle Framework, Domain and Business Model Ready Architecture. Provides content, workflow and social networking functionality. 
http://www.processpuzzle.com
    
ProcessPuzzle - Content and Workflow Management Integration Business Platform
    
Author(s): 
- Zsolt Zsuffa
    
Copyright: (C) 2011 This program is free software: you can redistribute it and/or modify it under the terms of the 
GNU General Public License as published by the Free Software Foundation, either version 3 of the License, 
or (at your option) any later version.
    
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
    
You should have received a copy of the GNU General Public License along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

/*
 * Created on Feb 12, 2006
 *
 * TODO To change the template for this generated file go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
package com.processpuzzle.application.domain;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.configuration.HierarchicalConfiguration;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.ResourceLoader;

import com.processpuzzle.application.configuration.domain.PersistentDataInitializationStrategies;
import com.processpuzzle.application.configuration.domain.ProcessPuzzleApplicationComponent;
import com.processpuzzle.application.configuration.domain.ProcessPuzzleContext;
import com.processpuzzle.application.configuration.domain.PropertyContext;
import com.processpuzzle.application.configuration.domain.PropertyContextOverrides;
import com.processpuzzle.application.configuration.domain.PropertyKeys;
import com.processpuzzle.application.resource.domain.DataLoader;
import com.processpuzzle.application.resource.domain.HardCodedDataLoader;
import com.processpuzzle.application.resource.domain.XmlDataLoader;
import com.processpuzzle.application.security.domain.PredefinedUsersLoader;
import com.processpuzzle.application.security.domain.User;
import com.processpuzzle.application.security.domain.UserRepository;
import com.processpuzzle.commons.persistence.AggregateRoot;
import com.processpuzzle.fundamental_types.domain.GenericEntity;
import com.processpuzzle.party.artifact.PredefinedUserDataSheetsCreator;
import com.processpuzzle.persistence.domain.DefaultUnitOfWork;
import com.processpuzzle.persistence.query.domain.DefaultQueryContext;
import com.processpuzzle.user_session.domain.UserRequestManager;

public abstract class Application extends GenericEntity<Application> implements AggregateRoot {
    private static final String PARAMETER_TYPE_ELEMENT_NAME = "type";
    private static final String INSTANTIATION_ARGUMENTS_SELECTOR = "dl:instantiationArguments.dl:argument";
    private static Logger log = LoggerFactory.getLogger(Application.class);
    protected ResourceLoader resourceLoader;
    protected String applicationName;
    protected String applicationVersion;
    protected String applicationDescription;
    protected ExecutionStatus executionStatus = ExecutionStatus.stopped;
    protected InstallationStatus installationStatus = InstallationStatus.notInstalled;
    protected ProcessPuzzleContext applicationContext;
    protected String configurationDescriptorPath = "classpath:com/itcodex/objectpuzzle/framework/configuration/domaintier/configuration_descriptor.xml";
    protected Map<Application.Events, List<ApplicationEvent>> history = new LinkedHashMap<Events, List<ApplicationEvent>>();
    protected List<DataLoader> dataLoaders = new ArrayList<DataLoader>();

    // Constructors
    protected Application(String configurationDescriptorPath) {
        this(configurationDescriptorPath, new DefaultResourceLoader());
    }

    protected Application(String configurationDescriptorPath, ResourceLoader resourceLoader) {
        this.configurationDescriptorPath = configurationDescriptorPath;
        this.resourceLoader = resourceLoader;
        defineApplicationDescription();
        determineInstallationConfiguration();
        determineInstallationStatus();
    }

    public @Override @SuppressWarnings("unchecked") ApplicationIdentity getDefaultIdentity() {
        DefaultQueryContext context = new DefaultQueryContext();
        context.addTextValueFor("applicationNameValue", applicationName);
        context.addTextValueFor("applicationVersionValue", applicationVersion);
        return new ApplicationIdentity(context);
    }

    // Public mutators
    public void install() throws ApplicationException {
        log.info("Installation of application: " + applicationName + " begins.");

        if (installationStatus.equals(InstallationStatus.installed))
            throw new ReinstallationException(this);

        PropertyContextOverrides overrides = defineInstallationOverrides();
        try {
            setUpApplicationContext(Action.install, overrides);
            applicationContext.createSystemInstallerRequestContext(this);
            persistSystemInstallerUser();
            dataLoaders = determineDataLoaders();
            executeDataLoaders(Action.install);

            executionStatus = ExecutionStatus.running;
            installationStatus = InstallationStatus.installed;
            addEventToHistory(Events.installed);
        } catch (Exception e) {
            throw new ApplicationInstallationException(this, e);
        }

        log.info("Installation of application: " + applicationName + " finished. \n");
    }

    public void unInstall() {
        if (executionStatus == ExecutionStatus.running)
            stop();

        log.info("Uninstallation of application: " + applicationName + " begins.");

        executionStatus = ExecutionStatus.stopped;
        installationStatus = InstallationStatus.notInstalled;

        log.info("Uninstallation of application: " + applicationName + " finished. \n");
    }

    public void start() throws ApplicationException {
        start(null);
    }

    public void start(PropertyContextOverrides overrides) throws ApplicationException {
        if (executionStatus == ExecutionStatus.running)
            return;
        log.info("Starting of application: " + applicationName + " begins.");

        setUpApplicationContext(Action.start, overrides);
        executionStatus = ExecutionStatus.running;
        addEventToHistory(Events.started);

        log.info("Starting of application: " + applicationName + " ended.");
    }

    public void stop() {
        if (executionStatus == ExecutionStatus.stopped)
            return;
        applicationContext.tearDown(Action.stop);
        applicationContext = null;
        executionStatus = ExecutionStatus.stopped;
        log.info("Application stopped.");
    };

    public User authenticateUser(String userName, String password) {
        UserRepository repository = (UserRepository) applicationContext.getRepository(UserRepository.class);
        DefaultUnitOfWork work = new DefaultUnitOfWork(true);
        User userInQuestion = repository.findUserByName(work, userName);
        if (userInQuestion != null && userInQuestion.getPassword().equals(password))
            return userInQuestion;
        else
            return null;
    }

    public boolean loginUser(String userName, String password) {
        User user = authenticateUser(userName, password);
        if (user != null)
            return true;
        else
            return false;
    }

    // Public accessors
    public List<ApplicationEvent> findApplicationEventsByType(Events searchedEvent) {
        return history.get(searchedEvent);
    }

    @Override
    public boolean equals(Object objectToCheck) {
        if (!(objectToCheck instanceof Application))
            return false;
        Application anotherApplication = (Application) objectToCheck;

        boolean returnValue = applicationName.equals(anotherApplication.applicationName)
                && applicationVersion.equals(anotherApplication.applicationVersion)
                && executionStatus.equals(anotherApplication.executionStatus)
                && installationStatus.equals(anotherApplication.installationStatus)
                && configurationDescriptorPath.equals(anotherApplication.configurationDescriptorPath)
                && applicationDescription.equals(anotherApplication.applicationDescription)
                && dataLoaders.equals(anotherApplication.dataLoaders);

        return returnValue;
    }

    // Collection facades
    public int getHistorySize() {
        return history.size();
    }

    // Properties
    public String getApplicationName() {
        return applicationName;
    }

    public String getApplicationVersion() {
        return applicationVersion;
    }

    public String getConfigurationDescriptorPath() {
        return configurationDescriptorPath;
    }

    public ProcessPuzzleContext getContext() {
        return applicationContext;
    }

    public List<DataLoader> getDataLoaders() {
        return dataLoaders;
    }

    public String getDescription() {
        return applicationDescription;
    }

    public ExecutionStatus getExecutionStatus() {
        return executionStatus;
    }

    public InstallationStatus getInstallationStatus() {
        return installationStatus;
    }

    // Embeded enumerations
    public enum InstallationStatus {
        installed, notInstalled
    }

    public enum ExecutionStatus {
        stopped, running, suspended
    }

    public enum Events {
        started, stopped, installed, unistalled, dataload, backup, restore
    }

    public enum Action {
        install, uninstall, start, stop
    }

    // Protedted, private helper methods
    protected abstract void defineApplicationDescription();

    protected void runDataLoader(String property) {
        String loaderClassName = (String) applicationContext.getProperty(property);
        if (loaderClassName != null) {
            try {
                DataLoader loader = (DataLoader) Class.forName(loaderClassName).newInstance();
                loader.loadData();
            } catch (Exception e) {
                e.printStackTrace();
                throw new Error("The data loader: " + loaderClassName + " doesn't exist!");
            }
        }
    }

    protected void addEventToHistory(Events eventName) {
        ApplicationEvent event = null;
        List<ApplicationEvent> eventList = history.get(eventName);
        if (eventList == null)
            eventList = new ArrayList<ApplicationEvent>();

        switch (eventName) {
        case started:
            event = new ApplicationStartedEvent();
            break;
        case stopped:
            event = new ApplicationStopped();
            break;
        case installed:
            event = new ApplicationInstallationEvent();
            break;
        case dataload:
            event = new DataLoadEvent();
            break;
        case backup:
            event = new BackupEvent();
            break;
        case restore:
            event = new RestoreEvent();
            break;
        default:
            break;
        }

        eventList.add(event);
        history.put(eventName, eventList);
    }

    protected @Override void defineIdentityExpressions() {
        identities.add(getDefaultIdentity());
    }

    private void addBusinessDefintionLoader(List<DataLoader> dataLoaders) {
        String path = null;
        try {
            path = determineBusinessDefintionsPaths();
            XmlDataLoader businessDefinitionLoader = (XmlDataLoader) applicationContext
                    .getBean(ProcessPuzzleApplicationComponent.BUSINESS_DEFINITION_LOADER.getComponentId());
            businessDefinitionLoader.setResourcePath(path);
            dataLoaders.add(businessDefinitionLoader);
        } catch (NoSuchBeanDefinitionException e) {
            if (path != null && path != "")
                throw e;
        }
    }

    private void addPredefinedUsersDataSheetLoader(List<DataLoader> dataLoaders) {
        PredefinedUserDataSheetsCreator userDataSheetCreator = new PredefinedUserDataSheetsCreator(
                applicationContext);
        dataLoaders.add(userDataSheetCreator);
    }

    private void addPredefinedUsersLoader(List<DataLoader> dataLoaders) {
        PredefinedUsersLoader usersLoader = (PredefinedUsersLoader) applicationContext
                .getBean(ProcessPuzzleApplicationComponent.PREDEFINED_USERS_LOADER.getComponentId());
        usersLoader.setApplicationContext(applicationContext);
        dataLoaders.add(usersLoader);
    }

    private void addSystemArtifactsLoader(List<DataLoader> dataLoaders) {
        String componentName = ProcessPuzzleApplicationComponent.SYSTEM_ARTIFACTS_LOADER.getComponentId();
        try {
            HardCodedDataLoader systemArtifactsLoader = (HardCodedDataLoader) applicationContext
                    .getBean(componentName);
            dataLoaders.add(systemArtifactsLoader);
        } catch (NoSuchBeanDefinitionException e) {
            log.warn("SystemArtifactsLoder not found.");
            throw e;
        }
    }

    private void determineInstallationConfiguration() {
    }

    private void determineInstallationStatus() {
    }

    private PropertyContextOverrides defineInstallationOverrides() {
        PropertyContextOverrides overrides = new PropertyContextOverrides();
        overrides.addProperty(PropertyKeys.APPLICATION_DATABASE_CREATION,
                PersistentDataInitializationStrategies.dropAndCreate);
        return overrides;
    }

    private List<DataLoader> determineDataLoaders() throws ApplicationException {
        List<DataLoader> dataLoaders = new ArrayList<DataLoader>();

        determinePredefinedDataLoaders(dataLoaders);
        determineCustomDataLoaders(dataLoaders);

        return dataLoaders;
    }

    private void determinePredefinedDataLoaders(List<DataLoader> dataLoaders) {
        addPredefinedUsersLoader(dataLoaders);
        addBusinessDefintionLoader(dataLoaders);
        addSystemArtifactsLoader(dataLoaders);
        addPredefinedUsersDataSheetLoader(dataLoaders);
    }

    private void determineCustomDataLoaders(List<DataLoader> dataLoaders) throws ApplicationException {
        List<String> dataLoaderClassNames = applicationContext.getPropertyContext()
                .getPropertyList(PropertyKeys.DATA_LOADER_CLASSES.getDefaultKey());
        Integer dataLoaderIndex = 0;
        for (Iterator<String> iter = dataLoaderClassNames.iterator(); iter.hasNext();) {
            String className = (String) iter.next();

            String selector = MessageFormat.format(PropertyKeys.DATA_LOADER_CONFIGURATION.getDefaultKey(),
                    new Object[] { dataLoaderIndex.toString() });
            HierarchicalConfiguration dataLoaderConfig = applicationContext.getPropertyContext()
                    .getConfigurationAt(selector);
            DataLoader dataLoader = instantitateDataLoader(className, dataLoaderConfig);
            dataLoaders.add(dataLoader);
            dataLoaderIndex++;
        }
    }

    private String determineBusinessDefintionsPaths() {
        PropertyContext propertyContext = applicationContext.getPropertyContext();
        List<String> businessDefinitionPaths = propertyContext
                .getPropertyList(PropertyKeys.BUSINESS_DEFINITION.getDefaultKey());
        if (businessDefinitionPaths.size() == 0) {
            throw new MissingRequiredConfigurationPropertyException(
                    PropertyKeys.BUSINESS_DEFINITION.getDefaultKey(), configurationDescriptorPath);
        }

        String combinedPath = "";
        for (String path : businessDefinitionPaths) {
            combinedPath += path + ";";
        }

        return combinedPath;
    }

    private void executeDataLoaders(Action action) throws ApplicationException {
        for (Iterator<DataLoader> iter = dataLoaders.iterator(); iter.hasNext();) {
            DataLoader dataLoader = iter.next();
            if ((action == Action.install && dataLoader.isResultInPersistentObjects())
                    || (action == Action.start && !dataLoader.isResultInPersistentObjects())) {
                dataLoader.setResourceLoader(applicationContext.getResourceLoader());
                try {
                    dataLoader.loadData();
                } catch (Exception e) {
                    throw new ApplicationInstallationException(applicationName, e);
                }
                addEventToHistory(Events.dataload);
            }
        }
    }

    @SuppressWarnings("unchecked")
    private DataLoader instantitateDataLoader(String className, HierarchicalConfiguration dataLoaderConfig)
            throws ApplicationException {
        DataLoader dataLoader = null;
        Constructor<DataLoader> dataLoaderConstructor;

        List<HierarchicalConfiguration> arguments = dataLoaderConfig
                .configurationsAt(INSTANTIATION_ARGUMENTS_SELECTOR);
        Class<?>[] parameterTypes = new Class[arguments.size()];
        Object[] parameterValues = new Object[arguments.size()];

        try {
            for (int j = 0; j < arguments.size(); j++) {
                String selectorBase = INSTANTIATION_ARGUMENTS_SELECTOR + PropertyContext.PROPERTY_ARRAY_BEGIN
                        + String.valueOf(j) + PropertyContext.PROPERTY_ARRAY_END;
                String typeSelector = selectorBase + PropertyContext.ATTRIBUTE_BEGIN
                        + PropertyContext.ATTRIBUTE_SIGNER + PARAMETER_TYPE_ELEMENT_NAME
                        + PropertyContext.ATTRIBUTE_END;
                String paremeterType = dataLoaderConfig.getString(typeSelector);
                parameterTypes[j] = Class.forName(paremeterType);

                //String nameSelector = selectorBase + PropertyContext.ATTRIBUTE_BEGIN + PropertyContext.ATTRIBUTE_SIGNER + PARAMETER_NAME_ELEMENT_NAME + PropertyContext.ATTRIBUTE_END;

                String parameterValue = dataLoaderConfig.getString(selectorBase);
                parameterValues[j] = parameterValue;
            }

            Class<DataLoader> dataLoaderClass = (Class<DataLoader>) Class.forName(className);
            dataLoaderConstructor = dataLoaderClass.getConstructor(parameterTypes);
            dataLoader = (DataLoader) dataLoaderConstructor.newInstance(parameterValues);
        } catch (SecurityException e) {
            throw new ApplicationStartException(this, e);
        } catch (NoSuchMethodException e) {
            throw new ApplicationStartException(this, e);
        } catch (IllegalArgumentException e) {
            throw new ApplicationStartException(this, e);
        } catch (InstantiationException e) {
            throw new ApplicationStartException(this, e);
        } catch (IllegalAccessException e) {
            throw new ApplicationStartException(this, e);
        } catch (InvocationTargetException e) {
            throw new ApplicationStartException(this, e);
        } catch (ClassNotFoundException e) {
            throw new ApplicationStartException(this, e);
        }

        return dataLoader;
    }

    private void persistSystemInstallerUser() {
        User systemInstaller = UserRequestManager.getInstance().currentUser();
        UserRepository userRepository = applicationContext.getRepository(UserRepository.class);
        userRepository.add(systemInstaller);
    }

    private void setUpApplicationContext(Action applicationAction, PropertyContextOverrides overrides)
            throws ApplicationException {
        try {
            if (applicationContext == null)
                applicationContext = new ProcessPuzzleContext(this, configurationDescriptorPath);

            if (!applicationContext.isConfigured()) {
                if (overrides != null)
                    applicationContext.setPropertyContextOverrides(overrides);

                applicationContext.setUp(applicationAction);
            }

            // applicationName = applicationContext.getProperty( PropertyKeys.APPLICATION_NAME.getXPathKey() );

        } catch (Exception e) {
            // applicationName = applicationContext.getProperty( PropertyKeys.APPLICATION_NAME.getXPathKey() );
            String message = "Starting " + applicationName + "application failed.";
            log.error(message, e);
            applicationContext = null;
            throw new ApplicationStartException(this, e);
        }
    }

}