From 38bf3dcef8b8d7280d63af6d1a7e4be017563595 Mon Sep 17 00:00:00 2001 From: JhonSGIzquierdo Date: Wed, 13 Mar 2024 08:57:38 -0500 Subject: [PATCH 1/8] :wrench: chore(QA Display): Update ftl with feedback --- .../WEB-INF/crp/views/projects/projectContributionCrp.ftl | 2 +- .../webapp/WEB-INF/crp/views/projects/projectDeliverable.ftl | 2 +- .../src/main/webapp/WEB-INF/crp/views/projects/projectStudy.ftl | 2 +- .../src/main/webapp/WEB-INF/crp/views/projects/safeguard.ftl | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/marlo-web/src/main/webapp/WEB-INF/crp/views/projects/projectContributionCrp.ftl b/marlo-web/src/main/webapp/WEB-INF/crp/views/projects/projectContributionCrp.ftl index 3b91fb6809..8e0724d1d1 100644 --- a/marlo-web/src/main/webapp/WEB-INF/crp/views/projects/projectContributionCrp.ftl +++ b/marlo-web/src/main/webapp/WEB-INF/crp/views/projects/projectContributionCrp.ftl @@ -5,7 +5,7 @@ [#assign customJS = [ "${baseUrlMedia}/js/projects/projectContributionCrp.js?20230310", "${baseUrlCdn}/global/js/fieldsValidation.js?20221031", - "${baseUrlCdn}/crp/js/feedback/feedbackAutoImplementation.js?20231017", + "${baseUrlCdn}/crp/js/feedback/feedbackAutoImplementation.js?20240313", "https://www.gstatic.com/charts/loader.js", "https://cdn.datatables.net/buttons/1.3.1/js/dataTables.buttons.min.js", "//cdn.datatables.net/buttons/1.3.1/js/buttons.html5.min.js", diff --git a/marlo-web/src/main/webapp/WEB-INF/crp/views/projects/projectDeliverable.ftl b/marlo-web/src/main/webapp/WEB-INF/crp/views/projects/projectDeliverable.ftl index 10ab6d76f1..80ebb2776f 100644 --- a/marlo-web/src/main/webapp/WEB-INF/crp/views/projects/projectDeliverable.ftl +++ b/marlo-web/src/main/webapp/WEB-INF/crp/views/projects/projectDeliverable.ftl @@ -7,7 +7,7 @@ "${baseUrlMedia}/js/projects/deliverables/deliverableShfrm.js?20240226", "${baseUrlMedia}/js/projects/deliverables/deliverableDissemination.js?20230810", "${baseUrlMedia}/js/projects/deliverables/deliverableQualityCheck.js?20220721", - "${baseUrlCdn}/crp/js/feedback/feedbackAutoImplementation.js?20241017", + "${baseUrlCdn}/crp/js/feedback/feedbackAutoImplementation.js?20240313", [#-- "${baseUrlMedia}/js/projects/deliverables/deliverableDataSharing.js?20180523",--] [#-- "${baseUrlCdn}/global/js/autoSave.js",--] "${baseUrlCdn}/global/js/fieldsValidation.js?20180529" diff --git a/marlo-web/src/main/webapp/WEB-INF/crp/views/projects/projectStudy.ftl b/marlo-web/src/main/webapp/WEB-INF/crp/views/projects/projectStudy.ftl index d92475a8f8..abbb52e0eb 100644 --- a/marlo-web/src/main/webapp/WEB-INF/crp/views/projects/projectStudy.ftl +++ b/marlo-web/src/main/webapp/WEB-INF/crp/views/projects/projectStudy.ftl @@ -5,7 +5,7 @@ [#assign customJS = [ "${baseUrlMedia}/js/projects/projectStudy.js?20240221", "${baseUrlCdn}/global/js/fieldsValidation.js", - "${baseUrlCdn}/crp/js/feedback/feedbackAutoImplementation.js?20231017" + "${baseUrlCdn}/crp/js/feedback/feedbackAutoImplementation.js?20240313" ] /] [#assign customCSS = [ diff --git a/marlo-web/src/main/webapp/WEB-INF/crp/views/projects/safeguard.ftl b/marlo-web/src/main/webapp/WEB-INF/crp/views/projects/safeguard.ftl index 0bc07c11b6..d772c01261 100644 --- a/marlo-web/src/main/webapp/WEB-INF/crp/views/projects/safeguard.ftl +++ b/marlo-web/src/main/webapp/WEB-INF/crp/views/projects/safeguard.ftl @@ -7,7 +7,7 @@ [#-- "${baseUrlCdn}/global/js/autoSave.js", --] "${baseUrlCdn}/global/js/impactGraphic.js", "${baseUrlCdn}/global/js/fieldsValidation.js", - "${baseUrlCdn}/crp/js/feedback/feedbackAutoImplementation.js?20231017" + "${baseUrlCdn}/crp/js/feedback/feedbackAutoImplementation.js?20240313" ] /] [#assign customCSS = [ From 0d9a95a0d0745b6b41015e6b76b4b20e7e5d9e6b Mon Sep 17 00:00:00 2001 From: JhonSGIzquierdo Date: Thu, 14 Mar 2024 09:10:10 -0500 Subject: [PATCH 2/8] :wrench: chore(Responsive CSS) Search Adjust --- .../monitoring/ADRESSED_IN_CRP_deliverable/deliverableList.ftl | 2 +- .../ADRESSED_IN_CRP_deliverable/projectDeliverable.ftl | 2 +- .../webapp/WEB-INF/crp/views/projects/projectCaseStudies.ftl | 2 +- .../main/webapp/WEB-INF/crp/views/projects/projectCaseStudy.ftl | 2 +- .../main/webapp/WEB-INF/crp/views/projects/projectStudies.ftl | 2 +- .../src/main/webapp/crp/css/projects/projectCaseStudies.css | 2 +- .../src/main/webapp/crp/css/projects/projectDeliverable.css | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/marlo-web/src/main/webapp/WEB-INF/center/views/monitoring/ADRESSED_IN_CRP_deliverable/deliverableList.ftl b/marlo-web/src/main/webapp/WEB-INF/center/views/monitoring/ADRESSED_IN_CRP_deliverable/deliverableList.ftl index eb630c7b3a..6519e38259 100644 --- a/marlo-web/src/main/webapp/WEB-INF/center/views/monitoring/ADRESSED_IN_CRP_deliverable/deliverableList.ftl +++ b/marlo-web/src/main/webapp/WEB-INF/center/views/monitoring/ADRESSED_IN_CRP_deliverable/deliverableList.ftl @@ -8,7 +8,7 @@ /] [#assign customCSS = [ "${baseUrlCdn}/global/css/customDataTable.css", - "${baseUrlMedia}/css/deliverable/projectDeliverable.css?20230531" + "${baseUrlMedia}/css/deliverable/projectDeliverable.css?20240314" ] /] [#assign currentSection = "monitoring" /] diff --git a/marlo-web/src/main/webapp/WEB-INF/center/views/monitoring/ADRESSED_IN_CRP_deliverable/projectDeliverable.ftl b/marlo-web/src/main/webapp/WEB-INF/center/views/monitoring/ADRESSED_IN_CRP_deliverable/projectDeliverable.ftl index d62a814166..383e59e53c 100644 --- a/marlo-web/src/main/webapp/WEB-INF/center/views/monitoring/ADRESSED_IN_CRP_deliverable/projectDeliverable.ftl +++ b/marlo-web/src/main/webapp/WEB-INF/center/views/monitoring/ADRESSED_IN_CRP_deliverable/projectDeliverable.ftl @@ -7,7 +7,7 @@ "${baseUrlCdn}/global/js/usersManagement.js", "${baseUrlMedia}/js/monitoring/deliverable/projectDeliverable.js", "${baseUrlCdn}/global/js/autoSave.js"] /] -[#assign customCSS = ["${baseUrlMedia}/css/deliverable/projectDeliverable.css?20230529"] /] +[#assign customCSS = ["${baseUrlMedia}/css/deliverable/projectDeliverable.css?20240314"] /] [#assign currentSection = "projects" /] [#assign currentStage = "deliverables" /] diff --git a/marlo-web/src/main/webapp/WEB-INF/crp/views/projects/projectCaseStudies.ftl b/marlo-web/src/main/webapp/WEB-INF/crp/views/projects/projectCaseStudies.ftl index a7766ec081..6a8caa01ec 100644 --- a/marlo-web/src/main/webapp/WEB-INF/crp/views/projects/projectCaseStudies.ftl +++ b/marlo-web/src/main/webapp/WEB-INF/crp/views/projects/projectCaseStudies.ftl @@ -5,7 +5,7 @@ [#assign customJS = [ "${baseUrlMedia}/js/projects/projectCaseStudiesList.js", "${baseUrlCdn}/global/js/fieldsValidation.js"] /] -[#assign customCSS = ["${baseUrlMedia}/css/projects/projectCaseStudies.css?20230106"] /] +[#assign customCSS = ["${baseUrlMedia}/css/projects/projectCaseStudies.css?20240314"] /] [#assign currentSection = "projects" /] [#assign currentStage = "caseStudies" /] [#assign hideJustification = true /] diff --git a/marlo-web/src/main/webapp/WEB-INF/crp/views/projects/projectCaseStudy.ftl b/marlo-web/src/main/webapp/WEB-INF/crp/views/projects/projectCaseStudy.ftl index 98001a0c38..00f5577849 100644 --- a/marlo-web/src/main/webapp/WEB-INF/crp/views/projects/projectCaseStudy.ftl +++ b/marlo-web/src/main/webapp/WEB-INF/crp/views/projects/projectCaseStudy.ftl @@ -7,7 +7,7 @@ "${baseUrlCdn}/global/js/fieldsValidation.js" ] /] -[#assign customCSS = ["${baseUrlMedia}/css/projects/projectCaseStudies.css?20230106"] /] +[#assign customCSS = ["${baseUrlMedia}/css/projects/projectCaseStudies.css?20240314"] /] [#assign currentSection = "projects" /] [#assign currentStage = "caseStudies" /] diff --git a/marlo-web/src/main/webapp/WEB-INF/crp/views/projects/projectStudies.ftl b/marlo-web/src/main/webapp/WEB-INF/crp/views/projects/projectStudies.ftl index d7a42ab200..f2b37ab9fc 100644 --- a/marlo-web/src/main/webapp/WEB-INF/crp/views/projects/projectStudies.ftl +++ b/marlo-web/src/main/webapp/WEB-INF/crp/views/projects/projectStudies.ftl @@ -5,7 +5,7 @@ [#assign customJS = [ "${baseUrlMedia}/js/projects/projectCaseStudiesList.js?20230306", "${baseUrlCdn}/global/js/fieldsValidation.js"] /] -[#assign customCSS = ["${baseUrlMedia}/css/projects/projectCaseStudies.css?20230306"] /] +[#assign customCSS = ["${baseUrlMedia}/css/projects/projectCaseStudies.css?20240314"] /] [#assign currentSection = "projects" /] [#assign currentStage = "projectStudies" /] [#assign hideJustification = true /] diff --git a/marlo-web/src/main/webapp/crp/css/projects/projectCaseStudies.css b/marlo-web/src/main/webapp/crp/css/projects/projectCaseStudies.css index b14a4a5a42..50b52a60a3 100644 --- a/marlo-web/src/main/webapp/crp/css/projects/projectCaseStudies.css +++ b/marlo-web/src/main/webapp/crp/css/projects/projectCaseStudies.css @@ -44,7 +44,7 @@ table#projectHighlights { .dataTables_filter label input{ height: 30px !important; width: 295px !important; - margin-left: -44px !important; + margin-left: 0 !important; } .iconSearch{ diff --git a/marlo-web/src/main/webapp/crp/css/projects/projectDeliverable.css b/marlo-web/src/main/webapp/crp/css/projects/projectDeliverable.css index ccbbce4b3c..f82ceb83c0 100644 --- a/marlo-web/src/main/webapp/crp/css/projects/projectDeliverable.css +++ b/marlo-web/src/main/webapp/crp/css/projects/projectDeliverable.css @@ -777,7 +777,7 @@ div#ccDimension-capacity { .dataTables_filter label input{ height: 30px !important; width: 295px !important; - margin-left: -44px !important; + margin-left: 0 !important; } .iconSearch{ From 983bb69d068fcb2879e3f70f801c53c8846dd3fb Mon Sep 17 00:00:00 2001 From: Kenji Tanaka Date: Mon, 18 Mar 2024 15:06:47 -0500 Subject: [PATCH 3/8] :wrench: chore(migration): Create encryption token field in TIP parameters table --- .../migrations/V2_6_0_20240315_1025__AddEncryptionKeyField.sql | 1 + 1 file changed, 1 insertion(+) create mode 100644 marlo-web/src/main/resources/database/migrations/V2_6_0_20240315_1025__AddEncryptionKeyField.sql diff --git a/marlo-web/src/main/resources/database/migrations/V2_6_0_20240315_1025__AddEncryptionKeyField.sql b/marlo-web/src/main/resources/database/migrations/V2_6_0_20240315_1025__AddEncryptionKeyField.sql new file mode 100644 index 0000000000..531ff1e0d4 --- /dev/null +++ b/marlo-web/src/main/resources/database/migrations/V2_6_0_20240315_1025__AddEncryptionKeyField.sql @@ -0,0 +1 @@ +ALTER TABLE tip_parameters ADD encryption_key text NULL; \ No newline at end of file From d3f22f97204b3ae272ed079abbad140c535e7901 Mon Sep 17 00:00:00 2001 From: Kenji Tanaka Date: Mon, 18 Mar 2024 15:07:59 -0500 Subject: [PATCH 4/8] :wrench: chore(TIP Integration): Update java and hibernate models --- .../cgiar/ccafs/marlo/data/model/TipParameters.java | 12 +++++++++++- .../src/main/resources/xmls/TipParameters.hbm.xml | 3 +++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/marlo-data/src/main/java/org/cgiar/ccafs/marlo/data/model/TipParameters.java b/marlo-data/src/main/java/org/cgiar/ccafs/marlo/data/model/TipParameters.java index 1d88399ba6..39d292d6a0 100644 --- a/marlo-data/src/main/java/org/cgiar/ccafs/marlo/data/model/TipParameters.java +++ b/marlo-data/src/main/java/org/cgiar/ccafs/marlo/data/model/TipParameters.java @@ -38,8 +38,14 @@ public class TipParameters extends MarloBaseEntity implements java.io.Serializab @Expose private String tipBaseUrl; @Expose + private String encryptionKey; + @Expose private Date tokenDueDate; + public String getEncryptionKey() { + return encryptionKey; + } + @Override public String getLogDeatil() { // TODO Auto-generated method stub @@ -82,17 +88,21 @@ public Date getTokenDueDate() { return tokenDueDate; } + public String getTokenValue() { return tokenValue; } - @Override public boolean isActive() { // TODO Auto-generated method stub return false; } + public void setEncryptionKey(String encryptionKey) { + this.encryptionKey = encryptionKey; + } + @Override public void setModifiedBy(User modifiedBy) { // TODO Auto-generated method stub diff --git a/marlo-data/src/main/resources/xmls/TipParameters.hbm.xml b/marlo-data/src/main/resources/xmls/TipParameters.hbm.xml index 01b56b2908..ca7569cad0 100644 --- a/marlo-data/src/main/resources/xmls/TipParameters.hbm.xml +++ b/marlo-data/src/main/resources/xmls/TipParameters.hbm.xml @@ -29,5 +29,8 @@ + + + \ No newline at end of file From a80877f0e46e4b206bc6565022ce77692a8693cf Mon Sep 17 00:00:00 2001 From: Kenji Tanaka Date: Mon, 18 Mar 2024 15:17:09 -0500 Subject: [PATCH 5/8] :sparkles: feat(TIP Integration): Update TIP management module with encryption key field --- .../ccafs/marlo/action/superadmin/TIPManagementAction.java | 3 +++ .../WEB-INF/global/views/superadmin/tipManagement.ftl | 6 +++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/marlo-web/src/main/java/org/cgiar/ccafs/marlo/action/superadmin/TIPManagementAction.java b/marlo-web/src/main/java/org/cgiar/ccafs/marlo/action/superadmin/TIPManagementAction.java index 27cc831365..c14edbe2dd 100644 --- a/marlo-web/src/main/java/org/cgiar/ccafs/marlo/action/superadmin/TIPManagementAction.java +++ b/marlo-web/src/main/java/org/cgiar/ccafs/marlo/action/superadmin/TIPManagementAction.java @@ -82,6 +82,9 @@ public String save() { if (tipParameter.getPrivateKey() != null) { tipParameterSave.setPrivateKey(tipParameter.getPrivateKey()); } + if (tipParameter.getEncryptionKey() != null) { + tipParameterSave.setEncryptionKey(tipParameter.getEncryptionKey()); + } tipParameterManager.saveTipParameters(tipParameterSave); diff --git a/marlo-web/src/main/webapp/WEB-INF/global/views/superadmin/tipManagement.ftl b/marlo-web/src/main/webapp/WEB-INF/global/views/superadmin/tipManagement.ftl index 555f8de4c5..3c9f644b61 100644 --- a/marlo-web/src/main/webapp/WEB-INF/global/views/superadmin/tipManagement.ftl +++ b/marlo-web/src/main/webapp/WEB-INF/global/views/superadmin/tipManagement.ftl @@ -44,7 +44,7 @@
- [@customForm.input name="tipParameter.tipTokenService" i18nkey="tipParameter.tipTokenService" className="description limitWords-100" required=true /] + [@customForm.input name="tipParameter.tipTokenService" i18nkey="tipParameter.tipTokenService" className="description" required=true /]
@@ -55,6 +55,10 @@ [@customForm.input name="tipParameter.tipStatusService" i18nkey="tipParameter.tipStatusService" className="description limitWords-100" required=true /]
+
+ [@customForm.input name="tipParameter.encryptionKey" i18nkey="tipParameter.tipEncryptionKey" className="description" required=true /] +
+
[@customForm.input id="tipParameter.tokenValue" name="tipParameter.tokenValue" i18nkey="tipParameter.tokenValue" className="description limitWords-100" required=true /] [@s.text name="tipParameter.updateToken" /] From 45e49c757a40c6d847affdebe0b46b85ef68b6e4 Mon Sep 17 00:00:00 2001 From: Kenji Tanaka Date: Mon, 18 Mar 2024 16:14:24 -0500 Subject: [PATCH 6/8] :sparkles: feat(TIP integration): Implement encryption key parameters in TIP services --- .../cgiar/ccafs/marlo/utils/AESConvert.java | 26 +++++++++++++------ .../tip/TipDinamicUrlGenerationAction.java | 6 ++++- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/marlo-utils/src/main/java/org/cgiar/ccafs/marlo/utils/AESConvert.java b/marlo-utils/src/main/java/org/cgiar/ccafs/marlo/utils/AESConvert.java index bbdb89eef3..157d2bcd7c 100644 --- a/marlo-utils/src/main/java/org/cgiar/ccafs/marlo/utils/AESConvert.java +++ b/marlo-utils/src/main/java/org/cgiar/ccafs/marlo/utils/AESConvert.java @@ -32,16 +32,26 @@ public class AESConvert { private static Logger LOG = LoggerFactory.getLogger(AESConvert.class); - public static String stringToAES(String value) { + /** + * @param value String with text to encrypt + * @param encryptionKey String with AES encryption key + * @return String with the encrypt text + */ + public static String stringToAES(String value, String encryptionKey) { MessageDigest md; try { - // Generate a secret key - KeyGenerator keygen = KeyGenerator.getInstance("AES"); - keygen.init(256); // Use a 256-bit key (AES-256) - SecretKey secretKey = keygen.generateKey(); - - // Convert the secret key to byte array - byte[] secretKeyBytes = secretKey.getEncoded(); + byte[] secretKeyBytes; + if (encryptionKey != null && !encryptionKey.isEmpty()) { + secretKeyBytes = encryptionKey.getBytes(); + } else { + // Generate a secret key + KeyGenerator keygen = KeyGenerator.getInstance("AES"); + keygen.init(256); // Use a 256-bit key (AES-256) + SecretKey secretKey = keygen.generateKey(); + + // Convert the secret key to byte array + secretKeyBytes = secretKey.getEncoded(); + } // Convert the text to compress into bytes String originalText = "Sample text to compress and encrypt using AES"; diff --git a/marlo-web/src/main/java/org/cgiar/ccafs/marlo/action/json/tip/TipDinamicUrlGenerationAction.java b/marlo-web/src/main/java/org/cgiar/ccafs/marlo/action/json/tip/TipDinamicUrlGenerationAction.java index e2e4e1492a..032ae76347 100644 --- a/marlo-web/src/main/java/org/cgiar/ccafs/marlo/action/json/tip/TipDinamicUrlGenerationAction.java +++ b/marlo-web/src/main/java/org/cgiar/ccafs/marlo/action/json/tip/TipDinamicUrlGenerationAction.java @@ -70,7 +70,11 @@ public String createDinamicURL() { } } if (this.hasSpecificities(APConstants.TIP_SECURITY_ACTIVE)) { - tipURL = loginService + "/" + (AESConvert.stringToAES(token + "/staff/" + userEmail)); + String encryptionKey = null; + if (tipParameters != null && tipParameters.get(0).getEncryptionKey() != null) { + encryptionKey = tipParameters.get(0).getEncryptionKey(); + } + tipURL = loginService + "/" + (AESConvert.stringToAES(token + "/staff/" + userEmail, encryptionKey)); } else { tipURL = loginService + "/" + token + "/staff/" + userEmail; } From 2ff715d77042b7492634d2ac6a09d22daab79f9d Mon Sep 17 00:00:00 2001 From: Kenji Tanaka Date: Tue, 19 Mar 2024 14:08:52 -0500 Subject: [PATCH 7/8] :wrench: chore(Validators): Update clusters validators --- .../project/ValidateProjectSectionAction.java | 13 +- .../projects/ProjectInnovationValidator.java | 585 +++++++++--------- 2 files changed, 306 insertions(+), 292 deletions(-) diff --git a/marlo-web/src/main/java/org/cgiar/ccafs/marlo/action/json/project/ValidateProjectSectionAction.java b/marlo-web/src/main/java/org/cgiar/ccafs/marlo/action/json/project/ValidateProjectSectionAction.java index d68330d148..c1d3997dfc 100644 --- a/marlo-web/src/main/java/org/cgiar/ccafs/marlo/action/json/project/ValidateProjectSectionAction.java +++ b/marlo-web/src/main/java/org/cgiar/ccafs/marlo/action/json/project/ValidateProjectSectionAction.java @@ -290,7 +290,7 @@ public String execute() throws Exception { && project.getProjecInfoPhase(this.getActualPhase()) != null && project.getProjecInfoPhase(this.getActualPhase()).getAdministrative() != null && !project.getProjecInfoPhase(this.getActualPhase()).getAdministrative()) { - section.put("missingFields", section.get("missingFields") + "-" + "deliveralbes"); + section.put("missingFields", section.get("missingFields") + "-" + "deliverables"); } Phase phase = this.getActualPhase(); @@ -332,6 +332,11 @@ public String execute() throws Exception { } } + if (deliverable.getDeliverableInfo(phase).getStatus() != null && deliverable.getDeliverableInfo(phase) + .getStatus().intValue() == Integer.parseInt(ProjectStatusEnum.Cancelled.getStatusId())) { + sectionStatus.setMissingFields(""); + } + } if (sectionStatus.getMissingFields().length() > 0) { @@ -431,6 +436,12 @@ public String execute() throws Exception { sectionStatus = new SectionStatus(); sectionStatus.setMissingFields("No section"); } + + // + if (this.isAWPBActive()) { + sectionStatus.setMissingFields(""); + } + if (sectionStatus.getMissingFields().length() > 0) { section.put("missingFields", section.get("missingFields") + "-" + sectionStatus.getMissingFields()); } diff --git a/marlo-web/src/main/java/org/cgiar/ccafs/marlo/validation/projects/ProjectInnovationValidator.java b/marlo-web/src/main/java/org/cgiar/ccafs/marlo/validation/projects/ProjectInnovationValidator.java index 6c63d65585..49fd96fd29 100644 --- a/marlo-web/src/main/java/org/cgiar/ccafs/marlo/validation/projects/ProjectInnovationValidator.java +++ b/marlo-web/src/main/java/org/cgiar/ccafs/marlo/validation/projects/ProjectInnovationValidator.java @@ -60,245 +60,255 @@ private Path getAutoSaveFilePath(ProjectInnovation innovation, long crpID, BaseA public void validate(BaseAction action, Project project, ProjectInnovation projectInnovation, Boolean clearLead, boolean saving, boolean struts, int year, boolean upkeep) { + if (!action.isAWPBActive()) { - // The validator is called by Struts - if (struts) { - action.setInvalidFields(new HashMap<>()); - baseAction = action; - } + // The validator is called by Struts + if (struts) { + action.setInvalidFields(new HashMap<>()); + baseAction = action; + } - if (!saving) { - Path path = this.getAutoSaveFilePath(projectInnovation, action.getCrpID(), action); - if (path.toFile().exists()) { - // Draft label cause that the section appears like there were missing fields - // this.addMissingField("draft"); + if (!saving) { + Path path = this.getAutoSaveFilePath(projectInnovation, action.getCrpID(), action); + if (path.toFile().exists()) { + // Draft label cause that the section appears like there were missing fields + // this.addMissingField("draft"); + } } - } - // this.clearLead = clearLead; + // this.clearLead = clearLead; - // this.validateProjectInnovation(baseAction, innovation, struts); + // this.validateProjectInnovation(baseAction, innovation, struts); - // Validate Title - if (!(this.isValidString(projectInnovation.getProjectInnovationInfo(baseAction.getActualPhase()).getTitle()) - && this.wordCount(projectInnovation.getProjectInnovationInfo(action.getActualPhase()).getTitle()) <= 30)) { - if (struts) { - action.addMessage(action.getText("projectInnovations.title")); - action.addMissingField("projectInnovations.title"); - action.getInvalidFields().put("input-innovation.projectInnovationInfo.title", InvalidFieldsMessages.EMPTYFIELD); + // Validate Title + if (!(this.isValidString(projectInnovation.getProjectInnovationInfo(baseAction.getActualPhase()).getTitle()) + && this.wordCount(projectInnovation.getProjectInnovationInfo(action.getActualPhase()).getTitle()) <= 30)) { + if (struts) { + action.addMessage(action.getText("projectInnovations.title")); + action.addMissingField("projectInnovations.title"); + action.getInvalidFields().put("input-innovation.projectInnovationInfo.title", + InvalidFieldsMessages.EMPTYFIELD); + } } - } - // Validate Narrative - if (!(this.wordCount(projectInnovation.getProjectInnovationInfo(action.getActualPhase()).getNarrative()) <= 75)) { - if (struts) { - action.addMessage(action.getText("projectInnovations.narrative")); - action.addMissingField("projectInnovations.narrative"); - action.getInvalidFields().put("input-innovation.projectPolicyInfo.narrativeEvidence", - InvalidFieldsMessages.EMPTYFIELD); + // Validate Narrative + if (!(this.wordCount(projectInnovation.getProjectInnovationInfo(action.getActualPhase()).getNarrative()) <= 75)) { + if (struts) { + action.addMessage(action.getText("projectInnovations.narrative")); + action.addMissingField("projectInnovations.narrative"); + action.getInvalidFields().put("input-innovation.projectPolicyInfo.narrativeEvidence", + InvalidFieldsMessages.EMPTYFIELD); + } } - } - - // validate Milestones - /* - * if (projectInnovation.getProjectInnovationInfo(baseAction.getActualPhase()) != null - * && (projectInnovation.getProjectInnovationInfo().getHasMilestones() != null - * && projectInnovation.getProjectInnovationInfo().getHasMilestones() == true - * && (projectInnovation.getProjectOutcomes() == null || projectInnovation.getProjectOutcomes().isEmpty())) - * || projectInnovation.getProjectInnovationInfo().getHasMilestones() == null) { - * action.addMessage(action.getText("projectOutcomes")); - * action.addMissingField("innovation.projectOutcomes"); - * action.getInvalidFields().put("list-innovation.projectOutcomes", - * action.getText(InvalidFieldsMessages.EMPTYLIST, new String[] {"projectOutcomes"})); - * } - */ - // validate crp outcomes - if (projectInnovation.getProjectInnovationInfo(baseAction.getActualPhase()) != null - && (projectInnovation.getProjectInnovationInfo().getHasMilestones() != null - && projectInnovation.getProjectInnovationInfo().getHasMilestones() == true - && (projectInnovation.getCrpOutcomes() == null || projectInnovation.getCrpOutcomes().isEmpty())) - || projectInnovation.getProjectInnovationInfo().getHasMilestones() == null) { - action.addMessage(action.getText("crpOutcomes")); - action.addMissingField("innovation.crpOutcomes"); - action.getInvalidFields().put("list-innovation.crpOutcomes", - action.getText(InvalidFieldsMessages.EMPTYLIST, new String[] {"crpOutcomes"})); - } - - if (projectInnovation.getProjectInnovationInfo(baseAction.getActualPhase()) != null - && (projectInnovation.getProjectInnovationInfo().getHasMilestones() == null)) { - action.addMessage(action.getText("projectOutcomes")); - action.addMissingField("innovation.projectOutcomes"); - action.getInvalidFields().put("list-innovation.projectOutcomes", - action.getText(InvalidFieldsMessages.EMPTYLIST, new String[] {"projectOutcomes"})); - } else { - // Validate primary milestones + // validate Milestones /* - * if (projectInnovation.getMilestones() != null + * if (projectInnovation.getProjectInnovationInfo(baseAction.getActualPhase()) != null * && (projectInnovation.getProjectInnovationInfo().getHasMilestones() != null * && projectInnovation.getProjectInnovationInfo().getHasMilestones() == true - * && !projectInnovation.getMilestones().isEmpty())) { - * int count = 0; - * for (ProjectInnovationMilestone innovationMilestone : projectInnovation.getMilestones()) { - * if (innovationMilestone.getPrimary() != null && innovationMilestone.getPrimary()) { - * count++; - * } - * } - * if (count == 0) { - * action.addMessage(action.getText("milestones")); - * action.addMissingField("innovation.milestones"); - * action.getInvalidFields().put("list-innovation.milestones", - * action.getText(InvalidFieldsMessages.EMPTYLIST, new String[] {"milestones"})); - * } + * && (projectInnovation.getProjectOutcomes() == null || projectInnovation.getProjectOutcomes().isEmpty())) + * || projectInnovation.getProjectInnovationInfo().getHasMilestones() == null) { + * action.addMessage(action.getText("projectOutcomes")); + * action.addMissingField("innovation.projectOutcomes"); + * action.getInvalidFields().put("list-innovation.projectOutcomes", + * action.getText(InvalidFieldsMessages.EMPTYLIST, new String[] {"projectOutcomes"})); * } */ - } + // validate crp outcomes + if (projectInnovation.getProjectInnovationInfo(baseAction.getActualPhase()) != null + && (projectInnovation.getProjectInnovationInfo().getHasMilestones() != null + && projectInnovation.getProjectInnovationInfo().getHasMilestones() == true + && (projectInnovation.getCrpOutcomes() == null || projectInnovation.getCrpOutcomes().isEmpty())) + || projectInnovation.getProjectInnovationInfo().getHasMilestones() == null) { + action.addMessage(action.getText("crpOutcomes")); + action.addMissingField("innovation.crpOutcomes"); + action.getInvalidFields().put("list-innovation.crpOutcomes", + action.getText(InvalidFieldsMessages.EMPTYLIST, new String[] {"crpOutcomes"})); + } - // Validate SubIdos - if (!action.isAiccra()) { - if (projectInnovation.getSubIdos() == null || projectInnovation.getSubIdos().isEmpty()) { - action.addMessage(action.getText("subIdos")); - action.addMissingField("innovation.subIdos"); - action.getInvalidFields().put("list-innovation.subIdos", - action.getText(InvalidFieldsMessages.EMPTYLIST, new String[] {"subIdos"})); + if (projectInnovation.getProjectInnovationInfo(baseAction.getActualPhase()) != null + && (projectInnovation.getProjectInnovationInfo().getHasMilestones() == null)) { + action.addMessage(action.getText("projectOutcomes")); + action.addMissingField("innovation.projectOutcomes"); + action.getInvalidFields().put("list-innovation.projectOutcomes", + action.getText(InvalidFieldsMessages.EMPTYLIST, new String[] {"projectOutcomes"})); } else { - // Validate primary Sub-IDOS - int count = 0; - for (ProjectInnovationSubIdo subido : projectInnovation.getSubIdos()) { - if (subido.getPrimary() != null && subido.getPrimary() == true) { - count++; - } - } - if (count == 0) { + + // Validate primary milestones + /* + * if (projectInnovation.getMilestones() != null + * && (projectInnovation.getProjectInnovationInfo().getHasMilestones() != null + * && projectInnovation.getProjectInnovationInfo().getHasMilestones() == true + * && !projectInnovation.getMilestones().isEmpty())) { + * int count = 0; + * for (ProjectInnovationMilestone innovationMilestone : projectInnovation.getMilestones()) { + * if (innovationMilestone.getPrimary() != null && innovationMilestone.getPrimary()) { + * count++; + * } + * } + * if (count == 0) { + * action.addMessage(action.getText("milestones")); + * action.addMissingField("innovation.milestones"); + * action.getInvalidFields().put("list-innovation.milestones", + * action.getText(InvalidFieldsMessages.EMPTYLIST, new String[] {"milestones"})); + * } + * } + */ + } + + // Validate SubIdos + if (!action.isAiccra()) { + if (projectInnovation.getSubIdos() == null || projectInnovation.getSubIdos().isEmpty()) { action.addMessage(action.getText("subIdos")); action.addMissingField("innovation.subIdos"); action.getInvalidFields().put("list-innovation.subIdos", action.getText(InvalidFieldsMessages.EMPTYLIST, new String[] {"subIdos"})); + } else { + // Validate primary Sub-IDOS + int count = 0; + for (ProjectInnovationSubIdo subido : projectInnovation.getSubIdos()) { + if (subido.getPrimary() != null && subido.getPrimary() == true) { + count++; + } + } + if (count == 0) { + action.addMessage(action.getText("subIdos")); + action.addMissingField("innovation.subIdos"); + action.getInvalidFields().put("list-innovation.subIdos", + action.getText(InvalidFieldsMessages.EMPTYLIST, new String[] {"subIdos"})); + } } } - } - // Validate Stage of Innovation - if (projectInnovation.getProjectInnovationInfo(baseAction.getActualPhase()).getRepIndStageInnovation() != null) { - if (projectInnovation.getProjectInnovationInfo(baseAction.getActualPhase()).getRepIndStageInnovation() - .getId() == null - || projectInnovation.getProjectInnovationInfo(baseAction.getActualPhase()).getRepIndStageInnovation() - .getId() == -1) { - if (struts) { - action.addMessage(action.getText("projectInnovations.stage")); - action.addMissingField("projectInnovations.stage"); - action.getInvalidFields().put("input-innovation.projectInnovationInfo.repIndStageInnovation.id", - InvalidFieldsMessages.EMPTYFIELD); - } - } else { - // Validate if Stage is = 4 and review if the innovation has an Organization Types and Outcome Case Study + // Validate Stage of Innovation + if (projectInnovation.getProjectInnovationInfo(baseAction.getActualPhase()).getRepIndStageInnovation() != null) { if (projectInnovation.getProjectInnovationInfo(baseAction.getActualPhase()).getRepIndStageInnovation() - .getId() == 4) { - // Validate Organization Types - if (projectInnovation.getOrganizations() == null || projectInnovation.getOrganizations().isEmpty()) { - if (struts) { - action.addMessage(action.getText("projectInnovations.nextUserOrganizationalType")); - action.addMissingField("projectInnovations.nextUserOrganizationalType"); - action.getInvalidFields().put("list-innovation.organizations", - action.getText(InvalidFieldsMessages.EMPTYLIST, new String[] {"Organization Types"})); - } + .getId() == null + || projectInnovation.getProjectInnovationInfo(baseAction.getActualPhase()).getRepIndStageInnovation() + .getId() == -1) { + if (struts) { + action.addMessage(action.getText("projectInnovations.stage")); + action.addMissingField("projectInnovations.stage"); + action.getInvalidFields().put("input-innovation.projectInnovationInfo.repIndStageInnovation.id", + InvalidFieldsMessages.EMPTYFIELD); } + } else { + // Validate if Stage is = 4 and review if the innovation has an Organization Types and Outcome Case Study + if (projectInnovation.getProjectInnovationInfo(baseAction.getActualPhase()).getRepIndStageInnovation() + .getId() == 4) { + // Validate Organization Types + if (projectInnovation.getOrganizations() == null || projectInnovation.getOrganizations().isEmpty()) { + if (struts) { + action.addMessage(action.getText("projectInnovations.nextUserOrganizationalType")); + action.addMissingField("projectInnovations.nextUserOrganizationalType"); + action.getInvalidFields().put("list-innovation.organizations", + action.getText(InvalidFieldsMessages.EMPTYLIST, new String[] {"Organization Types"})); + } + } - // Validate Outcome Case Study - if (projectInnovation.getProjectInnovationInfo(baseAction.getActualPhase()) - .getProjectExpectedStudy() != null) { - if (projectInnovation.getProjectInnovationInfo(baseAction.getActualPhase()).getProjectExpectedStudy() - .getId() == null - || projectInnovation.getProjectInnovationInfo(baseAction.getActualPhase()).getProjectExpectedStudy() - .getId() == -1) { + // Validate Outcome Case Study + if (projectInnovation.getProjectInnovationInfo(baseAction.getActualPhase()) + .getProjectExpectedStudy() != null) { + if (projectInnovation.getProjectInnovationInfo(baseAction.getActualPhase()).getProjectExpectedStudy() + .getId() == null + || projectInnovation.getProjectInnovationInfo(baseAction.getActualPhase()).getProjectExpectedStudy() + .getId() == -1) { + if (struts) { + action.addMessage(action.getText("projectInnovations.outcomeCaseStudy")); + action.addMissingField("projectInnovations.outcomeCaseStudy"); + action.getInvalidFields().put("input-innovation.projectInnovationInfo.projectExpectedStudy.id", + InvalidFieldsMessages.EMPTYFIELD); + } + } + } + } else { + // Validate Evidence Link (URL) + if (!this.isValidString( + projectInnovation.getProjectInnovationInfo(baseAction.getActualPhase()).getEvidenceLink())) { if (struts) { - action.addMessage(action.getText("projectInnovations.outcomeCaseStudy")); - action.addMissingField("projectInnovations.outcomeCaseStudy"); - action.getInvalidFields().put("input-innovation.projectInnovationInfo.projectExpectedStudy.id", + action.addMessage(action.getText("projectInnovations.evidenceLink")); + action.addMissingField("projectInnovations.evidenceLink"); + action.getInvalidFields().put("input-innovation.projectInnovationInfo.evidenceLink", InvalidFieldsMessages.EMPTYFIELD); } } } - } else { - // Validate Evidence Link (URL) - if (!this - .isValidString(projectInnovation.getProjectInnovationInfo(baseAction.getActualPhase()).getEvidenceLink())) { - if (struts) { - action.addMessage(action.getText("projectInnovations.evidenceLink")); - action.addMissingField("projectInnovations.evidenceLink"); - action.getInvalidFields().put("input-innovation.projectInnovationInfo.evidenceLink", - InvalidFieldsMessages.EMPTYFIELD); - } - } + } + } else { + if (struts) { + action.addMessage(action.getText("projectInnovations.stage")); + action.addMissingField("projectInnovations.stage"); + action.getInvalidFields().put("input-innovation.projectInnovationInfo.repIndStageInnovation.id", + InvalidFieldsMessages.EMPTYFIELD); } } - } else { - if (struts) { - action.addMessage(action.getText("projectInnovations.stage")); - action.addMissingField("projectInnovations.stage"); - action.getInvalidFields().put("input-innovation.projectInnovationInfo.repIndStageInnovation.id", - InvalidFieldsMessages.EMPTYFIELD); - } - } - // Validate Geographic Scope - boolean haveRegions = false; - boolean haveCountries = false; - - if (projectInnovation.getGeographicScopes() == null || projectInnovation.getGeographicScopes().isEmpty()) { - if (struts) { - action.addMessage(action.getText("projectInnovations.geographicScope")); - action.getInvalidFields().put("list-innovation.geographicScopes", - action.getText(InvalidFieldsMessages.EMPTYLIST, new String[] {"geographicScopes"})); - action.addMissingField("projectInnovations.geographicScope"); - } + // Validate Geographic Scope + boolean haveRegions = false; + boolean haveCountries = false; - } else { - for (ProjectInnovationGeographicScope innovationGeographicScope : projectInnovation.getGeographicScopes()) { - if (innovationGeographicScope.getRepIndGeographicScope().getId() == 2) { - haveRegions = true; + if (projectInnovation.getGeographicScopes() == null || projectInnovation.getGeographicScopes().isEmpty()) { + if (struts) { + action.addMessage(action.getText("projectInnovations.geographicScope")); + action.getInvalidFields().put("list-innovation.geographicScopes", + action.getText(InvalidFieldsMessages.EMPTYLIST, new String[] {"geographicScopes"})); + action.addMissingField("projectInnovations.geographicScope"); } - if (innovationGeographicScope.getRepIndGeographicScope().getId() != 1 - && innovationGeographicScope.getRepIndGeographicScope().getId() != 2) { - haveCountries = true; + + } else { + for (ProjectInnovationGeographicScope innovationGeographicScope : projectInnovation.getGeographicScopes()) { + if (innovationGeographicScope.getRepIndGeographicScope().getId() == 2) { + haveRegions = true; + } + if (innovationGeographicScope.getRepIndGeographicScope().getId() != 1 + && innovationGeographicScope.getRepIndGeographicScope().getId() != 2) { + haveCountries = true; + } } } - } - if (haveRegions) { - // Validate Regions - if (projectInnovation.getRegions() == null) { - if (struts) { - action.addMessage(action.getText("projectInnovations.region")); - action.addMissingField("projectInnovations.region"); - action.getInvalidFields().put("list-innovation.regions", - action.getText(InvalidFieldsMessages.EMPTYLIST, new String[] {"regions"})); + if (haveRegions) { + // Validate Regions + if (projectInnovation.getRegions() == null) { + if (struts) { + action.addMessage(action.getText("projectInnovations.region")); + action.addMissingField("projectInnovations.region"); + action.getInvalidFields().put("list-innovation.regions", + action.getText(InvalidFieldsMessages.EMPTYLIST, new String[] {"regions"})); + } } } - } - if (haveCountries) { - // Validate Countries - if (projectInnovation.getCountriesIds() == null || projectInnovation.getCountriesIds().isEmpty()) { - if (struts) { - action.addMessage(action.getText("innovation.countries")); - action.addMissingField("innovation.countries"); - action.getInvalidFields().put("input-innovation.countriesIds", - action.getText(InvalidFieldsMessages.EMPTYLIST, new String[] {"countries"})); - } + if (haveCountries) { + // Validate Countries + if (projectInnovation.getCountriesIds() == null || projectInnovation.getCountriesIds().isEmpty()) { + if (struts) { + action.addMessage(action.getText("innovation.countries")); + action.addMissingField("innovation.countries"); + action.getInvalidFields().put("input-innovation.countriesIds", + action.getText(InvalidFieldsMessages.EMPTYLIST, new String[] {"countries"})); + } + } } - } - // Validate Innovation Type - if (projectInnovation.getProjectInnovationInfo(baseAction.getActualPhase()).getRepIndInnovationType() != null) { - if (projectInnovation.getProjectInnovationInfo(baseAction.getActualPhase()).getRepIndInnovationType() - .getId() == null - || projectInnovation.getProjectInnovationInfo(baseAction.getActualPhase()).getRepIndInnovationType() - .getId() == -1) { + // Validate Innovation Type + if (projectInnovation.getProjectInnovationInfo(baseAction.getActualPhase()).getRepIndInnovationType() != null) { + if (projectInnovation.getProjectInnovationInfo(baseAction.getActualPhase()).getRepIndInnovationType() + .getId() == null + || projectInnovation.getProjectInnovationInfo(baseAction.getActualPhase()).getRepIndInnovationType() + .getId() == -1) { + if (struts) { + action.addMessage(action.getText("projectInnovations.innovationType")); + action.addMissingField("projectInnovations.innovationType"); + action.getInvalidFields().put("input-innovation.projectInnovationInfo.repIndInnovationType.id", + InvalidFieldsMessages.EMPTYFIELD); + } + } + } else { if (struts) { action.addMessage(action.getText("projectInnovations.innovationType")); action.addMissingField("projectInnovations.innovationType"); @@ -306,128 +316,121 @@ public void validate(BaseAction action, Project project, ProjectInnovation proje InvalidFieldsMessages.EMPTYFIELD); } } - } else { - if (struts) { - action.addMessage(action.getText("projectInnovations.innovationType")); - action.addMissingField("projectInnovations.innovationType"); - action.getInvalidFields().put("input-innovation.projectInnovationInfo.repIndInnovationType.id", - InvalidFieldsMessages.EMPTYFIELD); + + // Other Innovation Type Field + if (projectInnovation.getProjectInnovationInfo(baseAction.getActualPhase()).getRepIndInnovationType() != null) { + if (projectInnovation.getProjectInnovationInfo(baseAction.getActualPhase()).getRepIndInnovationType() + .getId() != null + && projectInnovation.getProjectInnovationInfo(baseAction.getActualPhase()).getRepIndInnovationType() + .getId() == 6 + && (projectInnovation.getProjectInnovationInfo(baseAction.getActualPhase()).getOtherInnovationType() == null + || projectInnovation.getProjectInnovationInfo(baseAction.getActualPhase()).getOtherInnovationType() + .isEmpty())) { + if (struts) { + action.addMessage(action.getText("projectInnovations.otherInnovation")); + action.addMissingField("projectInnovations.otherInnovation"); + action.getInvalidFields().put("input-innovation.projectInnovationInfo.otherInnovationType", + InvalidFieldsMessages.EMPTYFIELD); + } + } } - } - // Other Innovation Type Field - if (projectInnovation.getProjectInnovationInfo(baseAction.getActualPhase()).getRepIndInnovationType() != null) { - if (projectInnovation.getProjectInnovationInfo(baseAction.getActualPhase()).getRepIndInnovationType() - .getId() != null - && projectInnovation.getProjectInnovationInfo(baseAction.getActualPhase()).getRepIndInnovationType() - .getId() == 6 - && (projectInnovation.getProjectInnovationInfo(baseAction.getActualPhase()).getOtherInnovationType() == null - || projectInnovation.getProjectInnovationInfo(baseAction.getActualPhase()).getOtherInnovationType() - .isEmpty())) { + // Validate Description Stage + if (!(this + .isValidString(projectInnovation.getProjectInnovationInfo(baseAction.getActualPhase()).getDescriptionStage()) + && this.wordCount( + projectInnovation.getProjectInnovationInfo(action.getActualPhase()).getDescriptionStage()) <= 50)) { if (struts) { - action.addMessage(action.getText("projectInnovations.otherInnovation")); - action.addMissingField("projectInnovations.otherInnovation"); - action.getInvalidFields().put("input-innovation.projectInnovationInfo.otherInnovationType", + action.addMessage(action.getText("projectInnovations.stageDescription")); + action.addMissingField("projectInnovations.stageDescription"); + action.getInvalidFields().put("input-innovation.projectInnovationInfo.descriptionStage", InvalidFieldsMessages.EMPTYFIELD); } } - } - // Validate Description Stage - if (!(this - .isValidString(projectInnovation.getProjectInnovationInfo(baseAction.getActualPhase()).getDescriptionStage()) - && this - .wordCount(projectInnovation.getProjectInnovationInfo(action.getActualPhase()).getDescriptionStage()) <= 50)) { - if (struts) { - action.addMessage(action.getText("projectInnovations.stageDescription")); - action.addMissingField("projectInnovations.stageDescription"); - action.getInvalidFields().put("input-innovation.projectInnovationInfo.descriptionStage", - InvalidFieldsMessages.EMPTYFIELD); - } - } - - // Validate lead organization - // NOTE -> FOR SOME REASON "CLEAR LEAD" MEANS "NOT A CLEAR LEAD", SO WE HAVE TO REVERSE THE CONDITIONAL - if (clearLead == null || /* NO */clearLead == false) { - if (projectInnovation.getProjectInnovationInfo(baseAction.getActualPhase()).getLeadOrganization() == null - || projectInnovation.getProjectInnovationInfo(baseAction.getActualPhase()).getLeadOrganization() - .getId() == -1) { - if (struts) { - action.addMessage(action.getText("projectInnovations.leadOrganization")); - action.addMissingField("projectInnovations.leadOrganization"); - action.getInvalidFields().put("input-innovation.projectInnovationInfo.leadOrganization.id", - InvalidFieldsMessages.EMPTYFIELD); + // Validate lead organization + // NOTE -> FOR SOME REASON "CLEAR LEAD" MEANS "NOT A CLEAR LEAD", SO WE HAVE TO REVERSE THE CONDITIONAL + if (clearLead == null || /* NO */clearLead == false) { + if (projectInnovation.getProjectInnovationInfo(baseAction.getActualPhase()).getLeadOrganization() == null + || projectInnovation.getProjectInnovationInfo(baseAction.getActualPhase()).getLeadOrganization() + .getId() == -1) { + if (struts) { + action.addMessage(action.getText("projectInnovations.leadOrganization")); + action.addMissingField("projectInnovations.leadOrganization"); + action.getInvalidFields().put("input-innovation.projectInnovationInfo.leadOrganization.id", + InvalidFieldsMessages.EMPTYFIELD); + } } } - } - // Validate contributing organizations - // NOTE -> FOR SOME REASON "CLEAR LEAD" MEANS "NOT A CLEAR LEAD", SO WE HAVE TO REVERSE THE CONDITIONAL - if (clearLead != null && /* NO */clearLead == true) { - if (projectInnovation.getContributingOrganizations() == null - || projectInnovation.getContributingOrganizations().size() < 2 - || projectInnovation.getContributingOrganizations().size() > 5) { - if (struts) { - action.addMessage(action.getText(action.getText("projectInnovations.contributingOrganizations"))); - action.addMissingField("innovation.contributingOrganizations"); - action.getInvalidFields().put("list-innovation.contributingOrganizations", - action.getText(InvalidFieldsMessages.EMPTYLIST, new String[] {"Contributing organizations"})); + // Validate contributing organizations + // NOTE -> FOR SOME REASON "CLEAR LEAD" MEANS "NOT A CLEAR LEAD", SO WE HAVE TO REVERSE THE CONDITIONAL + if (clearLead != null && /* NO */clearLead == true) { + if (projectInnovation.getContributingOrganizations() == null + || projectInnovation.getContributingOrganizations().size() < 2 + || projectInnovation.getContributingOrganizations().size() > 5) { + if (struts) { + action.addMessage(action.getText(action.getText("projectInnovations.contributingOrganizations"))); + action.addMissingField("innovation.contributingOrganizations"); + action.getInvalidFields().put("list-innovation.contributingOrganizations", + action.getText(InvalidFieldsMessages.EMPTYLIST, new String[] {"Contributing organizations"})); + } + } + } else { + if (projectInnovation.getContributingOrganizations() != null + && projectInnovation.getContributingOrganizations().size() > 5) { + if (struts) { + action.addMessage(action.getText(action.getText("innovation.contributingOrganizations"))); + action.addMissingField("innovation.contributingOrganizations"); + action.getInvalidFields().put("list-innovation.contributingOrganizations", + action.getText(InvalidFieldsMessages.EMPTYLIST, new String[] {"Contributing organizations"})); + } } } - } else { - if (projectInnovation.getContributingOrganizations() != null - && projectInnovation.getContributingOrganizations().size() > 5) { + + // Validate adaptative research narrative + if (!(this.wordCount( + projectInnovation.getProjectInnovationInfo(action.getActualPhase()).getAdaptativeResearchNarrative()) <= 800)) { if (struts) { - action.addMessage(action.getText(action.getText("innovation.contributingOrganizations"))); - action.addMissingField("innovation.contributingOrganizations"); - action.getInvalidFields().put("list-innovation.contributingOrganizations", - action.getText(InvalidFieldsMessages.EMPTYLIST, new String[] {"Contributing organizations"})); + action.addMessage(action.getText("projectInnovations.adaptativeResearchNarrative")); + action.addMissingField("projectInnovations.adaptativeResearchNarrative"); + action.getInvalidFields().put("input-innovation.projectInnovationInfo.novelOrAdaptative", + InvalidFieldsMessages.EMPTYFIELD); } } - } - // Validate adaptative research narrative - if (!(this.wordCount( - projectInnovation.getProjectInnovationInfo(action.getActualPhase()).getAdaptativeResearchNarrative()) <= 800)) { - if (struts) { - action.addMessage(action.getText("projectInnovations.adaptativeResearchNarrative")); - action.addMissingField("projectInnovations.adaptativeResearchNarrative"); - action.getInvalidFields().put("input-innovation.projectInnovationInfo.novelOrAdaptative", - InvalidFieldsMessages.EMPTYFIELD); + // Validate Innovation Centers + if (projectInnovation.getCenters() == null || projectInnovation.getCenters().isEmpty()) { + action.addMessage(action.getText("projectInnovations.contributingCenters")); + action.addMissingField("innovation.centers"); + action.getInvalidFields().put("list-innovation.centers", + action.getText(InvalidFieldsMessages.EMPTYLIST, new String[] {"centers"})); } - } - // Validate Innovation Centers - if (projectInnovation.getCenters() == null || projectInnovation.getCenters().isEmpty()) { - action.addMessage(action.getText("projectInnovations.contributingCenters")); - action.addMissingField("innovation.centers"); - action.getInvalidFields().put("list-innovation.centers", - action.getText(InvalidFieldsMessages.EMPTYLIST, new String[] {"centers"})); - } - - // The validator is called by Struts - if (struts) { - if (!action.getFieldErrors().isEmpty()) { - action.addActionError(action.getText("saving.fields.required")); - } else if (action.getValidationMessage().length() > 0) { - action.addActionMessage( - " " + action.getText("saving.missingFields", new String[] {action.getValidationMessage().toString()})); + // The validator is called by Struts + if (struts) { + if (!action.getFieldErrors().isEmpty()) { + action.addActionError(action.getText("saving.fields.required")); + } else if (action.getValidationMessage().length() > 0) { + action.addActionMessage( + " " + action.getText("saving.missingFields", new String[] {action.getValidationMessage().toString()})); + } } + this.saveMissingFields(project, projectInnovation, action.getActualPhase().getDescription(), + action.getActualPhase().getYear(), action.getActualPhase().getUpkeep(), + ProjectSectionStatusEnum.INNOVATIONS.getStatus(), action); + /* + * if (action.getValidationMessage() == null || action.getValidationMessage().toString() == null + * || action.getValidationMessage().toString().isEmpty()) { + * this.saveMissingFields(project, projectInnovation, action.getActualPhase().getDescription(), year, upkeep, + * ProjectSectionStatusEnum.INNOVATIONS.getStatus(), ""); + * } else { + * this.saveMissingFields(project, projectInnovation, action.getActualPhase().getDescription(), year, upkeep, + * ProjectSectionStatusEnum.INNOVATIONS.getStatus(), action.getMissingFields().toString()); + * } + */ } - this.saveMissingFields(project, projectInnovation, action.getActualPhase().getDescription(), - action.getActualPhase().getYear(), action.getActualPhase().getUpkeep(), - ProjectSectionStatusEnum.INNOVATIONS.getStatus(), action); - /* - * if (action.getValidationMessage() == null || action.getValidationMessage().toString() == null - * || action.getValidationMessage().toString().isEmpty()) { - * this.saveMissingFields(project, projectInnovation, action.getActualPhase().getDescription(), year, upkeep, - * ProjectSectionStatusEnum.INNOVATIONS.getStatus(), ""); - * } else { - * this.saveMissingFields(project, projectInnovation, action.getActualPhase().getDescription(), year, upkeep, - * ProjectSectionStatusEnum.INNOVATIONS.getStatus(), action.getMissingFields().toString()); - * } - */ } /* From 41a7b7fab64d44e4f295071f6b69cb20b17d9361 Mon Sep 17 00:00:00 2001 From: Kenji Tanaka Date: Tue, 19 Mar 2024 14:53:03 -0500 Subject: [PATCH 8/8] :wrench: chore(Full cluster summary): Update full cluster summary information --- .../summaries/ReportingSummaryAction.java | 30 ++++++++++++------ .../crp/ProjectFullPDF(Reporting).prpt | Bin 263140 -> 263164 bytes 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/marlo-web/src/main/java/org/cgiar/ccafs/marlo/action/summaries/ReportingSummaryAction.java b/marlo-web/src/main/java/org/cgiar/ccafs/marlo/action/summaries/ReportingSummaryAction.java index 75e551d3f7..31c438a7b8 100644 --- a/marlo-web/src/main/java/org/cgiar/ccafs/marlo/action/summaries/ReportingSummaryAction.java +++ b/marlo-web/src/main/java/org/cgiar/ccafs/marlo/action/summaries/ReportingSummaryAction.java @@ -579,9 +579,11 @@ private MasterReport addi8nParameters(MasterReport masterReport) { masterReport.getParameterValues().put("i8nDeliverableNewExpectedYear", this.getText("deliverable.newExpectedYear")); masterReport.getParameterValues().put("i8nDeliverablesActivities", this.getText("project.activities.title")); masterReport.getParameterValues().put("i8nDeliverablesContributingSHFRM", - this.getText("deliverable.shfrmContribution.question.reporting")); + "Is this deliverable aligned with the Soil Health and Fertility Road Map (SHFRM) implementation?"); masterReport.getParameterValues().put("i8nDeliverablesContributingNarrative", - this.getText("deliverable.shfrmContribution.narrative.reporting")); + "How this deliverable is expecting to contribute to the SHFRM?"); + masterReport.getParameterValues().put("i8nDeliverablesContributingNarrativeReporting", + "How this deliverable is contributing to the SHFRM?"); masterReport.getParameterValues().put("i8nDeliverablesActions", "To which Priority(ies) action is contributing to:"); /* @@ -2725,7 +2727,7 @@ private TypedTableModel getDeliverablesReportingTableModel() { "intellectualAssetDateExpiry", "intellectualAssetAdditionalInformation", "intellectualAssetLinkPublished", "intellectualAssetCommunication", "otherPartner", "deliv_description", "activities", "geographicScope", "countries", "regions", "sharedClusters", "focusEvent", "likelyOutcomes", "isContributing", - "contributingNarrative", "shfrmActions"}, + "contributingNarrative", "shfrmActions", "contributingNarrativeReporting"}, new Class[] {Long.class, String.class, String.class, String.class, String.class, String.class, String.class, String.class, String.class, String.class, String.class, String.class, String.class, String.class, String.class, String.class, String.class, String.class, String.class, String.class, String.class, String.class, String.class, @@ -2738,7 +2740,7 @@ private TypedTableModel getDeliverablesReportingTableModel() { String.class, String.class, String.class, String.class, String.class, String.class, String.class, String.class, String.class, String.class, String.class, String.class, String.class, String.class, String.class, String.class, String.class, String.class, String.class, String.class, String.class, String.class, String.class, String.class, - String.class, String.class, String.class, String.class, String.class, String.class}, + String.class, String.class, String.class, String.class, String.class, String.class, String.class}, 0); SimpleDateFormat formatter = new SimpleDateFormat("MMM yyyy"); if (!project.getDeliverables().isEmpty()) { @@ -3660,7 +3662,7 @@ private TypedTableModel getDeliverablesReportingTableModel() { } } - String isContributing = "", contributingNarrative = "", shfrmActions = ""; + String isContributing = "", contributingNarrative = "", contributingNarrativeReporting = "", shfrmActions = ""; // SOIL Contribution if (deliverable.getDeliverableInfo() != null @@ -3676,12 +3678,18 @@ private TypedTableModel getDeliverablesReportingTableModel() { if (isContributing.equals("Yes")) { - if (deliverable.getDeliverableInfo().getShfrmContributionNarrativeAR() != null) { - contributingNarrative = deliverable.getDeliverableInfo().getShfrmContributionNarrativeAR(); + if (deliverable.getDeliverableInfo().getShfrmContributionNarrative() != null) { + contributingNarrative = deliverable.getDeliverableInfo().getShfrmContributionNarrative(); } else { contributingNarrative = ""; } + if (deliverable.getDeliverableInfo().getShfrmContributionNarrativeAR() != null) { + contributingNarrativeReporting = deliverable.getDeliverableInfo().getShfrmContributionNarrativeAR(); + } else { + contributingNarrativeReporting = ""; + } + List actions = new ArrayList<>(); List subActions = new ArrayList<>(); String actionsText = ""; @@ -3695,7 +3703,7 @@ private TypedTableModel getDeliverablesReportingTableModel() { if (action != null && action.getShfrmPriorityAction() != null && action.getShfrmPriorityAction().getId() != null && action.getShfrmPriorityAction().getComposedName() != null) { - actionsText += "
● " + action.getShfrmPriorityAction().getComposedName(); + actionsText += "
" + action.getShfrmPriorityAction().getComposedName(); subActions = deliverableShfrmSubActionManager.findByPriorityActionAndPhase(action.getId(), this.getSelectedPhase().getId()); @@ -3718,6 +3726,7 @@ private TypedTableModel getDeliverablesReportingTableModel() { } else { contributingNarrative = ""; shfrmActions = ""; + contributingNarrativeReporting = ""; } model.addRow(new Object[] {deliverable.getId(), deliverable.getDeliverableInfo().getTitle(), delivType, @@ -3737,7 +3746,8 @@ private TypedTableModel getDeliverablesReportingTableModel() { intellectualAssetPvpBreederCrop, intellectualAssetDateFilling, intellectualAssetDateRegistration, intellectualAssetDateExpiry, intellectualAssetAdditionalInformation, intellectualAssetLinkPublished, intellectualAssetCommunication, otherPartner, delivDescription, activities, geographicScope, countries, - regions, sharedClusters, focusEvent, likelyOutcomes, isContributing, contributingNarrative, shfrmActions}); + regions, sharedClusters, focusEvent, likelyOutcomes, isContributing, contributingNarrative, shfrmActions, + contributingNarrativeReporting}); } } return model; @@ -4700,7 +4710,7 @@ private TypedTableModel getDeliverablesTableModel() { if (action != null && action.getShfrmPriorityAction() != null && action.getShfrmPriorityAction().getId() != null && action.getShfrmPriorityAction().getComposedName() != null) { - actionsText += "
● " + action.getShfrmPriorityAction().getComposedName(); + actionsText += "
" + action.getShfrmPriorityAction().getComposedName(); subActions = deliverableShfrmSubActionManager.findByPriorityActionAndPhase(action.getId(), this.getSelectedPhase().getId()); diff --git a/marlo-web/src/main/resources/pentaho/crp/ProjectFullPDF(Reporting).prpt b/marlo-web/src/main/resources/pentaho/crp/ProjectFullPDF(Reporting).prpt index 09d70313a00367524baae4bce94216b60480ee00..f7d50d3e1e0b191987e2cc00406d8f6884efd226 100644 GIT binary patch delta 16630 zcmZuY2RxPU_xIkH>=7~|Gb@|yJ=*q2A+jr(A^X~7m+>ZLG$^t%E+HgI_R5Gt*?TAJ z|K9hiFa7@a^TG3;bDp!G^E~%Fub*L*+hLSs+Lr)4Vg!N^f%tLf&V4d<0QysCQUsu( zzgG|kJ`e@M-rCh%(8K}u!gCV1!P($>Z|KKuM#QsSz>mCi{wWoHA{_V=s0j=lAD<9XYrCT=-jGB!c}xGqCe(W>c^vSd#S^1l4S1h)BPq(o`hiT6yg4{%`a1F& zVbW2Hb6Ew>#+@W6Vy*|=Go>ZmU1%MX&AYE*Am&3gLh<=xQJHR`lc<$Wfe z!{@qU*Y$v+faJcw4JSGJ-l21b@5Cl0ul!JX%=Wg&_!V-9XTAze^RiY%K87456Pz;r z#iAIw&hB0RzGVJ{$Lc48!HAy%R|i{$S%U)S9rTHZWLHq^=|$4Do}*Tun)~h=qxo_o zA6o16%m%*6ZX9ApFtj#Y_w(PK>d#qSzEJD8e#h4|K-R+|Wg>3<{`$>wgcd7VP`F%F zx6kQOtAQJIgM&vKL+)BE?Yw4@5_DYNPzTZ*jHwx@e z$CPI^X$pVKS-jC~OQ`hBT3KpAXBqF{YhNNDA+up3w0 zvNGoLrv90oZWD9T#`Y6$V~5es8t04q0vO&16uueCQ;5pL{_4~3w!fUo+Zw*Iqz;T* zaJSmoeT#lqwcRzTqHb+xFR^eojU~(R9m~$*ZVIM^cv?fi&fYaVzcReqdb^@SB6wcN z&=9RDGo!Md*rchhZR~w>X#Dfb%RX7BmJBT<20j_|@GQ8wl}u|4eKPRs%2~a?P+eZ; z@s*bj%@!`Z^>{UC_1W2*E90B^bW=~hN3U+!jLbUfhKx&ut9@6lhf zmqgzZZVB$bcf6G)$apMllhVXzZSvRp5}+Uc9erg@SumAgM{&xxcXD9M(gW&3}J&j}j?wQHGQ`IiDA8f;ZTdt;kz4+p$3W61} z;rsG76W$tufKtO+8hrshSNzgy0A-DxPG3aIl{-Fk^Tah%>6LQ9@4h@H{S}=t1MsFN zJ->mzGGFYo>v%@KB=l@H*&0pwImGT5kFWcbqq@e((f3;3@q!7=w--jQGe7&1N{JxRntbK$ zJ~Z)k+8dLxSRP{5{L0gzCBNRVYtuz}tZ1Ro2R%?^*E+%E6gBnra=Cm++ljF|w$GNH zzw~w(dgb9z-*xZF+lgLZ8=v+O$_k~WJCW5&=%PxsztLTYmA~<3|%-{;Lvx3MCEv8%vA{@)ffz$18MA#*a2I zUW_d#M7Ltbh^R^ZLj_W6`yQH#FI6ydr)s9^Dye%-NQuPBah1+RcQgz=l4_T7aF==K zdxkM1;n=NT5}q|4ixymx0ljNpHx!k|(E1J>BWT;6Rg++CQZC=Gl1stG@f>7$QnOMeiu5n_&#G%mmF9n;Q_1X)9{DvWe!0ie^5;D}-B$0S-WGe$OF=zp zOIcTY6zxtmbF*am`pi=pFAeCTqjq0ki|*RZFw^l%-=5_m(pMa6J*TIh&ARrX^cu(M z_fDthf6fpcspE2@-yPUW?^P{%CdM_p6=k^`KO5^{hpIt%^!TMv3R7~mX1aKcQ0nCx zi=a)5CXYsaELrcob*GPu-hvoU#NqKvFBVTyrRTfdkrO(!GLoiT4OTg%Tii4OqeUD9 zlwrx$vCkL{kJ*vb(N|Jl`M6U%72%EN^fh(n6tlVKZPZltq+!eO7`17ICssP*iLEmr{W5A$MGXBzxpNQQ`ATD9OY7GYLe1# ztSt}5MuZhtiDj4TnfP3fY`gPr84<)fY@6Y{R^OK&-R=76n3AQ8qLAVxR(jSnub#<* zH1zEkzg3Kp40*Z59R4ac@1-7*YZeac92M40-CPq{ytE{kg~y(CWp05G_&K1tbk;aA zcq}#G=i+kgD~HL&8qbs%d>PDJ4pc%NhXYYSDU%3y6?o@W5!h%;Ik zT#H#jMws)ybL_)AHdA{2`#HJbatX8Ztg-q&PekzP>!(}Um&XTI))i&%m7m;{RM|q3`Db`I;RSI_X%?~q zai||=>C0M-CFY^zG_|q5RY#daMNv|M+a%*z$Jlne-zL?XY2#g5a%Rjcjm)*+ILdR6 z!a`Eh&G?$Ue$q~HZIOj4`Y0{3uI6I86PnRX+Fb>$qd>@AG5d}pF*@jK>PJt$Ol|@u z0xwN5Y7au+TwWi)k+5^A5fhiUb;_fI+s=0J;&txY_7q(7^jmUFm3bA|?X!A+dSxW+ zGdkF4HJ@+qfg1PjJe8dF5n;zT#a?$b@-y`*s2P ztlYf>Wh=pN#&u7SQ@?(e(@>b3*q6-Scyds_KCzdxL(di}L+bjK3~+3;EQsk6Ca-l3|16$|-Bkwnb6cAL_GlxE;3 za*OrP3_Cnp!Er1qwv5;2Y;8ay4tidQv9@a7vS`uYECh-awuot_ zxA#MeoO$G;1Ak^UAvxbgPP9koU5TX&O*d<~b!iOwStzT4)h&X;Nu^J)XYNL)h9MKH z-9se3@EK+e|9eX>y#nbvc)|^3vnjI3xrG-xTMpy&fGD zctfr3?LEtJQr_@Jb_ZtXvez-%^occ0WAEc;-=-yYQLW#NXfe3>{(VW#Y4(PBbaMe( zfUxm8FIU^>weNYsoG*z3SDsP7qUe1yd*d2$(u@ZlBPp#YZ} zP-AX_U)5!>nTq_HXg^*V=39g^sK>T#8at{dbR@+Ox>1?8O2)*!w{w+(pS`Bfra_ciQVV@; zySn>!1D+g}Jl$idD|XNQ)18XC+)imfdiwr6LX5&xu=PB`<&*`8dZ?UqDqhpRXG=Af zU$;gl{M^%*`I+9Rk0aWgN%0v7!p9_(q(RQ^*$nf1x6+KaR(@CNv*?hO_9*nI#aKSS z!!8tjCrdkc>7@jt&H0g4mbZkPVbA47&_7Khxmav|6!G~OeR4wGX&LXJe|B9kTcNs= z4gWTOWdGtRGCQuvA;(0j5E|DT)c`p>+IFEMctYKuS!+Ei0(|Q*PEkD% znTXAvFHzy$(z+fYom8_aux3@xdW1AI%ul@HT^2xba!({QWjg5fn}iQaOUjJ?(|OkC z)|96u-x?@$edQ5uLH13zMed=5nK}s_(FV}jGAg}|a3pl}Y=BNhKxHyq20XKFa|KU{}YDzO+|<>#Dq4de>cTKcFeq z*2B_O+6rH6(Z;TE)U?{tA4C-3Ul;}JR-b} zRp2zTR7Dm4`IS;-Re{Z$xffc)rDUejX=ZzAKRHz!MURsg{wf%vRB=y|Q)O{|DOb~f z+owIlHk?Au?@PN-G{SCDH7O(IZ0>7W*5P^|xH^Ge)yu?GIn`;m&a$HrKGTUrUh*H* zC=oS43tpory|6e1J>`=KH%df1Th^$sYhOH4FL-_a;Bw%LW? znFl};KqgKZB$XY}ThH)9u}w!_t%2-bwpHBT61sRO<3Shitw0-5*4x%OkGtbDHv+_i zmA0I6d}X3Piin!hVHim_B%6N(aV%cgfVSK+=CNu+&FImOXT`nqdC~5hU3%4&n9{r# z7#==<iL!HcB!cne|}<;LkK01!cA+H#~$0Va$bujT1+$ z&IsoPew!+&rZtn+SX;^7%TAq9sb{{%uyyJwdG$7C>W#av$A3OU>37vzq`)sEC2R} zYffE7M~WlIk)Z(vznv@{pPk=BJXN(z8(qR*Th}xF^tPI^N*S)5P*6#g;SO_pF(P#3 zWwg4t-iar{2G1(dk`cG$_|Pj)dvp?->Y%PjvTK$BWrv928Re*#?W+zcUaNqLJoIwQv zFs$i3N}T~79k)QSo`*;B*(d-vLp2B0kB^0c_eW62!Ouj%I84F*1|cg zMFuL80!%RJvm(@In98Xb6^P@rR)VS_gkfdxP@cG%(1;1tu0e6albod?KGk1P#9&%4 zKnkW=0|PL8-VHd8NvlN#<0jQKqfUZKeZT>6a!6=qTpj8y%wOXJiW*0{^%=zpMz5oY zF%RldHn0^K2CFI;mEYwP@1qF>20VU>>z0Z@&i22 zaR4}y7y}T3XnDCDwq+r`ufEZKNff~d6i@-n@TH!duj#KJGO~A;b`jDAw z{U}BpGQ$9}$!7oscWywe53o<Z=0|kGeaLWm67!LIM+d`>*BykSSM3b;5)2}5*cs~Cj;`O2&RG@Acxh!K#%uu2-sqmW59uw zbf*POa7Z{M7wCWkDOo-Zkb{Tf4#Fu3!5Kjo1^`!xuqzECbR1YZ0xJYR%CiAR2V@qr zACy_f0mL1U`I-}wvO~9@2=H2fK!vbTkhpz5ShgU^96*Zs!405@{u6}~IYiPd24%+I zw1PwMP83*z>9MJgfe37I(y<{2wZ(zcFcO>XAcUmE`j+so*?3?cDG&=&z=8Tpfr*m< zzM-%P43yKsxR665E)26Ga4^N_7NM+4SK6<4*g^mrF9I}}9A&`%fE#>N|Hlmw22bfzA=WGllD*CSgHJBdu?#wc9;&73{v|k2Z<49qS z$yWf{0|J^Y{|JDiP;~=xv6l6Iz+e}{phM{kVx0{_a7vIBg-4DlwgFNOxE(^!|F?i) z-$NkWhUR}0XvdLaJ&v)r1H^HU*xG@qz76ES#SbneAoNIzY1-Of)ELMENE|U-aY{g9hj8M_M`IK&C(h18$9QGqWV2|X6oE5uk5wOet$AGd`!CREHUG{r*BN5 zXXmY}?P|1KoGDzVh0zb6alNq-0Ql4GQTPJ_H=0iar8Fn{N;8YOVlt)+#yW2mmeSW! zGgeO*@LxT9^1OlaWxuBg%S$Oz51+UHR>+k$owUBu@w=%*L2R6s`y=76Zgn@KP}*1X zdR||4@so@~A6}}>%2F{-VYp)a^C3P)sVHK&GU-|sI=jJr4O53A87G;h~PdQi2?WU^QOK_{smtNDg z%?Jy5Ft#-3LSxTWVzUNbZtm|Py4G-O?)*0#( zys^6ldcT`Qc?0Nsf+fU~`)GfpD^+i29$&04PStn(fV465tmZMR?EtJ9_nAO5OVX`)FPiJNjp+(CXYM*8q^g(C|6a!sSduTfHh?#Uce?+^ zj02JJ7ML*U`kqFt4_%#1#F{JoMG-j^py=1V#5=apz@V`6YlkF&#OY!e*LmOQ%w+z6 zZRM~lma4N~=!Fz^f3W&Yi+$KR!*%6c61e7@vU3NmEy_Y(oZ(zDy=v=giW^O0yYtL3o zzn{!%z&3 zpR+_!oaNim#@*ZM;xBWo*7PVgC4KnXR0-KtCX>6(20{`%W&pIC7`DZoU|Cr|w#84382Q7(2*Ndah+YU5_+klO&Sp@tgYc3Gw>NOr~Ce zK~D_1&QPA7O^PHFF=IiE@i|X~d^Bjz(T}qnE*zsj5-{gD@x(P&bm$3{wRNccT3dWZpTvDAh-0pK5^0|_vs3B{g?1&X^uT)jr5@ODQb#io zm$`@Zn4DlG3PK`G=-f9Sg)<4;P}jm{PPI%7#Bm&|)s}nYzLh|8wM157XYt;|Y#& zAvEUdzMCndM;Nz6>z7NLiRpbW^55RvVLE%di}#bY$_>kM+DLT&1NLE()r&@P{yp?n z-!qqh*T9^j*}PH#7Z_at+L7Zl2PDi;kVaCy8Ri$Icsjojl8E*2r}0 zv#!SjYtaj*^gw=o&L<`}pK|I3uX6b#Fn$a<0ox^c zm#K0u1j^r+;F_R(5zT97d1Kl8w8)m-dD9yohQmIk#usyQ&NiZ}#5`GL>Pt9F#TfKL zyv0=6eOm$r$5LNb=&xjV%jq4v{Pb*|+- zxA4_l@8T(H8Ft3+HKMhI)OZbEzO8$OJq)wm7_b) zu$a$!74P&_XPqzpZK*;fm@vF`7Bk0%VAdq#aVmP^Znx_83_J^>4^-hf_@ibg813{# zqg|yLmB#q|H;?MEBsQQ4>@G%WCOR3`gaJsRh0_%&suPiIh6Ly|M;7wk&RLQ~SJk3I z{62=^Iz6GCCZ@i{FRZ*&XwKb>+qtx8p~-vRWOl;GZy<6=cW?IN$?dWDRJj#Q4HL?v zP?kS!PPS9u9(h2TTIGC(W_%Z%srXK=I(H)jRsNg#^)H4if|O@MGn|?d9IQQMb)T0T zjL6M(CZ7#GF`gukPBS7=X2<+35BCPwn`jz+nm_U)`Yw2c~BW6RuJv9qV7 zFKOlb5!f!3mDN)farSe&C=$@>3%QM&D@CrJY<{Dix+>clH-x|bX$P?I>DFW+p~V+QRA&RI@NRW!W%C!fI<$3(plh-#@oebr zqOyy^15~kvK2qrGZDX;=Fs3RrTtILY@$2L(Lu4zw$%+^c@?4>s_eUZbLjtvV;=m6; z`F3Obq~D#sk;9 z_j>J02_6F+_#8URrQwwVZyb^NErYaIYw4A%nxuu(ThZxUR~%l)1s4A_9y1&1$Y}~f|e__NJkx z1x=9=EEz7uVlTMpL}0J(FUU5_+M)L}ORbG*vi!ZKS>Y97_mHRJUgU#@(nQa;P|wo* zqghh#tLfd#q|#VPjUYihy(lzzQL35q(NiZ6{@!*f%t;5deGSPre&1?%V&)AlVJBAx zd5Q@I%K6VEKCj-)jttVin^Q?6{}rh|867aiC_wD)?`Qs%5-t0paf3^La)xr2_>Pj= zX#H62bx+;fywz1U6)p0u1!8fP)ZFzJMr9c2H%FDQ#*_1IgHktnIX8oj**{qM?eV&h zV2^E?s-=JfjlMd^--iF$?W}~$g_W&$&H2S|WG$>Q-&;-WWNxCl0(WYkj;Yts)wCj= z(*$G083j#B%`aZGDhPPcNqp~SX|YNt@ddt@w)_=2(0DnFr$xOfueA9{|tXw{Y_6G;^H&bq};&J>;HD!FT?e4cW&QzcW0An?Wa zpkv=&UDB}=&t8`4A@_;oOKXaMAL3i#QK*RF^Qu~$C{L;$Tgzd`Fk1|t`!1B_c>ir% zhgu$fzPf3&C5xrO-365-Z?=`8+E23Y-tjIy^V(h*OyOjH~uU&2~9zVrxF0S!*Y(NQ> zjn}mtd`}b|&uoyEfLEm8ixBI3Pc^phG0ACVF4)j< zroMBhd|Qlmj;3iC7jVtYiQ+$=R($Sdm!m9oaJUA@+?v28LAGF0Hgh8O(X)~3Ra}=p zG5Zy^$7jwbD<{;xxrRw_WaQ5wLajMc0>`d9EvPS=qL)9g@GK-rGM1aMre&*diy(b;~eTk>BjihzAjL_+6i#w zb{AT0)M&mN^P%)f-;Qol(w!msA0OClJnJZ`*&9UtTgz8|V^ZQb;-W6T2%x_bE1WiY z#W<-+dO8tZc8w?Yh}V}4naFh}JeLUF>Rs0h!3~{Un z8%@({nL0oC?S!z|D75uz5QM7SJ#+K@T7AnxN zdYh#6nfctrPEt7@qsrI5yP$0N(eOv2hBVDvc{@bbTH!&8&}sZ7cL@bSZb{z{zH9YYcS&JxWY|eq$ej8X-oIMCQy_GTW&O-}!JVkLT4#sy{kkO+V}ECU z*2%w_w{Qy0vUcKb_wJ3c2)8ZZdqDkk%+^Il8PoA0Yf!V(ROUj8G1|1R)KaG^5)XgR zx#{(rJ0Z+L0wx^-*EfosSl89kj<@m;ep(6RS=in?gpSZ*4~{pG){_-Wm^-1VM(&d+X4z-{ln?$Yb9- z?6Ll4a%V#G;-4(3yfCc5_hhx%Y}C^4waRp)pWQ%g_O}AJ{<7=}pSF~YZJRKTN?I?$ z;N?yK3hIE_TCeZFOw%&xCdxl0*=L(;bsZ6UdqvH#Pj$|bx~+LkrmQK8O3U%%3#V>7 z_p|d^_@OQ9&O-e0%NgIA4Np&9vXuBzP~_$3O=8-ah#oN2{<@)@RpDBtM&@uOxk5L& zDDi5T(%L)cA~LVXo9ydftM3Y|dDwf&9d}+W6N~eD{G#D*yTtw4r#p@>8dJPOjRa4J zSeRFoevVR~S(fT_VfKpGv2`(FB{!0JoNUUy`nI|^WTHHD<*Y=cP}~{ke0K`EYrq#dt`=i-i5*mZso5pLGT{nHlH1GB?F|(A5%E+N_t#2js#ms%x5M1mi6R)5A zQto-#d6;$PmwNSL0N>Z-)BHEsNqWa=AE)*jpRCuAGTP~1zFxZdUQzP}LuL>oS3wPm zN-kf(Ut_oT;Vo^$AqtLcK2~}?2ke(hE#6v79e1&D=rlPVaqfHDsK~9x;L3ETFK;N{ zldV7L3vD=wR@`_!=KkK4i~gl@Ec=n{2D|vwuOIL%?2%gIkBA+kwD@^eR(cuRtb%{X zi!?B(#C_X2f48l2|jQ8}50>x`fWEA4QlvuBTr{ zQb^m^@YZP@=f6NfG4XorEEjrveh+(-h1boNi=sv#GFXs@Z?fQK8U_^&*x(v+a4WGT z;Xt<*QxF5}U(mdZ{nN~bo3t<)`aVSax91PH4FACM;5IDOE%e9r?chcsgp4@QD8$lY z{F4v0X4f7a>`QN^0MZAVg<4Mz_QJEa|NmY%1ZM=%sr%hs*r?5INK#-L(2KkAz``)@ zFaNYq;U4YWs{?|;x*ez;jGqJO9gtr6`hVKN5D3=}cFF~=9&qC3E+lU`512gAfZr%N zB+mhJNZuYKFSP8>odnz({at?0TIh)!)Org%``aJIP*eb_{|Uu7RssS9Fc!A2yzY-Y z*agD%01u3WyTd0wL6K`k;{A88gX<1M@cr&^#z%l0#~h9~g!s2R41wSaKoIW2!vxxE z(A^(xBhZbTi48gkAxJ^!?t>U}q6wgYuRw8qVk`pNC)P%iAyLGLzwgU~Z`uGcSk=ik zK#350-GY7T8We5^1YxjwJ0JuP;@bgHc<`wm5QYa^e^3G)`^2Ul`?m>+9s4w&{-8Gh z3{G|Kqpo%COOEdZB*?Ln|GNeTdpq}~k#+%$$Wf4|3pl}!rCI5s7xaQ&lPM}F+f zXEh$qs(~0%L9fOiJHQx$UfywI=dyQd-6E=LdujzdI_#USe!D1rSxK=;P!LjWlp zx2V7~R|25_z@XIo*JrCGkZtDc0DN^1PJMyQ#k|ADZ3{&M4le+tu%>*y03%AQ1{CQB zXhBox4jqQtW1)BVq0rSS9SnVog$CEcw9r*49`*|6IE*3hgD{+Re=zhg&;$!~`wJw+ zUVhYL}m^S4+2~;nLKorihPNEK90To z$9er4G(fq31xE&;hR#*#u?A=bArZ)y$^)&+=X6vSKb5bwSJ=>JWq4F#vXYAB&*p=HN%XwpScX?VZL z!U4EEj}xjr1<=Bte1{E7?*b0${{tZYZ;_CUKq#)o11RiDfwkly$2efMjEB4+a!8=U z(tq@S*AP4hO9mMQfB5$Q;{HS}ADV;97sgRY`ov)jZi&I%ZZZxje21p{K`f;Xacf;U z#O;8uV1uWye5u#|p-G?I_lNoq2yL?d7tIPw+pN6PfvsBV(A$~3hon8)`b$a-9$u!{ zB8lSM!QyE_fuH-!RN*HCwcCgOU8d1ksMjuzw&o|m3Kt5jq(3fWKO~kC-1`ZL{7>0E z919CjYYb3g!{4=MA8_%9bo z0JMl;dMwEwH}D^#N0J_(|GT_qCm_++4x;|9G1y}M=8ujukd99{05Ff^UmbyqoB-&=1?|d*lmzbo0sp7wEX2f& z3#NwN_JOu+=9f76DF}AwoX9P!GyT zDFA^uaVRT&K&?f9A669J2#2+ef|=fgwnU^C7_xLA9?+Kg>CZEqFr*;K^1h}@S6r0NK$`YJi}J9hl%Uq~0ZoB) z0{|>E_&0r!6X5q{KpbA%`6b`A?n1ndKxf^`@FdUyJ z-n zq5VdN_TL11ej8`j--3kQ+L5=x^!5F;g9A1P&aLkU46|N*`4;44=l@BqB~WDJK){fh zVC}~Lq}Ci3C=R=76FP_i7487I>jp&?dhdq;j^e@g#o?lq=Lvw-o=~LFzxE>)1D#%x zD`57o1Cc_ygTk8-!$SuzWCa!|1Up0SL~!C75$J+*2y?1)FAnH zWsie*w)P8b$`<6b=@bB5Ncp$GqLiM1kGKEb1W;l7(7#0p4fRWq24Kqe{&(LF?6WO6 zw|#KQ+JeG6f1C;x7xHhf4wO_W(0^kXK zZT6v169#wgRj-zmTZPgv^MBIN^&`w6sqx<}2UXSZ2lLN{gChTg6Z*ILFpa`vM2+E~ z5GPtN@Av*bTJ^>nvj!#V49UO6;1_5H;Nf~M@Cje06~`26+7N@S03PL$iZ*E3BmNJ4 C2pYEl delta 16522 zcmZV_2Rv8b_xt@mD|_#~vz3bMy|;{HkF3Zn#Fwm8R?!n7X(EdFQZf?BCMm0ojFP?g z|9#(A#sBv{AKZJ+x#ygF&bjB_ckZ(tNBJX;lFUdKz#~Q=h!6-w*o71_JplUi@?0r^ zhW=VYz`qZc;(|+ngV^N@US(#6J_DSzHIt^CIj;fxTg|_c$MW-gzm~;WJVpNRHGK16NZ@ltVfRM%%9(Sg3i=h~ zj~=NiE19cR8&swhG}cECk9{tmdOKo{M^{0`hR4o_A#Y822fAe^G&XYv3We5+RX!i2 zk7Hze(z9YqGrjgIjaG{Ep%RnBD>ri@HWo&_SpR%y(Vxoidro_+N4wgT5Fd}VDs#G7 zdcqEzTK!P;7+oi(wrXE{!!2wn`CLQYgPh^QB=^{<%sydY%KQc;I#rEM`=_?w`dO-0 z{*hC=g8j{1!gStx(_Htzt2}uwX#A;Rh%`~i!)-R?c~=ysgOlfVI?a`j_o$8?f9(AQ ztQfQ}?@MC|w_5c3wMxV|@*ruIy>+eD&dex@`Eg&zN-+NJl=h%>Tvbw)p#U!)aWJD< zVtrGa0FQE9!pW{Rqfgcp-W(>yW`JKcckW@)!2+%IZBl#W39HT{l0E9 z`kH}Su(av>#XYLh!0^Y*L$X;(bGx!_zbK4!35oLj`oH8L5r}d;1On@3S_BahZ>^l!Hp8{d-`z0xN2Af+rUTx$N+A*RltXQ$_cm3HIT_%aO>xJq>L!s z;!8swk%U{4jYt+AxMlbgDJFnzff1CbRk#sMh2lf&`txAuV%B!)gl09bk0l77I4+h! zeV);jIlf-dfWxElbPvN&9H?_Bs6w0)>^k$==`Stq3 zhlSGvO;cfW4R7Cuglm7}@(Q%M!Sq(KY0)R|a_EY<%AUnW8VSFGY!64?-k`aVJ`DfG zH&5b0EZGCEp_yDdM7C6o#Lg8c{Vdf*J9!W%QHJ+t2IMZ=hcXZ@F_x`HBP=hg7!H+A zD=?h-{)Q~3Lv-8Gpv~ViT(ml)9V8LT2}>IPgwD3{SD1`&()(WCJahEQtYD5TOM-y< zkpHwngTHXL!S5dVn%U!HQRH!7@vrAtZ@aL@p0F(r@ULL!iX6n_FF#c`Gxx>Q#uy#F z>uYr8{$gL6A-h99dC0e;SG-5ibPb>QhRx=} z`-vVE8r5Sy0*z4&$19Ii6@5|NLJIBW`LP^PL>D}sCW3Jmj9o%^&BHa#H->cI#>84{i72Z)pJBmE1)b zPN6R_Sbob(mq`&iEi)u}RI&I%Sg%S%5S!8Vr!VJHBsNQRBn?6*j@CcqaCDwBZfG(* z#csa$XuV?9Y#8|4g8KhB=oi zHqTeU&QOB!WMuvPmv4k`+4I@5Bptq=XT6={j1I7-K@ijytPVs+L`wLcOsgk}OZOPM zzJSh9PqLRPDg(_k>rd8EnsQ$A9aHrh3$r8Q&Ya7^v7SqcM-L7s?#)pHgLL@iD9t7eaD%^j6v9?xxBVVDC zTQti1RPas6lttu8{A_^i4T@6&UByZpaJ3%I*qZm^ZNCvZb?fsgzqISZ*la}gS&JpN z>ml2L_BT%&?IjrpW~)1Rn-v_D|J8452~Z2{-OahyE0J8^QU0^fnfOxJSl>Cqay<0{ za5CIX?%_<9aa-2tC}4dhdnt{O5f7%%b<0oB@NLg$xPKvatqR`(W(0 zc`X^wbywBN;$~y*Y?E?j?JFsX7?%3Y%WedE$wG*ClG@1$y)S5EZ~C^8;7MHDimEKU zbdSP_RCgh)p8u&O27gOol&iIDLj~1$gmmZpT9uwEkbbv_Lgc9_De-G@Vx%&K1{EWE z;(^Dv-}jHc5T!_eM^#&3&ifFV=S!b*>Pt3euTQ&`?_&*BKZP5Dv>}RzkyZQBb$q4> zTE;z88oK`}+3|q;MB%@u6XqpSscL;k>?9PQ6D>UHEhF8%%58Z)Y2ad+jTaqDypr}6 z$~V6G1HXRdmi&G~mQBa9dE*5UBY`<8W&pk3{E}w##-g%xpUYad~fqIFXlRmP4Uv zwktb+Pv;rCS~5%Bd#gEtFfE>ko0XqyZaG}MS>L~0?xplE3r_5I>E`*@F(U)2+ zh_ck8eM&Q!J9?Y)^uUyd;_){2&t05+wm~B7NRf;mysuUW_l%p=3US;Z_V4@uSXG9 z^`x~CM;F~tdN(zP{HlrP&4fF&J;zy9)>25M;D7%KYNcgQ^!RrWuX@(;%W%FY)QVb>N)sXc?x6)wbV)g{H ztH#&Tsy72}4`kY||8gULMXf|S`c&v!7uq>>H#Pjy&9-0DJDsD^q>GZ$)6XYCFFjJt zdE!}3$ zjfc5cpY`~8EoD7=-=%ByE`ibSp5jdiGQ>K6*(tnt=S7XFSCI)deUZ&0Dw&`?r`QW< zWi0|-$zb}q%^*Gz`u^C07{mGu|Dcd2UUi`qaa>%ID3vK%aFX8T!LfQ~e+l*Nuaf~TTS(&j!M z`IyjD7J2AqG)Y~qhkIb4Xr|j68Y0%FJTzIp!wVy0y~o}8vFbj=oOL!l!m)QHgD&au zTV}^L^(t`UdCdY>HtnkUp_h%58+Fj<%@LN=b1y>quB_!oL~ z?~$u4|8UAwCvX)aqd;hG-r9v=}Yy!I0x+DQ4Chq+!vgiCT>&NU}E(l|heH^wks{XR0W;Kztl+&p*s z6@$dt`_y3O%IU-mx%+aXn4s5*sy0tw?BuV$M>Z_Dy_wUxUx@FqD8YYACAsw`c?LQ@ z`y%hF8f8lQ@~+R>yX068?%&2em$Y~UcGHrc{*Y5L7paoyjUP5lUpl?NU2>D$F|dF6o{$b zo&Ru_WJBWKmgeN>PVf_A$EH|^ikBNbH_nrvnP9qKbuUq)ephd$ltZU42bCww6N~07 zQN*JQDO!vOjFnU->Wf=yD@@2c@^geCWSBEnyr7acGIEztD*jWm)KanEy&v%fCgDUw zR(NHuL?>?6cS*{7n>rCU=j^4v9}bkds=5>vQ|c=?n4r8^+Rd-EJ-%#Qnebv3sdRyNXZ`Q$E@n6mJ?V#vOt#(|xKHPY~PN7=@^6~Vo?ejc=^PUiQ8>Ti^`DJ7w$5?)fgmau)}#?z^U$YrD#aIKuclPEhg z=MzNg(t33B96Dv9=jts(S=UM#@#&p;-`7=qgwlkop|w7B%gJ{nXezkV&~=f*)D{o- z6j#1yzx5RLybxfrF@IaIBxLNuoKU4S`9jo1`0(AZ-b;2Mb5nmtJg46^AaI>1_}4vFZl~B9``nYqX7mG>HP0k0 z?hXm&FBG=kFxNB|qbTnB?9%Nt;wQiTYrJ4hM&6}8X!O>Z4Lz6j-thHhvEANQv)T0C zt=$2^_W7%O%Pb0l4Bc@%?FBh|@>fO&3P8oRol`!=tc2I$ptzdI5tlp1i0r+^f8?Iw}f)v0t=MdQ5PO-x0;B1-G>G z_nBY}3s8OdSQyB~3^0RFYf%$0g;)tn8YjjJ1Hp-xQDk6pDT);)EiOeh!&FyZp|0X2 zBg;{>L@*L+v0%Peqik`*v0YHV9z_gVy8yW1FMCnEp#2Cy3VP3@`e8;Xb*O9{{flFe zIK6t*ahTcFdQ=ZgVD%nFgOlXbfJ(z@47K<$A}uIO+(>u=&`4sipcTaq5C6lA7@TiK zO~RnaMjU@)u(Jb20M-lwkhH7;)IULx9hkw6eiTjy*&B!) z!lV985K}dX`UVSu9fsK;1kV1$f?{JRL0BPp<`<6uB%t`@0YiiE^moQlly{P$iRb)4 zDdR@N6NlhZ@Mw6x1{0_^@NA%|YT>A$c`<{#b0|{q;xIsriJSTpJbw^mVD&I?1jAAe z7#tpP4Cecl2H*oPE}%%jXSJwtEGW$f;KM)=ejK@-CuEUYNbNhzD29Ilx4ek@0jn~w zgi?ViF`O&=KEt@LqGWLa0ktF!1O#k*Xig;m0^-j!Nx-ZfoKG-uyQteR%QQB?a9^cf zSQs?v{UH8hO)^X;v~Y03{=mpF+k}7xPW?YHT=4#x%r?xeh8WPpQIV4ZR#*_|K?;0_ zae8EcCJqN#ND^nsLP%`D zQef7O1N)%}dlG^({)-YgY9Y{TSO{!=ECJ@;N#Gj_hQVRVt_VpIZh_+WxeQ>2b0!vn zfe_9(p|BZpln$C9PZ@|jV1{d|kQoeB51Ii29WVn-pfHId!}zKJxYUJ9vCkF&Qp|I8 zV3FjXEvk(F*aDV(-1MO2Q)Ynw0m*~rkmQ7p{ZtG)fZY6mWDG=5h@*!y; z_<+2xPJiUVB!(`)fvnNu1=;7m3os7r2iqS8U0eb1;H**W3S{C0z)tvsB>g{6{DHH8 z^KQUhEHlhacc2p-rKl}SD`DAWFrTFBP?;|4*O82Tn zmiuX5d66+qt{9Zs6f3JL=exGHPup=6LG=xE`1Y(GVR2L4iCbS^bWHo-Y`bmVa+SYC zLc32Y7adv0dLre7CzCz$0*zp&x3be?rWcQU1=}6b zJ9N|{XOzu%RgjH$PWnn5$=%o~nYf$_9=$PPx4L?l%zNRTB{JOo@o7<0`j4~Va^Vh% zNSU64_mS{mp;u*hBg@nituE3?4HkBK1OlJjxds~1_9h-WZ;#!HnsgO85#g;;qh@j$ zX-uB_f%xf{r}J3|!n|009qD4HmIYP!)uq?OfeBNh`WL=<7Q9s0V93S){KNK%{%+v3 zVz@;?mgKl}kCkxl z%K7Y9tz1UAF(3RLe#IX>d=xhr$+!b>VzH_+}3P@PWy>L^>!AUZ-*OK8!x!ZwrJb7X3`Dm>gj zY@R`bacV3=FkIFr$An8-S}qGU#J{IVdLojjTK|0uowKg#1R1H_MW80bETkz%%)~F2 z)AyPQ!L!Lk6LC4coiXpFr>AsS@|B(yhS{c=avLQaH6C2rl)uMixfNnstefxtP(#(5uCl$NO1R8GWfEr;T-_0+_*4@?R>>pLWoBo}q+`L)6lV(*GX zY%9O9bh7!~`_=Nw_6Ozl9uCSihP(D`R<=EB7gjrVly7WYyib-;a3)VNPdK8E3p$?P zSS#?j+hzXhvcBg=n6xMUX@=xb!(S+6e`oi-TN&3X&{KF3BpZFt~ zm76oaRvMvxxa((B2U#e&9*3&u$)m(Y_BrIPJ6l{+6#c5y@uJH_EFIaugEFFA($DMk zX?^L5eoaFqQ^+56Qd7Ub(s{EmO}gDv{c6*cMy&Yvr)q?cOxb03BkmBB4y(q=eo+1~ zHL0HXD**kPqsP5CS1v8+gWsd>LgH-iflJk7%Pdl?79Rw3@xMou=aiYJhW1|1BrJ-j zI?mVbO7Ev1f zqoOPULoHL5o=tCwC0Q>65>oGqpIz+u*FU=OT#B7BE|s04jdI+5=ZJdZ-V|nf+A}N9FZC zex=}t6HG^&EZV*~_uOSQwXr|)RsnNVEkrq7r>s~Ho%ZvXC8bQkyX48rSO+n@g)16a zPdl{Sh6M5#u1fsg2xYVJk&u@uM&pqzr9SOCAMI&zQ3qk`qO6wdcwbaV@JOjQ>hlmj z^N)1bb}bUdYGDP7CUkDYg;y)MPW&CTal$7V?JD^R+@ z;hy+#O(wbo&HB1x^CIQEeBz0f7rjrzq-&XbM_ik@BgHDBjU{7 z;>@K^@VI(g-#2O{jL9+B+7(|bho0UwTrrj|!<`oW;{oMatD*+S@`prUQEzXNQrjnV zW!{c$dB;vuaeM6L5vnuAEdpghrJmKa!*?u0*GZDTN4O3$n$nJ>#M3#&A8Q>YG=C>? z261j9M&o?Xk88<{&Rr9PhD=}IO3EfnthP=|>KmOPNISt-%Ju}6$2!1EFSXuq=6Ft5 z2S@nCt8w(rnsrj=c_r300V1c62fPWyjJ5vjwQVgod?V4fX>ak$akr+FFKaEItiC1F zllo|$x5fFE*<&#)ORW&!N7|Z}<-&oEbPDFlD*P6m<|1wH-{;HAJ$ugBU|nqkr6{zT!8h$9~PgxAJ`uzf=B2 z9}V8_UJ*Bw+4$GGCyI62XacwOSFD+@cN?X~K9Hh)lxsN9z5e&nfelx{7W|gQet}ZOX;MFANnu=oKPA zsw`z)A!*74KR)GRjyJuvDKnY~df?*c+aH9;HvH+04T! zq2aBj5`6WzyH2)=8xq%jR7s zpL3Q(ksrOcKIo*$cRX;w@|m>E~Vu4~fXhZ?WBL*!e_H z(t1a*CV5Nd#r=?HG>_xx-L)?_srcU7`$XA`|8*>H;^`*_h)M5BDEjN@CTGRBlbBJjz*e72LRP*Jlf;EjAWspg##~Z)L>`uvy0TjFJ1q1Wlt} z5GQpMCJpsgT(FH8S@a6D(6(^@(Dk}%V>U2zr(D8erk8&;v$HoY>RF3{Q)btv*qPP0 zeVF7IsU5}KasNz-`kb-YHWbAWp7Q+?>&Yk8 z-|mEVJT$5J(DWm3M|LC<@7WRBni;+1m|*LL(T{1as>f!%oVK|(qs_gaes^WB>J%mF zvFLUv{$R8-6nS#a?Fy&1jlI3mFD-=g*Y)(Dgn?48(%tg?;0{c$O31i(Z#V=xO#gSK(NOxFbSNb zN@q+gC+6!WO|Ha$LPlE1^qz|+`pMnINB)IW<_+Y?E(_fxnYcv@MJ^k%@GHU&RX^TJ z86P4afbxSUYKHOIGM)Z0S=Ek`=YJEcdoHt96#G$Ytl?`YB3TsWc;X*Z>+@wy z$kQ<()Y5FPq+Lwcl~Ny>w=Bx#^VS~hkDyy8dGQlXC9L12XFoi3EQCEVj5AMIeEv~$ zNu0m+dL!}McY6$XJ6V8F7!%sxh@E%kT)RO!QFHoFJ1v;Mo*9j}_WpKDRNdmkuO{K4 zZ9$o#_Z-f11`8NmZ+Lal$MAYXNQgtm>6Bm6GVVu@Ze-CtzqLesxv+$APkEmD^9vrd z)rv?5elt2y989;VTt^HqL+L4>_IpX4|ADtaF+eOm7rL##yx%_p~w(auOcPH0-9$=L13#p%s@<8!AM(6;ChnYg({!!k0fnNU#(%Hq42q>{ z0`k*FS!i`@a+IXHZq06hcJzmCe)11N8NYrnpNda&jpp>5Ji!yvmN%MX*ygS^_>E1% zdX!pJPoFSW<&wI4?Mg%2P`ghYwQ2H7Ph5bZzXY*&-2I(!oq{e*qy8ML4mht zF}+2Bs=h6i(oC`M`gluxPd}^Nrn#O?37}oMJ{TE#aF7>KjJYU;I-OE}&3xVEm%qtY zc=K*nqvj1LGUXq?9bHM+-y68J^wKKZ{_GA1^Q7Hz-# zhR&>+7ojaN-xt^{3uh~yzsenR`DPR3&O7rcZY7;sQPD@(W z(+#156iEmj4VRydG`&mPo>j`E@4hjc%mck58XK1l+TMb;awVV8LIppv&smpTW?xNr zXXY(!(oUVcE2Pab*PW(aw-Zh-vUzjE)+e1H{G2Dc%l}iP!ZmZ25Cc~gXQ$81Al-*@ z*}?_FN4&R>@Tfl#Ud~newv@A|8fo2d%DPcpem3f*Y`th^lttH4)$(WzQZ%&aZe5b5 zkL)*J73pL_FUp+G*6QJ@VLBPLURrxOWM-6+%*e6&-*fC7r{XjnO3{>I>g+qw5!;sIva(w%OS_bV)ATDkNYW#N_dqgg*x0# zrC4#TexPl~T>3IL>+{lp_57`(p4F@U)fA_P9!;b9bSfNNW_4WJ&0X10pSK#@PEPqw z-1zFV_pPjFtnBB4+xxDucBNmwci6ux52z6=t=6RR`^++VRCdxX#?15!9Y6NGWlXCj zcuHR*>!UAH(arsmYe;tI^sX&U_9S!rbe~AI5`Dwle))55%j@QW?fS~Awg894QLbk_ zzv7c3(KmmK%X>wf@+Uc$(G<8jYq8o5)@hpvv}4Ssstj%L)QfNPwh!o4&q`|6&FQG! zY1WO~2x1v9vB8+w;4{27u_4JXz|;jA-U&`57kO4<;-Xtn_%*{k-%B~|k2roOIKP$>LM&F46tBB|k8!B!Ao1^6#jcm3que z!L-9l*5<`;Xj4*Sp56aud_Ht0uwGm6r%6=zbq1y9{Kr!tFIPRhbSm$&_Hn=7>*YNp z4(QjTEVCXV0@+dnTuP4) zx4S;Hhs0h&{brn?UZqALj&dLmUqa!o9+(pVS6m$qE~#ZD9xNh4JyOtq1G<0sbH@W; zJz(aO08!i^sCH-oR~VtPEquoV!WCP1;EPRw9us{FP&-hzg%NPsb}JPK*smC3?<25? z|F8O!Wge&)f&*IsEr##jpK3H*HoTJkpE7Du)`2oA2obFOtI#Iq0AslOE$n15iBJC& zP~ie4xC4-ZJFU3OED&3l2M2Z_nQR4s>48#ZLgB$uCDi->QY99IdGQ>O{AX9pZV|9d z@J|tn@_oq|NHP+p!$1OK{)tKR#3KheUmqw2 zOjrG%nZaI7XgE-o2jTk-2($n*f=a^&ugzf6`49V102kx`fJi}!B@_jCt_ipe&jj}L zKjgU;6fs8ZBhZ6W3ogcUv;chY1ttg=?V&Cy=0f`)-I_Z9_>SdHC!j<;YA_NyLh`eI(T~;=^|0Ih`%3uTW;nV2}27B z@tP5VfWGuU@JOpej24CfdYF-I55R(~219xP9=LxW+b097dH^OXtj;21GCx|O(X!Ad z<)jC=AP^GyD1^UDK!CgVd4KG`2mHSVB8qrFAL1hrWAy*8!AVf;GXP&cgF2s~sZqa# zG|H(((SaS`08&_u1T37c1Z#x_6f0P}0g!TI)xl~2Sr2|7z6TzoQiwQZ7T|`*v-Cpa z@4z5Z=yH)0x?O?c-dMQPD~J@ijN$=b^zOrJAUH5ph61U|AvF?K_rb_75P3m0M4sCR zaKcW+iu|Ji?E(1+gaDZP1z-SWmjP0klGA$lNi9S{4VjMP5Tz%UQj8NjA@<%3QhkWv z8pIR({nNkaavhlR6-pVM%K-C#By;|wgIY{r@>hTdq}be-y!44tEChnTgnq;iQMzL( z;r{{vyS@S}D5dvUA>1Hk-@Zdc`XH!z0~SgT+VuhSu$CKD{#{a#mU_@X6|f&-INOXP z9R%=5LHW-BF>L0@87PXp!QnoD7w#v2gZib|J|igG4=}*H2R8x8?Hu*w2_TE8nHu5OS7 zu|wQFI}dT=g2~5CkvuKX>{1#2-&qk|FgXa_;}e60V>rQg1|hlWy*SJkAwUc&4DPEG z`4fs6rms-UNc8VVV+ur#WCNcM0wVCFD1SjDXZj(Mhyf^K{?3ML2%@_O$`1i2U<oJtl7!E2i2{6FWZ;&5R20w7nd18PXUYRfoc2x8DUlbnr zVhZvUHYQ;_>?xLs|Hm6)7algF4S$DNFZ~DqH!$UfA-uvAZanmz0i3>IH|We_fsEL1 z4Cr8AVvX=;i5^~fEpu2>E_jW?qzBii&>`b7&*Mm;PZCJ}<)zRONQ+|&IF!)}6pz^D z2~VIOi;7tMiz0>R4ok@jJ$e!iaqowIP9KsoaFG75Eiy+TR_~S$u=;BT;9V|UP zxY`Gh|Ho`xheX-!lR_U-kbz#%*F3Ol{;&ByD?vf54Y@_|5WP28_X9WutG4w6QVkCQ za!oMvU)oiTPNlIPxzoDTuvPhx0kCV2Q=;mqU;(&afd6oQDJ^ zqi}S^f57( z7P`{@6FB);=n4rID)ujj$4)Pt2!=E-f_`M7pMQ@r$TyRKTN9UP9H-;Gl2!7Z8ZeR!Chi>nFem8)EDF)th3Fr%pkhf^2u-F$70` z9>`xn69WJ)FhH(4oW3YP-(SE9SdV8=nnMm@`^@0?U;7)(76b%{m;q3d8HyHYM8 z%}xM47XT`9L15X>2a+i=0nD1-SFdJ3CEpQJ51Q!zsh0wdOdn7WsQ~)^hU6YrE(QzS zSME0?(3Bqli};{9KwqZd4kTL;82JKZnAzXCuzDc}z_Wk)@Xlre4$nY?usc0GQFwa; zu|Qm)Xm9J8ibGneLPk8ivpqTvO3nc+|C|q}&7&u_}Gf+Cmz8L*I&A`cWS^P}B@y|F;EUw^bnZ3;@18 z^B?U7{(x;E)502vFF_hS19g}7kM5D!z8{#ibWo#5;P9V5*7E?X3jo%6VI%aQ?*WHD zVCVxG+-|{zJ=`h0KtG6t;$Zzhap2>+&j=U>xV6zya)i_eVgV;^5K@ zoH|B8{I&ge645ni@VGw!k_Y_1S5O&&px8RVba*+UM)sk9eL}Sk`JfmST?dZC5r44O zaQJNV07S0?yzne-9r_fpo683%-ybF#xCwxi35W8@48V#?1i;7?2+9V%Rlugju3sSU z4;ZRX;7&Us(Ag7snFLeg&fzdMcF6);$uOAv-vI}^W&ynv7%cg35nRE7d2a1fV=WEO z?9z{K8D}Ad%l~uUd<-sZ;@&T@3l`A73lF6S|8CZ>60q^x!5drqiLtdcah3!!0_A`5 zb~o6ubzu1-1wp&*|0G5qEbs)p%gu(B9;=0d<~78P_fVFR&j#(cAtxSQ$v?LtpBaMq zI|tW|A*l7I4{O>8-q_jKba(e^iVVbC<3E}t7xeIAp1LE%;)U*@S`qPIs)dX+s?Q6;}P8co^@mKzj zrn+Fq-T_TfpDNSr@%}Hmk<4j!c(`*szgcu9ImF27KZ;I4G|Yz$n)VZq1*rw%Bk^$W zPVf$N3)K44$L1l_kp{31g@=3D{2Rh3gMH|sGwU4`9t-MRBbNUE_8sIS&=-Y=D}Z35 z7rBb<^MZdjoG2L$32Yc>LA&kY{Lu#1Vk!S74r>4sGTe+)Dha^*cRJ^8#{r=#4KX+Y N;87CfbwKP8{{s(ZiE{t|