/* Name: - Artifact 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.artifact.domain; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.TreeMap; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlID; import javax.xml.bind.annotation.XmlIDREF; import javax.xml.bind.annotation.XmlSeeAlso; import javax.xml.bind.annotation.XmlTransient; import javax.xml.bind.annotation.XmlType; import org.apache.commons.io.output.ByteArrayOutputStream; import org.jibx.runtime.BindingDirectory; import org.jibx.runtime.IBindingFactory; import org.jibx.runtime.IMarshallingContext; import org.jibx.runtime.JiBXException; import com.processpuzzle.application.configuration.domain.ProcessPuzzleContext; import com.processpuzzle.application.security.domain.AccessControlledObject; import com.processpuzzle.application.security.domain.User; import com.processpuzzle.artifact.artifact.ArtifactList; import com.processpuzzle.artifact_type.domain.ArtifactType; import com.processpuzzle.artifact_type.domain.DocumentType; import com.processpuzzle.fundamental_types.domain.GenericEntity; import com.processpuzzle.fundamental_types.domain.HashCodeUtil; import com.processpuzzle.fundamental_types.domain.TimePoint; import com.processpuzzle.internalization.domain.ProcessPuzzleLocale; import com.processpuzzle.party.artifact.CompanyList; import com.processpuzzle.party.artifact.PersonDataSheet; import com.processpuzzle.party.artifact.PersonList; import com.processpuzzle.party.domain.Person; import com.processpuzzle.persistence.domain.DefaultUnitOfWork; import com.processpuzzle.persistence.query.domain.DefaultIdentityExpression; import com.processpuzzle.persistence.query.domain.DefaultQueryContext; import com.processpuzzle.resource.domain.Asset; import com.processpuzzle.resource.resourcetype.domain.AssetType; import com.processpuzzle.user_session.domain.UserRequestManager; import com.processpuzzle.workflow.activity.domain.Action; @SuppressWarnings("unchecked") @XmlSeeAlso( { ArtifactList.class, PersonList.class, CompanyList.class, PersonDataSheet.class } ) @XmlType( name = "Artifact", propOrder = { "name", "type" } ) public abstract class Artifact<A extends Artifact<?>> extends GenericEntity<A> implements Asset, AccessControlledObject, Comparable<Artifact> { protected @XmlID @XmlAttribute( required = true ) String name; protected @XmlIDREF @XmlAttribute ArtifactType type; protected @XmlTransient ArtifactFolder containingFolder; protected @XmlTransient String path; protected @XmlTransient Map<Integer, ArtifactVersion> versions = new TreeMap<Integer, ArtifactVersion>(); protected @XmlTransient List<String> htmlAttributeFormats = new ArrayList<String>(); protected @XmlTransient Map<String, ArtifactView<?>> availableViews = new HashMap<String, ArtifactView<?>>(); protected @XmlTransient ProcessPuzzleContext applicationContext; protected @XmlTransient User currentUser; protected @XmlTransient ProcessPuzzleLocale preferredLocale; protected @XmlTransient CommentListFactory commentListFactory; // Constructors protected Artifact() { super(); init(); } protected Artifact( String artifactName, ArtifactType type, User creator ) { this(); this.name = artifactName; this.type = type; instantiateVersion( artifactName, type, creator ); type.instantiateViewsFor( this ); initializeViews(); this.path = artifactName; } public void read( DefaultUnitOfWork work ) { } public void update( DefaultUnitOfWork work ) { } public void delete( DefaultUnitOfWork work ) { } // Public accessors public int compareTo( Artifact anotherArtifact ) { return name.compareTo( anotherArtifact.name ); } public ArtifactView<?> findAvailablesView( String name ) { return availableViews.get( name ); } public Artifact<?> findRelatedArtifact( String name ) { return latest().findRelatedArtifact( name ); } public ArtifactView<?> findViewByName( String searchedViewName ) { return availableViews.get( searchedViewName ); } public <V extends ArtifactView> V findViewByClass( Class<V> viewClass ) { for( Iterator<String> iter = availableViews.keySet().iterator(); iter.hasNext(); ){ String viewName = iter.next(); if( viewClass.isInstance( availableViews.get( viewName ))) return (V) availableViews.get( viewName ); } return null; } public @Override boolean equals( Object objectToCheck ) { if( !(objectToCheck instanceof Artifact )) return false; Artifact anotherArtifact = (Artifact) objectToCheck; if( !name.equals( anotherArtifact.name )) return false; return true; } public abstract String getAsXml(); public String getAsXml( Class<A> subjectClass, Object subjectObject ) { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); try{ IBindingFactory bindingFactory = BindingDirectory.getFactory( Action.class ); IMarshallingContext marshallingContext = bindingFactory.createMarshallingContext(); marshallingContext.setIndent( 3 ); marshallingContext.marshalDocument( subjectObject, "UTF-8", null, outputStream ); }catch( JiBXException e ){ e.printStackTrace(); } return outputStream.toString(); } public ProcessPuzzleLocale getDefaultLocale() { return applicationContext.getDefaultLocale(); } public @Override DefaultIdentityExpression<A> getDefaultIdentity() { DefaultQueryContext context = new DefaultQueryContext(); context.addTextValueFor( "nameValue", name ); DefaultIdentityExpression<A> identity = new ArtifactIdentity<A>( context ); return identity; } public ArtifactView<?> getDefaultView() { for( Iterator<String> iter = availableViews.keySet().iterator(); iter.hasNext(); ){ String key = iter.next(); if( availableViews.get( key ).getType().isDefault() ){ return availableViews.get( key ); } } return null; } public List<String> getLocales() { return applicationContext.getInternalizationContext().getSupportedLocalesList(); } public String getPrefferredLanguage() { User loggedInUser = UserRequestManager.getInstance().currentUser(); if( loggedInUser != null ) return loggedInUser.getPrefferedLocale().getLanguage(); else return null; } public PropertyView<A> getPropertyView() { return findViewByClass( PropertyView.class ); } public PrintView<A> getPrintView() { return findViewByClass( PrintView.class ); } public ArtifactVersion getReservedVersion() { if( isReserved() ) return latest().getNextModification().getTargetVersion(); else return null; } public ArtifactView<?> getView( String viewName ) { return availableViews.get( viewName ); } public int hashCode() { int result = HashCodeUtil.SEED; result = HashCodeUtil.hash( result, name ); result = HashCodeUtil.hash( result, containingFolder ); result = HashCodeUtil.hash( result, versions ); return result; } // Public mutators public void addComment( Comment comment ) { CommentList commentList = getCommentList(); if( commentList == null ){ commentList = commentListFactory.create( getName() + "_commentList", new DocumentType( "" ) ); latest().setCommentList( commentList ); } commentList.appendComment( comment ); } public void addComments( CommentList commentList ) { for( Comment comment : commentList.getComments() ){ this.addComment( comment ); } } public void addView( String viewName, ArtifactView<?> view ) { availableViews.put( viewName, view ); } public void addComment( Person author, String title, String commentText ) { if( (author != null) && (title != null) && (commentText != null) ){ addComment( new Comment( author, title, commentText ) ); } } public void addRelatedArtifact( Artifact<?> relatedArtifact ) { latest().addRelatedArtifact( relatedArtifact ); } public void removeRelatedArtifact( Artifact<?> relatedArtifact ) { latest().removeRelatedArtifact( relatedArtifact ); } public void instantiateViews() { type.instantiateViewsFor( this ); } public void removeRelatedArtifact( String artifactName ) { latest().removeRelatedArtifact( artifactName ); } public void release( User modifier ) throws VersionControlException { if( (latest().getNextModification() != null) && (latest().getNextModification().getModifier().getId().equals( modifier.getId() )) ){ if( (!latest().isVersionControlled()) && (latest().getNextModification().getTargetVersion() != null) ){ ArtifactVersion newVersion = versions.get( new Integer( 2 ) ); latest().getNextModification().release(); versions.clear(); versions.put( new Integer( 1 ), newVersion ); }else latest().getNextModification().setEnd( new TimePoint( new Date( System.currentTimeMillis() ) ) ); }else throw new VersionControlException( "" ); } public void renameName( String name ) { this.name = name; } public void reserve( User modifier, String comment ) throws VersionControlException { if( (latest().getNextModification() == null) || ((latest().getNextModification() != null) && (latest().getNextModification().getModificationPeriod().getBegin() == null)) ){ if( (latest().isVersionControlled()) || (!(latest().isVersionControlled()) && (latest().getNextModification() == null)) ){ new Modification( latest(), modifier, comment ); }else if( !(latest().isVersionControlled()) && (latest().getNextModification() != null) ){ latest().getNextModification().reserve( modifier ); } versions.put( new Integer( versions.size() + 1 ), latest().getNextModification().getTargetVersion() ); }else throw new VersionControlException( "" ); } // Properties public boolean isReserved() { if( ((latest().getNextModification() != null) && isVersionControlled()) || ((latest().getNextModification() != null && !isVersionControlled()) && (latest().getNextModification().getModificationPeriod().getBegin() != null)) ){ return true; } return false; } public boolean isVersionControlled() { return latest().isVersionControlled(); } public void setVersionControlled( boolean isVersionControlled ) { latest().setVersionControlled( isVersionControlled ); } public Map<String, ArtifactView<?>> getAvailableViews() { return availableViews; } public ArtifactFolder getContainingFolder() { return containingFolder; // return latest().getContainingFolder(); } public void setContainingFolder( ArtifactFolder containingFolder ) { this.containingFolder = containingFolder; // latest().setContainingFolder( containingFolder ); path = containingFolder.getPath() + ArtifactFolder.PATH_SEPARATOR + name; } public Date getCreation() { return latest().getCreation(); } public void setCreation( Date creation ) { latest().setCreation( creation ); } public CommentList getCommentList() { return latest().getCommentList(); } public String getPath() { return path; } public User getLastModifier() { if( latest().getPreviousModification() != null ){ return latest().getPreviousModification().getModifier(); }else return latest().getCreator(); } public Date getLastModification() { return latest().getModification(); } public String getName() { return name; } public ArtifactVersion getLatestVersion() { return latest(); } public Collection<Artifact<?>> getRelatedArtifacts() { return latest().getRelatedArtifacts(); } public User getResponsible() { return latest().getCreator(); } public void setResponsible( User responsible ) { latest().setResponsible( responsible ); } public AssetType getType() { return type; // return latest().getArtifactType(); } public ArtifactType getArtifactType() { return type; } public Map<Integer, ArtifactVersion> getVersions() { return versions; } // Protected, private helper methods protected void defineIdentityExpressions() { DefaultQueryContext context = new DefaultQueryContext(); context.addTextValueFor( "name", name ); defaultIdentity = new ArtifactNameIdentity<A>( context ); context = new DefaultQueryContext(); context.addTextValueFor( "path", getPath() ); identities.add( defaultIdentity ); identities.add( new ArtifactFullNameIdentity<A>( context ) ); } protected String formaInternationalizedText( Object value ) { if( value != null && !value.equals( "" ) ) return value.toString(); else return applicationContext.getText( "ui.generic.undefined", preferredLocale ); } protected void init() { applicationContext = UserRequestManager.getInstance().getApplicationContext(); currentUser = UserRequestManager.getInstance().currentUser(); preferredLocale = currentUser.getPrefferedLocale(); if( preferredLocale == null ) preferredLocale = applicationContext.getDefaultLocale(); commentListFactory = applicationContext.getEntityFactory( CommentListFactory.class ); } protected void instantiateVersion( String name, ArtifactType type, User creator ) { ArtifactVersion version = new ArtifactVersion( name, creator ); getVersions().put( new Integer( versions.size() + 1 ), version ); } protected ArtifactVersion latest() { ArtifactVersion version = versions.get( ((TreeMap<Integer, ArtifactVersion>) versions).lastKey() ); if( version.getPreviousModification() != null ){ if( version.getPreviousModification().getModificationPeriod().getEnd() != null ){ return version; }else{ return version.getPreviousModification().getSourceVersion(); } }else return version; } protected String notAvailableResponse() { return applicationContext.getText( "ui.generic.undefined", preferredLocale ); } private void initializeViews() { for( Iterator<String> iter = availableViews.keySet().iterator(); iter.hasNext(); ){ String key = iter.next(); ArtifactView<?> aView = availableViews.get( key ); aView.initializeView(); } } }