/*
Name:
- ApplicationRepository
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/>.
*/
package com.processpuzzle.application.domain;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.util.List;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import com.google.common.collect.Lists;
import com.processpuzzle.application.domain.Application.ExecutionStatus;
import com.processpuzzle.application.domain.Application.InstallationStatus;
import com.processpuzzle.application.resource.domain.ResourceNotFoundException;
import com.processpuzzle.commons.persistence.AggregateRoot;
import com.processpuzzle.commons.persistence.PersistenceStrategy;
import com.processpuzzle.commons.persistence.Repository;
import com.processpuzzle.commons.persistence.RepositoryResultSet;
import com.processpuzzle.commons.persistence.UnitOfWork;
import com.processpuzzle.commons.persistence.query.IdentityExpression;
import com.processpuzzle.commons.persistence.query.Query;
import com.processpuzzle.persistence.domain.DefaultUnitOfWork;
import com.processpuzzle.persistence.domain.IdentityCollisionException;
import com.processpuzzle.persistence.domain.RepositoryAction;
import com.processpuzzle.persistence.domain.RepositoryException;
import com.processpuzzle.persistence.domain.SimpleResultSet;
import com.processpuzzle.persistence.query.domain.DefaultIdentityExpression;
import com.processpuzzle.persistence.query.domain.DefaultQuery;
public class ApplicationRepository implements Repository<Application> {
static final String DEFAULT_STORAGE_PATH = "classpath:com/processpuzzle.application.domain.Application.xml";
static final String APPLICATION_ELEMENT = "application";
static final String DESCRIPTION_ELEMENT = "description";
static final String VERSION_ELEMENT = "version";
static final String CLASS_NAME_ELEMENT = "className";
static final String NAME_ATTRIBUTE = "name";
static final String EXECUTION_STATUS_ELEMENT = "executionStatus";
static final String INSTALLATION_STATUS_ELEMENT = "installationStatus";
static final String CONFIGURATION_PATH_ELEMENT = "configurationDescriptorPath";
private static String xmlStoragePath;
private static ResourceLoader resourceLoader;
private Document xmlDocument;
private Resource xmlResource;
//Public mutators
public static ApplicationRepository getInstance( String applicationStoragePath, ResourceLoader resourceLoader ) throws InstantiationException {
ApplicationRepository repository = (ApplicationRepository) SingletonRegistry.getInstance( ApplicationRepository.class );
xmlStoragePath = applicationStoragePath;
ApplicationRepository.resourceLoader = resourceLoader;
try {
repository.setStorageXmlPath( applicationStoragePath, resourceLoader );
repository.readXmlDocument();
}catch( DocumentException e ) {
throw new InstantiationException( "Instantiation of 'ApplicationRepository' caused an error." );
} catch (IOException e) {
throw new InstantiationException( "Instantiation of 'ApplicationRepository' caused an error." );
}
return repository;
}
public static ApplicationRepository getInstance( String applicationStoragePath ) throws InstantiationException {
return getInstance( applicationStoragePath, (ResourceLoader) new DefaultResourceLoader() );
}
public static ApplicationRepository getInstance() throws InstantiationException {
return getInstance( DEFAULT_STORAGE_PATH );
}
public Integer add( DefaultUnitOfWork work, Application application ) {
if( findByName( application.getApplicationName() ) != null ) throw new IdentityCollisionException( Application.class );
createApplicationElement(application);
try {
writeXmlDocument();
} catch (IOException e) {
throw new RepositoryException( this, RepositoryAction.add, application, e );
}
return null;
}
public void add( Application application ) {
DefaultUnitOfWork work = new DefaultUnitOfWork( true );
add( work, application );
work.finish();
}
public void update( DefaultUnitOfWork work, Application application ) {
Node applicationNode = findApplicationElement( application.getApplicationName() );
saveApplicationProperties( (Element) applicationNode, application );
try {
writeXmlDocument();
} catch (IOException e) {
throw new RepositoryException( this, RepositoryAction.delete, application, e );
}
}
public void update( Application application ) {
DefaultUnitOfWork work = new DefaultUnitOfWork( true );
update( work, application );
work.finish();
}
public void delete( DefaultUnitOfWork work, Application application ) {
Node applicationNode = findApplicationElement( application.getApplicationName() );
if( applicationNode != null ) {
applicationNode.detach();
try {
writeXmlDocument();
} catch (IOException e) {
throw new RepositoryException( this, RepositoryAction.delete, application, e );
}
}else throw new RepositoryException( this, RepositoryAction.delete, application );
}
public void delete( Application application ) {
DefaultUnitOfWork work = new DefaultUnitOfWork( true );
delete( work, application );
work.finish();
}
public Application findByName( String applicationName ) {
Node node = findApplicationElement(applicationName);
if( node == null ) return null;
Application application = instantiateApplicationObject( (Element) node );
restoreApplicationProperties( (Element) node, (Application) application );
return application;
}
public RepositoryResultSet<Application> findAll() {
DefaultUnitOfWork work = new DefaultUnitOfWork( true );
RepositoryResultSet<Application> applications = findAll( work );
work.finish();
return applications;
}
public RepositoryResultSet<Application> findAll( DefaultUnitOfWork work ) {
List<Node> applicationNodes = findApplicationElements();
List<Application> definedApplications = instantiateApplicationObjects( applicationNodes );
RepositoryResultSet<Application> resultSet = new SimpleResultSet<Application>( definedApplications );
return resultSet;
}
public Application findById(DefaultUnitOfWork work, Integer id) {
// TODO Auto-generated method stub
return null;
}
public Application findByIdentityExpression(DefaultUnitOfWork work, @SuppressWarnings( "rawtypes" ) DefaultIdentityExpression identity) {
// TODO Auto-generated method stub
return null;
}
public RepositoryResultSet<Application> findByQuery( DefaultUnitOfWork work, DefaultQuery query ) {
// TODO Auto-generated method stub
return null;
}
//Properties
public String getStorageXmlPath() { return xmlStoragePath; }
public Resource getStorageXmlResource() { return xmlResource; }
public PersistenceStrategy getPersistenceStrategy() {
// Note: with this repository no strategy defined.
return null;
}
public Class<? extends AggregateRoot> getSupportedAggregateRootClass() { return Application.class; }
//Protected, private heleper methods
protected ApplicationRepository() {} //Exists to defeat installation
private Node findApplicationElement(String applicationName) {
String xPath = "/applicationRepository/application[@name = '" + applicationName + "']";
Node node = null;
node = xmlDocument.selectSingleNode( xPath );
return node;
}
@SuppressWarnings( "unchecked" )
private List<Node> findApplicationElements() {
String xPath = "/applicationRepository/application";
List<Node> nodes = null;
nodes = xmlDocument.selectNodes( xPath );
return nodes;
}
private void createApplicationElement(Application application) {
Element root = xmlDocument.getRootElement();
Element applicationElement = root.addElement( APPLICATION_ELEMENT );
applicationElement.addAttribute( NAME_ATTRIBUTE, application.getApplicationName() );
Element versionElement = applicationElement.addElement( VERSION_ELEMENT );
versionElement.setText( application.getApplicationVersion() );
Element descriptionElement = applicationElement.addElement( DESCRIPTION_ELEMENT );
descriptionElement.setText( application.getDescription() );
Element classNameElement = applicationElement.addElement( CLASS_NAME_ELEMENT );
classNameElement.setText( application.getClass().getName() );
Element executionStatusElement = applicationElement.addElement( EXECUTION_STATUS_ELEMENT );
executionStatusElement.setText( application.getExecutionStatus().name() );
Element installationStatusElement = applicationElement.addElement( INSTALLATION_STATUS_ELEMENT );
installationStatusElement.setText( application.getInstallationStatus().name() );
Element configurationDescriptorPath = applicationElement.addElement( CONFIGURATION_PATH_ELEMENT );
configurationDescriptorPath.setText( application.getConfigurationDescriptorPath() );
}
private void setStorageXmlPath( String xmlStoragePath, ResourceLoader resourceLoader ) {
String previousPath = ApplicationRepository.xmlStoragePath;
Resource prevoiusResource = this.xmlResource;
ApplicationRepository.xmlStoragePath = xmlStoragePath;
xmlResource = resourceLoader.getResource( xmlStoragePath );
try{
if( !xmlResource.getFile().exists() ) {
ApplicationRepository.xmlStoragePath = previousPath;
this.xmlResource = prevoiusResource;
throw new ResourceNotFoundException( xmlStoragePath );
}
}catch( IOException e ){
ApplicationRepository.xmlStoragePath = previousPath;
this.xmlResource = prevoiusResource;
throw new ResourceNotFoundException( xmlStoragePath );
}
}
private void readXmlDocument() throws DocumentException, IOException {
SAXReader reader = new SAXReader();
Resource xmlResource = resourceLoader.getResource( xmlStoragePath );
xmlDocument = reader.read( xmlResource.getInputStream() );
}
private void writeXmlDocument() throws IOException {
OutputFormat outputFormat = OutputFormat.createPrettyPrint();
outputFormat.setEncoding( xmlDocument.getXMLEncoding() );
OutputStream output = new FileOutputStream( xmlResource.getFile() );
XMLWriter writer = new XMLWriter( output, outputFormat);
writer.write( xmlDocument );
writer.close();
}
@SuppressWarnings("unchecked")
private Application instantiateApplicationObject( Element applicationElement ) {
if( applicationElement == null ) return null;
String configurationDescriptorPath = applicationElement.element( CONFIGURATION_PATH_ELEMENT ).getText();
String applicationClassName = applicationElement.element( CLASS_NAME_ELEMENT ).getText();
Class<? extends Application> applicationClass;
Application application = null;
try {
applicationClass = (Class<? extends Application>) Class.forName( applicationClassName );
application = ApplicationFactory.create( applicationClass, configurationDescriptorPath, resourceLoader );
} catch( ClassNotFoundException e ) {
throw new RepositoryException( this, RepositoryAction.findById, application, e );
}
return application;
}
private List<Application> instantiateApplicationObjects( List<Node> applicationNodes ) {
List<Application> applications = Lists.newArrayList();
for( Node node : applicationNodes ){
Application application = instantiateApplicationObject( (Element) node );
applications.add( application );
}
return applications;
}
private void saveApplicationProperties( Element applicationElement, Application application ) {
applicationElement.element( VERSION_ELEMENT ).setText( application.getApplicationVersion() );
applicationElement.element( DESCRIPTION_ELEMENT ).setText( application.getDescription() );
applicationElement.element( CLASS_NAME_ELEMENT ).setText( application.getClass().getName() );
applicationElement.element( EXECUTION_STATUS_ELEMENT ).setText( application.getExecutionStatus().name() );
applicationElement.element( INSTALLATION_STATUS_ELEMENT ).setText( application.getInstallationStatus().name() );
applicationElement.element( CONFIGURATION_PATH_ELEMENT ).setText( application.getConfigurationDescriptorPath() );
}
private void restoreApplicationProperties( Element applicationElement, Application application ) {
setApplicationAttributeValue( application, "applicationVersion", applicationElement.element( VERSION_ELEMENT ).getText() );
setApplicationAttributeValue( application, "applicationDescription", applicationElement.element( DESCRIPTION_ELEMENT ).getText() );
setApplicationAttributeValue( application, "installationStatus", applicationElement.element( INSTALLATION_STATUS_ELEMENT ).getText() );
setApplicationAttributeValue( application, "executionStatus", applicationElement.element( EXECUTION_STATUS_ELEMENT ).getText() );
setApplicationAttributeValue( application, "configurationDescriptorPath", applicationElement.element( CONFIGURATION_PATH_ELEMENT ).getText() );
}
private void setApplicationAttributeValue( Application application, String attributeName, String value ) {
Class<? extends Application> applicationClass = Application.class;
Field field;
Class<?> fieldType;
try {
field = applicationClass.getDeclaredField( attributeName );
field.setAccessible( true );
fieldType = field.getType();
if( fieldType.equals( String.class ) ) field.set( application, value );
else if( fieldType.equals( Boolean.class ) ) field.setBoolean( application, new Boolean( value ).booleanValue() );
else if( fieldType.equals( Integer.class ) ) field.setInt( application, new Integer( value ).intValue() );
else if( fieldType.equals( Long.class ) ) field.setLong( application, new Long( value ).longValue() );
else if( fieldType.equals( Double.class ) ) field.setDouble( application, new Double( value ).doubleValue() );
else if( fieldType.equals( Application.ExecutionStatus.class ) ) field.set( application, ExecutionStatus.valueOf( value ));
else if( fieldType.equals( Application.InstallationStatus.class ) ) field.set( application, InstallationStatus.valueOf( value ));
else field.set( application, value );
} catch (SecurityException e ) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchFieldException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public Integer add( UnitOfWork work, Application entity ) {
// TODO Auto-generated method stub
return null;
}
@Override
public void delete( UnitOfWork work, Application entity ) {
// TODO Auto-generated method stub
}
@Override
public RepositoryResultSet<Application> findAll( UnitOfWork work ) {
// TODO Auto-generated method stub
return null;
}
@Override
public Application findById( UnitOfWork work, Integer id ) {
// TODO Auto-generated method stub
return null;
}
@Override
public Application findByIdentityExpression( UnitOfWork work, IdentityExpression<?> identity ) {
// TODO Auto-generated method stub
return null;
}
@Override
public RepositoryResultSet<Application> findByQuery( UnitOfWork work, Query query ) {
// TODO Auto-generated method stub
return null;
}
@Override
public void update( UnitOfWork work, Application entity ) {
// TODO Auto-generated method stub
}
}