/** * * Copyright * 2009-2015 Jayway Products AB * 2016-2017 Föreningen Sambruk * * Licensed under AGPL, Version 3.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.gnu.org/licenses/agpl.txt * * 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 se.streamsource.streamflow.web.domain.entity.project; import java.util.ArrayList; import java.util.List; import org.qi4j.api.concern.ConcernOf; import org.qi4j.api.concern.Concerns; import org.qi4j.api.entity.EntityReference; import org.qi4j.api.entity.Identity; import org.qi4j.api.injection.scope.Structure; import org.qi4j.api.injection.scope.This; import org.qi4j.api.mixin.Mixins; import org.qi4j.api.sideeffect.SideEffectOf; import org.qi4j.api.sideeffect.SideEffects; import org.qi4j.api.specification.Specification; import org.qi4j.api.structure.Module; import org.qi4j.api.util.Iterables; import org.qi4j.api.value.ValueBuilder; import se.streamsource.streamflow.api.ErrorResources; import se.streamsource.streamflow.api.administration.filter.ActionValue; import se.streamsource.streamflow.api.administration.filter.EmailActionValue; import se.streamsource.streamflow.api.administration.filter.EmailNotificationActionValue; import se.streamsource.streamflow.api.administration.filter.FilterValue; import se.streamsource.streamflow.web.domain.Describable; import se.streamsource.streamflow.web.domain.Removable; import se.streamsource.streamflow.web.domain.entity.DomainEntity; import se.streamsource.streamflow.web.domain.entity.gtd.AssignmentsQueries; import se.streamsource.streamflow.web.domain.entity.gtd.InboxQueries; import se.streamsource.streamflow.web.domain.entity.organization.GlobalCaseIdStateEntity; import se.streamsource.streamflow.web.domain.interaction.gtd.Assignable; import se.streamsource.streamflow.web.domain.interaction.gtd.Assignee; import se.streamsource.streamflow.web.domain.interaction.gtd.CaseId; import se.streamsource.streamflow.web.domain.interaction.gtd.IdGenerator; import se.streamsource.streamflow.web.domain.interaction.gtd.Ownable; import se.streamsource.streamflow.web.domain.interaction.security.CaseAccessDefaults; import se.streamsource.streamflow.web.domain.structure.casetype.CaseTypes; import se.streamsource.streamflow.web.domain.structure.casetype.DueOnNotificationSettings; import se.streamsource.streamflow.web.domain.structure.casetype.SelectedCaseTypes; import se.streamsource.streamflow.web.domain.structure.form.Forms; import se.streamsource.streamflow.web.domain.structure.label.Labels; import se.streamsource.streamflow.web.domain.structure.label.SelectedLabels; import se.streamsource.streamflow.web.domain.structure.organization.OwningOrganizationalUnit; import se.streamsource.streamflow.web.domain.structure.project.CaseTypeRequired; import se.streamsource.streamflow.web.domain.structure.project.Member; import se.streamsource.streamflow.web.domain.structure.project.Members; import se.streamsource.streamflow.web.domain.structure.project.Project; import se.streamsource.streamflow.web.domain.structure.project.filter.Filters; /** * JAVADOC */ @SideEffects(ProjectEntity.RemoveMemberSideEffect.class) @Mixins({ProjectEntity.ProjectIdGeneratorMixin.class}) @Concerns({ProjectEntity.RemovableConcern.class, ProjectEntity.RemoveMemberConcern.class}) public interface ProjectEntity extends DomainEntity, // Interactions IdGenerator, // Structure Project, OwningOrganizationalUnit, // Data CaseAccessDefaults.Data, Members.Data, Describable.Data, OwningOrganizationalUnit.Data, Ownable.Data, Ownable.Events, Forms.Data, Labels.Data, SelectedLabels.Data, CaseTypes.Data, Removable.Data, SelectedCaseTypes.Data, Filters.Data, Filters.Events, DueOnNotificationSettings.Data, DueOnNotificationSettings.Events, CaseTypeRequired.Data, CaseTypeRequired.Events, // Queries AssignmentsQueries, InboxQueries, ProjectLabelsQueries, ProjectOrganizationalUnitQueries, ProjectMembersQueries { class ProjectIdGeneratorMixin implements IdGenerator { @Structure Module module; public void assignId(CaseId aCase) { GlobalCaseIdStateEntity caseIdState = module.unitOfWorkFactory().currentUnitOfWork() .get(GlobalCaseIdStateEntity.class, GlobalCaseIdStateEntity.GLOBALCASEIDSTATE_ID); caseIdState.assignId( aCase ); } public void setCounter(Long current) { //NOOP } public Long getCounter() { return new Long(0); } public void changeDate(Long timeInMillis) { //NOOP } public Long getDate() { return new Long(0); } } abstract class RemoveMemberSideEffect extends SideEffectOf<Members> implements Members { @This AssignmentsQueries assignments; @Structure Module module; public void removeMember(Member member) { // Get all active cases in a project for a particular user and unassign. for (Assignable caze : assignments.assignments((Assignee) member, null).newQuery(module.unitOfWorkFactory().currentUnitOfWork())) { caze.unassign(); } } } abstract class RemovableConcern extends ConcernOf<Removable> implements Removable { @This Identity id; @This Members members; @This InboxQueries inbox; @This AssignmentsQueries assignments; public boolean removeEntity() { if (inbox.inboxHasActiveCases() || assignments.assignmentsHaveActiveCases()) { throw new IllegalStateException( ErrorResources.project_remove_failed_open_cases.name() ); } else { members.removeAllMembers(); return next.removeEntity(); } } } abstract class RemoveMemberConcern extends ConcernOf<Members> implements Members { @This Filters.Data filters; @Structure Module module; public void removeMember( final Member member ) { next.removeMember( member ); // find filters that contain actions that are either EmailActionValue or EmailNotificationActionValue // that contain the removed member // remove the action from the filter // and call filters.update to save the change in a fashion that allows event replay for( FilterValue filterValue : Iterables.filter( new Specification<FilterValue>() { public boolean satisfiedBy( FilterValue filter ) { return Iterables.matchesAny( new Specification<ActionValue>() { public boolean satisfiedBy(ActionValue action ) { if( action instanceof EmailActionValue ) { return ((EmailActionValue)action).participant().get().equals( EntityReference.getEntityReference( member ) ); } else if ( action instanceof EmailNotificationActionValue ) { return ((EmailNotificationActionValue)action).participant().get().equals( EntityReference.getEntityReference( member ) ); } return false; } }, filter.actions().get() ) ; } }, filters.filters().get() ) ) { int index = ((Filters) filters).indexOf( filterValue ); ValueBuilder<FilterValue> builder = module.valueBuilderFactory().newValueBuilder( FilterValue.class ).withPrototype( filterValue ); List<ActionValue> actionValueList = new ArrayList<ActionValue>( ); for( ActionValue action : builder.prototype().actions().get() ) { if( !( action instanceof EmailActionValue || action instanceof EmailNotificationActionValue ) ) { actionValueList.add( action ); } else if( action instanceof EmailActionValue ) { if( !((EmailActionValue)action).participant().get().equals( EntityReference.getEntityReference( member ) )) { actionValueList.add( action ); } } else if ( action instanceof EmailNotificationActionValue ) { if( !((EmailNotificationActionValue)action).participant().get().equals( EntityReference.getEntityReference( member ) )) { actionValueList.add( action ); } } } builder.prototype().actions().set( actionValueList ); ((Filters)filters).updateFilter( index, builder.newInstance() ); } } } }