/** * * 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.context.administration.surface.accesspoints; import org.qi4j.api.common.Optional; import org.qi4j.api.concern.ConcernOf; import org.qi4j.api.concern.Concerns; import org.qi4j.api.constraint.Name; import org.qi4j.api.entity.EntityReference; import org.qi4j.api.entity.Identity; import org.qi4j.api.injection.scope.Structure; import org.qi4j.api.mixin.Mixins; import org.qi4j.api.specification.Specification; import org.qi4j.api.structure.Module; import org.qi4j.api.unitofwork.NoSuchEntityException; import org.qi4j.api.unitofwork.UnitOfWork; import org.qi4j.api.unitofwork.UnitOfWorkCompletionException; import org.qi4j.api.usecase.UsecaseBuilder; import org.qi4j.api.util.Iterables; import org.qi4j.api.value.ValueBuilder; import org.qi4j.library.constraints.annotation.MaxLength; import org.qi4j.spi.entitystore.EntityNotFoundException; import org.restlet.data.Status; import org.restlet.resource.ResourceException; import se.streamsource.dci.api.Context; import se.streamsource.dci.api.DeleteContext; import se.streamsource.dci.api.IndexContext; import se.streamsource.dci.api.InteractionValidation; import se.streamsource.dci.api.RequiresValid; import se.streamsource.dci.api.RoleMap; import se.streamsource.dci.value.EntityValue; import se.streamsource.dci.value.link.LinkValue; import se.streamsource.streamflow.api.administration.form.RequiredSignatureValue; import se.streamsource.streamflow.api.administration.surface.AccessPointDTO; import se.streamsource.streamflow.util.Strings; import se.streamsource.streamflow.web.domain.Describable; import se.streamsource.streamflow.web.domain.entity.organization.OrganizationQueries; import se.streamsource.streamflow.web.domain.entity.organization.OrganizationVisitor; import se.streamsource.streamflow.web.domain.structure.attachment.AttachedFile; import se.streamsource.streamflow.web.domain.structure.attachment.Attachment; import se.streamsource.streamflow.web.domain.structure.attachment.Attachments; import se.streamsource.streamflow.web.domain.structure.attachment.FormPdfTemplate; import se.streamsource.streamflow.web.domain.structure.casetype.CaseType; import se.streamsource.streamflow.web.domain.structure.casetype.SelectedCaseTypes; import se.streamsource.streamflow.web.domain.structure.form.Form; import se.streamsource.streamflow.web.domain.structure.form.MailSelectionMessage; import se.streamsource.streamflow.web.domain.structure.form.RequiredSignatures; import se.streamsource.streamflow.web.domain.structure.form.SelectedForms; import se.streamsource.streamflow.web.domain.structure.label.Labelable; import se.streamsource.streamflow.web.domain.structure.organization.*; import se.streamsource.streamflow.web.domain.structure.project.Project; import se.streamsource.streamflow.web.domain.structure.project.Projects; import java.util.ArrayList; import java.util.List; import static se.streamsource.dci.api.RoleMap.*; /** * JAVADOC */ @Concerns(AccessPointAdministrationContext.SetFormConcern.class) @Mixins(AccessPointAdministrationContext.Mixin.class) public interface AccessPointAdministrationContext extends IndexContext<AccessPointDTO>, Context, DeleteContext, InteractionValidation { void changedescription( @MaxLength(50) @Name("name") String name ) throws IllegalArgumentException; List<Project> possibleprojects(); void changeproject( @Name("entity") Project project); List<CaseType> possiblecasetypes(); void changecasetype( @Name("entity") CaseType caseType); List<Form> possibleforms(); Iterable<Form> possiblesecondforms(); void setform( EntityValue id ); List<Attachment> possibleformtemplates( String filteron ); void setformtemplate( EntityValue id ); void changemailselectionmessage( @Optional @Name("mailmessage") String message ); void updateprimarysignactive( @Name("active") String active ); @RequiresValid("primarySignActive") void updateprimarysign( @Optional @Name("active") String active, @Optional @Name("name") String name, @Optional @Name("description") String description ); @RequiresValid("primarySignActive") void updatesecondarysignactive( @Name("active") String active ); @RequiresValid("secondarySignActive") void updatesecondarysign( @Optional @Name("active") String active, @Optional @Name("name") String name, @Optional @Name("description") String description, @Optional @Name("formid") String formid, @Optional @Name("formdescription") String formdescription, @Optional @Name("mandatory") String mandatory, @Optional @Name("question") String question ); void changesubject(@Name("subject") String subject); void changetemplate(@Name("key") String key, @Optional @Name("template") String template); void changecookieexpirationhours( @Optional @Name("cookieexpirationhours") String cookieExpiration ); abstract class Mixin implements AccessPointAdministrationContext { @Structure Module module; public AccessPointDTO index() { ValueBuilder<AccessPointDTO> builder = module.valueBuilderFactory().newValueBuilder( AccessPointDTO.class ); AccessPoint accessPoint = RoleMap.role( AccessPoint.class ); AccessPointSettings.Data accessPointData = RoleMap.role( AccessPointSettings.Data.class ); SelectedForms.Data forms = RoleMap.role( SelectedForms.Data.class ); Labelable.Data labelsData = RoleMap.role( Labelable.Data.class ); FormPdfTemplate.Data template = RoleMap.role( FormPdfTemplate.Data.class ); RequiredSignatures.Data signatures = RoleMap.role( RequiredSignatures.Data.class ); WebAPMailTemplates.Data messages = RoleMap.role( WebAPMailTemplates.Data.class ); builder.prototype().accessPoint().set( createLinkValue( accessPoint ) ); if (accessPointData.project().get() != null) builder.prototype().project().set( createLinkValue( accessPointData.project().get() ) ); if (accessPointData.caseType().get() != null) builder.prototype().caseType().set( createLinkValue( accessPointData.caseType().get() ) ); if (forms.selectedForms().toList().size() > 0) builder.prototype().form().set( createLinkValue( forms.selectedForms().toList().get( 0 ) ) ); builder.prototype().cookieExpirationHours().set(accessPointData.cookieExpirationHours().get()); Attachment attachment = null; try { attachment = template.formPdfTemplate().get(); } catch( NoSuchEntityException nse) { // Attachment removable concern might have failed // to avoid errors related to not found template - set it to null UnitOfWork uow = module.unitOfWorkFactory().newUnitOfWork( UsecaseBuilder.newUsecase( "Cleanup missing form template" ) ); AccessPoint cleanAp = uow.get( accessPoint ); cleanAp.setFormPdfTemplate( null ); try { uow.complete(); } catch (UnitOfWorkCompletionException e) { throw new ResourceException( Status.CLIENT_ERROR_CONFLICT, "Form pdf attachment is missing and association cleanup failed", e ); } } if (attachment != null) { ValueBuilder<LinkValue> linkBuilder = module.valueBuilderFactory().newValueBuilder( LinkValue.class ); EntityReference ref = EntityReference.getEntityReference( attachment ); linkBuilder.prototype().text().set( ((AttachedFile.Data) attachment).name().get() ); linkBuilder.prototype().id().set( ref.identity() ); linkBuilder.prototype().href().set( ref.identity() ); builder.prototype().template().set( linkBuilder.newInstance() ); } builder.prototype().mailSelectionMessage().set( accessPoint.getMailSelectionMessage() ); ValueBuilder<RequiredSignatureValue> primary = module.valueBuilderFactory().newValueBuilder( RequiredSignatureValue.class ); ValueBuilder<RequiredSignatureValue> secondary = module.valueBuilderFactory().newValueBuilder( RequiredSignatureValue.class ); switch ( signatures.requiredSignatures().get().size() ) { case 0: builder.prototype().primarysign().set( primary.newInstance() ); builder.prototype().secondarysign().set( secondary.newInstance() ); break; case 1: builder.prototype().primarysign().set( signatures.requiredSignatures().get().get( 0 ).<RequiredSignatureValue>buildWith().newInstance() ); builder.prototype().secondarysign().set( secondary.newInstance() ); break; case 2: builder.prototype().primarysign().set( signatures.requiredSignatures().get().get( 0 ).<RequiredSignatureValue>buildWith().newInstance() ); builder.prototype().secondarysign().set( signatures.requiredSignatures().get().get( 1 ).<RequiredSignatureValue>buildWith().newInstance() ); } builder.prototype().subject().set( messages.subject().get() ); builder.prototype().messages().set( messages.emailTemplates().get() ); builder.prototype().replacementValues().set( accessPoint.hasReplacements() ); return builder.newInstance(); } private LinkValue createLinkValue( Describable describable ) { ValueBuilder<LinkValue> linkBuilder = module.valueBuilderFactory().newValueBuilder( LinkValue.class ); EntityReference ref = EntityReference.getEntityReference( describable ); linkBuilder.prototype().text().set( describable.getDescription() ); linkBuilder.prototype().id().set( ref.identity() ); linkBuilder.prototype().href().set( ref.identity() ); return linkBuilder.newInstance(); } public void delete() { AccessPoint accessPoint = RoleMap.role( AccessPoint.class ); AccessPoints accessPoints = RoleMap.role( AccessPoints.class ); accessPoints.removeAccessPoint( accessPoint ); } public void changedescription( String name ) throws IllegalArgumentException { // check if the new description is valid AccessPoints.Data accessPoints = RoleMap.role( AccessPoints.Data.class ); List<AccessPoint> accessPointsList = accessPoints.accessPoints().toList(); for (AccessPoint accessPoint : accessPointsList) { if (accessPoint.getDescription().equals( name )) { throw new IllegalArgumentException( "accesspoint_already_exists" ); } } RoleMap.role( AccessPoint.class ).changeDescription( name ); } public List<Project> possibleprojects() { final List<Project> possibleProjects = new ArrayList<Project>(); OrganizationQueries organizationQueries = RoleMap.role( OrganizationQueries.class ); organizationQueries.visitOrganization( new OrganizationVisitor() { @Override public boolean visitProject( Project project ) { possibleProjects.add( project ); return true; } }, new OrganizationQueries.ClassSpecification( OrganizationalUnits.class, Projects.class, Project.class ) ); return possibleProjects; } public void changeproject( @Name("entity") Project project) { AccessPoint accessPoint = RoleMap.role( AccessPoint.class ); accessPoint.changedProject( project ); } public List<CaseType> possiblecasetypes() { AccessPointSettings.Data accessPoint = RoleMap.role( AccessPointSettings.Data.class ); Project project = accessPoint.project().get(); List<CaseType> possibleCaseTypes = new ArrayList<CaseType>(); if (project != null) { SelectedCaseTypes.Data data = (SelectedCaseTypes.Data) project; for (CaseType caseType : data.selectedCaseTypes()) { possibleCaseTypes.add( caseType ); } } return possibleCaseTypes; } public void changecasetype( @Name("entity") CaseType caseType) { AccessPoint accessPoint = RoleMap.role( AccessPoint.class ); accessPoint.changedCaseType( caseType ); } public List<Form> possibleforms() { AccessPointSettings.Data accessPoint = RoleMap.role( AccessPointSettings.Data.class ); SelectedForms.Data selected = RoleMap.role( SelectedForms.Data.class ); CaseType caseType = accessPoint.caseType().get(); List<Form> possibleForms = new ArrayList<Form>(); if (caseType != null) { List<Form> forms = ((SelectedForms.Data) caseType).selectedForms().toList(); for (Form f : forms) { if (!selected.selectedForms().contains( f )) { possibleForms.add( f ); } } } return possibleForms; } public Iterable<Form> possiblesecondforms() { AccessPointSettings.Data accessPoint = RoleMap.role( AccessPointSettings.Data.class ); final RequiredSignatures.Data signatures = RoleMap.role( RequiredSignatures.Data.class ); CaseType caseType = accessPoint.caseType().get(); return Iterables.filter( new Specification<Form>() { public boolean satisfiedBy( final Form form ) { return !((Identity)form).identity().get().equals( signatures.requiredSignatures().get().get( 1 ).formid().get() ); } }, ((SelectedForms.Data)caseType).selectedForms() ); } public void setform( EntityValue id ) { SelectedForms forms = RoleMap.role( SelectedForms.class ); SelectedForms.Data formsData = RoleMap.role( SelectedForms.Data.class ); // remove what's there - should only be one or none List<Form> selectedForms = formsData.selectedForms().toList(); for (Form f : selectedForms) { forms.removeSelectedForm( f ); } // if not null, add the last selected from if (id.entity().get() != null) { Form form = module.unitOfWorkFactory().currentUnitOfWork().get( Form.class, id.entity().get() ); forms.addSelectedForm( form ); } } public List<Attachment> possibleformtemplates( final String filteron ) { final List<Attachment> possibleFormPdfTemplates = new ArrayList<Attachment>(); OrganizationQueries organizationQueries = RoleMap.role( OrganizationQueries.class ); final FormPdfTemplate.Data accessPoint = RoleMap.role( FormPdfTemplate.Data.class ); organizationQueries.visitOrganization( new OrganizationVisitor() { @Override public boolean visitOrganization( Organization org ) { // STREAMFLOW-843 make fetch of possible templates fail save against missing attachment reference Attachment existingFormTemplate = null; try { existingFormTemplate = accessPoint.formPdfTemplate().get(); } catch( EntityNotFoundException enf ) { //do nothing } List<Attachment> allAttachments = ((Attachments.Data) org).attachments().toList(); for (Attachment attachment : allAttachments) { if (!attachment.equals( existingFormTemplate ) && ((AttachedFile.Data) attachment).mimeType().get().endsWith( filteron )) { possibleFormPdfTemplates.add( attachment ); } } return true; } }, new OrganizationQueries.ClassSpecification( Organization.class ) ); return possibleFormPdfTemplates; } public void setformtemplate( EntityValue id ) { FormPdfTemplate accessPoint = role( FormPdfTemplate.class ); accessPoint.setFormPdfTemplate( id.entity().get() == null ? null : module.unitOfWorkFactory().currentUnitOfWork().get( Attachment.class, id.entity().get() ) ); } public void changemailselectionmessage( String message ) { MailSelectionMessage role = role( MailSelectionMessage.class ); role.changeMailSelectionMessage( message ); } public void updateprimarysignactive( @Name("active") String active ) { updateprimarysign( active, null, null ); } public void updateprimarysign( @Optional @Name("active") String active, @Optional @Name("name") String name, @Optional @Name("description") String description ) { SelectedForms.Data forms = role( SelectedForms.Data.class ); RequiredSignatures.Data signaturesData = role( RequiredSignatures.Data.class ); RequiredSignatures signatures = role( RequiredSignatures.class ); RequiredSignatureValue primarySignature = signaturesData.requiredSignatures().get().size() > 0 ? signaturesData.requiredSignatures().get().get( 0 ) : null; ValueBuilder<RequiredSignatureValue> valueBuilder = null; if( primarySignature != null ) { valueBuilder = primarySignature.buildWith(); } else { valueBuilder = module.valueBuilderFactory().newValueBuilder( RequiredSignatureValue.class ); } RequiredSignatureValue updated = valueBuilder.prototype(); if( active != null ) { updated.active().set( new Boolean( active ) ); } else if( name != null ) { updated.name().set( name ); } else if( description != null ) { updated.description().set( description ); } if( forms.selectedForms().get( 0 ) != null ) { updated.formid().set( ((Identity)forms.selectedForms().get( 0 )).identity().get() ); updated.formdescription().set( forms.selectedForms().get( 0 ).getDescription() ); } updated.mandatory().set( Boolean.TRUE ); List<RequiredSignatureValue> tempList = signaturesData.requiredSignatures().get(); if( tempList.size() > 0 ) { signatures.updateRequiredSignature( 0, valueBuilder.newInstance() ); } else { signatures.createRequiredSignature( valueBuilder.newInstance() ); } // if active false and secondary is active set secondary to active false as well if( active != null && !new Boolean( active ).booleanValue() && signaturesData.requiredSignatures().get().size() > 1 ) { if( signaturesData.requiredSignatures().get().get( 1 ).active().get() ) { updatesecondarysign( "false", null, null, null, null, null, null ); } } } public void updatesecondarysignactive( @Name("active") String active ) { updatesecondarysign( active, null, null, null, null, null, null ); } public void updatesecondarysign( @Optional @Name("active") String active, @Optional @Name("name") String name, @Optional @Name("description") String description, @Optional @Name("formid") String formid, @Optional @Name("formdescription") String formdescription, @Optional @Name("mandatory") String mandatory, @Optional @Name("question") String question ) { SelectedForms.Data forms = role( SelectedForms.Data.class ); RequiredSignatures.Data signaturesData = role( RequiredSignatures.Data.class ); RequiredSignatures signatures = role( RequiredSignatures.class ); RequiredSignatureValue secondarySignature = signaturesData.requiredSignatures().get().size() > 1 ? signaturesData.requiredSignatures().get().get( 1 ) : null; ValueBuilder<RequiredSignatureValue> valueBuilder = null; if( secondarySignature != null ) { valueBuilder = secondarySignature.buildWith(); } else { valueBuilder = module.valueBuilderFactory().newValueBuilder( RequiredSignatureValue.class ); } RequiredSignatureValue updated = valueBuilder.prototype(); if( active != null ) { updated.active().set( new Boolean( active ) ); } else if( name != null ) { updated.name().set( name ); } else if( description != null ) { updated.description().set( description ); } else if( formid != null && formdescription != null ) { updated.formid().set( formid ); updated.formdescription().set( formdescription ); } else if( mandatory != null ) { updated.mandatory().set( new Boolean( mandatory ) ); } else if( question != null ) { updated.question().set( question ); } List<RequiredSignatureValue> tempList = signaturesData.requiredSignatures().get(); if( tempList.size() > 1 ) { signatures.updateRequiredSignature( 1, valueBuilder.newInstance() ); } else { signatures.createRequiredSignature( valueBuilder.newInstance() ); } } public boolean isValid( String name ) { RequiredSignatures.Data signaturesData = role( RequiredSignatures.Data.class ); List<RequiredSignatureValue> signatures = signaturesData.requiredSignatures().get(); if( "primarySignActive".equals( name ) ) { return signatures.size() > 0 && signatures.get( 0 ).active().get(); } else if( "secondarySignActive".equals( name ) ) { return signatures.size() > 1 && signatures.get( 1 ).active().get(); } return false; } public void changesubject(@Name("subject") String subject) { role(WebAPMailTemplates.class).changeSubject(subject); } public void changetemplate(@Name("key") String key, @Optional @Name("template") String template) { role(WebAPMailTemplates.class).changeTemplate(key, template); } public void changecookieexpirationhours( @Optional @Name("cookieexpirationhours") String cookieExpiration ) { if(Strings.empty( cookieExpiration )) { role(AccessPointSettings.class).changeCookieExpirationHours(null); } else { role(AccessPointSettings.class).changeCookieExpirationHours(Integer.parseInt(cookieExpiration)); } } } abstract class SetFormConcern extends ConcernOf<AccessPointAdministrationContext> implements AccessPointAdministrationContext { public void setform(EntityValue id) { next.setform(id); WebAPReplacedSelectionFieldValues.Data replacements = RoleMap.role( WebAPReplacedSelectionFieldValues.Data.class ); replacements.replacements().get().clear(); } } }