/** * * 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.organization; import static org.qi4j.api.query.QueryExpressions.and; import static org.qi4j.api.query.QueryExpressions.contains; import static org.qi4j.api.query.QueryExpressions.eq; import static org.qi4j.api.query.QueryExpressions.matches; import static org.qi4j.api.query.QueryExpressions.templateFor; import org.qi4j.api.injection.scope.Structure; import org.qi4j.api.injection.scope.This; import org.qi4j.api.mixin.Mixins; import org.qi4j.api.query.QueryBuilder; import org.qi4j.api.specification.Specification; import org.qi4j.spi.structure.ModuleSPI; import se.streamsource.streamflow.util.HierarchicalVisitor; import se.streamsource.streamflow.web.domain.entity.user.UserEntity; import se.streamsource.streamflow.web.domain.structure.casetype.CaseType; import se.streamsource.streamflow.web.domain.structure.casetype.CaseTypes; import se.streamsource.streamflow.web.domain.structure.casetype.Resolution; import se.streamsource.streamflow.web.domain.structure.casetype.Resolutions; import se.streamsource.streamflow.web.domain.structure.casetype.SelectedCaseTypes; import se.streamsource.streamflow.web.domain.structure.casetype.SelectedResolutions; import se.streamsource.streamflow.web.domain.structure.form.Form; import se.streamsource.streamflow.web.domain.structure.form.Forms; import se.streamsource.streamflow.web.domain.structure.form.SelectedForms; import se.streamsource.streamflow.web.domain.structure.group.Group; import se.streamsource.streamflow.web.domain.structure.group.Groups; import se.streamsource.streamflow.web.domain.structure.label.Label; 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.Organization; import se.streamsource.streamflow.web.domain.structure.organization.OrganizationalUnit; import se.streamsource.streamflow.web.domain.structure.organization.OrganizationalUnits; import se.streamsource.streamflow.web.domain.structure.project.Project; import se.streamsource.streamflow.web.domain.structure.project.Projects; import se.streamsource.streamflow.web.domain.structure.user.UserAuthentication; @Mixins(OrganizationQueries.Mixin.class) public interface OrganizationQueries { public QueryBuilder<UserEntity> findUsersByUsername( String query ); public <ThrowableType extends Throwable> boolean accept(HierarchicalVisitor<Object, Object, ThrowableType> visitor) throws ThrowableType; public void visitOrganization(OrganizationVisitor visitor, Specification<Class> typeSelector); class Mixin implements OrganizationQueries { @Structure ModuleSPI module; @This Organization org; public QueryBuilder<UserEntity> findUsersByUsername( String userName ) { QueryBuilder<UserEntity> queryBuilder = module.queryBuilderFactory().newQueryBuilder( UserEntity.class ); queryBuilder = queryBuilder.where( and( eq( templateFor( UserAuthentication.Data.class ).disabled(), false ), contains( templateFor( UserEntity.class ).organizations(), org ) ) ); if (userName.length() > 0) { queryBuilder = queryBuilder.where( matches( templateFor( UserEntity.class ).userName(), "^" + userName ) ); } return queryBuilder; } public <ThrowableType extends Throwable> boolean accept(HierarchicalVisitor<Object, Object, ThrowableType> visitor) throws ThrowableType { if (visitor.visitEnter(org)) { if (visitor.visitEnter(Labels.class)) { for (Label label : ((Labels.Data) org).labels()) { if (!visitor.visit( label )) break; } } if (!visitor.visitLeave(Labels.class)) return false; if (visitor.visitEnter(Forms.class)) { for (Form form : ((Forms.Data) org).forms()) { if (!visitor.visit( form )) break; } } if (!visitor.visitLeave(Forms.class)) return false; if (visitor.visitEnter(CaseTypes.class)) { for (CaseType caseType : ((CaseTypes.Data) org).caseTypes()) { if (!visitor.visit( caseType )) break; } } if (!visitor.visitLeave(CaseTypes.class)) return false; if (visitor.visitEnter(OrganizationalUnits.class)) { for (OrganizationalUnit ou : ((OrganizationalUnits.Data) org).organizationalUnits()) { if (!acceptOu(visitor, ou)) break; } } if (!visitor.visitLeave(OrganizationalUnits.class)) return false; } return visitor.visitLeave(org); } public void visitOrganization( OrganizationVisitor visitor, Specification<Class> typeSpecification) { if (typeSpecification.satisfiedBy( Organization.class ) && !visitor.visitOrganization( org )) return; // Visit items on Organization if (typeSpecification.satisfiedBy( Groups.class )) for (Group group : ((Groups.Data) org).groups()) { if (!visitor.visitGroup( group )) return; } if (typeSpecification.satisfiedBy( Labels.class )) for (Label label : ((Labels.Data) org).labels()) { if (!visitor.visitLabel( label )) return; } if (typeSpecification.satisfiedBy( Forms.class )) for (Form form : ((Forms.Data)org).forms()) { if (!visitor.visitForm( form )) return; } if (typeSpecification.satisfiedBy( CaseTypes.class )) for (CaseType caseType : ((CaseTypes.Data)org).caseTypes()) { if (!visitCaseType( caseType, visitor, typeSpecification )) return; } if (typeSpecification.satisfiedBy( OrganizationalUnits.class )) for (OrganizationalUnit organizationalUnit : ((OrganizationalUnits.Data) org).organizationalUnits()) { if (!visitOu(organizationalUnit, visitor, typeSpecification)) return; } } private boolean visitOu( OrganizationalUnit organizationalUnit, OrganizationVisitor visitor, Specification<Class> typeSpecification ) { if (typeSpecification.satisfiedBy( OrganizationalUnit.class ) && !visitor.visitOrganizationalUnit( organizationalUnit )) return false; if (typeSpecification.satisfiedBy( Labels.class )) for (Label label : ((Labels.Data) organizationalUnit).labels()) { if (!visitor.visitLabel( label )) return false; } if (typeSpecification.satisfiedBy( Forms.class )) for (Form form : ((Forms.Data)organizationalUnit).forms()) { if (!visitor.visitForm( form )) return false; } if (typeSpecification.satisfiedBy( CaseTypes.class )) for (CaseType caseType : ((CaseTypes.Data)organizationalUnit).caseTypes()) { if (!visitCaseType( caseType, visitor, typeSpecification )) return false; } if (typeSpecification.satisfiedBy( Groups.class )) for (Group group : ((Groups.Data) organizationalUnit).groups()) { if (!visitor.visitGroup( group )) return false; } if (typeSpecification.satisfiedBy( Projects.class )) for (Project project : ((Projects.Data) organizationalUnit).projects()) { if (!visitProject(project, visitor, typeSpecification)) return false; } for (OrganizationalUnit ou : ((OrganizationalUnits.Data) organizationalUnit).organizationalUnits()) { if (!visitOu(ou, visitor, typeSpecification )) return false; } return true; } private boolean visitProject( Project project, OrganizationVisitor visitor, Specification<Class> typeSpecification) { if (typeSpecification.satisfiedBy( Project.class )) if (!visitor.visitProject( project )) return false; if (typeSpecification.satisfiedBy( Labels.class )) for (Label label : ((Labels.Data) project).labels()) { if (!visitor.visitLabel( label )) return false; } if (typeSpecification.satisfiedBy( Forms.class )) for (Form form : ((Forms.Data)project).forms()) { if (!visitor.visitForm( form )) return false; } if (typeSpecification.satisfiedBy( CaseTypes.class )) for (CaseType caseType : ((CaseTypes.Data)project).caseTypes()) { if (!visitCaseType( caseType, visitor, typeSpecification )) return false; } if (typeSpecification.satisfiedBy( SelectedCaseTypes.class )) for (CaseType caseType : ((SelectedCaseTypes.Data)project).selectedCaseTypes()) { if (!visitor.visitSelectedCaseType( caseType )) return false; } if (typeSpecification.satisfiedBy( SelectedLabels.class )) for (Label label : ((SelectedLabels.Data)project).selectedLabels()) { if (!visitor.visitSelectedLabel( label )) return false; } return true; } private boolean visitCaseType( CaseType caseType, OrganizationVisitor visitor, Specification<Class> typeSpecification ) { if (typeSpecification.satisfiedBy( CaseType.class ) && !visitor.visitCaseType( caseType )) return false; if (typeSpecification.satisfiedBy( Labels.class )) for (Label label : ((Labels.Data) caseType).labels()) { if (!visitor.visitLabel( label )) return false; } if (typeSpecification.satisfiedBy( SelectedLabels.class )) for (Label label : ((SelectedLabels.Data) caseType).selectedLabels()) { if (!visitor.visitSelectedLabel( label )) return false; } if (typeSpecification.satisfiedBy( Forms.class )) for (Form form : ((Forms.Data)caseType).forms()) { if (!visitor.visitForm( form )) return false; } if (typeSpecification.satisfiedBy( SelectedForms.class )) for (Form form : ((SelectedForms.Data)caseType).selectedForms()) { if (!visitor.visitSelectedForm( form )) return false; } if (typeSpecification.satisfiedBy( Resolutions.class )) for (Resolution resolution : ((Resolutions.Data)caseType).resolutions()) { if (!visitor.visitResolution( resolution )) return false; } if (typeSpecification.satisfiedBy( SelectedResolutions.class )) for (Resolution resolution : ((SelectedResolutions.Data)caseType).selectedResolutions()) { if (!visitor.visitSelectedResolution( resolution )) return false; } return true; } private <ThrowableType extends Throwable> boolean acceptOu( HierarchicalVisitor<Object, Object, ThrowableType> visitor, OrganizationalUnit organizationalUnit) throws ThrowableType { if (visitor.visitEnter(organizationalUnit)) { if (visitor.visitEnter(Labels.class)) { for (Label label : ((Labels.Data) organizationalUnit).labels()) { if (!visitor.visit( label )) break; } } if (!visitor.visitLeave(Labels.class)) return false; if (visitor.visitEnter(Forms.class)) { for (Form form : ((Forms.Data) organizationalUnit).forms()) { if (!visitor.visit( form )) break; } } if (!visitor.visitLeave(Forms.class)) return false; if (visitor.visitEnter(Groups.class)) { for (Group group : ((Groups.Data) organizationalUnit).groups()) { if (!visitor.visit( group )) break; } } if (!visitor.visitLeave(Groups.class)) return false; if (visitor.visitEnter(CaseTypes.class)) { for (CaseType caseType : ((CaseTypes.Data) organizationalUnit).caseTypes()) { if (!acceptCaseType(visitor, caseType)) break; } } if (!visitor.visitLeave(CaseTypes.class)) return false; if (visitor.visitEnter(Projects.class)) { for (Project project : ((Projects.Data) organizationalUnit).projects()) { if (!acceptProject(visitor, project)) break; } } if (!visitor.visitLeave(Projects.class)) return false; if (visitor.visitEnter(OrganizationalUnits.class)) { for (OrganizationalUnit ou : ((OrganizationalUnits.Data) organizationalUnit).organizationalUnits()) { if (!acceptOu(visitor, ou)) break; } } if (!visitor.visitLeave(OrganizationalUnits.class)) return false; } return visitor.visitLeave(organizationalUnit); } private <ThrowableType extends Throwable> boolean acceptProject( HierarchicalVisitor<Object, Object, ThrowableType> visitor, Project project) throws ThrowableType { if (visitor.visitEnter(project)) { if (visitor.visitEnter(Labels.class)) { for (Label label : ((Labels.Data) project).labels()) { if (!visitor.visit( label )) break; } } if (!visitor.visitLeave(Labels.class)) return false; if (visitor.visitEnter(Forms.class)) { for (Form form : ((Forms.Data) project).forms()) { if (!visitor.visit( form )) break; } } if (!visitor.visitLeave(Forms.class)) return false; if (visitor.visitEnter(CaseTypes.class)) { for (CaseType caseType : ((CaseTypes.Data) project).caseTypes()) { if (!acceptCaseType(visitor, caseType)) break; } } if (!visitor.visitLeave(CaseTypes.class)) return false; } return visitor.visitLeave(project); } private <ThrowableType extends Throwable> boolean acceptCaseType( HierarchicalVisitor<Object, Object, ThrowableType> visitor, CaseType caseType) throws ThrowableType { if (visitor.visitEnter(caseType)) { if (visitor.visitEnter(Labels.class)) { for (Label label : ((Labels.Data) caseType).labels()) { if (!visitor.visit( label )) break; } } if (!visitor.visitLeave(Labels.class)) return false; if (visitor.visitEnter(Forms.class)) { for (Form form : ((Forms.Data) caseType).forms()) { if (!visitor.visit( form )) break; } } if (!visitor.visitLeave(Forms.class)) return false; if (visitor.visitEnter(Resolutions.class)) { for (Resolution resolution : ((Resolutions.Data) caseType).resolutions()) { if (!visitor.visit( resolution )) break; } } if (!visitor.visitLeave(Forms.class)) return false; } return visitor.visitLeave(caseType); } } public static class ClassSpecification implements Specification<Class> { private Class[] classes; public ClassSpecification(Class... classes) { this.classes = classes; } public boolean satisfiedBy( Class instance ) { for (int i = 0; i < classes.length; i++) { Class aClass = classes[i]; if (aClass.equals(instance)) return true; } return false; } } }