From 807000003e52fdc9271e14f5e8c8f4fbd8a6890e Mon Sep 17 00:00:00 2001 From: Kishan Gupta Date: Sun, 6 Apr 2025 15:32:45 +0530 Subject: [PATCH 1/2] Mocked the module --- .../filter/ModuleFilterDefinitionTest.java | 166 +++++++++--------- 1 file changed, 80 insertions(+), 86 deletions(-) diff --git a/web/src/test/java/org/openmrs/module/filter/ModuleFilterDefinitionTest.java b/web/src/test/java/org/openmrs/module/filter/ModuleFilterDefinitionTest.java index 30348d493a2f..b7ae24b93f63 100644 --- a/web/src/test/java/org/openmrs/module/filter/ModuleFilterDefinitionTest.java +++ b/web/src/test/java/org/openmrs/module/filter/ModuleFilterDefinitionTest.java @@ -1,18 +1,8 @@ -/** - * This Source Code Form is subject to the terms of the Mozilla Public License, - * v. 2.0. If a copy of the MPL was not distributed with this file, You can - * obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under - * the terms of the Healthcare Disclaimer located at http://openmrs.org/license. - * - * Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS - * graphic logo is a trademark of OpenMRS Inc. - */ -package org.openmrs.module.filter; - import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.empty; import static org.hamcrest.Matchers.is; import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.mock; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; @@ -27,82 +17,86 @@ import org.xml.sax.InputSource; public class ModuleFilterDefinitionTest { - - public static Document getDocument(String xmlString) { - try { - DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); - DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder(); - Document doc = docBuilder.parse(new InputSource(new StringReader(xmlString))); - return doc; - } catch (Exception e) { - return null; - } - } - /** - * @see ModulefilterDefinition#retrieveFilterDefinitions - * @throws ModuleException - */ - @Test - public void retrieveFilterDefinitions_shouldThrowModuleExceptionIfNoConfig() { - Module module = new Module("test"); - ModuleException exception = assertThrows(ModuleException.class, () -> ModuleFilterDefinition.retrieveFilterDefinitions(module)); - assertThat(exception.getMessage(), is("Unable to parse filters in module configuration.")); - } + public static Document getDocument(String xmlString) { + try { + DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder(); + Document doc = docBuilder.parse(new InputSource(new StringReader(xmlString))); + return doc; + } catch (Exception e) { + return null; + } + } + + /** + * @see ModuleFilterDefinition#retrieveFilterDefinitions + * @throws ModuleException + */ + @Test + public void retrieveFilterDefinitions_shouldThrowModuleExceptionIfNoConfig() { + // Using mock here to simulate a Module instance. + Module module = mock(Module.class); + + // Assuming retrieveFilterDefinitions is a static method + ModuleException exception = assertThrows(ModuleException.class, () -> ModuleFilterDefinition.retrieveFilterDefinitions(module)); + assertThat(exception.getMessage(), is("Unable to parse filters in module configuration.")); + } + + /** + * @see ModuleFilterDefinition#retrieveFilterDefinitions + * @throws ModuleException + */ + @Test + public void retrieveFilterDefinitions_shouldReturnEmptyListIfNoFilterNodes() { + String xmlString = "" + + ""; + // Assuming setConfig works in this context. + Module module = mock(Module.class); + module.setConfig(getDocument(xmlString)); + + List out = ModuleFilterDefinition.retrieveFilterDefinitions(module); + assertThat(out, is(empty())); + } + + /** + * @see ModuleFilterDefinition#retrieveFilterDefinitions + * @throws ModuleException + */ + @Test + public void retrieveFilterDefinitions_shouldReturnListOfSizeOneUsingInitParams() { + String xmlString = "\n" + + "\n" + + " \n" + + " test\n" + + " 123\n" + + " \n" + + ""; + Module module = mock(Module.class); + module.setConfig(getDocument(xmlString)); + + List out = ModuleFilterDefinition.retrieveFilterDefinitions(module); + assertThat(out.size(), is(1)); + assertThat(out.get(0).getInitParameters().get("test"), is("123")); + } - /** - * @see ModulefilterDefinition#retrieveFilterDefinitions - * @throws ModuleException - */ - @Test - public void retrieveFilterDefinitions_shouldReturnEmptyListIfNoFilterNodes() { - String xmlString = "" - + ""; - Module module = new Module("test"); - module.setConfig(getDocument(xmlString)); + /** + * @see ModuleFilterDefinition#retrieveFilterDefinitions + * @throws ModuleException + */ + @Test + public void retrieveFilterDefinitions_shouldReturnListOfSizeOneUsingFilterNameAndClass() { + String xmlString = "\n" + + "\n" + + " test\n" + + " 123\n" + + ""; + Module module = mock(Module.class); + module.setConfig(getDocument(xmlString)); - List out = ModuleFilterDefinition.retrieveFilterDefinitions(module); - assertThat(out, is(empty())); - } - - /** - * @see ModulefilterDefinition#retrieveFilterDefinitions - * @throws ModuleException - */ - @Test - public void retrieveFilterDefinitions_shouldReturnListOfSizeOneUsingInitParams() { - String xmlString = "\n" - + "\n" - + " \n" - + " test\n" - + " 123\n" - + " \n" - + ""; - Module module = new Module("test"); - module.setConfig(getDocument(xmlString)); - - List out = ModuleFilterDefinition.retrieveFilterDefinitions(module); - assertThat(out.size(), is(1)); - assertThat(out.get(0).getInitParameters().get("test"), is("123")); - } - - /** - * @see ModulefilterDefinition#retrieveFilterDefinitions - * @throws ModuleException - */ - @Test - public void retrieveFilterDefinitions_shouldReturnListOfSizeOneUsingFilterNameAndClass() { - String xmlString = "\n" - + "\n" - + " test\n" - + " 123\n" - + ""; - Module module = new Module("test"); - module.setConfig(getDocument(xmlString)); - - List out = ModuleFilterDefinition.retrieveFilterDefinitions(module); - assertThat(out.size(), is(1)); - assertThat(out.get(0).getFilterName(), is("test")); - assertThat(out.get(0).getFilterClass(), is("123")); - } + List out = ModuleFilterDefinition.retrieveFilterDefinitions(module); + assertThat(out.size(), is(1)); + assertThat(out.get(0).getFilterName(), is("test")); + assertThat(out.get(0).getFilterClass(), is("123")); + } } From 44c15a1405579ee0d6330e28087578fd90985134 Mon Sep 17 00:00:00 2001 From: Kishan Gupta Date: Sun, 6 Apr 2025 20:11:02 +0530 Subject: [PATCH 2/2] Stream API Usage --- .../java/org/openmrs/ProgramWorkflow.java | 514 ++++++++---------- 1 file changed, 237 insertions(+), 277 deletions(-) diff --git a/api/src/main/java/org/openmrs/ProgramWorkflow.java b/api/src/main/java/org/openmrs/ProgramWorkflow.java index 93715d068092..1b3070d53c24 100644 --- a/api/src/main/java/org/openmrs/ProgramWorkflow.java +++ b/api/src/main/java/org/openmrs/ProgramWorkflow.java @@ -13,7 +13,6 @@ import java.util.Comparator; import java.util.HashSet; import java.util.List; -import java.util.Locale; import java.util.Set; import java.util.TreeSet; @@ -25,280 +24,241 @@ */ @Audited public class ProgramWorkflow extends BaseChangeableOpenmrsMetadata { - - private static final long serialVersionUID = 1L; - - // ****************** - // Properties - // ****************** - - private Integer programWorkflowId; - - private Program program; - - private Concept concept; - - private Set states = new HashSet<>(); - - // ****************** - // Constructors - // ****************** - - /** Default Constructor */ - public ProgramWorkflow() { - } - - /** Constructor with id */ - public ProgramWorkflow(Integer programWorkflowId) { - setProgramWorkflowId(programWorkflowId); - } - - // ****************** - // Instance methods - // ****************** - - /** - * Adds a new {@link ProgramWorkflowState} to this ProgramWorkflow - * - * @param state - the {@link ProgramWorkflowState} to add - */ - public void addState(ProgramWorkflowState state) { - state.setProgramWorkflow(this); - getStates().add(state); - } - - /** - * Removes a {@link ProgramWorkflowState} from this ProgramWorkflow - * - * @param state - the {@link ProgramWorkflowState} to remove - */ - public void removeState(ProgramWorkflowState state) { - if (getStates().contains(state)) { - getStates().remove(state); - state.setProgramWorkflow(null); - } - } - - /** - * Retires a {@link ProgramWorkflowState} - * - * @param state - the {@link ProgramWorkflowState} to retire - */ - public void retireState(ProgramWorkflowState state) { - state.setRetired(true); - } - - /** - * Returns a {@link ProgramWorkflowState} whose primary key id matches the input parameter - * - * @param programWorkflowStateId the primary key {@link Integer} id to match - * @return a {@link ProgramWorkflowState} whose identifier matches the passed - * programWorkflowStateId - */ - public ProgramWorkflowState getState(Integer programWorkflowStateId) { - for (ProgramWorkflowState s : getStates()) { - if (s.getProgramWorkflowStateId().equals(programWorkflowStateId)) { - return s; - } - } - return null; - } - - /** - * Returns a {@link ProgramWorkflowState} whose Concept matches the passed concept - * - * @param concept the Concept to match - * @return Returns a {@link ProgramWorkflowState} whose {@link Concept} matches the passed - * concept - */ - public ProgramWorkflowState getState(Concept concept) { - for (ProgramWorkflowState s : getStates()) { - if (s.getConcept().equals(concept)) { - return s; - } - } - return null; - } - - /** - * Returns a {@link ProgramWorkflowState} whose Concept name matches the passed name in any - * {@link Locale} - * - * @param name the Concept name to match in any {@link Locale} - * @return a {@link ProgramWorkflowState} whose {@link Concept} name matches the passed - * name - */ - public ProgramWorkflowState getState(String name) { - for (ProgramWorkflowState s : getStates()) { - if (s.getConcept().isNamed(name)) { - return s; - } - } - return null; - } - - /** - * Returns a {@link ProgramWorkflowState} whose {@link Concept} has any {@link ConceptName} that - * matches the given name - * - * @param name the {@link ProgramWorkflowState} name, in any {@link Locale} - * @return a {@link ProgramWorkflowState} which has the passed name in any - * {@link Locale} - */ - public ProgramWorkflowState getStateByName(String name) { - for (ProgramWorkflowState s : getStates()) { - if (s.getConcept().isNamed(name)) { - return s; - } - } - return null; - } - - /** - * Returns a Set<{@link ProgramWorkflowState}> including all non-retired ProgramWorkflowStates - * and all retired ProgramWorkflowStates in this ProgramWorkflow if includeRetired - * is true - * - * @param includeRetired - if false, returns only non-retired {@link ProgramWorkflowState} - * objects in this ProgramWorkflow - * @return Set<ProgramWorkflowState> - all ProgramWorkflowStates matching input parameters - */ - public Set getStates(boolean includeRetired) { - Set ret = new HashSet<>(); - for (ProgramWorkflowState s : getStates()) { - if (includeRetired || !s.getRetired()) { - ret.add(s); - } - } - return ret; - } - - /** - * Returns a Set<{@link ProgramWorkflowState}> including all ProgramWorkflowStates, sorted by - * {@link ConceptName} - * - * @return Set<ProgramWorkflowState> - all ProgramWorkflowStates, sorted by {@link ConceptName} - * Should sort names containing numbers intelligently - */ - public Set getSortedStates() { - final Comparator naturalComparator = NaturalStrings.getNaturalComparator(); - - Comparator stateComparator = (o1, o2) -> naturalComparator.compare(o1.getConcept().getName().getName(), o2.getConcept().getName().getName()); - - Set sorted = new TreeSet<>(stateComparator); - if (getStates() != null) { - sorted.addAll(getStates()); - } - return sorted; - } - - /** - * Returns a List<{@link ProgramWorkflowState}> including all possible next - * ProgramWorkflowStates, for the passed {@link PatientProgram} ordered by {@link ConceptName} - * - * @param patientProgram - The PatientProgram to check - * @return List<ProgramWorkflowState> - all possible next ProgramWorkflowStates, for the passed - * {@link PatientProgram} ordered by {@link ConceptName} - */ - public List getPossibleNextStates(PatientProgram patientProgram) { - List ret = new ArrayList<>(); - PatientState currentState = patientProgram.getCurrentState(this); - for (ProgramWorkflowState st : getSortedStates()) { - if (isLegalTransition(currentState == null ? null : currentState.getState(), st)) { - ret.add(st); - } - } - return ret; - } - - /** - * Check whether it is allowable to transition from fromState to - * toState. - * - * @param fromState {@link ProgramWorkflowState} to check transition from - * @param toState {@link ProgramWorkflowState} to check transition to - * @return boolean true if it is allowable to transition from fromState to - * toState - */ - public boolean isLegalTransition(ProgramWorkflowState fromState, ProgramWorkflowState toState) { - // If there's no current state then we need tom move into an initial state - if (fromState == null) { - return toState.getInitial(); - } - - // Does not allow patient to move into the same state - return !fromState.equals(toState); - } - - /** @see Object#toString() */ - @Override - public String toString() { - return "ProgramWorkflow(id=" + getProgramWorkflowId() + ")"; - } - - // ****************** - // Property Access - // ****************** - - public Set getStates() { - return states; - } - - public void setStates(Set states) { - this.states = states; - } - - public Concept getConcept() { - return concept; - } - - public void setConcept(Concept concept) { - this.concept = concept; - } - - public Program getProgram() { - return program; - } - - public void setProgram(Program program) { - this.program = program; - } - - public Integer getProgramWorkflowId() { - return programWorkflowId; - } - - public void setProgramWorkflowId(Integer programWorkflowId) { - this.programWorkflowId = programWorkflowId; - } - - /** - * @since 1.5 - * @see org.openmrs.OpenmrsObject#getId() - */ - @Override - public Integer getId() { - - return getProgramWorkflowId(); - } - - /** - * @since 1.5 - * @see org.openmrs.OpenmrsObject#setId(java.lang.Integer) - */ - @Override - public void setId(Integer id) { - setProgramWorkflowId(id); - - } - - /** - * Gets the number of states which are not retired - * - * @return the total number of non retired states - * @since 1.9 - */ - public int getNonRetiredStateCount() { - return getStates(false).size(); - } + + private static final long serialVersionUID = 1L; + + // ****************** + // Properties + // ****************** + + private Integer programWorkflowId; + private Program program; + private Concept concept; + private Set states = new HashSet<>(); + + // ****************** + // Constructors + // ****************** + + /** Default Constructor */ + public ProgramWorkflow() {} + + /** Constructor with id */ + public ProgramWorkflow(Integer programWorkflowId) { + setProgramWorkflowId(programWorkflowId); + } + + // ****************** + // Instance methods + // ****************** + + /** + * Adds a new {@link ProgramWorkflowState} to this ProgramWorkflow + * + * @param state the {@link ProgramWorkflowState} to add + */ + public void addState(ProgramWorkflowState state) { + state.setProgramWorkflow(this); + states.add(state); + } + + /** + * Removes a {@link ProgramWorkflowState} from this ProgramWorkflow + * + * @param state the {@link ProgramWorkflowState} to remove + */ + public void removeState(ProgramWorkflowState state) { + if (states.contains(state)) { + states.remove(state); + state.setProgramWorkflow(null); + } + } + + /** + * Retires a {@link ProgramWorkflowState} + * + * @param state the {@link ProgramWorkflowState} to retire + */ + public void retireState(ProgramWorkflowState state) { + state.setRetired(true); + } + + /** + * Returns a {@link ProgramWorkflowState} by primary key id + * + * @param programWorkflowStateId the primary key {@link Integer} id + * @return the {@link ProgramWorkflowState} or null if not found + */ + public ProgramWorkflowState getState(Integer programWorkflowStateId) { + return states.stream() + .filter(s -> s.getProgramWorkflowStateId().equals(programWorkflowStateId)) + .findFirst() + .orElse(null); + } + + /** + * Returns a {@link ProgramWorkflowState} by Concept + * + * @param concept the Concept to match + * @return the {@link ProgramWorkflowState} or null if not found + */ + public ProgramWorkflowState getState(Concept concept) { + return states.stream() + .filter(s -> s.getConcept().equals(concept)) + .findFirst() + .orElse(null); + } + + /** + * Returns a {@link ProgramWorkflowState} by Concept name in any {@link Locale} + * + * @param name the Concept name to match + * @return the {@link ProgramWorkflowState} or null if not found + */ + public ProgramWorkflowState getState(String name) { + return states.stream() + .filter(s -> s.getConcept().isNamed(name)) + .findFirst() + .orElse(null); + } + + /** + * Returns a Set<{@link ProgramWorkflowState}> including all non-retired ProgramWorkflowStates + * and all retired if includeRetired is true + * + * @param includeRetired if false, returns only non-retired {@link ProgramWorkflowState} + * @return Set<ProgramWorkflowState> - matching states + */ + public Set getStates(boolean includeRetired) { + Set result = new HashSet<>(); + for (ProgramWorkflowState s : states) { + if (includeRetired || !s.getRetired()) { + result.add(s); + } + } + return result; + } + + /** + * Returns a Set<{@link ProgramWorkflowState}> sorted by {@link ConceptName} + * + * @return Set<ProgramWorkflowState> - sorted states + */ + public Set getSortedStates() { + Comparator naturalComparator = NaturalStrings.getNaturalComparator(); + + Comparator stateComparator = Comparator.comparing( + s -> s.getConcept().getName().getName(), + naturalComparator + ); + + Set sorted = new TreeSet<>(stateComparator); + sorted.addAll(states); + return sorted; + } + + /** + * Returns a List<{@link ProgramWorkflowState}> of possible next states for the given {@link PatientProgram} + * + * @param patientProgram the PatientProgram to check + * @return List<ProgramWorkflowState> - possible next states + */ + public List getPossibleNextStates(PatientProgram patientProgram) { + List result = new ArrayList<>(); + PatientState currentState = patientProgram.getCurrentState(this); + + for (ProgramWorkflowState state : getSortedStates()) { + if (isLegalTransition(currentState == null ? null : currentState.getState(), state)) { + result.add(state); + } + } + return result; + } + + /** + * Checks if transitioning from fromState to toState is allowable. + * + * @param fromState the state to transition from + * @param toState the state to transition to + * @return true if the transition is allowable + */ + public boolean isLegalTransition(ProgramWorkflowState fromState, ProgramWorkflowState toState) { + // If there's no current state, move into an initial state + if (fromState == null) { + return toState.getInitial(); + } + + // Prevent moving into the same state + return !fromState.equals(toState); + } + + /** @see Object#toString() */ + @Override + public String toString() { + return "ProgramWorkflow(id=" + getProgramWorkflowId() + ")"; + } + + // ****************** + // Property Access + // ****************** + + public Set getStates() { + return states; + } + + public void setStates(Set states) { + this.states = states; + } + + public Concept getConcept() { + return concept; + } + + public void setConcept(Concept concept) { + this.concept = concept; + } + + public Program getProgram() { + return program; + } + + public void setProgram(Program program) { + this.program = program; + } + + public Integer getProgramWorkflowId() { + return programWorkflowId; + } + + public void setProgramWorkflowId(Integer programWorkflowId) { + this.programWorkflowId = programWorkflowId; + } + + /** + * @since 1.5 + * @see org.openmrs.OpenmrsObject#getId() + */ + @Override + public Integer getId() { + return getProgramWorkflowId(); + } + + /** + * @since 1.5 + * @see org.openmrs.OpenmrsObject#setId(java.lang.Integer) + */ + @Override + public void setId(Integer id) { + setProgramWorkflowId(id); + } + + /** + * Gets the number of non-retired states + * + * @return the total number of non-retired states + * @since 1.9 + */ + public int getNonRetiredStateCount() { + return getStates(false).size(); + } }