From b9eba78ec7521da0194b982834c41db934157f01 Mon Sep 17 00:00:00 2001 From: thierrico Date: Mon, 9 Sep 2024 22:24:02 +0200 Subject: [PATCH] Initial commit --- .gitignore | 4 + Jenkinsfile | 64 + core-ear/pom.xml | 65 + deployment-tool/pom.xml | 96 + .../framework/common/FileHelper.java | 71 + .../framework/common/FolderHelper.java | 35 + .../capgemini/framework/db/DbConnection.java | 48 + .../com/capgemini/framework/db/DbManager.java | 69 + .../com/capgemini/framework/db/SqlHelper.java | 105 + .../deployment/DeployProperties.java | 77 + .../framework/deployment/Install.java | 137 + .../src/main/resources/log4j.properties | 15 + .../resources/input/deploy.test.properties | 1 + .../input/sampleArchives/sampleEar.ear | Bin 0 -> 1315 bytes .../input/sampleArchives/sampleJar.jar | Bin 0 -> 923 bytes .../input/sampleArchives/sampleWar.war | Bin 0 -> 547 bytes .../updated/repackedSampleEar.ear | Bin 0 -> 1357 bytes .../updated/repackedSampleJar.jar | Bin 0 -> 1009 bytes .../updated/repackedSampleWar.war | Bin 0 -> 579 bytes .../PropertyUpdaterTest.properties | 7 + .../input/updatedFiles/XmlUpdaterTest.xml | 19 + .../resources/input/xml/updateSampleEar.xml | 56 + .../src/test/resources/log4j.properties | 9 + .../resources/ref/PropertyUpdaterTest.ref | 7 + .../src/test/resources/ref/XmlUpdaterTest.ref | 17 + distribution/assembly.xml | 97 + .../DBcreate/001_hibernate_sequence.sql | 9 + .../install/reports/DBcreate/002_table.sql | 101 + .../reports/DBcreate/003_report_type_data.sql | 81 + .../reports/DBcreate/004_criteria_data.sql | 111 + .../reports/DBcreate/006_quartz_tables.sql | 192 ++ .../DBupdate/003_report_type_data_1.28.0.sql | 5 + .../DBupdate/003_report_type_data_1.30.0.sql | 2 + .../DBupdate/003_report_type_data_1.32.0.sql | 2 + .../DBupdate/003_report_type_data_1.32.7.sql | 1 + .../DBupdate/004_criteria_data_1.28.0.sql | 4 + .../DBupdate/004_criteria_data_1.32.0.sql | 4 + .../DBupdate/004_criteria_data_1.32.6.sql | 14 + .../install/reports/create_database.bat | 35 + .../create_database.bat:Zone.Identifier | 2 + distribution/install/reports/db.properties | 4 + distribution/install/reports/log/readme.txt | 1 + .../install/reports/modules/modules.zip | Bin 0 -> 2600978 bytes .../001_procedure_drop_sequence_if_exist.sql | 11 + .../002_procedure_drop_table_if_exist.sql | 11 + .../install/reports/update_database.bat | 35 + .../update_database.bat:Zone.Identifier | 2 + .../data/bin/clause_propriete_update | Bin 0 -> 2090194 bytes .../install/teamcenter/data/bin/encrypt | Bin 0 -> 139008 bytes .../data/queries/Report_All_Sequences.xml | 11 + .../data/queries/Report_Alternate.xml | 12 + .../data/queries/Report_ChangeNotice_R07.xml | 11 + .../data/queries/Report_ChangeRequest.xml | 11 + .../data/queries/Report_ChangeRequest_R07.xml | 11 + .../queries/Report_ChangeRequest_With_Seq.xml | 11 + .../data/queries/Report_ChangeRevision.xml | 11 + .../data/queries/Report_Change_from_Part.xml | 11 + .../teamcenter/data/queries/Report_DET.xml | 12 + .../data/queries/Report_FPP_With_Seq.xml | 11 + .../data/queries/Report_Generic.xml | 11 + .../data/queries/Report_Generic_Assemb.xml | 11 + .../teamcenter/data/queries/Report_Item.xml | 11 + .../data/queries/Report_ItemRevision.xml | 11 + .../data/queries/Report_Product.xml | 11 + .../data/queries/Report_ProductType.xml | 11 + .../data/queries/Report_Relationship.xml | 9 + .../teamcenter/data/queries/Report_Unit.xml | 11 + .../data/queries/Report_Unit_from_CR.xml | 11 + .../data/queries/Report_Unit_with_WKF.xml | 11 + .../Report_WKF_ValidationUnit_on_Unit.xml | 11 + .../data/queries/Report_WKF_on_Change.xml | 11 + .../queries/Report_WKF_on_ItemRevision.xml | 11 + .../__pv_snecma_search_report_by_source.xml | 11 + .../install/teamcenter/data/report_prefs.xml | 20 + .../data/reports/REPORT_R01/REPORT_R01.xml | 8 + .../data/reports/REPORT_R03/REPORT_R03.xml | 8 + .../data/reports/REPORT_R07/REPORT_R07.xml | 8 + .../data/reports/REPORT_R10/REPORT_R10.xml | 8 + .../data/reports/REPORT_R11/REPORT_R11.xml | 8 + .../data/reports/REPORT_R13/REPORT_R13.xml | 8 + .../data/reports/REPORT_R15/REPORT_R15.xml | 8 + .../data/reports/REPORT_R16/REPORT_R16.xml | 8 + .../data/reports/REPORT_R17/REPORT_R17.xml | 8 + .../REPORT_R19_Document.xml | 8 + .../REPORT_R19_Document_Design.xml | 8 + .../REPORT_R19_Document_Revision.xml | 8 + .../data/reports/REPORT_R20/REPORT_R20.xml | 8 + .../data/reports/REPORT_R21/REPORT_R21.xml | 8 + .../data/reports/REPORT_R22/REPORT_R22.xml | 8 + .../data/reports/REPORT_R23/REPORT_R23.xml | 8 + .../data/reports/REPORT_R24/REPORT_R24.xml | 8 + .../data/reports/REPORT_R25/REPORT_R25.xml | 8 + .../REPORT_R26_Item/REPORT_R26_Item.xml | 8 + .../REPORT_R26_Item_Revision.xml | 8 + .../data/revision_rule/revisionrule.xml | 139 + .../install/teamcenter/report_install.pl | 273 ++ distribution/pom.xml | 58 + jasper/pom.xml | 56 + .../jasper/compilers/JasperCompiler.java | 69 + .../reports/jasper/fillers/JasperFiller.java | 20 + .../reports/jasper/fillers/MonoFiller.java | 46 + .../reports/jasper/fillers/MultiFiller.java | 81 + .../jasper/printers/JasperCSVPrinter.java | 44 + .../jasper/printers/JasperPDFPrinter.java | 39 + .../jasper/printers/JasperPrinter.java | 21 + .../jasper/printers/JasperXLSXPrinter.java | 55 + .../jasper/compilers/JasperCompilerTest.java | 19 + .../jasper/fillers/MonoFillerTest.java | 45 + .../jasper/fillers/MultiFillerTest.java | 87 + .../jasper/printers/JasperPDFPrinterTest.java | 46 + .../resources/Jasper/images/Snecma_logo.png | Bin 0 -> 3973 bytes .../Jasper/images/confidentiel_industrie.jpg | Bin 0 -> 33675 bytes .../template/dynamic_table/reference.jrxml | 174 + .../template/dynamic_table/template.jrxml | 23 + .../Jasper/template/report_r01.jrxml | 749 ++++ .../Jasper/template/report_r03.jrxml | 750 ++++ .../Jasper/template/report_r10.jrxml | 975 ++++++ .../Jasper/template/report_r11.jrxml | 687 ++++ .../Jasper/template/report_r15r16.jrxml | 686 ++++ .../Jasper/template/report_r17.jrxml | 621 ++++ .../Jasper/template/report_r19.jrxml | 518 +++ .../report_r20/page2/r20_p2_generics.jrxml | 64 + .../report_r20/page2/r20_p2_impacts.jrxml | 32 + .../report_r20/page2/r20_p2_noimpacts.jrxml | 32 + .../report_r20/page3/page3reference.jrxml | 126 + .../report_r20/page3/report_r20_p3.jrxml | 114 + .../report_r20/report_r20_master.jrxml | 300 ++ .../template/report_r20/report_r20_p1.jrxml | 267 ++ .../template/report_r20/report_r20_p2.jrxml | 119 + .../template/report_r20/report_r20_p4.jrxml | 279 ++ .../Jasper/template/report_r21.jrxml | 876 +++++ .../Jasper/template/report_r22.jrxml | 897 +++++ .../Jasper/template/template_R07.jrxml | 24 + jasper/src/test/resources/log4j.properties | 13 + jasper/src/test/resources/logging.properties | 3 + .../test/resources/simplelogger.properties | 0 kurt-ejb/pom.xml | 240 ++ .../posting/DelayedPostingStategy.java | 56 + .../execution/posting/IPostingStrategy.java | 30 + .../posting/ImmediatePostingStrategy.java | 18 + .../posting/SchedulingPostingStrategy.java | 46 + .../capgemini/reports/quartz/JobDataKeys.java | 13 + .../reports/quartz/SchedulerServer.java | 309 ++ .../reports/quartz/TriggerPreparator.java | 378 ++ .../reports/quartz/jobs/DelayedJob.java | 65 + .../reports/quartz/jobs/PurgeJob.java | 210 ++ .../reports/quartz/jobs/ScheduledJob.java | 212 ++ .../reports/queuing/EmbeddedServer.java | 115 + .../queuing/consumer/ReportConsumer.java | 96 + .../src/main/resources/META-INF/beans.xml | 27 + kurt-ejb/src/main/resources/log4j.properties | 21 + kurt-ejb/src/test/resources/log4j.properties | 13 + .../src/test/resources/logging.properties | 3 + kurt-ejb/src/test/resources/quartz.properties | 58 + .../test/resources/simplelogger.properties | 0 kurt-ejb/src/test/resources/test_policy.xml | 213 ++ kurt-utility/pom.xml | 209 ++ .../common/AbstractPropertiesManager.java | 241 ++ .../framework/common/DateHelper.java | 136 + .../framework/common/DoubleFormatter.java | 116 + .../common/DynamicErrorTemplateHelper.java | 37 + .../framework/common/FileHelper.java | 210 ++ .../framework/common/FileTemplate.java | 137 + .../framework/common/FolderHelper.java | 112 + .../common/HashMapComparingStringIDs.java | 226 ++ .../framework/common/MailHelper.java | 156 + .../capgemini/framework/common/MapHelper.java | 55 + .../framework/common/MemoryHelper.java | 75 + .../framework/common/QuartzHelper.java | 45 + .../common/ReportFolderOutputHelper.java | 117 + .../framework/common/ResourceHelper.java | 134 + .../framework/common/SerializationHelper.java | 53 + .../framework/common/SettingsHelper.java | 577 ++++ .../framework/common/TimeHelper.java | 103 + .../activedirectory/ActiveDirectory.java | 409 +++ .../activedirectory/SearchCriteria.java | 6 + .../common/activedirectory/SearchFilter.java | 58 + .../com/capgemini/reports/JasperTemplate.java | 68 + .../com/capgemini/reports/ReportEnum.java | 106 + .../reports/ReportLaunchTypeEnum.java | 57 + .../reports/builder/AbstractR13Builder.java | 40 + .../builder/AbstractR15R16R17Builder.java | 34 + .../builder/AbstractR15R17Builder.java | 35 + .../capgemini/reports/builder/R01Builder.java | 50 + .../capgemini/reports/builder/R03Builder.java | 29 + .../capgemini/reports/builder/R07Builder.java | 50 + .../capgemini/reports/builder/R10Builder.java | 47 + .../capgemini/reports/builder/R11Builder.java | 48 + .../reports/builder/R13CrBuilder.java | 14 + .../reports/builder/R13FppBuilder.java | 14 + .../capgemini/reports/builder/R15Builder.java | 14 + .../capgemini/reports/builder/R16Builder.java | 40 + .../capgemini/reports/builder/R17Builder.java | 14 + .../capgemini/reports/builder/R19Builder.java | 46 + .../capgemini/reports/builder/R20Builder.java | 104 + .../capgemini/reports/builder/R21Builder.java | 46 + .../capgemini/reports/builder/R22Builder.java | 29 + .../capgemini/reports/builder/R23Builder.java | 52 + .../capgemini/reports/builder/R24Builder.java | 52 + .../capgemini/reports/builder/R25Builder.java | 46 + .../capgemini/reports/builder/R26Builder.java | 31 + .../capgemini/reports/builder/R27Builder.java | 19 + .../capgemini/reports/builder/R28Builder.java | 19 + .../reports/builder/ReportBuilder.java | 26 + .../reports/checkdata/CheckingDataHelper.java | 77 + .../database/DataBaseReportHelper.java | 282 ++ .../capgemini/reports/database/DbInit.java | 107 + .../reports/database/HibernateUtil.java | 35 + .../reports/database/javabean/DbCriteria.java | 34 + .../database/javabean/DbCriteriaVal.java | 34 + .../database/javabean/DbMemMonitor.java | 39 + .../reports/database/javabean/DbReport.java | 77 + .../database/javabean/DbReportOwner.java | 50 + .../database/javabean/DbReportType.java | 43 + .../javabean/DbSchedulingCriteriaVal.java | 35 + .../database/javabean/DbSchedulingReport.java | 38 + .../reports/database/javabean/DbUser.java | 89 + .../database/javabean/IPersistedObject.java | 6 + .../enumeration/ReportCriteriaEnum.java | 136 + .../enumeration/ReportErrorTypeEnum.java | 9 + .../javabean/enumeration/ReportStateEnum.java | 31 + .../javabean/enumeration/SchedulingEnum.java | 59 + .../manager/AbstractHibernateManager.java | 106 + .../reports/database/manager/MngCriteria.java | 35 + .../database/manager/MngCriteriaVal.java | 145 + .../database/manager/MngMemMonitor.java | 97 + .../reports/database/manager/MngReport.java | 659 ++++ .../database/manager/MngReportOwner.java | 63 + .../database/manager/MngReportType.java | 110 + .../manager/MngSchedulingCriteriaVal.java | 300 ++ .../database/manager/MngSchedulingReport.java | 239 ++ .../reports/database/manager/MngUser.java | 134 + .../reports/database/stats/GenJspStats.java | 291 ++ .../database/stats/ReportStatBean.java | 85 + .../reports/database/stats/UserStatBean.java | 69 + .../r01report/DataReportPreparatorR01.java | 110 + .../definition/r01report/ExecutionR01.java | 170 + .../r01report/visitors/R01Visitor.java | 103 + .../r01report/visitors/R01VisitorKeys.java | 49 + .../bomlineholder/R01AltOrDetBehaviour.java | 61 + .../R01BOMLineHolderVisitor.java | 83 + .../snecmaobject/R01ComponentVisitor.java | 393 +++ .../snecmaobject/R01ReceptorVisitor.java | 164 + .../r03report/DataReportPreparatorR03.java | 96 + .../definition/r03report/ExecutionR03.java | 137 + .../r03report/visitors/R03Visitor.java | 99 + .../r03report/visitors/R03VisitorKeys.java | 35 + .../bomlineholder/R03AltOrDetBehaviour.java | 57 + .../R03BOMLineHolderVisitor.java | 96 + .../snecmaobject/R03ComponentVisitor.java | 217 ++ .../snecmaobject/R03ReceptorVisitor.java | 148 + .../r07report/CRExtractorHelper.java | 58 + .../definition/r07report/ExecutionR07.java | 171 + .../definition/r07report/R07Printer.java | 327 ++ .../definition/r07report/ReportDataR07.java | 22 + .../checker/R07ProductUnitChecker.java | 41 + .../data/DataReportPreparatorR07.java | 177 + .../r07report/data/TransformerR07.java | 51 + .../data/extractor/BomFlattenerR07.java | 153 + .../data/extractor/DataExtractorR07.java | 130 + .../data/extractor/lines/ComparableLine.java | 57 + .../data/extractor/lines/R07AltPart.java | 74 + .../data/extractor/lines/R07PartRfPart.java | 78 + .../extractor/lines/R07ProductGeneric.java | 77 + .../data/extractor/lines/R07Quad.java | 80 + .../data/extractor/lines/R07ReceptorLine.java | 60 + .../data/filter/ConfigurationFilterR07.java | 302 ++ .../data/filter/ContentComparator.java | 25 + .../data/filter/StructuralComparator.java | 31 + .../AbstractBomLineComparator.java | 73 + .../comparators/AbstractItemComparator.java | 80 + .../generics/GenericBLComparator.java | 58 + .../generics/GenericComparator.java | 55 + .../part/AlternateBLComparator.java | 21 + .../comparators/part/AlternateComparator.java | 28 + .../comparators/part/DetBLComparator.java | 21 + .../comparators/part/DetComparator.java | 29 + .../part/PartAeroBLComparator.java | 21 + .../comparators/part/PartAeroComparator.java | 28 + .../part/PartAssembBLComparator.java | 20 + .../part/PartAssembComparator.java | 28 + .../comparators/part/PartBLComparator.java | 74 + .../comparators/part/PartComparator.java | 89 + .../comparators/part/PartMatBLComparator.java | 20 + .../comparators/part/PartMatComparator.java | 25 + .../part/PartNoAeroBLComparator.java | 20 + .../part/PartNoAeroComparator.java | 24 + .../part/StandardBLComparator.java | 20 + .../comparators/part/StandardComparator.java | 24 + .../filter/comparators/rf/RfComparator.java | 49 + .../comparators/rf/RfGenericComparator.java | 37 + .../rf/RfPartAssembComparator.java | 68 + .../comparators/rf/RfPartComparator.java | 91 + .../identifiers/ReceptorIdExtractor.java | 35 + .../filter/identifiers/RepereIdExtractor.java | 36 + .../r07report/data/sorter/R07DataSorter.java | 133 + .../printing/BuilderTemplateR07.java | 339 ++ .../printing/DynamicGridTemplateR07.java | 250 ++ .../r07report/printing/EnumChangeR07.java | 18 + .../r07report/printing/EnumComposantR07.java | 20 + .../printing/EnumLienNomenclatureR07.java | 12 + .../r07report/printing/EnumMapDelta.java | 30 + .../r07report/printing/EnumRecepteurR07.java | 11 + .../r07report/printing/EnumRepereR07.java | 11 + .../r10report/DataReportPreparatorR10.java | 127 + .../r10report/DocumentExtractor.java | 257 ++ .../definition/r10report/ExecutionR10.java | 168 + .../r10report/R10BomLineFlattener.java | 88 + .../reports/definition/r10report/R10Keys.java | 33 + .../definition/r10report/R10Printer.java | 105 + .../r10report/lines/R10AltPart.java | 35 + .../r10report/lines/R10PartRfPart.java | 36 + .../r10report/lines/R10ProductGeneric.java | 62 + .../definition/r10report/lines/R10Quad.java | 88 + .../r10report/lines/R10ReceptorLine.java | 46 + .../r10report/lines/R10TopLine.java | 85 + .../r11report/DataReportPreparatorR11.java | 106 + .../definition/r11report/ExecutionR11.java | 154 + .../reports/definition/r11report/R11Keys.java | 36 + .../definition/r11report/R11Printer.java | 236 ++ .../checker/R11GenericExistenceChecker.java | 41 + .../data/extractor/BomLineBrowserR11.java | 36 + .../data/extractor/FilterByTypeObject.java | 32 + .../data/extractor/R11ReceptorRepere.java | 52 + .../reports/definition/r13report/R13Keys.java | 58 + .../AbstractDataReportPreparatorR13.java | 84 + .../DataReportPreparatorR13CR.java | 86 + .../DataReportPreparatorR13FPP.java | 105 + .../execution/AbstractExecutionR13.java | 115 + .../r13report/execution/ExecutionR13CR.java | 52 + .../r13report/execution/ExecutionR13FPP.java | 50 + .../r13report/printer/AbstractR13Printer.java | 372 ++ .../r13report/printer/R13PrinterCR.java | 246 ++ .../r13report/printer/R13PrinterFPP.java | 53 + ...AbstractDataReportPreparatorR15R16R17.java | 206 ++ .../AbstractExecutionR15R16R17.java | 66 + .../AbstractR15R16R17Printer.java | 190 ++ .../CommunR15R16R17ComponentVisitor.java | 222 ++ .../r15r16r17reports/R15R16R17R24R25Keys.java | 52 + .../AbstractDataReportPreparatorR15R17.java | 357 ++ .../AbstractExecutionR15R17.java | 76 + .../r15r17reports/AbstractR15R17Printer.java | 94 + .../r15report/AttachDatasetR15Action.java | 109 + .../r15report/DataReportPreparatorR15.java | 178 + .../r15r17reports/r15report/ExecutionR15.java | 174 + .../r15r17reports/r15report/R15Printer.java | 48 + .../r17report/DataReportPreparatorR17.java | 53 + .../r15r17reports/r17report/ExecutionR17.java | 109 + .../r15r17reports/r17report/R17Printer.java | 36 + .../r16report/DataReportPreparatorR16.java | 179 + .../r16report/ExecutionR16.java | 166 + .../r16report/R16BOMLineExplorer.java | 35 + .../r16report/R16Printer.java | 105 + .../r19report/DataReportPreparatorR19.java | 251 ++ .../definition/r19report/ExecutionR19.java | 151 + .../r19report/PartIdRevComparator.java | 28 + .../reports/definition/r19report/R19Keys.java | 30 + .../definition/r19report/R19Printer.java | 169 + .../AbstractR19ComponentVisitor.java | 95 + .../snecmaobject/R19ComponentVisitor.java | 203 ++ .../reports/definition/r20report/Classe.java | 51 + .../definition/r20report/ConjointUnique.java | 51 + .../r20report/DataReportPreparatorR20.java | 439 +++ .../definition/r20report/ExecutionR20.java | 261 ++ .../definition/r20report/MajorMinor.java | 51 + .../r20report/checker/R20LMRChecker.java | 233 ++ .../checker/R20UnitRevisionChecker.java | 92 + .../comparator/ChangeComparator.java | 22 + .../comparator/GenericComparator.java | 15 + .../printing/Page3TemplateGenerator.java | 342 ++ .../r20report/printing/R20Printer.java | 416 +++ .../r20report/visitors/R20Keys.java | 84 + .../r21report/DataReportPreparatorR21.java | 117 + .../definition/r21report/ExecutionR21.java | 148 + .../definition/r21report/R21ReportKeys.java | 38 + .../r21report/visitors/R21Visitor.java | 577 ++++ .../r21report/visitors/R21VisitorKeys.java | 20 + .../bomlineholder/R21AltOrDetBehaviour.java | 36 + .../R21BOMLineHolderVisitor.java | 71 + .../snecmaobject/R21ComponentVisitor.java | 157 + .../snecmaobject/R21ReceptorVisitor.java | 158 + .../r22report/DataReportPreparatorR22.java | 112 + .../definition/r22report/ExecutionR22.java | 353 ++ .../r22report/visitors/R22Visitor.java | 123 + .../r22report/visitors/R22VisitorKeys.java | 25 + .../visitors/R22VisitorParametersKeys.java | 14 + .../bomlineholder/R22AltOrDetBehaviour.java | 50 + .../R22BOMLineHolderVisitor.java | 97 + .../snecmaobject/R22ComponentVisitor.java | 218 ++ .../snecmaobject/R22ReceptorVisitor.java | 160 + .../r23report/DataReportPreparatorR23.java | 170 + .../definition/r23report/ExecutionR23.java | 259 ++ .../r23report/visitors/R23Visitor.java | 121 + .../r23report/visitors/R23VisitorKeys.java | 63 + .../bomlineholder/R23AltOrDetBehaviour.java | 77 + .../R23BOMLineHolderVisitor.java | 83 + .../snecmaobject/R23ComponentVisitor.java | 407 +++ .../snecmaobject/R23ReceptorVisitor.java | 154 + .../r24report/DataReportPreparatorR24.java | 270 ++ .../definition/r24report/ExecutionR24.java | 232 ++ .../r24report/R24BOMLineExplorer.java | 33 + .../definition/r24report/R24Printer.java | 192 ++ .../r25report/DataReportPreparatorR25.java | 298 ++ .../definition/r25report/ExecutionR25.java | 241 ++ .../r25report/R25BOMLineExplorer.java | 33 + .../definition/r25report/R25Printer.java | 230 ++ .../r26report/DataReportPreparatorR26.java | 232 ++ .../r26report/EffectivityHelper.java | 205 ++ .../definition/r26report/ExecutionR26.java | 167 + .../definition/r26report/LineManager.java | 272 ++ .../r26report/R26BOMLineExplorer.java | 29 + .../definition/r26report/R26BomLine.java | 78 + .../reports/definition/r26report/R26Keys.java | 28 + .../definition/r26report/R26Printer.java | 165 + .../reports/definition/r26report/Range.java | 59 + .../reports/definition/r26report/Ranges.java | 190 ++ .../r26report/RevisionRuleManager.java | 57 + .../definition/r26report/RfPUManager.java | 108 + .../r27report/DataReportPreparatorR27.java | 53 + .../definition/r27report/ExecutionR27.java | 151 + .../reports/definition/r27report/R27Keys.java | 8 + .../definition/r27report/R27Printer.java | 57 + .../r28report/DataReportPreparatorR28.java | 53 + .../definition/r28report/ExecutionR28.java | 151 + .../reports/definition/r28report/R28Keys.java | 10 + .../definition/r28report/R28Printer.java | 79 + .../templates/AbstractEmailTemplate.java | 133 + .../templates/BadParamEmailTemplate.java | 39 + .../emailing/templates/EmailReportHelper.java | 146 + .../templates/FailedEmailTemplate.java | 54 + .../templates/FailedEmailTemplateAdmin.java | 35 + .../FailedWorkflowEmailTemplate.java | 27 + .../FailedWorkflowEmailTemplateAdmin.java | 26 + .../templates/SuccessfulEmailTemplate.java | 59 + .../exceptions/DuplicateReportEntryFound.java | 28 + .../DuplicateSchedulingEntryFound.java | 33 + .../exceptions/FileLoadingException.java | 32 + .../InsufficientParametersException.java | 32 + .../InvalidActiveDirectoryInputException.java | 19 + ...InvalidActiveDirectorySearchException.java | 19 + .../InvalidCredentialsException.java | 32 + .../exceptions/InvalidDatasetException.java | 30 + ...oConnectionToActiveDirectoryException.java | 29 + .../exceptions/NothingToBeShownException.java | 24 + .../exceptions/ReportPrintException.java | 32 + .../execution/AbstractExecutionReport.java | 348 ++ .../execution/IDataReportPreparator.java | 31 + .../actions/AbstractPostExecutionStep.java | 57 + .../actions/AbstractPreExecutionStep.java | 53 + .../actions/CompositeErrorAction.java | 53 + .../actions/CompositePostAction.java | 40 + .../execution/actions/CompositePreAction.java | 38 + .../execution/actions/DoNothingAction.java | 48 + .../actions/IErrorExecutionStep.java | 41 + .../execution/actions/IPostExecutionStep.java | 30 + .../execution/actions/IPreExecutionStep.java | 26 + .../actions/InteractiveEmailAction.java | 58 + .../execution/actions/LoggingAction.java | 48 + .../execution/actions/QuickCheckAction.java | 28 + .../actions/ReLaunchEmailAction.java | 55 + .../actions/ScheduledEmailAction.java | 49 + .../execution/actions/UpdateReportAction.java | 52 + .../actions/UpdateReportInDbAction.java | 59 + .../ondataset/CreateDatasetAction.java | 92 + .../ondataset/DestroyRelationshipsAction.java | 81 + .../ondataset/LinkFicheArticleAction.java | 75 + .../ondataset/SerializableProvider.java | 8 + .../actions/ondataset/SetStatusAction.java | 75 + .../AbstractStaticTemplateMapConstructor.java | 40 + .../mapconstructor/IMapConstructor.java | 53 + .../strategies/AbstractExecutionStrategy.java | 212 ++ .../AutomaticExecutionStrategy.java | 76 + .../strategies/DelayedExecutionStrategy.java | 16 + .../strategies/IExecutionStrategy.java | 102 + .../ImmediateExecutionStrategy.java | 16 + .../ScheduledExecutionStrategy.java | 143 + .../reports/logging/EventsLogger.java | 31 + .../reports/logging/ReportLoggerHelper.java | 181 + .../capgemini/reports/optimized/Folder.java | 53 + .../reports/optimized/OptimizedFile.java | 11 + .../reports/optimized/OptimizedFolder.java | 10 + .../optimized/r23report/OptimizedR23File.java | 37 + .../r23report/OptimizedR23Folder.java | 26 + .../optimized/r24report/OptimizedR24File.java | 38 + .../r24report/OptimizedR24Folder.java | 26 + .../reports/periodicity/DailyPeriod.java | 44 + .../reports/periodicity/DayInMonth.java | 45 + .../reports/periodicity/PeriodFactory.java | 176 + .../reports/periodicity/SchedulingPeriod.java | 90 + .../reports/periodicity/SpecificDay.java | 82 + .../reports/periodicity/WeekendPeriod.java | 99 + .../reports/periodicity/WeeklyPeriod.java | 35 + .../reports/printing/PrintParameters.java | 444 +++ .../reports/printing/PrintReportHelper.java | 65 + .../capgemini/reports/printing/Printer.java | 60 + .../reports/queuing/ReportPriority.java | 76 + .../reports/reports/IReportVisitor.java | 24 + .../reports/reports/output/ReportOutput.java | 8 + .../reports/reports/output/ZipReport.java | 53 + .../reports/templates/Alignment.java | 22 + .../com/capgemini/reports/templates/Cell.java | 237 ++ .../reports/templates/CellFormat.java | 93 + .../capgemini/reports/templates/Column.java | 122 + .../templates/DynamicGridTemplateBuilder.java | 220 ++ .../resources/Jasper/images/Snecma_logo.png | Bin 0 -> 3973 bytes .../Jasper/images/confidentiel_industrie.jpg | Bin 0 -> 33675 bytes .../template/dynamic_table/template.jrxml | 17 + .../Jasper/template/report_r01.jrxml | 1076 ++++++ .../Jasper/template/report_r03.jrxml | 726 ++++ .../Jasper/template/report_r10.jrxml | 918 +++++ .../Jasper/template/report_r11.jrxml | 638 ++++ .../template/report_r13/report_r13_cr.jrxml | 975 ++++++ .../template/report_r13/report_r13_fpp.jrxml | 579 ++++ .../Jasper/template/report_r15r16.jrxml | 695 ++++ .../Jasper/template/report_r17.jrxml | 620 ++++ .../Jasper/template/report_r19.jrxml | 649 ++++ .../template/report_r20/Snecma_logo.png | Bin 0 -> 3973 bytes .../report_r20/page2/r20_p2_generics.jrxml | 61 + .../report_r20/page2/r20_p2_impacts.jrxml | 28 + .../report_r20/page2/r20_p2_noimpacts.jrxml | 28 + .../report_r20/page3/report_r20_p3.jrxml | 108 + .../report_r20/report_r20_master.jrxml | 286 ++ .../template/report_r20/report_r20_p1.jrxml | 255 ++ .../template/report_r20/report_r20_p2.jrxml | 106 + .../template/report_r20/report_r20_p4.jrxml | 265 ++ .../Jasper/template/report_r21.jrxml | 1027 ++++++ .../Jasper/template/report_r22.jrxml | 912 +++++ .../Jasper/template/report_r23.jrxml | 1404 ++++++++ .../Jasper/template/report_r24.jrxml | 499 +++ .../Jasper/template/report_r25.jrxml | 790 +++++ .../report_r26/report_r26_master.jrxml | 142 + .../report_r26/report_r26_subreport.jrxml | 536 +++ .../Jasper/template/report_r27.jrxml | 30 + .../Jasper/template/report_r28.jrxml | 55 + .../Jasper/template/template_R07.jrxml | 18 + .../src/main/resources/hibernate.cfg.xml | 42 + .../hibernate/DbCriteriaVal_mapping.xml | 19 + .../hibernate/DbCriteria_mapping.xml | 19 + .../hibernate/DbMemMonitor_mapping.xml | 24 + .../hibernate/DbReportOwner_mapping.xml | 21 + .../hibernate/DbReportType_mapping.xml | 23 + .../resources/hibernate/DbReport_mapping.xml | 28 + .../DbSchedulingCriteriaVal_mapping.xml | 18 + .../hibernate/DbSchedulingReport_mapping.xml | 20 + .../resources/hibernate/DbUser_mapping.xml | 23 + .../email/template_email_bad_parameters.html | 7 + .../html/email/template_email_failed.html | 7 + .../email/template_email_failed_admin.html | 7 + .../html/email/template_email_finished.html | 7 + .../html/email/template_email_posted.html | 4 + .../html/email/template_email_started.html | 5 + .../main/resources/html/error_jsp_page.html | 30 + .../src/main/resources/log4j.properties | 16 + .../src/main/resources/quartz.properties | 56 + .../src/main/resources/reporting.properties | 99 + .../policies/r01report/R01_policy_full.xml | 128 + .../policies/r01report/R01_policy_light.xml | 48 + .../policies/r03report/R03_policy_full.xml | 127 + .../policies/r03report/R03_policy_light.xml | 63 + .../policies/r07report/R07_policy_full.xml | 145 + .../policies/r07report/R07_policy_light.xml | 48 + .../policies/r10report/R10_policy_full.xml | 167 + .../policies/r10report/R10_policy_light.xml | 48 + .../policies/r11report/R11_policy_full.xml | 59 + .../policies/r11report/R11_policy_light.xml | 48 + .../policies/r13report/R13_policy_full.xml | 75 + .../policies/r13report/R13_policy_light.xml | 87 + .../policies/r15report/R15_policy_full.xml | 115 + .../policies/r15report/R15_policy_light.xml | 47 + .../xml/policies/r15report/R15_policy_wkf.xml | 52 + .../policies/r16report/R16_policy_full.xml | 98 + .../policies/r16report/R16_policy_light.xml | 50 + .../policies/r17report/R17_policy_full.xml | 108 + .../policies/r17report/R17_policy_light.xml | 46 + .../policies/r19report/R19_policy_full.xml | 144 + .../policies/r19report/R19_policy_light.xml | 28 + .../policies/r20report/R20_policy_full.xml | 71 + .../policies/r20report/R20_policy_light.xml | 91 + .../policies/r21report/R21_policy_full.xml | 27 + .../policies/r21report/R21_policy_light.xml | 36 + .../policies/r22report/R22_policy_full.xml | 119 + .../policies/r22report/R22_policy_light.xml | 46 + .../xml/policies/r22report/R22_policy_wkf.xml | 51 + .../policies/r23report/R23_policy_full.xml | 152 + .../policies/r23report/R23_policy_light.xml | 48 + .../policies/r24report/R24_policy_full.xml | 100 + .../policies/r24report/R24_policy_light.xml | 50 + .../policies/r25report/R25_policy_full.xml | 100 + .../policies/r25report/R25_policy_light.xml | 50 + .../policies/r26report/R26_policy_full.xml | 86 + .../policies/r26report/R26_policy_light.xml | 48 + .../policies/r27report/R27_policy_full.xml | 13 + .../policies/r27report/R27_policy_light.xml | 13 + .../policies/r28report/R28_policy_full.xml | 19 + .../policies/r28report/R28_policy_light.xml | 19 + .../src/main/resources/xsd/policies.xsd | 26 + kurt-utility/src/main/sh/JenkinsDeploy.bat | 41 + .../main/sh/JenkinsDeploy.bat:Zone.Identifier | 2 + kurt-utility/src/main/sh/JenkinsDeploy.vbs | 8 + .../main/sh/JenkinsDeploy.vbs:Zone.Identifier | 2 + kurt-utility/src/main/sh/jenkins_packaging.sh | 165 + kurt-utility/src/main/xsd/policies.xsd | 26 + .../framework/common/DateHelperTest.java | 43 + .../framework/common/DoubleFormatterTest.java | 52 + .../DynamicErrorTemplateHelperTest.java | 14 + .../definition/r26report/RangesTest.java | 306 ++ .../reports/printing/PrintParametersTest.java | 36 + .../capgemini/reports/templates/CellTest.java | 148 + .../reports/templates/ColumnTest.java | 125 + .../DynamicGridTemplateBuilderTest.java | 69 + .../template/dynamic_table/reference.jrxml | 175 + .../template/dynamic_table/template.jrxml | 23 + .../src/test/resources/hibernate.cfg.xml | 49 + .../email/template_email_bad_parameters.html | 8 + .../html/email/template_email_failed.html | 7 + .../email/template_email_failed_admin.html | 7 + .../html/email/template_email_finished.html | 7 + .../html/email/template_email_posted.html | 4 + .../html/email/template_email_started.html | 5 + .../src/test/resources/log4j.properties | 13 + .../xml/policies/PoliciesDomParserTest.xml | 17 + .../resources/xml/policies/bom_policy.xml | 54 + .../resources/xml/policies/policy_full.xml | 171 + .../resources/xml/policies/policy_light.xml | 48 + .../resources/xml/policies/test_policy.xml | 159 + .../MultiStructureServiceCallerTest_item.xml | 17 + ...ructureServiceCallerTest_item_revision.xml | 17 + .../ref/StructureServiceCallerTest_mono.xml | 14 + .../ref/StructureServiceCallerTest_multi.xml | 17 + .../TripleStructureServiceCallerTest_item.xml | 14 + ...ructureServiceCallerTest_item_revision.xml | 0 .../definition/r01report/Test_R01.java | 106 + .../definition/r03report/Test_R03.java | 103 + .../definition/r07report/Test_R07.java | 108 + .../definition/r10report/Test_R10.java | 115 + .../definition/r11report/Test_R11.java | 110 + .../definition/r13report/Test_CrR13.java | 105 + .../definition/r13report/Test_FppR13.java | 106 + .../definition/r15report/Test_R15.java | 94 + .../definition/r16report/Test_R16.java | 96 + .../definition/r17report/Test_R17.java | 91 + .../definition/r19report/Test_R19.java | 107 + .../definition/r20report/Test_R20.java | 96 + .../definition/r21report/Test_R21.java | 109 + .../definition/r22report/Test_R22.java | 98 + .../definition/r23report/Test_R23.java | 130 + .../definition/r24report/Test_R24.java | 138 + .../definition/r25report/Test_R25.java | 161 + .../src/val/java/compare/Comparer_XML.java | 112 + .../val/java/compare/CriteresComparaison.java | 54 + .../src/val/java/compare/ExcelTest.java | 152 + .../FolderFilesReferenced/r01/r01.xlsx | Bin 0 -> 4815 bytes .../r01/r01.xlsx:Zone.Identifier | 2 + .../FolderFilesReferenced/r03/r03.xlsx | Bin 0 -> 15745 bytes .../r03/r03.xlsx:Zone.Identifier | 2 + .../FolderFilesReferenced/r07/r07.xlsx | Bin 0 -> 17954 bytes .../r07/r07.xlsx:Zone.Identifier | 2 + .../FolderFilesReferenced/r10/r10.xlsx | Bin 0 -> 5610 bytes .../r10/r10.xlsx:Zone.Identifier | 2 + .../FolderFilesReferenced/r11/r11.xlsx | Bin 0 -> 5774 bytes .../r11/r11.xlsx:Zone.Identifier | 2 + .../FolderFilesReferenced/r13/r13_cr.xlsx | Bin 0 -> 6548 bytes .../r13/r13_cr.xlsx:Zone.Identifier | 2 + .../FolderFilesReferenced/r13/r13_fpp.xlsx | Bin 0 -> 4869 bytes .../r13/r13_fpp.xlsx:Zone.Identifier | 2 + .../FolderFilesReferenced/r15/r15.pdf | Bin 0 -> 13349 bytes .../FolderFilesReferenced/r16/r16.pdf | Bin 0 -> 12601 bytes .../FolderFilesReferenced/r17/r17.pdf | Bin 0 -> 19217 bytes .../FolderFilesReferenced/r19/r19.xlsx | Bin 0 -> 4689 bytes .../r19/r19.xlsx:Zone.Identifier | 2 + .../FolderFilesReferenced/r20/r20.pdf | Bin 0 -> 18548 bytes .../FolderFilesReferenced/r21/r21.xlsx | Bin 0 -> 4842 bytes .../r21/r21.xlsx:Zone.Identifier | 2 + .../FolderFilesReferenced/r22/r22.pdf | Bin 0 -> 59350 bytes .../FolderFilesReferenced/r23/r23.zip | Bin 0 -> 4181 bytes .../FolderFilesReferenced/r24/r24.zip | Bin 0 -> 10539 bytes .../FolderFilesReferenced/r25/r25.zip | Bin 0 -> 364055 bytes .../src/val/resources/reporting.properties | 200 ++ kurt-utility/src/val/resources/testng.xml | 694 ++++ kurt-utility/src/val/resources/testng.yaml | 179 + kurt-web/pom.xml | 136 + .../capgemini/reports/DispatcherServlet.java | 91 + .../auto/AbstractAutoLaunchServlet.java | 160 + .../reports/common/AbstractKurtServlet.java | 165 + .../reports/common/AbstractSubmitServlet.java | 177 + .../AbstractSubmitServletForItemRevision.java | 35 + .../reports/common/DownloadServlet.java | 127 + .../reports/common/ServletMessageHelper.java | 146 + .../capgemini/reports/common/TestServlet.java | 77 + .../AbstractObtainDataFromItemRevision.java | 95 + .../AbstractObtainDataFromModelObject.java | 86 + .../AbstractObtainDataFromPartRevision.java | 38 + .../obtaindata/AbstractObtainDataServlet.java | 50 + ...tractGenerateScheduledTemplateServlet.java | 240 ++ .../scheduling/DeleteServletScheduling.java | 64 + .../scheduling/ModifyServletScheduling.java | 90 + .../scheduling/SubmitServletScheduling.java | 132 + .../controller/QueueReaderServlet.java | 91 + .../controller/SchedulingReaderServlet.java | 227 ++ .../utilities/AbstractActionManager.java | 118 + .../ReportActivationReaderServlet.java | 58 + .../utilities/ReportActivatorServlet.java | 53 + .../SchedulingPeriodReaderServlet.java | 70 + .../view/NewSchedulingFormatter.java | 37 + .../scheduling/view/SchedulingFormatter.java | 306 ++ .../view/SchedulingParametersReader.java | 56 + .../view/UpdateSchedulingFormatter.java | 79 + .../formatting/AbstractTableFormatter.java | 99 + .../formatting/AllSchedulingReports.java | 289 ++ .../reports/formatting/ErrorPageTemplate.java | 38 + .../reports/formatting/JsArrayCreator.java | 55 + .../reports/formatting/JsTableCreator.java | 104 + .../reports/formatting/MyReports.java | 133 + .../reports/formatting/QueueStatus.java | 94 + .../reports/formatting/RunningReports.java | 57 + .../statsgen/AbstractTableGenerator.java | 68 + .../ExecutionCountTableGenerator.java | 50 + .../statsgen/TimingsTableGenerator.java | 30 + .../reports/r01/SubmitServletR01.java | 58 + .../reports/r03/ObtainDataServletR03.java | 39 + .../reports/r03/SubmitServletR03.java | 21 + .../reports/r07/SubmitServletR07.java | 44 + .../reports/r10/SubmitServletR10.java | 47 + .../reports/r11/SubmitServletR11.java | 43 + .../reports/r13/SubmitServletR13.java | 46 + .../reports/r15/ObtainDataServletR15.java | 39 + .../capgemini/reports/r15/R15AutoServlet.java | 50 + .../reports/r15/SubmitServletR15.java | 25 + .../reports/r16/SubmitServletR16.java | 33 + .../reports/r17/ObtainDataServletR17.java | 38 + .../reports/r17/SubmitServletR17.java | 25 + .../reports/r19/ObtainDataServletR19.java | 102 + .../reports/r19/SubmitServletR19.java | 29 + .../reports/r20/SubmitServletR20.java | 62 + .../reports/r21/SubmitServletR21.java | 44 + .../reports/r22/ObtainDataServletR22.java | 45 + .../capgemini/reports/r22/R22AutoServlet.java | 54 + .../reports/r22/SubmitServletR22.java | 22 + .../reports/r23/SubmitServletR23.java | 76 + .../reports/r24/SubmitServletR24.java | 32 + .../reports/r25/SubmitServletR25.java | 35 + .../reports/r26/ObtainDataServletR26.java | 50 + .../reports/r26/SubmitServletR26.java | 31 + .../reports/r27/SubmitServletR27.java | 28 + .../reports/r28/SubmitServletR28.java | 21 + .../html/myReports/my_reports_failed.html | 28 + .../html/myReports/my_reports_success.html | 46 + .../html/queueStatus/queue_status_failed.html | 31 + .../queueStatus/queue_status_success.html | 36 + .../running_reports_failed.html | 40 + .../running_reports_success.html | 54 + .../schedulingReports_error.html | 31 + .../schedulingReports_success.html | 132 + kurt-web/src/main/webapp/WEB-INF/beans.xml | 27 + kurt-web/src/main/webapp/WEB-INF/ejb-jar.xml | 26 + kurt-web/src/main/webapp/WEB-INF/web.xml | 58 + kurt-web/src/main/webapp/css/dialog.css | 66 + .../src/main/webapp/css/kurt-style-frame.css | 177 + kurt-web/src/main/webapp/css/kurt-style.css | 114 + kurt-web/src/main/webapp/css/pikaday.css | 194 ++ kurt-web/src/main/webapp/css/scheduling.css | 29 + .../webapp/frames/all_scheduling_reports.jsp | 57 + kurt-web/src/main/webapp/frames/criteria.jsp | 65 + .../src/main/webapp/frames/mem_monitoring.jsp | 79 + .../src/main/webapp/frames/my_reports.jsp | 9 + kurt-web/src/main/webapp/frames/queue.jsp | 26 + .../frames/report_not_authorized_message.jsp | 1 + .../main/webapp/frames/running_reports.jsp | 9 + .../webapp/frames/scheduling_criteria.jsp | 67 + .../main/webapp/frames/scheduling_delete.jsp | 68 + .../src/main/webapp/frames/scheduling_new.jsp | 122 + .../main/webapp/frames/scheduling_update.jsp | 127 + .../webapp/frames/statistics_per_report.jsp | 104 + .../webapp/frames/statistics_per_user.jsp | 100 + .../main/webapp/frames/submitNewReport.jsp | 101 + .../src/main/webapp/frames/template_r01.jsp | 164 + .../src/main/webapp/frames/template_r03.jsp | 82 + .../src/main/webapp/frames/template_r07.jsp | 172 + .../src/main/webapp/frames/template_r10.jsp | 136 + .../src/main/webapp/frames/template_r11.jsp | 118 + .../src/main/webapp/frames/template_r13.jsp | 140 + .../src/main/webapp/frames/template_r15.jsp | 86 + .../src/main/webapp/frames/template_r16.jsp | 148 + .../src/main/webapp/frames/template_r17.jsp | 91 + .../src/main/webapp/frames/template_r19.jsp | 80 + .../src/main/webapp/frames/template_r20.jsp | 375 ++ .../src/main/webapp/frames/template_r21.jsp | 116 + .../src/main/webapp/frames/template_r22.jsp | 85 + .../src/main/webapp/frames/template_r23.jsp | 231 ++ .../src/main/webapp/frames/template_r24.jsp | 137 + .../src/main/webapp/frames/template_r25.jsp | 140 + .../src/main/webapp/frames/template_r26.jsp | 94 + .../src/main/webapp/frames/template_r27.jsp | 45 + .../src/main/webapp/frames/template_r28.jsp | 45 + .../main/webapp/ihm/bt-error-functional.png | Bin 0 -> 543 bytes .../main/webapp/ihm/bt-error-technical.png | Bin 0 -> 314 bytes kurt-web/src/main/webapp/ihm/bt-refresh.png | Bin 0 -> 832 bytes kurt-web/src/main/webapp/ihm/bt-save.png | Bin 0 -> 620 bytes kurt-web/src/main/webapp/ihm/bt-search.png | Bin 0 -> 800 bytes kurt-web/src/main/webapp/ihm/button-back.png | Bin 0 -> 465 bytes .../webapp/ihm/calendar_planification.png | Bin 0 -> 27629 bytes kurt-web/src/main/webapp/ihm/delete.png | Bin 0 -> 9186 bytes kurt-web/src/main/webapp/ihm/dialog.gif | Bin 0 -> 129 bytes .../ihm/generateur-rapports-teamcenter.png | Bin 0 -> 21397 bytes kurt-web/src/main/webapp/ihm/ico-admin.png | Bin 0 -> 876 bytes kurt-web/src/main/webapp/ihm/ico-email.png | Bin 0 -> 692 bytes kurt-web/src/main/webapp/ihm/ico-jboss.png | Bin 0 -> 654 bytes kurt-web/src/main/webapp/ihm/ico-progress.png | Bin 0 -> 7236 bytes kurt-web/src/main/webapp/ihm/ico-queue.png | Bin 0 -> 3653 bytes kurt-web/src/main/webapp/ihm/ico-queued.png | Bin 0 -> 418 bytes .../src/main/webapp/ihm/ico-report-stats.png | Bin 0 -> 7278 bytes kurt-web/src/main/webapp/ihm/ico-report.png | Bin 0 -> 737 bytes .../src/main/webapp/ihm/ico-scheduled.png | Bin 0 -> 824 bytes kurt-web/src/main/webapp/ihm/ico-stats.png | Bin 0 -> 1021 bytes kurt-web/src/main/webapp/ihm/ico-user.png | Bin 0 -> 876 bytes kurt-web/src/main/webapp/ihm/icone-moins.png | Bin 0 -> 507 bytes kurt-web/src/main/webapp/ihm/icone-plus.png | Bin 0 -> 558 bytes kurt-web/src/main/webapp/ihm/input-back.png | Bin 0 -> 245 bytes .../webapp/ihm/left-bar-action-back-hover.png | Bin 0 -> 207 bytes .../main/webapp/ihm/left-bar-action-back.png | Bin 0 -> 206 bytes kurt-web/src/main/webapp/ihm/left-bar-top.png | Bin 0 -> 261 bytes kurt-web/src/main/webapp/ihm/left-bar.png | Bin 0 -> 365 bytes kurt-web/src/main/webapp/ihm/left-bar_160.png | Bin 0 -> 356 bytes kurt-web/src/main/webapp/ihm/left-bar_260.png | Bin 0 -> 359 bytes kurt-web/src/main/webapp/ihm/progress.gif | Bin 0 -> 7110 bytes kurt-web/src/main/webapp/ihm/report.png | Bin 0 -> 12614 bytes .../src/main/webapp/ihm/state_executing.png | Bin 0 -> 3400 bytes kurt-web/src/main/webapp/ihm/state_failed.png | Bin 0 -> 2928 bytes .../src/main/webapp/ihm/state_finished.png | Bin 0 -> 3028 bytes kurt-web/src/main/webapp/ihm/state_ready.png | Bin 0 -> 2683 bytes .../src/main/webapp/ihm/state_unknown.png | Bin 0 -> 3099 bytes kurt-web/src/main/webapp/ihm/state_wait.png | Bin 0 -> 3051 bytes kurt-web/src/main/webapp/ihm/title.png | Bin 0 -> 36599 bytes kurt-web/src/main/webapp/ihm/top-bar.png | Bin 0 -> 386 bytes kurt-web/src/main/webapp/ihm/update.png | Bin 0 -> 7249 bytes kurt-web/src/main/webapp/index.jsp | 225 ++ kurt-web/src/main/webapp/js/criteria.js | 17 + kurt-web/src/main/webapp/js/dialog_box.js | 71 + kurt-web/src/main/webapp/js/index.js | 20 + kurt-web/src/main/webapp/js/json2.js | 489 +++ .../src/main/webapp/js/kurt-common-submit.js | 167 + kurt-web/src/main/webapp/js/moment.js | 3037 +++++++++++++++++ kurt-web/src/main/webapp/js/my_reports.js | 53 + kurt-web/src/main/webapp/js/obtain_data.js | 27 + kurt-web/src/main/webapp/js/pikaday.js | 915 +++++ kurt-web/src/main/webapp/js/post_form.js | 60 + kurt-web/src/main/webapp/js/queue.js | 83 + .../src/main/webapp/js/running_reports.js | 49 + .../src/main/webapp/js/schedulingReport.js | 412 +++ .../webapp/js/schedulingReportsCreaUpd.js | 42 + kurt-web/src/main/webapp/js/statistics.js | 109 + .../common/AbstractKurtServletTest.java | 178 + .../common/AbstractSubmitServletTest.java | 368 ++ .../scheduling/SchedulingServletTest.java | 87 + .../reports/formatting/MyReportsTest.java | 58 + .../capgemini/servlet/test/Report01Test.java | 84 + .../htmlRef/my_reports_failed_ref.html | 28 + .../htmlRef/my_reports_success_ref.html | 46 + kurt-web/src/test/resources/log4j.properties | 13 + .../src/test/resources/logging.properties | 3 + .../test/resources/simplelogger.properties | 0 .../resources/xml/policies/simple_policy.xml | 91 + .../resources/xml/policies/test_policy.xml | 165 + pom.xml | 500 +++ scripts/reports_installation_script.pl | 96 + standalone-pv-reports-auth.xml | 580 ++++ standalone-pv-reports.xml | 584 ++++ teamcenter/pom.xml | 196 ++ .../framework/common/BeanHelper.java | 79 + .../framework/common/LanguageHelper.java | 91 + .../framework/common/ReflectionHelper.java | 93 + .../framework/common/StringHelper.java | 228 ++ .../common/TeamcenterDateFormatter.java | 161 + .../framework/common/security/AesEncoded.java | 39 + .../teamcenter/ServiceDataHelper.java | 72 + .../TeamcenterObjectProperties.java | 146 + .../teamcenter/TeamcenterObjectTypes.java | 83 + .../teamcenter/authent/AuthentPropLoader.java | 92 + .../teamcenter/authent/FscParameters.java | 20 + .../authent/KurtModelEventListener.java | 57 + .../authent/TcCredentialManager.java | 77 + .../authent/TcExceptionHandler.java | 108 + .../teamcenter/authent/TcSession.java | 716 ++++ .../ConnectionMisconguredException.java | 24 + .../EmptyNomenclatureException.java | 35 + .../FailedRelationshipActionException.java | 29 + .../InvalidConfigurationException.java | 29 + .../teamcenter/exceptions/KurtException.java | 40 + .../exceptions/MalformedDataSetException.java | 27 + .../exceptions/NoSuchBomViewException.java | 28 + .../NoSuchRevisionRuleException.java | 29 + .../NoTeamcenterConnectionException.java | 27 + .../exceptions/QueryDoesNotExist.java | 27 + .../UnableToCreateStatusException.java | 28 + .../runtime/ConnectionLostException.java | 19 + .../runtime/KurtRuntimeException.java | 26 + .../teamcenter/files/DatasetPreparator.java | 154 + .../teamcenter/files/FileManagement.java | 117 + .../object/SnecmaObjectProperties.java | 221 ++ .../teamcenter/object/TcBusinessObject.java | 4 + .../teamcenter/object/TcModelObject.java | 6 + .../teamcenter/object/pom/TcPomObject.java | 6 + .../object/pom/status/StatusEnum.java | 273 ++ .../object/pom/status/TcEffectivity.java | 62 + .../object/pom/status/TcReleaseStatus.java | 202 ++ .../object/pom/workspace/TcItem.java | 5 + .../object/pom/workspace/TcItemRevision.java | 4 + .../pom/workspace/TcWorkspaceObject.java | 6 + .../object/pom/workspace/bom/TcBomObject.java | 8 + .../pom/workspace/bom/TcBomObjectFactory.java | 105 + .../pom/workspace/bom/TcRFPartRevision.java | 17 + .../pom/workspace/bom/TcRevisionRule.java | 29 + .../bom/TcRevisionRuleProperties.java | 43 + .../pom/workspace/bom/generic/TcGeneric.java | 21 + .../bom/generic/TcGenericAssemb.java | 19 + .../bom/generic/TcGenericAssembRevision.java | 18 + .../workspace/bom/generic/TcGenericPv.java | 6 + .../bom/generic/TcGenericPvRevision.java | 6 + .../bom/generic/TcGenericRevision.java | 18 + .../workspace/bom/generic/TcRFGeneric.java | 18 + .../bom/generic/TcRFGenericRevision.java | 16 + .../pom/workspace/bom/part/TcAlternate.java | 20 + .../bom/part/TcAlternateRevision.java | 18 + .../object/pom/workspace/bom/part/TcDet.java | 20 + .../pom/workspace/bom/part/TcDetRevision.java | 18 + .../pom/workspace/bom/part/TcPartAero.java | 19 + .../bom/part/TcPartAeroRevision.java | 18 + .../pom/workspace/bom/part/TcPartAssemb.java | 18 + .../bom/part/TcPartAssembRevision.java | 18 + .../pom/workspace/bom/part/TcPartMat.java | 18 + .../workspace/bom/part/TcPartMatRevision.java | 18 + .../pom/workspace/bom/part/TcPartNoAero.java | 18 + .../bom/part/TcPartNoAeroRevision.java | 18 + .../pom/workspace/bom/part/TcStandard.java | 18 + .../bom/part/TcStandardRevision.java | 18 + .../pom/workspace/bom/product/TcProduct.java | 43 + .../bom/product/TcProductRevision.java | 219 ++ .../workspace/bom/unit/TcUnitRevision.java | 177 + .../teamcenter/object/runtime/TcBomLine.java | 23 + .../object/runtime/TcBomWindow.java | 32 + .../runtime/TcBomWindowConfiguration.java | 30 + .../object/runtime/TcBomWindowFactory.java | 27 + .../runtime/TcRevisionRulesConfiguration.java | 27 + .../runtime/TcRuntimeBusinessObject.java | 6 + .../object/types/SnecmaObjectTypes.java | 465 +++ .../teamcenter/policies/PolicyLocation.java | 53 + .../saved/AbstractReplicatedQuery.java | 157 + .../queries/saved/AbstractSavedQuery.java | 249 ++ .../modelobject/AbstractModelObjectQuery.java | 80 + .../saved/modelobject/IMANRelationQuery.java | 69 + .../queries/saved/modelobject/ItemQuery.java | 25 + .../saved/modelobject/ItemRevisionQuery.java | 26 + .../resolution/filtering/AllFilter.java | 33 + .../resolution/filtering/AndFilter.java | 22 + .../resolution/filtering/ITcTypeFilter.java | 22 + .../resolution/filtering/OrFilter.java | 21 + .../filtering/TcTypeExclusionFilter.java | 30 + .../filtering/TcTypeInclusionFilter.java | 30 + .../AbstractStructureServiceRaw.java | 29 + .../MultiStructureServiceCallerRaw.java | 85 + .../SingleStructureServiceCallerRaw.java | 136 + .../teamcenter/statuating/StatusSetter.java | 74 + .../reports/ItemRevisionComparator.java | 21 + .../reports/bomlineholder/BOMLineHolder.java | 422 +++ .../bomlineholder/BOMLineHolderFactory.java | 114 + .../bomlineholder/BOMLineHolderHelper.java | 138 + .../reports/bomlineholder/IBOMTree.java | 92 + .../bomlineholder/ISnecmaLineProcessor.java | 106 + .../AbstractDualBomLineFlattener.java | 214 ++ .../comparison/DualBomLineBrowser.java | 588 ++++ .../comparison/IDualSnecmaLineProcessor.java | 105 + .../flattener/AbstractBomLineFlattener.java | 158 + .../flattener/AbstractRepereFlattener.java | 104 + .../flattener/line/AbstractAltPart.java | 254 ++ .../flattener/line/AbstractPartNumber.java | 80 + .../flattener/line/AbstractPartPart.java | 73 + .../flattener/line/AbstractPartRfPart.java | 293 ++ .../line/AbstractProductGeneric.java | 283 ++ .../flattener/line/AbstractQuad.java | 386 +++ .../flattener/line/AbstractReceptorLine.java | 264 ++ .../line/AbstractReceptorRepere.java | 207 ++ .../flattener/line/AbstractTopLine.java | 223 ++ .../line/PartTypeExtractorHelper.java | 71 + .../flattener/line/SnecmaLine.java | 241 ++ .../processor/AltOrDetBehaviour.java | 48 + .../processor/DefaultAltOrDetBehaviour.java | 127 + .../processor/IBOMLineHolderProcessor.java | 20 + .../visitor/AbstractBOMLineHolderVisitor.java | 597 ++++ .../bomlineholder/visitor/BomLineBrowser.java | 376 ++ .../visitor/IBOMLineHolderExtractor.java | 23 + .../visitor/IBOMLineHolderVisitor.java | 26 + .../reports/changeobjects/UnitRevision.java | 343 ++ .../change/AbstractChangeObject.java | 195 ++ .../changeobjects/change/FPPRevision.java | 41 + .../change/TcChangeNoticeRevision.java | 121 + .../change/TcChangeRequestRevision.java | 114 + .../documentationobjects/AbstractDoc.java | 113 + .../documentationobjects/DocDrawing.java | 32 + .../documentationobjects/DocFactory.java | 56 + .../documentationobjects/DocGeometry.java | 37 + .../reports/documentationobjects/DocNorm.java | 82 + .../documentationobjects/DocNormStandard.java | 75 + .../documentationobjects/DocTechnic.java | 50 + .../documentationobjects/IDocVisitor.java | 49 + .../exceptions/InvalidInputException.java | 84 + .../exceptions/InvalidUserInputException.java | 90 + .../MalformedNomenclatureException.java | 31 + .../exceptions/NoConfChangesException.java | 10 + .../reports/exceptions/NotFoundException.java | 29 + .../exceptions/NotSupportedException.java | 30 + .../reports/exceptions/ServiceException.java | 32 + .../exceptions/UserInputErrorEnum.java | 184 + .../reports/filter/AllIsGoodFilter.java | 30 + .../reports/filter/FilterExcludeByType.java | 29 + .../reports/filter/FilterIncludeByType.java | 30 + .../filter/IFilterExplosionNomenclature.java | 28 + .../DefaultRevisionSelector.java | 69 + .../EffectivityBehaviourHelper.java | 99 + .../releasestatus/RevisionSelector.java | 23 + .../releasestatus/RevisionStatusAndDate.java | 20 + .../reports/parameters/DualGenerics.java | 50 + .../reports/parameters/EffectivityDate.java | 102 + .../reports/reports/parameters/Generics.java | 197 ++ .../reports/reports/parameters/IChecker.java | 20 + .../reports/reports/parameters/MonoMulti.java | 28 + .../reports/parameters/ProductUnit.java | 106 + .../reports/parameters/SuperModel.java | 116 + .../checker/EffectivityChecker.java | 37 + .../checker/GenericConditionR21Checker.java | 89 + .../checker/GenericExistenceChecker.java | 64 + .../GenericUnderProductUnitChecker.java | 98 + .../checker/ModelObjectChecker.java | 64 + .../parameters/checker/ObjectTypeChecker.java | 63 + .../parameters/checker/ProductChecker.java | 47 + .../checker/ProductUnitChecker.java | 80 + .../checker/ProductUnitGenericChecker.java | 110 + .../checker/UnitRevisionChecker.java | 131 + .../snecmaobjects/AbstractSnecmaObject.java | 352 ++ .../reports/snecmaobjects/ISnecmaObject.java | 121 + .../snecmaobjects/SnecmaObjectFactory.java | 96 + .../snecmaobjects/admin/AbstractAdmin.java | 22 + .../admin/RFAdminAGRevision.java | 49 + .../admin/RFAdminAPRevision.java | 53 + .../snecmaobjects/admin/RFAdminARevision.java | 58 + .../snecmaobjects/admin/RFAdminRevision.java | 93 + .../descriptif/DescriptifRevision.java | 37 + .../generic/AbstractGeneric.java | 42 + .../generic/AbstractGenericRevision.java | 59 + .../snecmaobjects/generic/Generic.java | 11 + .../snecmaobjects/generic/GenericAssemb.java | 11 + .../generic/GenericAssembRevision.java | 39 + .../generic/GenericRevision.java | 32 + .../snecmaobjects/mockup/MockupRevision.java | 42 + .../part/AbstractAltOrDetRevision.java | 52 + .../snecmaobjects/part/AbstractPart.java | 320 ++ .../snecmaobjects/part/AlternateRevision.java | 52 + .../snecmaobjects/part/DETRevision.java | 50 + .../snecmaobjects/part/PartAeroRevision.java | 60 + .../part/PartAssembRevision.java | 49 + .../snecmaobjects/part/PartMatRevision.java | 49 + .../part/PartNoAeroRevision.java | 44 + .../snecmaobjects/part/StandardRevision.java | 49 + .../product/ProductRevision.java | 85 + .../reports/snecmaobjects/rf/AbstractRF.java | 27 + .../snecmaobjects/rf/RFGenericRevision.java | 44 + .../rf/RFPartAssembRevision.java | 44 + .../snecmaobjects/rf/RFPartRevision.java | 44 + .../supermodel/AbstractSuperModel.java | 42 + .../AbstractSuperModelRevision.java | 59 + .../snecmaobjects/supermodel/SuperModel.java | 12 + .../supermodel/SuperModelRevision.java | 33 + .../visitor/IComponentVisitor.java | 206 ++ .../visitor/IReceptorVisitor.java | 220 ++ .../reports/teamcenter/ObjectInfoHelper.java | 687 ++++ .../reports/teamcenter/ObjectInfoLoader.java | 396 +++ .../reports/teamcenter/Platform.java | 19 + .../teamcenter/queries/DirectQuery.java | 33 + .../reports/teamcenter/queries/TypeQuery.java | 88 + .../saved/AllSequencesOfItemQuery.java | 43 + .../queries/saved/ChangeFromPartQuery.java | 42 + .../queries/saved/ChangeNoticeR07Query.java | 42 + .../queries/saved/ChangeRequestQuery.java | 31 + .../queries/saved/ChangeRequestR07Query.java | 44 + .../saved/ChangeRequestWithSeqQuery.java | 31 + .../queries/saved/FppWithSeqQuery.java | 31 + .../queries/saved/GenericAssembQuery.java | 37 + .../queries/saved/GenericQuery.java | 29 + .../queries/saved/ProductTypeQuery.java | 39 + .../saved/UnitFromChangeRequestQuery.java | 38 + .../teamcenter/queries/saved/UnitQuery.java | 52 + .../queries/saved/WorkflowOnChangeQuery.java | 48 + .../queries/saved/WorkflowOnUnitQuery.java | 44 + .../resolution/IBOMLineExplorer.java | 25 + .../IStructureServiceCaller.java | 27 + .../MultiStructureServiceCaller.java | 29 + .../SingleStructureServiceCaller.java | 89 + .../TripleStructureServiceCaller.java | 187 + .../explorer/PartNumberFinder.java | 38 + .../capgemini/reports/users/SnecmaPerson.java | 31 + .../capgemini/reports/users/SnecmaUser.java | 53 + .../com/capgemini/reports/workflows/Task.java | 234 ++ .../soa/exceptions/NotLoadedException.java | 14 + .../capgemini/framework/common/DummyBean.java | 52 + .../common/ReflectionHelperTest.java | 28 + .../framework/common/StringHelperTest.java | 25 + .../common/TeamcenterDateFormatterTest.java | 30 + .../files/DatasetPreparatorTest.java | 99 + .../teamcenter/files/FileManagementTest.java | 104 + .../saved/modelobject/ItemQueryTest.java | 69 + .../modelobject/ItemRevisionQueryTest.java | 140 + .../relations/RelationshipManagerTest.java | 63 + .../statuating/StatusSetterTest.java | 58 + .../reports/AbstractTeamcenterTest.java | 233 ++ .../capgemini/reports/ScenarioForTests.java | 101 + .../reports/TeamcenterTypeObjectsTest.java | 78 + .../AbstractChangeObjectTest.java | 103 + .../changeobjects/UnitRevisionTest.java | 215 ++ .../documentationobjects/DocDrawingTest.java | 36 + .../documentationobjects/DocGeometryTest.java | 37 + .../DocNormStandardTest.java | 37 + .../documentationobjects/DocNormTest.java | 40 + .../documentationobjects/DocTechnicTest.java | 51 + .../releasestatus/TcReleaseStatusTest.java | 58 + .../reports/parameters/DualsGenericsTest.java | 47 + .../reports/parameters/GenericsTest.java | 58 + .../reports/parameters/ProductUnitTest.java | 56 + .../parameters/TcEffectivityDateTest.java | 76 + .../checker/GenericExistenceCheckTest.java | 55 + .../checker/ObjectTypeCheckerTest.java | 86 + .../parameters/checker/ProductCheckTest.java | 31 + .../checker/ProductUnitCheckTest.java | 40 + .../checker/TcEffectivityCheckerTest.java | 41 + .../teamcenter/ObjectInfoHelperTest.java | 217 ++ .../teamcenter/TeamcenterConnectionTest.java | 27 + .../teamcenter/queries/TypeQueryTest.java | 44 + .../queries/saved/AllSequencesQueryTest.java | 35 + .../queries/saved/ChangeRequestQueryTest.java | 49 + .../queries/saved/UnitFromCRTest.java | 41 + .../queries/saved/UnitQueryTest.java | 44 + .../saved/WorkflowOnChangeQueryTest.java | 33 + .../queries/saved/WorkflowQueryTest.java | 34 + .../reports/users/SnecmaPersonTest.java | 41 + .../reports/users/SnecmaUserTest.java | 38 + .../capgemini/reports/workflows/TaskTest.java | 87 + teamcenter/src/test/resources/TextFile.txt | 1 + .../test/resources/jasperPdfPrinterTest.pdf | Bin 0 -> 2219 bytes .../src/test/resources/log4j.properties | 22 + .../src/test/resources/logging.properties | 3 + .../src/test/resources/reporting.properties | 12 + teamcenter/src/test/resources/test_policy.xml | 19 + .../xml/policies/PoliciesDomParserTest.xml | 17 + .../resources/xml/policies/bom_policy.xml | 54 + .../resources/xml/policies/policy_full.xml | 167 + .../resources/xml/policies/policy_light.xml | 48 + .../resources/xml/policies/test_policy.xml | 159 + .../MultiStructureServiceCallerTest_item.xml | 19 + ...ructureServiceCallerTest_item_revision.xml | 18 + .../ref/StructureServiceCallerTest_mono.xml | 15 + .../ref/StructureServiceCallerTest_multi.xml | 18 + .../TripleStructureServiceCallerTest_item.xml | 15 + ...ructureServiceCallerTest_item_revision.xml | 0 1161 files changed, 113125 insertions(+) create mode 100644 .gitignore create mode 100644 Jenkinsfile create mode 100644 core-ear/pom.xml create mode 100644 deployment-tool/pom.xml create mode 100644 deployment-tool/src/main/java/com/capgemini/framework/common/FileHelper.java create mode 100644 deployment-tool/src/main/java/com/capgemini/framework/common/FolderHelper.java create mode 100644 deployment-tool/src/main/java/com/capgemini/framework/db/DbConnection.java create mode 100644 deployment-tool/src/main/java/com/capgemini/framework/db/DbManager.java create mode 100644 deployment-tool/src/main/java/com/capgemini/framework/db/SqlHelper.java create mode 100644 deployment-tool/src/main/java/com/capgemini/framework/deployment/DeployProperties.java create mode 100644 deployment-tool/src/main/java/com/capgemini/framework/deployment/Install.java create mode 100644 deployment-tool/src/main/resources/log4j.properties create mode 100644 deployment-tool/src/test/resources/input/deploy.test.properties create mode 100644 deployment-tool/src/test/resources/input/sampleArchives/sampleEar.ear create mode 100644 deployment-tool/src/test/resources/input/sampleArchives/sampleJar.jar create mode 100644 deployment-tool/src/test/resources/input/sampleArchives/sampleWar.war create mode 100644 deployment-tool/src/test/resources/input/sampleArchives/updated/repackedSampleEar.ear create mode 100644 deployment-tool/src/test/resources/input/sampleArchives/updated/repackedSampleJar.jar create mode 100644 deployment-tool/src/test/resources/input/sampleArchives/updated/repackedSampleWar.war create mode 100644 deployment-tool/src/test/resources/input/updatedFiles/PropertyUpdaterTest.properties create mode 100644 deployment-tool/src/test/resources/input/updatedFiles/XmlUpdaterTest.xml create mode 100644 deployment-tool/src/test/resources/input/xml/updateSampleEar.xml create mode 100644 deployment-tool/src/test/resources/log4j.properties create mode 100644 deployment-tool/src/test/resources/ref/PropertyUpdaterTest.ref create mode 100644 deployment-tool/src/test/resources/ref/XmlUpdaterTest.ref create mode 100644 distribution/assembly.xml create mode 100644 distribution/install/reports/DBcreate/001_hibernate_sequence.sql create mode 100644 distribution/install/reports/DBcreate/002_table.sql create mode 100644 distribution/install/reports/DBcreate/003_report_type_data.sql create mode 100644 distribution/install/reports/DBcreate/004_criteria_data.sql create mode 100644 distribution/install/reports/DBcreate/006_quartz_tables.sql create mode 100644 distribution/install/reports/DBupdate/003_report_type_data_1.28.0.sql create mode 100644 distribution/install/reports/DBupdate/003_report_type_data_1.30.0.sql create mode 100644 distribution/install/reports/DBupdate/003_report_type_data_1.32.0.sql create mode 100644 distribution/install/reports/DBupdate/003_report_type_data_1.32.7.sql create mode 100644 distribution/install/reports/DBupdate/004_criteria_data_1.28.0.sql create mode 100644 distribution/install/reports/DBupdate/004_criteria_data_1.32.0.sql create mode 100644 distribution/install/reports/DBupdate/004_criteria_data_1.32.6.sql create mode 100644 distribution/install/reports/create_database.bat create mode 100644 distribution/install/reports/create_database.bat:Zone.Identifier create mode 100644 distribution/install/reports/db.properties create mode 100644 distribution/install/reports/log/readme.txt create mode 100644 distribution/install/reports/modules/modules.zip create mode 100644 distribution/install/reports/plsql/001_procedure_drop_sequence_if_exist.sql create mode 100644 distribution/install/reports/plsql/002_procedure_drop_table_if_exist.sql create mode 100644 distribution/install/reports/update_database.bat create mode 100644 distribution/install/reports/update_database.bat:Zone.Identifier create mode 100644 distribution/install/teamcenter/data/bin/clause_propriete_update create mode 100644 distribution/install/teamcenter/data/bin/encrypt create mode 100644 distribution/install/teamcenter/data/queries/Report_All_Sequences.xml create mode 100644 distribution/install/teamcenter/data/queries/Report_Alternate.xml create mode 100644 distribution/install/teamcenter/data/queries/Report_ChangeNotice_R07.xml create mode 100644 distribution/install/teamcenter/data/queries/Report_ChangeRequest.xml create mode 100644 distribution/install/teamcenter/data/queries/Report_ChangeRequest_R07.xml create mode 100644 distribution/install/teamcenter/data/queries/Report_ChangeRequest_With_Seq.xml create mode 100644 distribution/install/teamcenter/data/queries/Report_ChangeRevision.xml create mode 100644 distribution/install/teamcenter/data/queries/Report_Change_from_Part.xml create mode 100644 distribution/install/teamcenter/data/queries/Report_DET.xml create mode 100644 distribution/install/teamcenter/data/queries/Report_FPP_With_Seq.xml create mode 100644 distribution/install/teamcenter/data/queries/Report_Generic.xml create mode 100644 distribution/install/teamcenter/data/queries/Report_Generic_Assemb.xml create mode 100644 distribution/install/teamcenter/data/queries/Report_Item.xml create mode 100644 distribution/install/teamcenter/data/queries/Report_ItemRevision.xml create mode 100644 distribution/install/teamcenter/data/queries/Report_Product.xml create mode 100644 distribution/install/teamcenter/data/queries/Report_ProductType.xml create mode 100644 distribution/install/teamcenter/data/queries/Report_Relationship.xml create mode 100644 distribution/install/teamcenter/data/queries/Report_Unit.xml create mode 100644 distribution/install/teamcenter/data/queries/Report_Unit_from_CR.xml create mode 100644 distribution/install/teamcenter/data/queries/Report_Unit_with_WKF.xml create mode 100644 distribution/install/teamcenter/data/queries/Report_WKF_ValidationUnit_on_Unit.xml create mode 100644 distribution/install/teamcenter/data/queries/Report_WKF_on_Change.xml create mode 100644 distribution/install/teamcenter/data/queries/Report_WKF_on_ItemRevision.xml create mode 100644 distribution/install/teamcenter/data/queries/__pv_snecma_search_report_by_source.xml create mode 100644 distribution/install/teamcenter/data/report_prefs.xml create mode 100644 distribution/install/teamcenter/data/reports/REPORT_R01/REPORT_R01.xml create mode 100644 distribution/install/teamcenter/data/reports/REPORT_R03/REPORT_R03.xml create mode 100644 distribution/install/teamcenter/data/reports/REPORT_R07/REPORT_R07.xml create mode 100644 distribution/install/teamcenter/data/reports/REPORT_R10/REPORT_R10.xml create mode 100644 distribution/install/teamcenter/data/reports/REPORT_R11/REPORT_R11.xml create mode 100644 distribution/install/teamcenter/data/reports/REPORT_R13/REPORT_R13.xml create mode 100644 distribution/install/teamcenter/data/reports/REPORT_R15/REPORT_R15.xml create mode 100644 distribution/install/teamcenter/data/reports/REPORT_R16/REPORT_R16.xml create mode 100644 distribution/install/teamcenter/data/reports/REPORT_R17/REPORT_R17.xml create mode 100644 distribution/install/teamcenter/data/reports/REPORT_R19_Document/REPORT_R19_Document.xml create mode 100644 distribution/install/teamcenter/data/reports/REPORT_R19_Document_Design/REPORT_R19_Document_Design.xml create mode 100644 distribution/install/teamcenter/data/reports/REPORT_R19_Document_Revision/REPORT_R19_Document_Revision.xml create mode 100644 distribution/install/teamcenter/data/reports/REPORT_R20/REPORT_R20.xml create mode 100644 distribution/install/teamcenter/data/reports/REPORT_R21/REPORT_R21.xml create mode 100644 distribution/install/teamcenter/data/reports/REPORT_R22/REPORT_R22.xml create mode 100644 distribution/install/teamcenter/data/reports/REPORT_R23/REPORT_R23.xml create mode 100644 distribution/install/teamcenter/data/reports/REPORT_R24/REPORT_R24.xml create mode 100644 distribution/install/teamcenter/data/reports/REPORT_R25/REPORT_R25.xml create mode 100644 distribution/install/teamcenter/data/reports/REPORT_R26_Item/REPORT_R26_Item.xml create mode 100644 distribution/install/teamcenter/data/reports/REPORT_R26_Item_Revision/REPORT_R26_Item_Revision.xml create mode 100644 distribution/install/teamcenter/data/revision_rule/revisionrule.xml create mode 100644 distribution/install/teamcenter/report_install.pl create mode 100644 distribution/pom.xml create mode 100644 jasper/pom.xml create mode 100644 jasper/src/main/java/com/capgemini/reports/jasper/compilers/JasperCompiler.java create mode 100644 jasper/src/main/java/com/capgemini/reports/jasper/fillers/JasperFiller.java create mode 100644 jasper/src/main/java/com/capgemini/reports/jasper/fillers/MonoFiller.java create mode 100644 jasper/src/main/java/com/capgemini/reports/jasper/fillers/MultiFiller.java create mode 100644 jasper/src/main/java/com/capgemini/reports/jasper/printers/JasperCSVPrinter.java create mode 100644 jasper/src/main/java/com/capgemini/reports/jasper/printers/JasperPDFPrinter.java create mode 100644 jasper/src/main/java/com/capgemini/reports/jasper/printers/JasperPrinter.java create mode 100644 jasper/src/main/java/com/capgemini/reports/jasper/printers/JasperXLSXPrinter.java create mode 100644 jasper/src/test/java/com/capgemini/reports/jasper/compilers/JasperCompilerTest.java create mode 100644 jasper/src/test/java/com/capgemini/reports/jasper/fillers/MonoFillerTest.java create mode 100644 jasper/src/test/java/com/capgemini/reports/jasper/fillers/MultiFillerTest.java create mode 100644 jasper/src/test/java/com/capgemini/reports/jasper/printers/JasperPDFPrinterTest.java create mode 100644 jasper/src/test/resources/Jasper/images/Snecma_logo.png create mode 100644 jasper/src/test/resources/Jasper/images/confidentiel_industrie.jpg create mode 100644 jasper/src/test/resources/Jasper/template/dynamic_table/reference.jrxml create mode 100644 jasper/src/test/resources/Jasper/template/dynamic_table/template.jrxml create mode 100644 jasper/src/test/resources/Jasper/template/report_r01.jrxml create mode 100644 jasper/src/test/resources/Jasper/template/report_r03.jrxml create mode 100644 jasper/src/test/resources/Jasper/template/report_r10.jrxml create mode 100644 jasper/src/test/resources/Jasper/template/report_r11.jrxml create mode 100644 jasper/src/test/resources/Jasper/template/report_r15r16.jrxml create mode 100644 jasper/src/test/resources/Jasper/template/report_r17.jrxml create mode 100644 jasper/src/test/resources/Jasper/template/report_r19.jrxml create mode 100644 jasper/src/test/resources/Jasper/template/report_r20/page2/r20_p2_generics.jrxml create mode 100644 jasper/src/test/resources/Jasper/template/report_r20/page2/r20_p2_impacts.jrxml create mode 100644 jasper/src/test/resources/Jasper/template/report_r20/page2/r20_p2_noimpacts.jrxml create mode 100644 jasper/src/test/resources/Jasper/template/report_r20/page3/page3reference.jrxml create mode 100644 jasper/src/test/resources/Jasper/template/report_r20/page3/report_r20_p3.jrxml create mode 100644 jasper/src/test/resources/Jasper/template/report_r20/report_r20_master.jrxml create mode 100644 jasper/src/test/resources/Jasper/template/report_r20/report_r20_p1.jrxml create mode 100644 jasper/src/test/resources/Jasper/template/report_r20/report_r20_p2.jrxml create mode 100644 jasper/src/test/resources/Jasper/template/report_r20/report_r20_p4.jrxml create mode 100644 jasper/src/test/resources/Jasper/template/report_r21.jrxml create mode 100644 jasper/src/test/resources/Jasper/template/report_r22.jrxml create mode 100644 jasper/src/test/resources/Jasper/template/template_R07.jrxml create mode 100644 jasper/src/test/resources/log4j.properties create mode 100644 jasper/src/test/resources/logging.properties create mode 100644 jasper/src/test/resources/simplelogger.properties create mode 100644 kurt-ejb/pom.xml create mode 100644 kurt-ejb/src/main/java/com/capgemini/reports/execution/posting/DelayedPostingStategy.java create mode 100644 kurt-ejb/src/main/java/com/capgemini/reports/execution/posting/IPostingStrategy.java create mode 100644 kurt-ejb/src/main/java/com/capgemini/reports/execution/posting/ImmediatePostingStrategy.java create mode 100644 kurt-ejb/src/main/java/com/capgemini/reports/execution/posting/SchedulingPostingStrategy.java create mode 100644 kurt-ejb/src/main/java/com/capgemini/reports/quartz/JobDataKeys.java create mode 100644 kurt-ejb/src/main/java/com/capgemini/reports/quartz/SchedulerServer.java create mode 100644 kurt-ejb/src/main/java/com/capgemini/reports/quartz/TriggerPreparator.java create mode 100644 kurt-ejb/src/main/java/com/capgemini/reports/quartz/jobs/DelayedJob.java create mode 100644 kurt-ejb/src/main/java/com/capgemini/reports/quartz/jobs/PurgeJob.java create mode 100644 kurt-ejb/src/main/java/com/capgemini/reports/quartz/jobs/ScheduledJob.java create mode 100644 kurt-ejb/src/main/java/com/capgemini/reports/queuing/EmbeddedServer.java create mode 100644 kurt-ejb/src/main/java/com/capgemini/reports/queuing/consumer/ReportConsumer.java create mode 100644 kurt-ejb/src/main/resources/META-INF/beans.xml create mode 100644 kurt-ejb/src/main/resources/log4j.properties create mode 100644 kurt-ejb/src/test/resources/log4j.properties create mode 100644 kurt-ejb/src/test/resources/logging.properties create mode 100644 kurt-ejb/src/test/resources/quartz.properties create mode 100644 kurt-ejb/src/test/resources/simplelogger.properties create mode 100644 kurt-ejb/src/test/resources/test_policy.xml create mode 100644 kurt-utility/pom.xml create mode 100644 kurt-utility/src/main/java/com/capgemini/framework/common/AbstractPropertiesManager.java create mode 100644 kurt-utility/src/main/java/com/capgemini/framework/common/DateHelper.java create mode 100644 kurt-utility/src/main/java/com/capgemini/framework/common/DoubleFormatter.java create mode 100644 kurt-utility/src/main/java/com/capgemini/framework/common/DynamicErrorTemplateHelper.java create mode 100644 kurt-utility/src/main/java/com/capgemini/framework/common/FileHelper.java create mode 100644 kurt-utility/src/main/java/com/capgemini/framework/common/FileTemplate.java create mode 100644 kurt-utility/src/main/java/com/capgemini/framework/common/FolderHelper.java create mode 100644 kurt-utility/src/main/java/com/capgemini/framework/common/HashMapComparingStringIDs.java create mode 100644 kurt-utility/src/main/java/com/capgemini/framework/common/MailHelper.java create mode 100644 kurt-utility/src/main/java/com/capgemini/framework/common/MapHelper.java create mode 100644 kurt-utility/src/main/java/com/capgemini/framework/common/MemoryHelper.java create mode 100644 kurt-utility/src/main/java/com/capgemini/framework/common/QuartzHelper.java create mode 100644 kurt-utility/src/main/java/com/capgemini/framework/common/ReportFolderOutputHelper.java create mode 100644 kurt-utility/src/main/java/com/capgemini/framework/common/ResourceHelper.java create mode 100644 kurt-utility/src/main/java/com/capgemini/framework/common/SerializationHelper.java create mode 100644 kurt-utility/src/main/java/com/capgemini/framework/common/SettingsHelper.java create mode 100644 kurt-utility/src/main/java/com/capgemini/framework/common/TimeHelper.java create mode 100644 kurt-utility/src/main/java/com/capgemini/framework/common/activedirectory/ActiveDirectory.java create mode 100644 kurt-utility/src/main/java/com/capgemini/framework/common/activedirectory/SearchCriteria.java create mode 100644 kurt-utility/src/main/java/com/capgemini/framework/common/activedirectory/SearchFilter.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/JasperTemplate.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/ReportEnum.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/ReportLaunchTypeEnum.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/builder/AbstractR13Builder.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/builder/AbstractR15R16R17Builder.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/builder/AbstractR15R17Builder.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/builder/R01Builder.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/builder/R03Builder.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/builder/R07Builder.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/builder/R10Builder.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/builder/R11Builder.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/builder/R13CrBuilder.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/builder/R13FppBuilder.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/builder/R15Builder.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/builder/R16Builder.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/builder/R17Builder.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/builder/R19Builder.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/builder/R20Builder.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/builder/R21Builder.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/builder/R22Builder.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/builder/R23Builder.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/builder/R24Builder.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/builder/R25Builder.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/builder/R26Builder.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/builder/R27Builder.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/builder/R28Builder.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/builder/ReportBuilder.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/checkdata/CheckingDataHelper.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/database/DataBaseReportHelper.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/database/DbInit.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/database/HibernateUtil.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/database/javabean/DbCriteria.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/database/javabean/DbCriteriaVal.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/database/javabean/DbMemMonitor.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/database/javabean/DbReport.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/database/javabean/DbReportOwner.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/database/javabean/DbReportType.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/database/javabean/DbSchedulingCriteriaVal.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/database/javabean/DbSchedulingReport.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/database/javabean/DbUser.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/database/javabean/IPersistedObject.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/database/javabean/enumeration/ReportCriteriaEnum.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/database/javabean/enumeration/ReportErrorTypeEnum.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/database/javabean/enumeration/ReportStateEnum.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/database/javabean/enumeration/SchedulingEnum.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/database/manager/AbstractHibernateManager.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/database/manager/MngCriteria.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/database/manager/MngCriteriaVal.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/database/manager/MngMemMonitor.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/database/manager/MngReport.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/database/manager/MngReportOwner.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/database/manager/MngReportType.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/database/manager/MngSchedulingCriteriaVal.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/database/manager/MngSchedulingReport.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/database/manager/MngUser.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/database/stats/GenJspStats.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/database/stats/ReportStatBean.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/database/stats/UserStatBean.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r01report/DataReportPreparatorR01.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r01report/ExecutionR01.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r01report/visitors/R01Visitor.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r01report/visitors/R01VisitorKeys.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r01report/visitors/bomlineholder/R01AltOrDetBehaviour.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r01report/visitors/bomlineholder/R01BOMLineHolderVisitor.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r01report/visitors/snecmaobject/R01ComponentVisitor.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r01report/visitors/snecmaobject/R01ReceptorVisitor.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r03report/DataReportPreparatorR03.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r03report/ExecutionR03.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r03report/visitors/R03Visitor.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r03report/visitors/R03VisitorKeys.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r03report/visitors/bomlineholder/R03AltOrDetBehaviour.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r03report/visitors/bomlineholder/R03BOMLineHolderVisitor.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r03report/visitors/snecmaobject/R03ComponentVisitor.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r03report/visitors/snecmaobject/R03ReceptorVisitor.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/CRExtractorHelper.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/ExecutionR07.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/R07Printer.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/ReportDataR07.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/checker/R07ProductUnitChecker.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/DataReportPreparatorR07.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/TransformerR07.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/extractor/BomFlattenerR07.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/extractor/DataExtractorR07.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/extractor/lines/ComparableLine.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/extractor/lines/R07AltPart.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/extractor/lines/R07PartRfPart.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/extractor/lines/R07ProductGeneric.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/extractor/lines/R07Quad.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/extractor/lines/R07ReceptorLine.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/ConfigurationFilterR07.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/ContentComparator.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/StructuralComparator.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/AbstractBomLineComparator.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/AbstractItemComparator.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/generics/GenericBLComparator.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/generics/GenericComparator.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/AlternateBLComparator.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/AlternateComparator.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/DetBLComparator.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/DetComparator.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/PartAeroBLComparator.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/PartAeroComparator.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/PartAssembBLComparator.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/PartAssembComparator.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/PartBLComparator.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/PartComparator.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/PartMatBLComparator.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/PartMatComparator.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/PartNoAeroBLComparator.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/PartNoAeroComparator.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/StandardBLComparator.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/StandardComparator.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/rf/RfComparator.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/rf/RfGenericComparator.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/rf/RfPartAssembComparator.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/rf/RfPartComparator.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/identifiers/ReceptorIdExtractor.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/identifiers/RepereIdExtractor.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/sorter/R07DataSorter.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/printing/BuilderTemplateR07.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/printing/DynamicGridTemplateR07.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/printing/EnumChangeR07.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/printing/EnumComposantR07.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/printing/EnumLienNomenclatureR07.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/printing/EnumMapDelta.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/printing/EnumRecepteurR07.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/printing/EnumRepereR07.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r10report/DataReportPreparatorR10.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r10report/DocumentExtractor.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r10report/ExecutionR10.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r10report/R10BomLineFlattener.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r10report/R10Keys.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r10report/R10Printer.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r10report/lines/R10AltPart.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r10report/lines/R10PartRfPart.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r10report/lines/R10ProductGeneric.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r10report/lines/R10Quad.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r10report/lines/R10ReceptorLine.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r10report/lines/R10TopLine.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r11report/DataReportPreparatorR11.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r11report/ExecutionR11.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r11report/R11Keys.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r11report/R11Printer.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r11report/checker/R11GenericExistenceChecker.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r11report/data/extractor/BomLineBrowserR11.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r11report/data/extractor/FilterByTypeObject.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r11report/data/extractor/R11ReceptorRepere.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r13report/R13Keys.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r13report/datapreparator/AbstractDataReportPreparatorR13.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r13report/datapreparator/DataReportPreparatorR13CR.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r13report/datapreparator/DataReportPreparatorR13FPP.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r13report/execution/AbstractExecutionR13.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r13report/execution/ExecutionR13CR.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r13report/execution/ExecutionR13FPP.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r13report/printer/AbstractR13Printer.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r13report/printer/R13PrinterCR.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r13report/printer/R13PrinterFPP.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/AbstractDataReportPreparatorR15R16R17.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/AbstractExecutionR15R16R17.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/AbstractR15R16R17Printer.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/CommunR15R16R17ComponentVisitor.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/R15R16R17R24R25Keys.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/r15r17reports/AbstractDataReportPreparatorR15R17.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/r15r17reports/AbstractExecutionR15R17.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/r15r17reports/AbstractR15R17Printer.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/r15r17reports/r15report/AttachDatasetR15Action.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/r15r17reports/r15report/DataReportPreparatorR15.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/r15r17reports/r15report/ExecutionR15.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/r15r17reports/r15report/R15Printer.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/r15r17reports/r17report/DataReportPreparatorR17.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/r15r17reports/r17report/ExecutionR17.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/r15r17reports/r17report/R17Printer.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/r16report/DataReportPreparatorR16.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/r16report/ExecutionR16.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/r16report/R16BOMLineExplorer.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/r16report/R16Printer.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r19report/DataReportPreparatorR19.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r19report/ExecutionR19.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r19report/PartIdRevComparator.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r19report/R19Keys.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r19report/R19Printer.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r19report/snecmaobject/AbstractR19ComponentVisitor.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r19report/snecmaobject/R19ComponentVisitor.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r20report/Classe.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r20report/ConjointUnique.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r20report/DataReportPreparatorR20.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r20report/ExecutionR20.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r20report/MajorMinor.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r20report/checker/R20LMRChecker.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r20report/checker/R20UnitRevisionChecker.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r20report/comparator/ChangeComparator.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r20report/comparator/GenericComparator.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r20report/printing/Page3TemplateGenerator.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r20report/printing/R20Printer.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r20report/visitors/R20Keys.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r21report/DataReportPreparatorR21.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r21report/ExecutionR21.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r21report/R21ReportKeys.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r21report/visitors/R21Visitor.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r21report/visitors/R21VisitorKeys.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r21report/visitors/bomlineholder/R21AltOrDetBehaviour.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r21report/visitors/bomlineholder/R21BOMLineHolderVisitor.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r21report/visitors/snecmaobject/R21ComponentVisitor.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r21report/visitors/snecmaobject/R21ReceptorVisitor.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r22report/DataReportPreparatorR22.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r22report/ExecutionR22.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r22report/visitors/R22Visitor.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r22report/visitors/R22VisitorKeys.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r22report/visitors/R22VisitorParametersKeys.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r22report/visitors/bomlineholder/R22AltOrDetBehaviour.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r22report/visitors/bomlineholder/R22BOMLineHolderVisitor.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r22report/visitors/snecmaobject/R22ComponentVisitor.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r22report/visitors/snecmaobject/R22ReceptorVisitor.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r23report/DataReportPreparatorR23.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r23report/ExecutionR23.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r23report/visitors/R23Visitor.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r23report/visitors/R23VisitorKeys.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r23report/visitors/bomlineholder/R23AltOrDetBehaviour.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r23report/visitors/bomlineholder/R23BOMLineHolderVisitor.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r23report/visitors/snecmaobject/R23ComponentVisitor.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r23report/visitors/snecmaobject/R23ReceptorVisitor.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r24report/DataReportPreparatorR24.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r24report/ExecutionR24.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r24report/R24BOMLineExplorer.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r24report/R24Printer.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r25report/DataReportPreparatorR25.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r25report/ExecutionR25.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r25report/R25BOMLineExplorer.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r25report/R25Printer.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r26report/DataReportPreparatorR26.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r26report/EffectivityHelper.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r26report/ExecutionR26.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r26report/LineManager.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r26report/R26BOMLineExplorer.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r26report/R26BomLine.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r26report/R26Keys.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r26report/R26Printer.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r26report/Range.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r26report/Ranges.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r26report/RevisionRuleManager.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r26report/RfPUManager.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r27report/DataReportPreparatorR27.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r27report/ExecutionR27.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r27report/R27Keys.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r27report/R27Printer.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r28report/DataReportPreparatorR28.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r28report/ExecutionR28.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r28report/R28Keys.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/definition/r28report/R28Printer.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/emailing/templates/AbstractEmailTemplate.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/emailing/templates/BadParamEmailTemplate.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/emailing/templates/EmailReportHelper.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/emailing/templates/FailedEmailTemplate.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/emailing/templates/FailedEmailTemplateAdmin.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/emailing/templates/FailedWorkflowEmailTemplate.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/emailing/templates/FailedWorkflowEmailTemplateAdmin.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/emailing/templates/SuccessfulEmailTemplate.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/exceptions/DuplicateReportEntryFound.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/exceptions/DuplicateSchedulingEntryFound.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/exceptions/FileLoadingException.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/exceptions/InsufficientParametersException.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/exceptions/InvalidActiveDirectoryInputException.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/exceptions/InvalidActiveDirectorySearchException.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/exceptions/InvalidCredentialsException.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/exceptions/InvalidDatasetException.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/exceptions/NoConnectionToActiveDirectoryException.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/exceptions/NothingToBeShownException.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/exceptions/ReportPrintException.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/execution/AbstractExecutionReport.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/execution/IDataReportPreparator.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/execution/actions/AbstractPostExecutionStep.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/execution/actions/AbstractPreExecutionStep.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/execution/actions/CompositeErrorAction.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/execution/actions/CompositePostAction.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/execution/actions/CompositePreAction.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/execution/actions/DoNothingAction.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/execution/actions/IErrorExecutionStep.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/execution/actions/IPostExecutionStep.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/execution/actions/IPreExecutionStep.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/execution/actions/InteractiveEmailAction.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/execution/actions/LoggingAction.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/execution/actions/QuickCheckAction.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/execution/actions/ReLaunchEmailAction.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/execution/actions/ScheduledEmailAction.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/execution/actions/UpdateReportAction.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/execution/actions/UpdateReportInDbAction.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/execution/actions/ondataset/CreateDatasetAction.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/execution/actions/ondataset/DestroyRelationshipsAction.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/execution/actions/ondataset/LinkFicheArticleAction.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/execution/actions/ondataset/SerializableProvider.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/execution/actions/ondataset/SetStatusAction.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/execution/mapconstructor/AbstractStaticTemplateMapConstructor.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/execution/mapconstructor/IMapConstructor.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/execution/strategies/AbstractExecutionStrategy.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/execution/strategies/AutomaticExecutionStrategy.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/execution/strategies/DelayedExecutionStrategy.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/execution/strategies/IExecutionStrategy.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/execution/strategies/ImmediateExecutionStrategy.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/execution/strategies/ScheduledExecutionStrategy.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/logging/EventsLogger.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/logging/ReportLoggerHelper.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/optimized/Folder.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/optimized/OptimizedFile.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/optimized/OptimizedFolder.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/optimized/r23report/OptimizedR23File.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/optimized/r23report/OptimizedR23Folder.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/optimized/r24report/OptimizedR24File.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/optimized/r24report/OptimizedR24Folder.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/periodicity/DailyPeriod.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/periodicity/DayInMonth.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/periodicity/PeriodFactory.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/periodicity/SchedulingPeriod.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/periodicity/SpecificDay.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/periodicity/WeekendPeriod.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/periodicity/WeeklyPeriod.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/printing/PrintParameters.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/printing/PrintReportHelper.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/printing/Printer.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/queuing/ReportPriority.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/reports/IReportVisitor.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/reports/output/ReportOutput.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/reports/output/ZipReport.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/templates/Alignment.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/templates/Cell.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/templates/CellFormat.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/templates/Column.java create mode 100644 kurt-utility/src/main/java/com/capgemini/reports/templates/DynamicGridTemplateBuilder.java create mode 100644 kurt-utility/src/main/resources/Jasper/images/Snecma_logo.png create mode 100644 kurt-utility/src/main/resources/Jasper/images/confidentiel_industrie.jpg create mode 100644 kurt-utility/src/main/resources/Jasper/template/dynamic_table/template.jrxml create mode 100644 kurt-utility/src/main/resources/Jasper/template/report_r01.jrxml create mode 100644 kurt-utility/src/main/resources/Jasper/template/report_r03.jrxml create mode 100644 kurt-utility/src/main/resources/Jasper/template/report_r10.jrxml create mode 100644 kurt-utility/src/main/resources/Jasper/template/report_r11.jrxml create mode 100644 kurt-utility/src/main/resources/Jasper/template/report_r13/report_r13_cr.jrxml create mode 100644 kurt-utility/src/main/resources/Jasper/template/report_r13/report_r13_fpp.jrxml create mode 100644 kurt-utility/src/main/resources/Jasper/template/report_r15r16.jrxml create mode 100644 kurt-utility/src/main/resources/Jasper/template/report_r17.jrxml create mode 100644 kurt-utility/src/main/resources/Jasper/template/report_r19.jrxml create mode 100644 kurt-utility/src/main/resources/Jasper/template/report_r20/Snecma_logo.png create mode 100644 kurt-utility/src/main/resources/Jasper/template/report_r20/page2/r20_p2_generics.jrxml create mode 100644 kurt-utility/src/main/resources/Jasper/template/report_r20/page2/r20_p2_impacts.jrxml create mode 100644 kurt-utility/src/main/resources/Jasper/template/report_r20/page2/r20_p2_noimpacts.jrxml create mode 100644 kurt-utility/src/main/resources/Jasper/template/report_r20/page3/report_r20_p3.jrxml create mode 100644 kurt-utility/src/main/resources/Jasper/template/report_r20/report_r20_master.jrxml create mode 100644 kurt-utility/src/main/resources/Jasper/template/report_r20/report_r20_p1.jrxml create mode 100644 kurt-utility/src/main/resources/Jasper/template/report_r20/report_r20_p2.jrxml create mode 100644 kurt-utility/src/main/resources/Jasper/template/report_r20/report_r20_p4.jrxml create mode 100644 kurt-utility/src/main/resources/Jasper/template/report_r21.jrxml create mode 100644 kurt-utility/src/main/resources/Jasper/template/report_r22.jrxml create mode 100644 kurt-utility/src/main/resources/Jasper/template/report_r23.jrxml create mode 100644 kurt-utility/src/main/resources/Jasper/template/report_r24.jrxml create mode 100644 kurt-utility/src/main/resources/Jasper/template/report_r25.jrxml create mode 100644 kurt-utility/src/main/resources/Jasper/template/report_r26/report_r26_master.jrxml create mode 100644 kurt-utility/src/main/resources/Jasper/template/report_r26/report_r26_subreport.jrxml create mode 100644 kurt-utility/src/main/resources/Jasper/template/report_r27.jrxml create mode 100644 kurt-utility/src/main/resources/Jasper/template/report_r28.jrxml create mode 100644 kurt-utility/src/main/resources/Jasper/template/template_R07.jrxml create mode 100644 kurt-utility/src/main/resources/hibernate.cfg.xml create mode 100644 kurt-utility/src/main/resources/hibernate/DbCriteriaVal_mapping.xml create mode 100644 kurt-utility/src/main/resources/hibernate/DbCriteria_mapping.xml create mode 100644 kurt-utility/src/main/resources/hibernate/DbMemMonitor_mapping.xml create mode 100644 kurt-utility/src/main/resources/hibernate/DbReportOwner_mapping.xml create mode 100644 kurt-utility/src/main/resources/hibernate/DbReportType_mapping.xml create mode 100644 kurt-utility/src/main/resources/hibernate/DbReport_mapping.xml create mode 100644 kurt-utility/src/main/resources/hibernate/DbSchedulingCriteriaVal_mapping.xml create mode 100644 kurt-utility/src/main/resources/hibernate/DbSchedulingReport_mapping.xml create mode 100644 kurt-utility/src/main/resources/hibernate/DbUser_mapping.xml create mode 100644 kurt-utility/src/main/resources/html/email/template_email_bad_parameters.html create mode 100644 kurt-utility/src/main/resources/html/email/template_email_failed.html create mode 100644 kurt-utility/src/main/resources/html/email/template_email_failed_admin.html create mode 100644 kurt-utility/src/main/resources/html/email/template_email_finished.html create mode 100644 kurt-utility/src/main/resources/html/email/template_email_posted.html create mode 100644 kurt-utility/src/main/resources/html/email/template_email_started.html create mode 100644 kurt-utility/src/main/resources/html/error_jsp_page.html create mode 100644 kurt-utility/src/main/resources/log4j.properties create mode 100644 kurt-utility/src/main/resources/quartz.properties create mode 100644 kurt-utility/src/main/resources/reporting.properties create mode 100644 kurt-utility/src/main/resources/xml/policies/r01report/R01_policy_full.xml create mode 100644 kurt-utility/src/main/resources/xml/policies/r01report/R01_policy_light.xml create mode 100644 kurt-utility/src/main/resources/xml/policies/r03report/R03_policy_full.xml create mode 100644 kurt-utility/src/main/resources/xml/policies/r03report/R03_policy_light.xml create mode 100644 kurt-utility/src/main/resources/xml/policies/r07report/R07_policy_full.xml create mode 100644 kurt-utility/src/main/resources/xml/policies/r07report/R07_policy_light.xml create mode 100644 kurt-utility/src/main/resources/xml/policies/r10report/R10_policy_full.xml create mode 100644 kurt-utility/src/main/resources/xml/policies/r10report/R10_policy_light.xml create mode 100644 kurt-utility/src/main/resources/xml/policies/r11report/R11_policy_full.xml create mode 100644 kurt-utility/src/main/resources/xml/policies/r11report/R11_policy_light.xml create mode 100644 kurt-utility/src/main/resources/xml/policies/r13report/R13_policy_full.xml create mode 100644 kurt-utility/src/main/resources/xml/policies/r13report/R13_policy_light.xml create mode 100644 kurt-utility/src/main/resources/xml/policies/r15report/R15_policy_full.xml create mode 100644 kurt-utility/src/main/resources/xml/policies/r15report/R15_policy_light.xml create mode 100644 kurt-utility/src/main/resources/xml/policies/r15report/R15_policy_wkf.xml create mode 100644 kurt-utility/src/main/resources/xml/policies/r16report/R16_policy_full.xml create mode 100644 kurt-utility/src/main/resources/xml/policies/r16report/R16_policy_light.xml create mode 100644 kurt-utility/src/main/resources/xml/policies/r17report/R17_policy_full.xml create mode 100644 kurt-utility/src/main/resources/xml/policies/r17report/R17_policy_light.xml create mode 100644 kurt-utility/src/main/resources/xml/policies/r19report/R19_policy_full.xml create mode 100644 kurt-utility/src/main/resources/xml/policies/r19report/R19_policy_light.xml create mode 100644 kurt-utility/src/main/resources/xml/policies/r20report/R20_policy_full.xml create mode 100644 kurt-utility/src/main/resources/xml/policies/r20report/R20_policy_light.xml create mode 100644 kurt-utility/src/main/resources/xml/policies/r21report/R21_policy_full.xml create mode 100644 kurt-utility/src/main/resources/xml/policies/r21report/R21_policy_light.xml create mode 100644 kurt-utility/src/main/resources/xml/policies/r22report/R22_policy_full.xml create mode 100644 kurt-utility/src/main/resources/xml/policies/r22report/R22_policy_light.xml create mode 100644 kurt-utility/src/main/resources/xml/policies/r22report/R22_policy_wkf.xml create mode 100644 kurt-utility/src/main/resources/xml/policies/r23report/R23_policy_full.xml create mode 100644 kurt-utility/src/main/resources/xml/policies/r23report/R23_policy_light.xml create mode 100644 kurt-utility/src/main/resources/xml/policies/r24report/R24_policy_full.xml create mode 100644 kurt-utility/src/main/resources/xml/policies/r24report/R24_policy_light.xml create mode 100644 kurt-utility/src/main/resources/xml/policies/r25report/R25_policy_full.xml create mode 100644 kurt-utility/src/main/resources/xml/policies/r25report/R25_policy_light.xml create mode 100644 kurt-utility/src/main/resources/xml/policies/r26report/R26_policy_full.xml create mode 100644 kurt-utility/src/main/resources/xml/policies/r26report/R26_policy_light.xml create mode 100644 kurt-utility/src/main/resources/xml/policies/r27report/R27_policy_full.xml create mode 100644 kurt-utility/src/main/resources/xml/policies/r27report/R27_policy_light.xml create mode 100644 kurt-utility/src/main/resources/xml/policies/r28report/R28_policy_full.xml create mode 100644 kurt-utility/src/main/resources/xml/policies/r28report/R28_policy_light.xml create mode 100644 kurt-utility/src/main/resources/xsd/policies.xsd create mode 100644 kurt-utility/src/main/sh/JenkinsDeploy.bat create mode 100644 kurt-utility/src/main/sh/JenkinsDeploy.bat:Zone.Identifier create mode 100644 kurt-utility/src/main/sh/JenkinsDeploy.vbs create mode 100644 kurt-utility/src/main/sh/JenkinsDeploy.vbs:Zone.Identifier create mode 100644 kurt-utility/src/main/sh/jenkins_packaging.sh create mode 100644 kurt-utility/src/main/xsd/policies.xsd create mode 100644 kurt-utility/src/test/java/com/capgemini/framework/common/DateHelperTest.java create mode 100644 kurt-utility/src/test/java/com/capgemini/framework/common/DoubleFormatterTest.java create mode 100644 kurt-utility/src/test/java/com/capgemini/framework/common/DynamicErrorTemplateHelperTest.java create mode 100644 kurt-utility/src/test/java/com/capgemini/reports/definition/r26report/RangesTest.java create mode 100644 kurt-utility/src/test/java/com/capgemini/reports/printing/PrintParametersTest.java create mode 100644 kurt-utility/src/test/java/com/capgemini/reports/templates/CellTest.java create mode 100644 kurt-utility/src/test/java/com/capgemini/reports/templates/ColumnTest.java create mode 100644 kurt-utility/src/test/java/com/capgemini/reports/templates/DynamicGridTemplateBuilderTest.java create mode 100644 kurt-utility/src/test/resources/Jasper/template/dynamic_table/reference.jrxml create mode 100644 kurt-utility/src/test/resources/Jasper/template/dynamic_table/template.jrxml create mode 100644 kurt-utility/src/test/resources/hibernate.cfg.xml create mode 100644 kurt-utility/src/test/resources/html/email/template_email_bad_parameters.html create mode 100644 kurt-utility/src/test/resources/html/email/template_email_failed.html create mode 100644 kurt-utility/src/test/resources/html/email/template_email_failed_admin.html create mode 100644 kurt-utility/src/test/resources/html/email/template_email_finished.html create mode 100644 kurt-utility/src/test/resources/html/email/template_email_posted.html create mode 100644 kurt-utility/src/test/resources/html/email/template_email_started.html create mode 100644 kurt-utility/src/test/resources/log4j.properties create mode 100644 kurt-utility/src/test/resources/xml/policies/PoliciesDomParserTest.xml create mode 100644 kurt-utility/src/test/resources/xml/policies/bom_policy.xml create mode 100644 kurt-utility/src/test/resources/xml/policies/policy_full.xml create mode 100644 kurt-utility/src/test/resources/xml/policies/policy_light.xml create mode 100644 kurt-utility/src/test/resources/xml/policies/test_policy.xml create mode 100644 kurt-utility/src/test/resources/xml/ref/MultiStructureServiceCallerTest_item.xml create mode 100644 kurt-utility/src/test/resources/xml/ref/MultiStructureServiceCallerTest_item_revision.xml create mode 100644 kurt-utility/src/test/resources/xml/ref/StructureServiceCallerTest_mono.xml create mode 100644 kurt-utility/src/test/resources/xml/ref/StructureServiceCallerTest_multi.xml create mode 100644 kurt-utility/src/test/resources/xml/ref/TripleStructureServiceCallerTest_item.xml create mode 100644 kurt-utility/src/test/resources/xml/ref/TripleStructureServiceCallerTest_item_revision.xml create mode 100644 kurt-utility/src/val/java/com/capgemini/reports/definition/r01report/Test_R01.java create mode 100644 kurt-utility/src/val/java/com/capgemini/reports/definition/r03report/Test_R03.java create mode 100644 kurt-utility/src/val/java/com/capgemini/reports/definition/r07report/Test_R07.java create mode 100644 kurt-utility/src/val/java/com/capgemini/reports/definition/r10report/Test_R10.java create mode 100644 kurt-utility/src/val/java/com/capgemini/reports/definition/r11report/Test_R11.java create mode 100644 kurt-utility/src/val/java/com/capgemini/reports/definition/r13report/Test_CrR13.java create mode 100644 kurt-utility/src/val/java/com/capgemini/reports/definition/r13report/Test_FppR13.java create mode 100644 kurt-utility/src/val/java/com/capgemini/reports/definition/r15report/Test_R15.java create mode 100644 kurt-utility/src/val/java/com/capgemini/reports/definition/r16report/Test_R16.java create mode 100644 kurt-utility/src/val/java/com/capgemini/reports/definition/r17report/Test_R17.java create mode 100644 kurt-utility/src/val/java/com/capgemini/reports/definition/r19report/Test_R19.java create mode 100644 kurt-utility/src/val/java/com/capgemini/reports/definition/r20report/Test_R20.java create mode 100644 kurt-utility/src/val/java/com/capgemini/reports/definition/r21report/Test_R21.java create mode 100644 kurt-utility/src/val/java/com/capgemini/reports/definition/r22report/Test_R22.java create mode 100644 kurt-utility/src/val/java/com/capgemini/reports/definition/r23report/Test_R23.java create mode 100644 kurt-utility/src/val/java/com/capgemini/reports/definition/r24report/Test_R24.java create mode 100644 kurt-utility/src/val/java/com/capgemini/reports/definition/r25report/Test_R25.java create mode 100644 kurt-utility/src/val/java/compare/Comparer_XML.java create mode 100644 kurt-utility/src/val/java/compare/CriteresComparaison.java create mode 100644 kurt-utility/src/val/java/compare/ExcelTest.java create mode 100644 kurt-utility/src/val/resources/FolderFilesReferenced/r01/r01.xlsx create mode 100644 kurt-utility/src/val/resources/FolderFilesReferenced/r01/r01.xlsx:Zone.Identifier create mode 100644 kurt-utility/src/val/resources/FolderFilesReferenced/r03/r03.xlsx create mode 100644 kurt-utility/src/val/resources/FolderFilesReferenced/r03/r03.xlsx:Zone.Identifier create mode 100644 kurt-utility/src/val/resources/FolderFilesReferenced/r07/r07.xlsx create mode 100644 kurt-utility/src/val/resources/FolderFilesReferenced/r07/r07.xlsx:Zone.Identifier create mode 100644 kurt-utility/src/val/resources/FolderFilesReferenced/r10/r10.xlsx create mode 100644 kurt-utility/src/val/resources/FolderFilesReferenced/r10/r10.xlsx:Zone.Identifier create mode 100644 kurt-utility/src/val/resources/FolderFilesReferenced/r11/r11.xlsx create mode 100644 kurt-utility/src/val/resources/FolderFilesReferenced/r11/r11.xlsx:Zone.Identifier create mode 100644 kurt-utility/src/val/resources/FolderFilesReferenced/r13/r13_cr.xlsx create mode 100644 kurt-utility/src/val/resources/FolderFilesReferenced/r13/r13_cr.xlsx:Zone.Identifier create mode 100644 kurt-utility/src/val/resources/FolderFilesReferenced/r13/r13_fpp.xlsx create mode 100644 kurt-utility/src/val/resources/FolderFilesReferenced/r13/r13_fpp.xlsx:Zone.Identifier create mode 100644 kurt-utility/src/val/resources/FolderFilesReferenced/r15/r15.pdf create mode 100644 kurt-utility/src/val/resources/FolderFilesReferenced/r16/r16.pdf create mode 100644 kurt-utility/src/val/resources/FolderFilesReferenced/r17/r17.pdf create mode 100644 kurt-utility/src/val/resources/FolderFilesReferenced/r19/r19.xlsx create mode 100644 kurt-utility/src/val/resources/FolderFilesReferenced/r19/r19.xlsx:Zone.Identifier create mode 100644 kurt-utility/src/val/resources/FolderFilesReferenced/r20/r20.pdf create mode 100644 kurt-utility/src/val/resources/FolderFilesReferenced/r21/r21.xlsx create mode 100644 kurt-utility/src/val/resources/FolderFilesReferenced/r21/r21.xlsx:Zone.Identifier create mode 100644 kurt-utility/src/val/resources/FolderFilesReferenced/r22/r22.pdf create mode 100644 kurt-utility/src/val/resources/FolderFilesReferenced/r23/r23.zip create mode 100644 kurt-utility/src/val/resources/FolderFilesReferenced/r24/r24.zip create mode 100644 kurt-utility/src/val/resources/FolderFilesReferenced/r25/r25.zip create mode 100644 kurt-utility/src/val/resources/reporting.properties create mode 100644 kurt-utility/src/val/resources/testng.xml create mode 100644 kurt-utility/src/val/resources/testng.yaml create mode 100644 kurt-web/pom.xml create mode 100644 kurt-web/src/main/java/com/capgemini/reports/DispatcherServlet.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/auto/AbstractAutoLaunchServlet.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/common/AbstractKurtServlet.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/common/AbstractSubmitServlet.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/common/AbstractSubmitServletForItemRevision.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/common/DownloadServlet.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/common/ServletMessageHelper.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/common/TestServlet.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/common/obtaindata/AbstractObtainDataFromItemRevision.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/common/obtaindata/AbstractObtainDataFromModelObject.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/common/obtaindata/AbstractObtainDataFromPartRevision.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/common/obtaindata/AbstractObtainDataServlet.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/common/scheduling/AbstractGenerateScheduledTemplateServlet.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/common/scheduling/DeleteServletScheduling.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/common/scheduling/ModifyServletScheduling.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/common/scheduling/SubmitServletScheduling.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/common/scheduling/controller/QueueReaderServlet.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/common/scheduling/controller/SchedulingReaderServlet.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/common/scheduling/utilities/AbstractActionManager.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/common/scheduling/utilities/ReportActivationReaderServlet.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/common/scheduling/utilities/ReportActivatorServlet.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/common/scheduling/utilities/SchedulingPeriodReaderServlet.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/common/scheduling/view/NewSchedulingFormatter.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/common/scheduling/view/SchedulingFormatter.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/common/scheduling/view/SchedulingParametersReader.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/common/scheduling/view/UpdateSchedulingFormatter.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/formatting/AbstractTableFormatter.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/formatting/AllSchedulingReports.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/formatting/ErrorPageTemplate.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/formatting/JsArrayCreator.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/formatting/JsTableCreator.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/formatting/MyReports.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/formatting/QueueStatus.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/formatting/RunningReports.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/formatting/statsgen/AbstractTableGenerator.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/formatting/statsgen/ExecutionCountTableGenerator.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/formatting/statsgen/TimingsTableGenerator.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/r01/SubmitServletR01.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/r03/ObtainDataServletR03.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/r03/SubmitServletR03.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/r07/SubmitServletR07.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/r10/SubmitServletR10.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/r11/SubmitServletR11.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/r13/SubmitServletR13.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/r15/ObtainDataServletR15.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/r15/R15AutoServlet.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/r15/SubmitServletR15.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/r16/SubmitServletR16.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/r17/ObtainDataServletR17.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/r17/SubmitServletR17.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/r19/ObtainDataServletR19.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/r19/SubmitServletR19.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/r20/SubmitServletR20.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/r21/SubmitServletR21.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/r22/ObtainDataServletR22.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/r22/R22AutoServlet.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/r22/SubmitServletR22.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/r23/SubmitServletR23.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/r24/SubmitServletR24.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/r25/SubmitServletR25.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/r26/ObtainDataServletR26.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/r26/SubmitServletR26.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/r27/SubmitServletR27.java create mode 100644 kurt-web/src/main/java/com/capgemini/reports/r28/SubmitServletR28.java create mode 100644 kurt-web/src/main/resources/html/myReports/my_reports_failed.html create mode 100644 kurt-web/src/main/resources/html/myReports/my_reports_success.html create mode 100644 kurt-web/src/main/resources/html/queueStatus/queue_status_failed.html create mode 100644 kurt-web/src/main/resources/html/queueStatus/queue_status_success.html create mode 100644 kurt-web/src/main/resources/html/runningReports/running_reports_failed.html create mode 100644 kurt-web/src/main/resources/html/runningReports/running_reports_success.html create mode 100644 kurt-web/src/main/resources/html/schedulingReports/schedulingReports_error.html create mode 100644 kurt-web/src/main/resources/html/schedulingReports/schedulingReports_success.html create mode 100644 kurt-web/src/main/webapp/WEB-INF/beans.xml create mode 100644 kurt-web/src/main/webapp/WEB-INF/ejb-jar.xml create mode 100644 kurt-web/src/main/webapp/WEB-INF/web.xml create mode 100644 kurt-web/src/main/webapp/css/dialog.css create mode 100644 kurt-web/src/main/webapp/css/kurt-style-frame.css create mode 100644 kurt-web/src/main/webapp/css/kurt-style.css create mode 100644 kurt-web/src/main/webapp/css/pikaday.css create mode 100644 kurt-web/src/main/webapp/css/scheduling.css create mode 100644 kurt-web/src/main/webapp/frames/all_scheduling_reports.jsp create mode 100644 kurt-web/src/main/webapp/frames/criteria.jsp create mode 100644 kurt-web/src/main/webapp/frames/mem_monitoring.jsp create mode 100644 kurt-web/src/main/webapp/frames/my_reports.jsp create mode 100644 kurt-web/src/main/webapp/frames/queue.jsp create mode 100644 kurt-web/src/main/webapp/frames/report_not_authorized_message.jsp create mode 100644 kurt-web/src/main/webapp/frames/running_reports.jsp create mode 100644 kurt-web/src/main/webapp/frames/scheduling_criteria.jsp create mode 100644 kurt-web/src/main/webapp/frames/scheduling_delete.jsp create mode 100644 kurt-web/src/main/webapp/frames/scheduling_new.jsp create mode 100644 kurt-web/src/main/webapp/frames/scheduling_update.jsp create mode 100644 kurt-web/src/main/webapp/frames/statistics_per_report.jsp create mode 100644 kurt-web/src/main/webapp/frames/statistics_per_user.jsp create mode 100644 kurt-web/src/main/webapp/frames/submitNewReport.jsp create mode 100644 kurt-web/src/main/webapp/frames/template_r01.jsp create mode 100644 kurt-web/src/main/webapp/frames/template_r03.jsp create mode 100644 kurt-web/src/main/webapp/frames/template_r07.jsp create mode 100644 kurt-web/src/main/webapp/frames/template_r10.jsp create mode 100644 kurt-web/src/main/webapp/frames/template_r11.jsp create mode 100644 kurt-web/src/main/webapp/frames/template_r13.jsp create mode 100644 kurt-web/src/main/webapp/frames/template_r15.jsp create mode 100644 kurt-web/src/main/webapp/frames/template_r16.jsp create mode 100644 kurt-web/src/main/webapp/frames/template_r17.jsp create mode 100644 kurt-web/src/main/webapp/frames/template_r19.jsp create mode 100644 kurt-web/src/main/webapp/frames/template_r20.jsp create mode 100644 kurt-web/src/main/webapp/frames/template_r21.jsp create mode 100644 kurt-web/src/main/webapp/frames/template_r22.jsp create mode 100644 kurt-web/src/main/webapp/frames/template_r23.jsp create mode 100644 kurt-web/src/main/webapp/frames/template_r24.jsp create mode 100644 kurt-web/src/main/webapp/frames/template_r25.jsp create mode 100644 kurt-web/src/main/webapp/frames/template_r26.jsp create mode 100644 kurt-web/src/main/webapp/frames/template_r27.jsp create mode 100644 kurt-web/src/main/webapp/frames/template_r28.jsp create mode 100644 kurt-web/src/main/webapp/ihm/bt-error-functional.png create mode 100644 kurt-web/src/main/webapp/ihm/bt-error-technical.png create mode 100644 kurt-web/src/main/webapp/ihm/bt-refresh.png create mode 100644 kurt-web/src/main/webapp/ihm/bt-save.png create mode 100644 kurt-web/src/main/webapp/ihm/bt-search.png create mode 100644 kurt-web/src/main/webapp/ihm/button-back.png create mode 100644 kurt-web/src/main/webapp/ihm/calendar_planification.png create mode 100644 kurt-web/src/main/webapp/ihm/delete.png create mode 100644 kurt-web/src/main/webapp/ihm/dialog.gif create mode 100644 kurt-web/src/main/webapp/ihm/generateur-rapports-teamcenter.png create mode 100644 kurt-web/src/main/webapp/ihm/ico-admin.png create mode 100644 kurt-web/src/main/webapp/ihm/ico-email.png create mode 100644 kurt-web/src/main/webapp/ihm/ico-jboss.png create mode 100644 kurt-web/src/main/webapp/ihm/ico-progress.png create mode 100644 kurt-web/src/main/webapp/ihm/ico-queue.png create mode 100644 kurt-web/src/main/webapp/ihm/ico-queued.png create mode 100644 kurt-web/src/main/webapp/ihm/ico-report-stats.png create mode 100644 kurt-web/src/main/webapp/ihm/ico-report.png create mode 100644 kurt-web/src/main/webapp/ihm/ico-scheduled.png create mode 100644 kurt-web/src/main/webapp/ihm/ico-stats.png create mode 100644 kurt-web/src/main/webapp/ihm/ico-user.png create mode 100644 kurt-web/src/main/webapp/ihm/icone-moins.png create mode 100644 kurt-web/src/main/webapp/ihm/icone-plus.png create mode 100644 kurt-web/src/main/webapp/ihm/input-back.png create mode 100644 kurt-web/src/main/webapp/ihm/left-bar-action-back-hover.png create mode 100644 kurt-web/src/main/webapp/ihm/left-bar-action-back.png create mode 100644 kurt-web/src/main/webapp/ihm/left-bar-top.png create mode 100644 kurt-web/src/main/webapp/ihm/left-bar.png create mode 100644 kurt-web/src/main/webapp/ihm/left-bar_160.png create mode 100644 kurt-web/src/main/webapp/ihm/left-bar_260.png create mode 100644 kurt-web/src/main/webapp/ihm/progress.gif create mode 100644 kurt-web/src/main/webapp/ihm/report.png create mode 100644 kurt-web/src/main/webapp/ihm/state_executing.png create mode 100644 kurt-web/src/main/webapp/ihm/state_failed.png create mode 100644 kurt-web/src/main/webapp/ihm/state_finished.png create mode 100644 kurt-web/src/main/webapp/ihm/state_ready.png create mode 100644 kurt-web/src/main/webapp/ihm/state_unknown.png create mode 100644 kurt-web/src/main/webapp/ihm/state_wait.png create mode 100644 kurt-web/src/main/webapp/ihm/title.png create mode 100644 kurt-web/src/main/webapp/ihm/top-bar.png create mode 100644 kurt-web/src/main/webapp/ihm/update.png create mode 100644 kurt-web/src/main/webapp/index.jsp create mode 100644 kurt-web/src/main/webapp/js/criteria.js create mode 100644 kurt-web/src/main/webapp/js/dialog_box.js create mode 100644 kurt-web/src/main/webapp/js/index.js create mode 100644 kurt-web/src/main/webapp/js/json2.js create mode 100644 kurt-web/src/main/webapp/js/kurt-common-submit.js create mode 100644 kurt-web/src/main/webapp/js/moment.js create mode 100644 kurt-web/src/main/webapp/js/my_reports.js create mode 100644 kurt-web/src/main/webapp/js/obtain_data.js create mode 100644 kurt-web/src/main/webapp/js/pikaday.js create mode 100644 kurt-web/src/main/webapp/js/post_form.js create mode 100644 kurt-web/src/main/webapp/js/queue.js create mode 100644 kurt-web/src/main/webapp/js/running_reports.js create mode 100644 kurt-web/src/main/webapp/js/schedulingReport.js create mode 100644 kurt-web/src/main/webapp/js/schedulingReportsCreaUpd.js create mode 100644 kurt-web/src/main/webapp/js/statistics.js create mode 100644 kurt-web/src/test/java/com/capgemini/reports/common/AbstractKurtServletTest.java create mode 100644 kurt-web/src/test/java/com/capgemini/reports/common/AbstractSubmitServletTest.java create mode 100644 kurt-web/src/test/java/com/capgemini/reports/common/scheduling/SchedulingServletTest.java create mode 100644 kurt-web/src/test/java/com/capgemini/reports/formatting/MyReportsTest.java create mode 100644 kurt-web/src/test/java/com/capgemini/servlet/test/Report01Test.java create mode 100644 kurt-web/src/test/resources/htmlRef/my_reports_failed_ref.html create mode 100644 kurt-web/src/test/resources/htmlRef/my_reports_success_ref.html create mode 100644 kurt-web/src/test/resources/log4j.properties create mode 100644 kurt-web/src/test/resources/logging.properties create mode 100644 kurt-web/src/test/resources/simplelogger.properties create mode 100644 kurt-web/src/test/resources/xml/policies/simple_policy.xml create mode 100644 kurt-web/src/test/resources/xml/policies/test_policy.xml create mode 100644 pom.xml create mode 100644 scripts/reports_installation_script.pl create mode 100644 standalone-pv-reports-auth.xml create mode 100644 standalone-pv-reports.xml create mode 100644 teamcenter/pom.xml create mode 100644 teamcenter/src/main/java/com/capgemini/framework/common/BeanHelper.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/common/LanguageHelper.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/common/ReflectionHelper.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/common/StringHelper.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/common/TeamcenterDateFormatter.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/common/security/AesEncoded.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/ServiceDataHelper.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/TeamcenterObjectProperties.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/TeamcenterObjectTypes.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/authent/AuthentPropLoader.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/authent/FscParameters.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/authent/KurtModelEventListener.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/authent/TcCredentialManager.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/authent/TcExceptionHandler.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/authent/TcSession.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/exceptions/ConnectionMisconguredException.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/exceptions/EmptyNomenclatureException.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/exceptions/FailedRelationshipActionException.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/exceptions/InvalidConfigurationException.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/exceptions/KurtException.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/exceptions/MalformedDataSetException.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/exceptions/NoSuchBomViewException.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/exceptions/NoSuchRevisionRuleException.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/exceptions/NoTeamcenterConnectionException.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/exceptions/QueryDoesNotExist.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/exceptions/UnableToCreateStatusException.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/exceptions/runtime/ConnectionLostException.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/exceptions/runtime/KurtRuntimeException.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/files/DatasetPreparator.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/files/FileManagement.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/SnecmaObjectProperties.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/TcBusinessObject.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/TcModelObject.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/TcPomObject.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/status/StatusEnum.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/status/TcEffectivity.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/status/TcReleaseStatus.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/TcItem.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/TcItemRevision.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/TcWorkspaceObject.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/TcBomObject.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/TcBomObjectFactory.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/TcRFPartRevision.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/TcRevisionRule.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/TcRevisionRuleProperties.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/generic/TcGeneric.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/generic/TcGenericAssemb.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/generic/TcGenericAssembRevision.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/generic/TcGenericPv.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/generic/TcGenericPvRevision.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/generic/TcGenericRevision.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/generic/TcRFGeneric.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/generic/TcRFGenericRevision.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/part/TcAlternate.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/part/TcAlternateRevision.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/part/TcDet.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/part/TcDetRevision.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/part/TcPartAero.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/part/TcPartAeroRevision.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/part/TcPartAssemb.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/part/TcPartAssembRevision.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/part/TcPartMat.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/part/TcPartMatRevision.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/part/TcPartNoAero.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/part/TcPartNoAeroRevision.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/part/TcStandard.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/part/TcStandardRevision.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/product/TcProduct.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/product/TcProductRevision.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/unit/TcUnitRevision.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/runtime/TcBomLine.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/runtime/TcBomWindow.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/runtime/TcBomWindowConfiguration.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/runtime/TcBomWindowFactory.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/runtime/TcRevisionRulesConfiguration.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/runtime/TcRuntimeBusinessObject.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/types/SnecmaObjectTypes.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/policies/PolicyLocation.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/queries/saved/AbstractReplicatedQuery.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/queries/saved/AbstractSavedQuery.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/queries/saved/modelobject/AbstractModelObjectQuery.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/queries/saved/modelobject/IMANRelationQuery.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/queries/saved/modelobject/ItemQuery.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/queries/saved/modelobject/ItemRevisionQuery.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/resolution/filtering/AllFilter.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/resolution/filtering/AndFilter.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/resolution/filtering/ITcTypeFilter.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/resolution/filtering/OrFilter.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/resolution/filtering/TcTypeExclusionFilter.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/resolution/filtering/TcTypeInclusionFilter.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/resolution/structureservice/AbstractStructureServiceRaw.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/resolution/structureservice/MultiStructureServiceCallerRaw.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/resolution/structureservice/SingleStructureServiceCallerRaw.java create mode 100644 teamcenter/src/main/java/com/capgemini/framework/teamcenter/statuating/StatusSetter.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/ItemRevisionComparator.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/bomlineholder/BOMLineHolder.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/bomlineholder/BOMLineHolderFactory.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/bomlineholder/BOMLineHolderHelper.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/bomlineholder/IBOMTree.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/bomlineholder/ISnecmaLineProcessor.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/bomlineholder/comparison/AbstractDualBomLineFlattener.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/bomlineholder/comparison/DualBomLineBrowser.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/bomlineholder/comparison/IDualSnecmaLineProcessor.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/bomlineholder/flattener/AbstractBomLineFlattener.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/bomlineholder/flattener/AbstractRepereFlattener.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/bomlineholder/flattener/line/AbstractAltPart.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/bomlineholder/flattener/line/AbstractPartNumber.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/bomlineholder/flattener/line/AbstractPartPart.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/bomlineholder/flattener/line/AbstractPartRfPart.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/bomlineholder/flattener/line/AbstractProductGeneric.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/bomlineholder/flattener/line/AbstractQuad.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/bomlineholder/flattener/line/AbstractReceptorLine.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/bomlineholder/flattener/line/AbstractReceptorRepere.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/bomlineholder/flattener/line/AbstractTopLine.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/bomlineholder/flattener/line/PartTypeExtractorHelper.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/bomlineholder/flattener/line/SnecmaLine.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/bomlineholder/processor/AltOrDetBehaviour.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/bomlineholder/processor/DefaultAltOrDetBehaviour.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/bomlineholder/processor/IBOMLineHolderProcessor.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/bomlineholder/visitor/AbstractBOMLineHolderVisitor.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/bomlineholder/visitor/BomLineBrowser.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/bomlineholder/visitor/IBOMLineHolderExtractor.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/bomlineholder/visitor/IBOMLineHolderVisitor.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/changeobjects/UnitRevision.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/changeobjects/change/AbstractChangeObject.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/changeobjects/change/FPPRevision.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/changeobjects/change/TcChangeNoticeRevision.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/changeobjects/change/TcChangeRequestRevision.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/documentationobjects/AbstractDoc.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/documentationobjects/DocDrawing.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/documentationobjects/DocFactory.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/documentationobjects/DocGeometry.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/documentationobjects/DocNorm.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/documentationobjects/DocNormStandard.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/documentationobjects/DocTechnic.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/documentationobjects/IDocVisitor.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/exceptions/InvalidInputException.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/exceptions/InvalidUserInputException.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/exceptions/MalformedNomenclatureException.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/exceptions/NoConfChangesException.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/exceptions/NotFoundException.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/exceptions/NotSupportedException.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/exceptions/ServiceException.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/exceptions/UserInputErrorEnum.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/filter/AllIsGoodFilter.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/filter/FilterExcludeByType.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/filter/FilterIncludeByType.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/filter/IFilterExplosionNomenclature.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/releasestatus/DefaultRevisionSelector.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/releasestatus/EffectivityBehaviourHelper.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/releasestatus/RevisionSelector.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/releasestatus/RevisionStatusAndDate.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/reports/parameters/DualGenerics.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/reports/parameters/EffectivityDate.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/reports/parameters/Generics.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/reports/parameters/IChecker.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/reports/parameters/MonoMulti.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/reports/parameters/ProductUnit.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/reports/parameters/SuperModel.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/reports/parameters/checker/EffectivityChecker.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/reports/parameters/checker/GenericConditionR21Checker.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/reports/parameters/checker/GenericExistenceChecker.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/reports/parameters/checker/GenericUnderProductUnitChecker.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/reports/parameters/checker/ModelObjectChecker.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/reports/parameters/checker/ObjectTypeChecker.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/reports/parameters/checker/ProductChecker.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/reports/parameters/checker/ProductUnitChecker.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/reports/parameters/checker/ProductUnitGenericChecker.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/reports/parameters/checker/UnitRevisionChecker.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/AbstractSnecmaObject.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/ISnecmaObject.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/SnecmaObjectFactory.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/admin/AbstractAdmin.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/admin/RFAdminAGRevision.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/admin/RFAdminAPRevision.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/admin/RFAdminARevision.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/admin/RFAdminRevision.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/descriptif/DescriptifRevision.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/generic/AbstractGeneric.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/generic/AbstractGenericRevision.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/generic/Generic.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/generic/GenericAssemb.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/generic/GenericAssembRevision.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/generic/GenericRevision.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/mockup/MockupRevision.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/part/AbstractAltOrDetRevision.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/part/AbstractPart.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/part/AlternateRevision.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/part/DETRevision.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/part/PartAeroRevision.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/part/PartAssembRevision.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/part/PartMatRevision.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/part/PartNoAeroRevision.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/part/StandardRevision.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/product/ProductRevision.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/rf/AbstractRF.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/rf/RFGenericRevision.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/rf/RFPartAssembRevision.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/rf/RFPartRevision.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/supermodel/AbstractSuperModel.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/supermodel/AbstractSuperModelRevision.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/supermodel/SuperModel.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/supermodel/SuperModelRevision.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/visitor/IComponentVisitor.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/visitor/IReceptorVisitor.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/teamcenter/ObjectInfoHelper.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/teamcenter/ObjectInfoLoader.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/teamcenter/Platform.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/DirectQuery.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/TypeQuery.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/saved/AllSequencesOfItemQuery.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/saved/ChangeFromPartQuery.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/saved/ChangeNoticeR07Query.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/saved/ChangeRequestQuery.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/saved/ChangeRequestR07Query.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/saved/ChangeRequestWithSeqQuery.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/saved/FppWithSeqQuery.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/saved/GenericAssembQuery.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/saved/GenericQuery.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/saved/ProductTypeQuery.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/saved/UnitFromChangeRequestQuery.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/saved/UnitQuery.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/saved/WorkflowOnChangeQuery.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/saved/WorkflowOnUnitQuery.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/teamcenter/resolution/IBOMLineExplorer.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/teamcenter/resolution/structureservice/IStructureServiceCaller.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/teamcenter/resolution/structureservice/MultiStructureServiceCaller.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/teamcenter/resolution/structureservice/SingleStructureServiceCaller.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/teamcenter/resolution/structureservice/TripleStructureServiceCaller.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/teamcenter/resolution/structureservice/explorer/PartNumberFinder.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/users/SnecmaPerson.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/users/SnecmaUser.java create mode 100644 teamcenter/src/main/java/com/capgemini/reports/workflows/Task.java create mode 100644 teamcenter/src/main/java/com/teamcenter/soa/exceptions/NotLoadedException.java create mode 100644 teamcenter/src/test/java/com/capgemini/framework/common/DummyBean.java create mode 100644 teamcenter/src/test/java/com/capgemini/framework/common/ReflectionHelperTest.java create mode 100644 teamcenter/src/test/java/com/capgemini/framework/common/StringHelperTest.java create mode 100644 teamcenter/src/test/java/com/capgemini/framework/common/TeamcenterDateFormatterTest.java create mode 100644 teamcenter/src/test/java/com/capgemini/framework/teamcenter/files/DatasetPreparatorTest.java create mode 100644 teamcenter/src/test/java/com/capgemini/framework/teamcenter/files/FileManagementTest.java create mode 100644 teamcenter/src/test/java/com/capgemini/framework/teamcenter/queries/saved/modelobject/ItemQueryTest.java create mode 100644 teamcenter/src/test/java/com/capgemini/framework/teamcenter/queries/saved/modelobject/ItemRevisionQueryTest.java create mode 100644 teamcenter/src/test/java/com/capgemini/framework/teamcenter/relations/RelationshipManagerTest.java create mode 100644 teamcenter/src/test/java/com/capgemini/framework/teamcenter/statuating/StatusSetterTest.java create mode 100644 teamcenter/src/test/java/com/capgemini/reports/AbstractTeamcenterTest.java create mode 100644 teamcenter/src/test/java/com/capgemini/reports/ScenarioForTests.java create mode 100644 teamcenter/src/test/java/com/capgemini/reports/TeamcenterTypeObjectsTest.java create mode 100644 teamcenter/src/test/java/com/capgemini/reports/changeobjects/AbstractChangeObjectTest.java create mode 100644 teamcenter/src/test/java/com/capgemini/reports/changeobjects/UnitRevisionTest.java create mode 100644 teamcenter/src/test/java/com/capgemini/reports/documentationobjects/DocDrawingTest.java create mode 100644 teamcenter/src/test/java/com/capgemini/reports/documentationobjects/DocGeometryTest.java create mode 100644 teamcenter/src/test/java/com/capgemini/reports/documentationobjects/DocNormStandardTest.java create mode 100644 teamcenter/src/test/java/com/capgemini/reports/documentationobjects/DocNormTest.java create mode 100644 teamcenter/src/test/java/com/capgemini/reports/documentationobjects/DocTechnicTest.java create mode 100644 teamcenter/src/test/java/com/capgemini/reports/releasestatus/TcReleaseStatusTest.java create mode 100644 teamcenter/src/test/java/com/capgemini/reports/reports/parameters/DualsGenericsTest.java create mode 100644 teamcenter/src/test/java/com/capgemini/reports/reports/parameters/GenericsTest.java create mode 100644 teamcenter/src/test/java/com/capgemini/reports/reports/parameters/ProductUnitTest.java create mode 100644 teamcenter/src/test/java/com/capgemini/reports/reports/parameters/TcEffectivityDateTest.java create mode 100644 teamcenter/src/test/java/com/capgemini/reports/reports/parameters/checker/GenericExistenceCheckTest.java create mode 100644 teamcenter/src/test/java/com/capgemini/reports/reports/parameters/checker/ObjectTypeCheckerTest.java create mode 100644 teamcenter/src/test/java/com/capgemini/reports/reports/parameters/checker/ProductCheckTest.java create mode 100644 teamcenter/src/test/java/com/capgemini/reports/reports/parameters/checker/ProductUnitCheckTest.java create mode 100644 teamcenter/src/test/java/com/capgemini/reports/reports/parameters/checker/TcEffectivityCheckerTest.java create mode 100644 teamcenter/src/test/java/com/capgemini/reports/teamcenter/ObjectInfoHelperTest.java create mode 100644 teamcenter/src/test/java/com/capgemini/reports/teamcenter/TeamcenterConnectionTest.java create mode 100644 teamcenter/src/test/java/com/capgemini/reports/teamcenter/queries/TypeQueryTest.java create mode 100644 teamcenter/src/test/java/com/capgemini/reports/teamcenter/queries/saved/AllSequencesQueryTest.java create mode 100644 teamcenter/src/test/java/com/capgemini/reports/teamcenter/queries/saved/ChangeRequestQueryTest.java create mode 100644 teamcenter/src/test/java/com/capgemini/reports/teamcenter/queries/saved/UnitFromCRTest.java create mode 100644 teamcenter/src/test/java/com/capgemini/reports/teamcenter/queries/saved/UnitQueryTest.java create mode 100644 teamcenter/src/test/java/com/capgemini/reports/teamcenter/queries/saved/WorkflowOnChangeQueryTest.java create mode 100644 teamcenter/src/test/java/com/capgemini/reports/teamcenter/queries/saved/WorkflowQueryTest.java create mode 100644 teamcenter/src/test/java/com/capgemini/reports/users/SnecmaPersonTest.java create mode 100644 teamcenter/src/test/java/com/capgemini/reports/users/SnecmaUserTest.java create mode 100644 teamcenter/src/test/java/com/capgemini/reports/workflows/TaskTest.java create mode 100644 teamcenter/src/test/resources/TextFile.txt create mode 100644 teamcenter/src/test/resources/jasperPdfPrinterTest.pdf create mode 100644 teamcenter/src/test/resources/log4j.properties create mode 100644 teamcenter/src/test/resources/logging.properties create mode 100644 teamcenter/src/test/resources/reporting.properties create mode 100644 teamcenter/src/test/resources/test_policy.xml create mode 100644 teamcenter/src/test/resources/xml/policies/PoliciesDomParserTest.xml create mode 100644 teamcenter/src/test/resources/xml/policies/bom_policy.xml create mode 100644 teamcenter/src/test/resources/xml/policies/policy_full.xml create mode 100644 teamcenter/src/test/resources/xml/policies/policy_light.xml create mode 100644 teamcenter/src/test/resources/xml/policies/test_policy.xml create mode 100644 teamcenter/src/test/resources/xml/ref/MultiStructureServiceCallerTest_item.xml create mode 100644 teamcenter/src/test/resources/xml/ref/MultiStructureServiceCallerTest_item_revision.xml create mode 100644 teamcenter/src/test/resources/xml/ref/StructureServiceCallerTest_mono.xml create mode 100644 teamcenter/src/test/resources/xml/ref/StructureServiceCallerTest_multi.xml create mode 100644 teamcenter/src/test/resources/xml/ref/TripleStructureServiceCallerTest_item.xml create mode 100644 teamcenter/src/test/resources/xml/ref/TripleStructureServiceCallerTest_item_revision.xml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..aa3957c --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +/.idea/ +*.iml +**/target/** +**/out/** \ No newline at end of file diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 0000000..e4e3064 --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,64 @@ +pipeline { + agent {node 'debian'} + options { + buildDiscarder(logRotator(numToKeepStr: '10', artifactNumToKeepStr: '10')) + } + environment { + VERSION = readMavenPom().getVersion() + } + stages { + stage('Checkout') { + steps { + checkout scm + script { + currentBuild.displayName = "${env.BRANCH_NAME}-${env.BUILD_NUMBER}" + } + } + } + stage ('Build') { + steps { + withMaven(jdk: 'JDK1.7_Oracle', maven: 'Maven3', mavenSettingsConfig: 'nexus_settings') { + sh "mvn -Dhttps.protocols=TLSv1.2 -Dmaven.test.failure.ignore=true -P validation clean install" + } + } + post { + success { + archiveArtifacts artifacts: '**/*.ear', fingerprint: true + // + // junit '**/build/surefire-reports/**/*.xml' + } + } + } + stage ('Quality') { + steps { + withSonarQubeEnv('Sonarqube') { + withMaven(jdk: 'JDK1.8_Oracle', maven: 'Maven3', mavenSettingsConfig: 'nexus_settings', mavenOpts: '-Xms256m -Xmx1024m') { + sh "mvn -Dhttps.protocols=TLSv1.2 -Dmaven.test.failure.ignore=true org.sonarsource.scanner.maven:sonar-maven-plugin:3.5.0.1254:sonar" + } + } + } + } + stage('Deploy VAL') { + when { + beforeAgent true + branch 'TM*' + } + steps { + sh '' + } + } + stage('Package') { + steps { + withMaven(jdk: 'JDK1.7_Oracle', maven: 'Maven3', mavenSettingsConfig: 'nexus_settings') { + sh "mvn -Dhttps.protocols=TLSv1.2 package" + } + } + post { + success { + archiveArtifacts '**/target/*.ear' + archiveArtifacts '**/target/*.zip' + } + } + } + } +} \ No newline at end of file diff --git a/core-ear/pom.xml b/core-ear/pom.xml new file mode 100644 index 0000000..ba33d7f --- /dev/null +++ b/core-ear/pom.xml @@ -0,0 +1,65 @@ + + + 4.0.0 + core-ear + ear + core-ear + + + com.capgemini.reports + kurt + 1.32.9 + + + + + com.capgemini.reports + kurt-web + 1.32.9 + war + + + + + + + org.apache.maven.plugins + maven-ear-plugin + + 6 + lib + + + com.capgemini.reports + kurt-web + /kurt-web + + + + + + + + + + validation + + + + org.jboss.as.plugins + jboss-as-maven-plugin + + ${hostname} + 9999 + admin + jboss + true + + + + + + + + + diff --git a/deployment-tool/pom.xml b/deployment-tool/pom.xml new file mode 100644 index 0000000..e1459bb --- /dev/null +++ b/deployment-tool/pom.xml @@ -0,0 +1,96 @@ + + + 4.0.0 + deployment-tool + jar + Deployment tool + Deployment tool for JAVA project facilitating resources updates in archives (jar, war, ear) + + + + kurt + com.capgemini.reports + 1.32.9 + + + + + org.testng + testng + test + + + org.assertj + assertj-core + test + + + org.slf4j + slf4j-api + 1.7.7 + + + + org.slf4j + slf4j-log4j12 + 1.7.7 + + + + log4j + log4j + 1.2.16 + + + + com.google.guava + guava + + + + com.oracle + ojdbc6 + 11.2.0.3 + + + + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + copy-dependencies + prepare-package + + unpack-dependencies + + + ${project.build.directory}/classes + runtime + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + com.capgemini.framework.deployment.Install + true + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + + + diff --git a/deployment-tool/src/main/java/com/capgemini/framework/common/FileHelper.java b/deployment-tool/src/main/java/com/capgemini/framework/common/FileHelper.java new file mode 100644 index 0000000..c14ecef --- /dev/null +++ b/deployment-tool/src/main/java/com/capgemini/framework/common/FileHelper.java @@ -0,0 +1,71 @@ +package com.capgemini.framework.common; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; + +/** + * Class for common file management. + **/ +public final class FileHelper { + private static final Logger log = LoggerFactory.getLogger(FileHelper.class); + private static final char LINE_FEED = 0x000A; + + private FileHelper() { + // Constructor of helper classes must be private + } + + /** + * Check file existence. + * + * @param aFilePath File which must be checked + * @return True when the file exists + */ + public static boolean fileExist(final String aFilePath) { + boolean status = true; + if (aFilePath == null) { + log.debug("File name is null"); + return false; + } + + File theFile = new File(aFilePath); + if (!theFile.exists() || theFile.isDirectory()) { + log.debug("File does not exist: {}", theFile.getAbsolutePath()); + status = false; + } + + return status; + } + + /** + * Read a text file and findAll its content. + * + * @param aSourceFilePath parsed source file path + * @return string with text file content + */ + public static String read(final String aSourceFilePath) throws IOException { + // Check file existence + if (!fileExist(aSourceFilePath)) { + throw new FileNotFoundException("File does not exist: " + aSourceFilePath); + } + + StringBuilder theContent = new StringBuilder(); + try (BufferedReader reader = new BufferedReader(new FileReader(aSourceFilePath))) { + // Browse lines of file + String theCurrentLine = reader.readLine(); + while (theCurrentLine != null) { + theContent.append(theCurrentLine); + theContent.append(LINE_FEED); + theCurrentLine = reader.readLine(); + } + } + + // Read file content + return theContent.toString(); + } +} diff --git a/deployment-tool/src/main/java/com/capgemini/framework/common/FolderHelper.java b/deployment-tool/src/main/java/com/capgemini/framework/common/FolderHelper.java new file mode 100644 index 0000000..9009468 --- /dev/null +++ b/deployment-tool/src/main/java/com/capgemini/framework/common/FolderHelper.java @@ -0,0 +1,35 @@ +package com.capgemini.framework.common; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +/** + * Class for folder management. + **/ +public final class FolderHelper { + + private FolderHelper() { + // Constructor of helper classes must be private + } + + + /** + * Get file list from a specific directory with a filtered extension. + * + * @param aDirectory Directory path containing searched files + * @param anExtension Extension of searched files (Set to null when all files should be returned) + * @return List of files + */ + public static List dirList(final File aDirectory, final String anExtension) { + List filteredFileList = new ArrayList<>(); + for (String element : aDirectory.list()) { + if (anExtension == null || (element.endsWith(anExtension))) { + filteredFileList.add(element); + } + } + + return filteredFileList; + } + +} diff --git a/deployment-tool/src/main/java/com/capgemini/framework/db/DbConnection.java b/deployment-tool/src/main/java/com/capgemini/framework/db/DbConnection.java new file mode 100644 index 0000000..6696c38 --- /dev/null +++ b/deployment-tool/src/main/java/com/capgemini/framework/db/DbConnection.java @@ -0,0 +1,48 @@ +package com.capgemini.framework.db; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; + +/** + * Define the migration database connection. + **/ +class DbConnection { + private static final Logger log = LoggerFactory.getLogger(DbConnection.class); + private Connection connection; + + /** + * Connect directly to the database by specifying user and password. + * + * @param anUrl Database URL. + * @param anUser User required for authentication. + * @param aPassword Password required for authentication. + **/ + DbConnection(final String anUrl, final String anUser, final String aPassword) { + try { + /* Load driver */ + DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver()); + + /* Connect to database */ + connection = DriverManager.getConnection(anUrl, anUser, aPassword); + + /* By default enabled auto commit */ + connection.setAutoCommit(true); + } + catch (SQLException e) { + log.error("Unable to prepare connection", e); + } + } + + /** + * Getter for connection attribute. + * + * @return Active connection. + */ + Connection getConnection() { + return connection; + } +} diff --git a/deployment-tool/src/main/java/com/capgemini/framework/db/DbManager.java b/deployment-tool/src/main/java/com/capgemini/framework/db/DbManager.java new file mode 100644 index 0000000..d344b67 --- /dev/null +++ b/deployment-tool/src/main/java/com/capgemini/framework/db/DbManager.java @@ -0,0 +1,69 @@ +package com.capgemini.framework.db; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.sql.SQLException; +import java.sql.Statement; + +/** + * Class for all JDBC connections. + */ +public class DbManager { + private static final Logger log = LoggerFactory.getLogger(DbManager.class); + private final DbConnection connection; + + public DbManager(final String url, final String login, final String password) { + connection = new DbConnection(url, login, password); + } + + /** + * Execute a query for private use of this utility class. + * + * @param query the SQL query + * @return the number of affected rows + */ + private int execute(final String query) throws SQLException { + try (Statement theStatement = connection.getConnection().createStatement()) { + return theStatement.executeUpdate(query); + } + } + + /** + * Execute a SQL query with stack trace display parameter. + * + * @param aQuery SQL query content. + * @return True when the query has been executed successfully. + */ + boolean executeQuery(final String aQuery) { + boolean status = true; + int nbRowsImpacted = executeQueryAndGetRowCount(aQuery); + if (nbRowsImpacted < 0) { + status = false; + } + return status; + } + + /** + * Execute a SQL query and findAll its impacted rows count (for UPDATE and DELETE operations). + * + * @param aQuery SQL query content. + * @return impacted row count (-1 = error). + */ + private int executeQueryAndGetRowCount(final String aQuery) { + try { + return execute(aQuery); + } + catch (SQLException e) { + if (!isIgnoredError(e)) { + log.error("SQL error detected during following query execution: " + aQuery, e); + } + return -1; + } + } + + private boolean isIgnoredError(final SQLException exc) { + int theErrorCode = exc.getErrorCode(); + return theErrorCode == 2289 || theErrorCode == 942; + } +} diff --git a/deployment-tool/src/main/java/com/capgemini/framework/db/SqlHelper.java b/deployment-tool/src/main/java/com/capgemini/framework/db/SqlHelper.java new file mode 100644 index 0000000..f13a721 --- /dev/null +++ b/deployment-tool/src/main/java/com/capgemini/framework/db/SqlHelper.java @@ -0,0 +1,105 @@ +package com.capgemini.framework.db; + +import com.capgemini.framework.common.FileHelper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; + +/** + * Utility class for running SQL queries from an SQL file. + **/ +public final class SqlHelper { + private static final Logger log = LoggerFactory.getLogger(SqlHelper.class); + + private SqlHelper() { + /* Constructor of helper classes must be private */ + } + + /** + * Load a set of SQL queries from a text file. + * + * @param aDbManager Database manager for executing SQL queries + * @param aFilePath File path for the loaded SQL file + * @return True when all executed queries have been successfully run + **/ + public static boolean runSqlFile(DbManager aDbManager, String aFilePath) throws IOException { + + /* Check file existence */ + if (!FileHelper.fileExist(aFilePath)) { + log.error("SQL file does not exist: {}", aFilePath); + return false; + } + + /* Extract the SQL file content */ + String theFileContent = FileHelper.read(aFilePath); + + /* Separate each query */ + String[] theQueryArray = theFileContent.split(";\n"); + + return runSqlFile(aDbManager, aFilePath, theQueryArray); + } + + /** + * Load a set of SQL queries from a text file. + * + * @param aDbManager Database manager for executing SQL queries + * @param aFilePath File path for the loaded SQL file + * @param aQueryArray List of SQL queries executed + * @return True when all executed queries have been successfully run + **/ + public static boolean runSqlFile(DbManager aDbManager, String aFilePath, String[] aQueryArray) { + + boolean isSuccess = true; + int successQueryCount = 0; + + /* Browse SQL queries from file */ + for (String currentQuery : aQueryArray) { + + /* Check if current query could be managed by loader */ + String currentUnformatedQuery = unformatQuery(currentQuery); + if (currentUnformatedQuery.isEmpty()) { + continue; + } + + /* Run the SQL query */ + if (aDbManager.executeQuery(currentUnformatedQuery)) { + successQueryCount++; + } + else { + isSuccess = false; + } + } + + /* Log correct queries */ + if (successQueryCount > 0) { + log.debug("{} queries have been executed successfully from file: {}", successQueryCount, aFilePath); + } + + return isSuccess; + } + + /** + * Clean the special characters used for indentation in the query. + * + * @param aQueryValue Original query (with pretty print format) + * @return Cleaned query + **/ + private static String unformatQuery(String aQueryValue) { + + String theUnformatedQuery = aQueryValue; + + /* Delete "pretty print" */ + theUnformatedQuery = theUnformatedQuery.replace("\n", " ").replace("\r", "").replace("\t", " "); + + /* Delete comments */ + theUnformatedQuery = theUnformatedQuery.replaceAll("/\\*.*?\\*/", "").trim(); + + /* Ignore query with only "COMMIT" instruction */ + if ("COMMIT".equalsIgnoreCase(theUnformatedQuery)) { + theUnformatedQuery = ""; + } + + return theUnformatedQuery; + } +} diff --git a/deployment-tool/src/main/java/com/capgemini/framework/deployment/DeployProperties.java b/deployment-tool/src/main/java/com/capgemini/framework/deployment/DeployProperties.java new file mode 100644 index 0000000..3608c67 --- /dev/null +++ b/deployment-tool/src/main/java/com/capgemini/framework/deployment/DeployProperties.java @@ -0,0 +1,77 @@ +package com.capgemini.framework.deployment; + + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.Map.Entry; +import java.util.Properties; + +/** + * Property ready for user inputs. + **/ +class DeployProperties { + private static final Logger log = LoggerFactory.getLogger(DeployProperties.class); + private final Properties propFile; + + DeployProperties(String aFilePath) { + propFile = new Properties(); + try (FileInputStream theFileStream = getInputStream(aFilePath)) { + propFile.load(theFileStream); + displayValues(); + } + catch (FileNotFoundException e) { + log.error("The file has not been found: " + aFilePath, e); + } + catch (IOException e) { + log.error("Error while reading file: " + aFilePath, e); + } + + } + + /** + * Display property file content for debug purpose. + */ + private void displayValues() { + if (log.isDebugEnabled()) { + StringBuilder thePropValues = new StringBuilder(); + thePropValues.append("Property values:\n"); + + for (Entry currentProp : propFile.entrySet()) { + String currentKey = currentProp.getKey().toString(); + String currentValue = currentProp.getValue().toString(); + thePropValues.append("\t").append(currentKey).append("=").append(currentValue).append("\n"); + } + + log.debug(thePropValues.toString()); + } + } + + /** + * Read input properties file. + */ + private FileInputStream getInputStream(String aFilePath) throws FileNotFoundException { + return new FileInputStream(new File(aFilePath)); + } + + /** + * Retrieve a property value. + * + * @param aDynamicRef Reference of the the searched property + * @return Property value + */ + String getString(String aDynamicRef) { + String thePropValue = ""; + if (propFile.containsKey(aDynamicRef)) { + thePropValue = propFile.getProperty(aDynamicRef); + } + else { + log.debug("Unknown property reference: {}", aDynamicRef); + } + return thePropValue; + } +} diff --git a/deployment-tool/src/main/java/com/capgemini/framework/deployment/Install.java b/deployment-tool/src/main/java/com/capgemini/framework/deployment/Install.java new file mode 100644 index 0000000..5af8dfc --- /dev/null +++ b/deployment-tool/src/main/java/com/capgemini/framework/deployment/Install.java @@ -0,0 +1,137 @@ +package com.capgemini.framework.deployment; + +import com.capgemini.framework.common.FileHelper; +import com.capgemini.framework.common.FolderHelper; +import com.capgemini.framework.db.DbManager; +import com.capgemini.framework.db.SqlHelper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.IOException; +import java.util.List; + +/** + * Main class of executable JAR. + **/ +public class Install { + private static final Logger log = LoggerFactory.getLogger(Install.class); + private String homeDir; + private DeployProperties deployProperties; + + /** + * Main entry point of executable JAR. + * + * @param args Command line arguments + */ + public static void main(String[] args) { + log.info("Start installation"); + log.info("=================="); + + boolean isSuccess = true; + int theStatus = 0; + try { + Install theInstaller = new Install(); + + /* Check that the execution mode has been selected */ + isSuccess = theInstaller.checkEnvironment(); + if (isSuccess) { + isSuccess = theInstaller.runSqlExec(); + } + } + catch (Exception e) { + log.error("Unexpected error occurred", e); + } + finally { + if (!isSuccess) { + log.info("Installation status: FAILED"); + theStatus = 1; + } + else { + log.info("Installation status: SUCCESS"); + } + log.info("==============================="); + } + System.exit(theStatus); + } + + /** + * Check if a environment variable is set. + * + * @return True when variable is set + */ + private static boolean checkEnvVar() { + boolean isSet = true; + String theEnvValue = System.getenv("DEPLOY_TOOL_HOME"); + if (theEnvValue == null) { + isSet = false; + } + return isSet; + } + + /** + * Load SQL files which are in the "sql" sub-folder. + * + * @return True when all the SQL queries have been executed successfully + **/ + private boolean runSqlExec() throws IOException { + + boolean isSuccess = true; + + /* Retrieve database parameters from properties */ + String url = deployProperties.getString("database.url"); + String theLogin = deployProperties.getString("database.schema.login"); + String thePass = deployProperties.getString("database.schema.password"); + + /* Instantiate database connector */ + DbManager theDbManager = new DbManager(url, theLogin, thePass); + + /* Browse PL/SQL folder and load each SQL file */ + File thePlSqlFolder = new File(homeDir + "/plsql"); + List theDirList = FolderHelper.dirList(thePlSqlFolder, "sql"); + for (String currentFile : theDirList) { + String currentFilePath = homeDir + "/plsql/" + currentFile; + String currentFileContent = FileHelper.read(currentFilePath); + isSuccess &= SqlHelper.runSqlFile(theDbManager, currentFilePath, new String[]{currentFileContent}); + } + + /* Browse SQL folder and load each SQL file */ + File theSqlFolder = new File(homeDir + "/sql"); + theDirList = FolderHelper.dirList(theSqlFolder, "sql"); + for (String currentFile : theDirList) { + isSuccess &= SqlHelper.runSqlFile(theDbManager, homeDir + "/sql/" + currentFile); + } + + return isSuccess; + } + + /** + * Run all prerequisite checks for verifying the environment setup. + **/ + private boolean checkEnvironment() { + /* Check environment */ + if (!checkEnvVar()) { + log.error("The environment variable DEPLOY_TOOL_HOME must be set"); + return false; + } + homeDir = getEnvDir(); + String propFilePath = homeDir + "/db.properties"; + if (!FileHelper.fileExist(propFilePath)) { + log.error("The property file for installation is missing: {}", propFilePath); + return false; + } + + /* Call the properties loader when all prerequisites checks have been done. */ + deployProperties = new DeployProperties(propFilePath); + + return true; + } + + /** + * Get directory path and replace backslash separator to slash separator. + **/ + private String getEnvDir() { + String theDirPath = System.getenv("DEPLOY_TOOL_HOME"); + return theDirPath.replace("\\", "/"); + } +} diff --git a/deployment-tool/src/main/resources/log4j.properties b/deployment-tool/src/main/resources/log4j.properties new file mode 100644 index 0000000..2567034 --- /dev/null +++ b/deployment-tool/src/main/resources/log4j.properties @@ -0,0 +1,15 @@ +# Root logger option +log4j.rootLogger=DEBUG, stdout, file +# Direct log messages to stdout +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.Target=System.out +log4j.appender.stdout.threshold=DEBUG +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} - %m%n + +log4j.appender.file=org.apache.log4j.RollingFileAppender +log4j.appender.file.File=./log/install.log +log4j.appender.file.MaxFileSize=10MB +log4j.appender.file.MaxBackupIndex=10 +log4j.appender.file.layout=org.apache.log4j.PatternLayout +log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n diff --git a/deployment-tool/src/test/resources/input/deploy.test.properties b/deployment-tool/src/test/resources/input/deploy.test.properties new file mode 100644 index 0000000..9daadde --- /dev/null +++ b/deployment-tool/src/test/resources/input/deploy.test.properties @@ -0,0 +1 @@ +# This file may be empty for test but must exist diff --git a/deployment-tool/src/test/resources/input/sampleArchives/sampleEar.ear b/deployment-tool/src/test/resources/input/sampleArchives/sampleEar.ear new file mode 100644 index 0000000000000000000000000000000000000000..613209f9f61e1ba6640144a70a4e336da9854498 GIT binary patch literal 1315 zcmWIWW@Zs#U|`^22rKb%J2*-HYYUKf94x}XP?VovqF0fdW7_A)cSu3N_4=#|cB5+7 z1(Wm|-tB3)Y8&e0p{2rc?D6W$n`YVP$En5h&VTN6PjA0dm(-1i97m2;SGBw_jXC~# zU;Du~+q9O4)DgyhZHR1R<+IqG`y*UrwFmA@DZQk^nRwM?8Ux>W4>bTQTCVuwu& z3_3)A@930Wqs7bo$&7iURT;19%A>0DD&sm`t5{usvaWPhow@Spz31oRzka*?@q>N! zw=*xbZ%HlxVq3B`Y*x<2uXc-HX8(G!^19*LKdL;9obG<|wtGu@53G5)`MLir%iL#c zTzM2fr=RDFH%Vlxw%VNiNWXnu?`CT=4!`-;ItO-57ks#7v%_-JO24&txSm`!GBVH* zD2j5;^UG_{t)JX@LgsS+H??xt#i^-vB_Dq7+$cY__OR{CQ(KvD$)Elc&o4+4bn!)}Ioeg(A-%uY4DLN6qrO^#1DHS+O-5507gmxfV(wkNr4NtOzFUb^S>b-ny_ujza0>U})J?XPo5TjP|zhpyI1AKhrOJ`wY@!z1>$pAcda;Cob@zJVg0m; zjgB(y-C9M(Ma(%rXY;r`n^CvLe5baQuJ-4}&F9be{$24#`kiO^I@t^Ve%S2NKKS$4 z-o3j|uTMX}qH}hNP(f+tjD%NN!B<&}0)xX!Q$iwNPn})TRe$fmvrW}sqownl-%8I3 z627+OlO=v zF~Gdbz{sEgqJRKa;2`V5mfaz$6@b(#AV$gj$XcS|Nf1#(eSR&``lS?iUXbc%o8z~-`h^;;WmL+u-! zQWMs+%01&duNQR3IJ3dhOyc6&IsXgRKk+;2zN$C>m;X(n&tj5IH$zh5}PYfHx}}NCztrrh-xv6Nm=@gv z>7{D~W=)?xf6~lpGiNPg2$?^7R`{X`GuYFaT@!yfbZwm7u|aV9++zXOy^H~H7o7#V zsL69`Dz?Q$sKxB^TM|+dIqS3N4KRWpQ+}MxGzTuv9<=O%5 zkI$pK5}a?`+q=8`diIQ(xJf1fSC@tfrmi+sT_6`VWmQK;m9<{ENvHVd4QwvESHHF4 zHq^esDK%kDtK2ib^Ljydj58Z7%_J_ao%6q7{S&{V?yGw9fBD}O`Ya~dbVE5THBUe( zt5>HeZVJmsfj5yA{E4-^cCpDy4}M*7>)L#bd5Ns&<2?5%Zj+qrjo-aC%`QHa@Z*$z zfHxzP2m|iW2YQ!*kwF1O0RjHFKsF0oxPeT7m^BH9S-?;X@MdKLDP#h|i9osr80ZWP E0A5LKz31neu-X1ZjNc6Bi|tf0oUuZD%g#xT^CH!Yk0S( z;i_$@lZTcH$Faw&FK?P)o$_2>|ak-UN>C(N0q0M)7?+rc5g}Vfi*8TKlh(ynfq*wE05ym^z&Tt zCW&m-R-3aQ>9?=z-E3{f;Wxip=fJM%f)BTBc35s&>9_U{*ORM8Mg|%JMNzJKet8YL z^^+S<$XxFKrdIB{I5oAdu1VW(*7Zw zUHLX?@>ID$yB=NJ`cvYwP~`dJmG6S@s99c@-d~+NE4D`C;c?A`90Q|Hg9m--90CoO zJT~@SXw$tXc&org>kz}6mkcZt2M@|Q)~s?c6N%s->-IHm8Qt98;x_nTe$zg64k_qG4OxjEf0{^B)@rSBK6-g+se zd);?Q-}uYw{(Ji}pXw)a_*fMEdhv2;HcOiCeB1gKW$>8qfC3ZR#9;gbI#A%JTA{> z)NL`}sV$|e{dsZo`SZPhSGz*G0FlJ9~V_^b=Kf=Zfb)GCR5R-jBQ4m)|^c=Ct>F$zEX$ie$c8frONRhD{%i zvu=vKafmnZn#!Gp5)aOvVhcLK(jweg!mHfD4vx_0f83&{0V7nI2^67>Od<@3!U#FD zg9;;504ti%bs;AaP(gqIyMRoTVgX$%vSZM+0-XoZ3QbV~-mGjOlbL~V4Uq0;0r3E7 Cr6aWf literal 0 HcmV?d00001 diff --git a/deployment-tool/src/test/resources/input/sampleArchives/updated/repackedSampleJar.jar b/deployment-tool/src/test/resources/input/sampleArchives/updated/repackedSampleJar.jar new file mode 100644 index 0000000000000000000000000000000000000000..86feaeeef03fc6b600cd774ac8a1792fd9bb8c44 GIT binary patch literal 1009 zcmWIWW@Zs#;Nak3;Ec2KVL$?$Kz4CavVLx2W}ZGXLx49s2S}C)sw4oXMqy-)MXAO4 zrA5i9#UvRagWZVK+=7xym&_uP%u>g0R!M4ciD#ZyVv$}!QGP*cQAuWMvG=+2SH1mo zJp9j|J#+esw#F%a4_&R5CR=p9&uIFZK6&bOOe=p0Ltw&@(??G)T_Z4S`t13WW=@+q zYY{`p{Moa@7fqPKp3dx=_{*Vdjm90 z&TOzWleoBc&i{h-PyCL$uj(X`e)rlmyZBJTk5l@fAZYTOTDcYI!CFR85HK={ zFrcP8Si%COJ5&Hqh4{3AQXK+V0-11ah%|`L08pAkfEpkZivjQyh;9;c1cOo>0-OLc qv6zG{{h=F*9ApXz6F~+70}-#Gz?2f;&B_MS#0rF|K=ozd5C#BjRRhWZ literal 0 HcmV?d00001 diff --git a/deployment-tool/src/test/resources/input/sampleArchives/updated/repackedSampleWar.war b/deployment-tool/src/test/resources/input/sampleArchives/updated/repackedSampleWar.war new file mode 100644 index 0000000000000000000000000000000000000000..53ba982b66fdec8ed30d819722a8ffa82964d074 GIT binary patch literal 579 zcmWIWW@Zs#;Nak3;Ec2KVL$?MKz31Taeir0a%!=DNosM4XI^+>kzPSjenDzcNoH!X z_qp>|z5R4N{Lh{}bNY(5#wmRdU9FWSTXen8X!@EydFpjcD}M;sPMbMv5ktuQ*|WkIO_;%+&g`1_%b{!I?2ZkB)8`%wuA|lnZe5#?F)xwze4OV##ch&vz45!(rrE`Z5`LW02l>3ob86*Q zpucJvK|W_>5@A5Z4sxh~Vh0uAk1KSuknI75BLXY}GO?Kj4AlT{RyL4ACLo*$q~`z~ H$-n>rIMcnM literal 0 HcmV?d00001 diff --git a/deployment-tool/src/test/resources/input/updatedFiles/PropertyUpdaterTest.properties b/deployment-tool/src/test/resources/input/updatedFiles/PropertyUpdaterTest.properties new file mode 100644 index 0000000..bc1bd3f --- /dev/null +++ b/deployment-tool/src/test/resources/input/updatedFiles/PropertyUpdaterTest.properties @@ -0,0 +1,7 @@ +com.capgemini.property1=value1 +com.capgemini.property2 =value2 + +# Unmodified comment and commented property +# com.capgemini.property1=value1 + +com.capgemini.property3 =value3 \ No newline at end of file diff --git a/deployment-tool/src/test/resources/input/updatedFiles/XmlUpdaterTest.xml b/deployment-tool/src/test/resources/input/updatedFiles/XmlUpdaterTest.xml new file mode 100644 index 0000000..6dd1e96 --- /dev/null +++ b/deployment-tool/src/test/resources/input/updatedFiles/XmlUpdaterTest.xml @@ -0,0 +1,19 @@ + + + + + + OldValue1 + + OldValue2 + + + + + + + Should not be updated + + Changed + Unchanged + \ No newline at end of file diff --git a/deployment-tool/src/test/resources/input/xml/updateSampleEar.xml b/deployment-tool/src/test/resources/input/xml/updateSampleEar.xml new file mode 100644 index 0000000..f0e03c7 --- /dev/null +++ b/deployment-tool/src/test/resources/input/xml/updateSampleEar.xml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/deployment-tool/src/test/resources/log4j.properties b/deployment-tool/src/test/resources/log4j.properties new file mode 100644 index 0000000..eef248b --- /dev/null +++ b/deployment-tool/src/test/resources/log4j.properties @@ -0,0 +1,9 @@ +# Direct log messages to stdout +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.Target=System.out +log4j.appender.stdout.threshold=DEBUG +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %c{1}:%L - %m%n + +# Root logger option +log4j.rootLogger=DEBUG, stdout diff --git a/deployment-tool/src/test/resources/ref/PropertyUpdaterTest.ref b/deployment-tool/src/test/resources/ref/PropertyUpdaterTest.ref new file mode 100644 index 0000000..039027b --- /dev/null +++ b/deployment-tool/src/test/resources/ref/PropertyUpdaterTest.ref @@ -0,0 +1,7 @@ +com.capgemini.property1=NewValueOne +com.capgemini.property2=NewValueTwo + +# Unmodified comment and commented property +# com.capgemini.property1=value1 + +com.capgemini.property3=NewValueThree diff --git a/deployment-tool/src/test/resources/ref/XmlUpdaterTest.ref b/deployment-tool/src/test/resources/ref/XmlUpdaterTest.ref new file mode 100644 index 0000000..3018e0d --- /dev/null +++ b/deployment-tool/src/test/resources/ref/XmlUpdaterTest.ref @@ -0,0 +1,17 @@ + + + + + NewValueOne + NewValueTwo + + + + + + + Should not be updated + + Changed by condition + Unchanged + \ No newline at end of file diff --git a/distribution/assembly.xml b/distribution/assembly.xml new file mode 100644 index 0000000..38b111e --- /dev/null +++ b/distribution/assembly.xml @@ -0,0 +1,97 @@ + + report-assembly + + zip + + false + + + true + + com.capgemini.reports:core-ear + + + Installation/reports + false + false + snecma-reports.${module.extension} + + + + true + + com.capgemini.reports:deployment-tool + + + Installation/reports/bin + false + false + install-reports.${module.extension} + + + + true + + com.capgemini.reports:distribution + + + + + + target/ + src/test/ + **/*.iml + + + + Sources/${module.basedir.name} + + + + true + + com.capgemini.reports:kurt-utility + + + + + src/main/resources/xml/policies/ + + **/*.xml + + + + Installation/teamcenter/data/policies + + + + + + ${basedir}/install + Installation + + **/bin/** + **/modules/** + + unix + + + ${basedir}/install + Installation + + **/bin/** + **/modules/** + + + + + + install/teamcenter/report_install.pl + Installation/teamcenter + true + + + + diff --git a/distribution/install/reports/DBcreate/001_hibernate_sequence.sql b/distribution/install/reports/DBcreate/001_hibernate_sequence.sql new file mode 100644 index 0000000..255e723 --- /dev/null +++ b/distribution/install/reports/DBcreate/001_hibernate_sequence.sql @@ -0,0 +1,9 @@ +CALL PR_DROP_SEQ_IF_EXIST('HIBERNATE_SEQUENCE'); + +CREATE SEQUENCE HIBERNATE_SEQUENCE + START WITH 1 + MAXVALUE 9999999999999999999999999999 + MINVALUE 1 + NOCYCLE + CACHE 20 + NOORDER; diff --git a/distribution/install/reports/DBcreate/002_table.sql b/distribution/install/reports/DBcreate/002_table.sql new file mode 100644 index 0000000..9f17927 --- /dev/null +++ b/distribution/install/reports/DBcreate/002_table.sql @@ -0,0 +1,101 @@ +CALL PR_DROP_IF_EXIST('CRITERIA_VAL'); +CALL PR_DROP_IF_EXIST('CRITERIA'); +CALL PR_DROP_IF_EXIST('MEM_MONITOR'); +CALL PR_DROP_IF_EXIST('REP_USER'); +CALL PR_DROP_IF_EXIST('REPORT_OWNER'); +CALL PR_DROP_IF_EXIST('CRITERIA'); +CALL PR_DROP_IF_EXIST('REPORT'); +CALL PR_DROP_IF_EXIST('REPORT_OWNER'); +CALL PR_DROP_IF_EXIST('REPORT_TYPE'); +CALL PR_DROP_IF_EXIST('SCHEDULING_REPORT'); +CALL PR_DROP_IF_EXIST('SCHEDULING_CRITERIA_VAL'); + +CREATE TABLE CRITERIA +( + CRITERIA_ID NUMBER(19) NOT NULL PRIMARY KEY, + CRITERIA_NAME VARCHAR2(32 CHAR) NOT NULL, + CRITERIA_TYPE VARCHAR2(32 CHAR) NOT NULL, + IS_TEMPOREL VARCHAR2(5 CHAR) NOT NULL +); + +CREATE TABLE CRITERIA_VAL +( + CRITERIA_VAL_ID NUMBER(19) NOT NULL PRIMARY KEY, + REPORT_ID NUMBER(19), + CRITERIA_ID NUMBER(19) NOT NULL, + CRITERIA_VALUE VARCHAR2(3999 CHAR) +); + +CREATE TABLE MEM_MONITOR +( + MEM_MONITOR_ID NUMBER(19) NOT NULL PRIMARY KEY, + MONITORDATE TIMESTAMP(6), + TOTALMEMORY FLOAT(126), + MAXMEMORY FLOAT(126), + FREEMEMORY FLOAT(126), + USEDMEMORY FLOAT(126), + MAXPERCENT FLOAT(126) +); + +CREATE TABLE REP_USER +( + USER_ID NUMBER(19) NOT NULL PRIMARY KEY, + LOGIN VARCHAR2(16 CHAR) NOT NULL, + EMAIL VARCHAR2(255 CHAR), + SURNAME VARCHAR2(32 CHAR), + FIRSTNAME VARCHAR2(32 CHAR), + LASTCONNECTIONDATE DATE, + IS_ADMIN VARCHAR2(5 CHAR) +); + +CREATE TABLE REPORT +( + REPORT_ID NUMBER(19) NOT NULL PRIMARY KEY, + STARTGENERATIONDATE TIMESTAMP(6), + ENDGENERATIONDATE TIMESTAMP(6), + GENERATION_DURATION NUMBER(19), + REPORT_CODE VARCHAR2(3 CHAR) NOT NULL, + REPORTUID VARCHAR2(64 CHAR) NOT NULL, + FILE_NAME VARCHAR2(255 CHAR), + STATE VARCHAR2(16 CHAR) NOT NULL, + ERROR_TYPE VARCHAR2(16 CHAR), + ERROR_MESSAGE VARCHAR2(3999 CHAR), + SCHEDULING_REPORT_ID NUMBER(19,0) +); + +CREATE TABLE REPORT_OWNER +( + REPORT_OWNER_ID NUMBER(19) NOT NULL PRIMARY KEY, + REPORT_ID NUMBER(19) NOT NULL, + USER_ID NUMBER(19) NOT NULL, + REQUESTDATE TIMESTAMP(6), + MONTH_PERIOD VARCHAR2(7 CHAR) +); + +CREATE TABLE REPORT_TYPE +( + REPORT_TYPE_ID NUMBER(19) NOT NULL PRIMARY KEY, + CODE VARCHAR2(3 CHAR) NOT NULL, + TITLE VARCHAR2(255 CHAR) NOT NULL, + REVISION_RULE VARCHAR2(255 CHAR), + PRIORITY NUMBER(19) NOT NULL, + REPORT_AUTHORIZED VARCHAR2(5 CHAR), + IS_CANDIDATE_FOR_SCHEDULING VARCHAR2(5 CHAR) +); + +CREATE TABLE SCHEDULING_CRITERIA_VAL +( + SCHEDULING_CRITERIA_VAL_ID NUMBER(19) NOT NULL PRIMARY KEY, + CRITERIA_ID NUMBER(19) NOT NULL, + SCHEDULING_REPORT_ID NUMBER(19) NOT NULL, + CRITERIA_VALUE VARCHAR2(32 CHAR) +); + +CREATE TABLE SCHEDULING_REPORT +( + SCHEDULING_REPORT_ID NUMBER(19) NOT NULL PRIMARY KEY, + SCHEDULING_NAME VARCHAR2(200 CHAR) NOT NULL, + USER_ID NUMBER(19) NOT NULL, + LAST_UPDATE TIMESTAMP(6), + REPORT_CODE VARCHAR2(3 CHAR) NOT NULL +); diff --git a/distribution/install/reports/DBcreate/003_report_type_data.sql b/distribution/install/reports/DBcreate/003_report_type_data.sql new file mode 100644 index 0000000..6b2d4ff --- /dev/null +++ b/distribution/install/reports/DBcreate/003_report_type_data.sql @@ -0,0 +1,81 @@ +Insert into REPORT_TYPE +(REPORT_TYPE_ID, CODE, TITLE, REVISION_RULE, PRIORITY, REPORT_AUTHORIZED, IS_CANDIDATE_FOR_SCHEDULING) +Values (HIBERNATE_SEQUENCE.NEXTVAL, 'R01', 'BOM assemblage PU', ' DMA Configuration Interface R01', 2, 'TRUE', 'TRUE'); +Insert into REPORT_TYPE +(REPORT_TYPE_ID, CODE, TITLE, REVISION_RULE, PRIORITY, REPORT_AUTHORIZED, IS_CANDIDATE_FOR_SCHEDULING) +Values (HIBERNATE_SEQUENCE.NEXTVAL, 'R03', 'BOM fabrication date', ' DMA Configuration Interface', 1, 'TRUE', 'FALSE'); +Insert into REPORT_TYPE +(REPORT_TYPE_ID, CODE, TITLE, REVISION_RULE, PRIORITY, REPORT_AUTHORIZED, IS_CANDIDATE_FOR_SCHEDULING) +Values (HIBERNATE_SEQUENCE.NEXTVAL, 'R05', 'BOM Multi r�cepteurs PU', ' DMA Configuration Interface', 1, 'FALSE', + 'FALSE'); +Insert into REPORT_TYPE +(REPORT_TYPE_ID, CODE, TITLE, REVISION_RULE, PRIORITY, REPORT_AUTHORIZED, IS_CANDIDATE_FOR_SCHEDULING) +Values (HIBERNATE_SEQUENCE.NEXTVAL, 'R06', 'Statut Def et Indus PU', ' DMA Configuration Interface', 1, 'FALSE', + 'FALSE'); +Insert into REPORT_TYPE +(REPORT_TYPE_ID, CODE, TITLE, REVISION_RULE, PRIORITY, REPORT_AUTHORIZED, IS_CANDIDATE_FOR_SCHEDULING) +Values (HIBERNATE_SEQUENCE.NEXTVAL, 'R07', 'Comparaison BOM PU', ' DMA Configuration Rapport PU', 1, 'TRUE', 'TRUE'); +Insert into REPORT_TYPE +(REPORT_TYPE_ID, CODE, TITLE, REVISION_RULE, PRIORITY, REPORT_AUTHORIZED, IS_CANDIDATE_FOR_SCHEDULING) +Values (HIBERNATE_SEQUENCE.NEXTVAL, 'R10', 'Documents associes g�n�rique', ' DMA Configuration Validated', 1, 'TRUE', + 'TRUE'); +Insert into REPORT_TYPE +(REPORT_TYPE_ID, CODE, TITLE, REVISION_RULE, PRIORITY, REPORT_AUTHORIZED, IS_CANDIDATE_FOR_SCHEDULING) +Values (HIBERNATE_SEQUENCE.NEXTVAL, 'R11', 'Mise en maquette et coh�rence', ' DMA Configuration Mockup Best So Far', 1, + 'TRUE', + 'TRUE'); +Insert into REPORT_TYPE +(REPORT_TYPE_ID, CODE, TITLE, REVISION_RULE, PRIORITY, REPORT_AUTHORIZED, IS_CANDIDATE_FOR_SCHEDULING) +Values (HIBERNATE_SEQUENCE.NEXTVAL, 'R13', 'Etat avancement processus', ' DMA Configuration Interface', 2, 'TRUE', + 'TRUE'); +Insert into REPORT_TYPE +(REPORT_TYPE_ID, CODE, TITLE, REVISION_RULE, PRIORITY, REPORT_AUTHORIZED, IS_CANDIDATE_FOR_SCHEDULING) +Values (HIBERNATE_SEQUENCE.NEXTVAL, 'R15', 'Fiche article', ' DMA Configuration Interface', 1, 'TRUE', 'FALSE'); +Insert into REPORT_TYPE +(REPORT_TYPE_ID, CODE, TITLE, REVISION_RULE, PRIORITY, REPORT_AUTHORIZED, IS_CANDIDATE_FOR_SCHEDULING) +Values (HIBERNATE_SEQUENCE.NEXTVAL, 'W15', 'Fiche article', ' DMA Configuration Interface', 1, 'FALSE', 'FALSE'); +Insert into REPORT_TYPE +(REPORT_TYPE_ID, CODE, TITLE, REVISION_RULE, PRIORITY, REPORT_AUTHORIZED, IS_CANDIDATE_FOR_SCHEDULING) +Values (HIBERNATE_SEQUENCE.NEXTVAL, 'R16', 'Fiche g�n�rique', ' DMA Configuration Validated', 1, 'TRUE', 'TRUE'); +Insert into REPORT_TYPE +(REPORT_TYPE_ID, CODE, TITLE, REVISION_RULE, PRIORITY, REPORT_AUTHORIZED, IS_CANDIDATE_FOR_SCHEDULING) +Values (HIBERNATE_SEQUENCE.NEXTVAL, 'R17', 'Liste document associ�s article', ' DMA Configuration Interface', 1, 'TRUE', + 'FALSE'); +Insert into REPORT_TYPE +(REPORT_TYPE_ID, CODE, TITLE, REVISION_RULE, PRIORITY, REPORT_AUTHORIZED, IS_CANDIDATE_FOR_SCHEDULING) +Values (HIBERNATE_SEQUENCE.NEXTVAL, 'R19', 'Cas utilisation document', ' DMA Configuration Interface', 1, 'TRUE', + 'FALSE'); +Insert into REPORT_TYPE +(REPORT_TYPE_ID, CODE, TITLE, REVISION_RULE, PRIORITY, REPORT_AUTHORIZED, IS_CANDIDATE_FOR_SCHEDULING) +Values (HIBERNATE_SEQUENCE.NEXTVAL, 'R20', 'Gel de UNIT', ' DMA Configuration Interface', 2, 'TRUE', 'TRUE'); +Insert into REPORT_TYPE +(REPORT_TYPE_ID, CODE, TITLE, REVISION_RULE, PRIORITY, REPORT_AUTHORIZED, IS_CANDIDATE_FOR_SCHEDULING) +Values (HIBERNATE_SEQUENCE.NEXTVAL, 'R21', 'Compare Net', ' DMA Configuration Interface', 3, 'TRUE', 'TRUE'); +Insert into REPORT_TYPE +(REPORT_TYPE_ID, CODE, TITLE, REVISION_RULE, PRIORITY, REPORT_AUTHORIZED, IS_CANDIDATE_FOR_SCHEDULING) +Values (HIBERNATE_SEQUENCE.NEXTVAL, 'R22', 'BOM fabrication date PDF eDOC', ' DMA Configuration Interface', 1, 'TRUE', + 'FALSE'); +Insert into REPORT_TYPE +(REPORT_TYPE_ID, CODE, TITLE, REVISION_RULE, PRIORITY, REPORT_AUTHORIZED, IS_CANDIDATE_FOR_SCHEDULING) +Values (HIBERNATE_SEQUENCE.NEXTVAL, 'W22', 'BOM fabrication date PDF eDOC', ' DMA Configuration Interface', 1, 'FALSE', + 'FALSE'); +Insert into REPORT_TYPE +(REPORT_TYPE_ID, CODE, TITLE, REVISION_RULE, PRIORITY, REPORT_AUTHORIZED, IS_CANDIDATE_FOR_SCHEDULING) +Values (HIBERNATE_SEQUENCE.NEXTVAL, 'R23', 'BOM assemblage PU(s)', ' DMA Configuration Interface PU R23', 2, 'FALSE', 'TRUE'); +Insert into REPORT_TYPE +(REPORT_TYPE_ID, CODE, TITLE, REVISION_RULE, PRIORITY, REPORT_AUTHORIZED, IS_CANDIDATE_FOR_SCHEDULING) +Values (HIBERNATE_SEQUENCE.NEXTVAL, 'R24', 'Fiche(s) g�n�rique(s)', ' DMA Configuration Validated', 1, 'FALSE', 'TRUE'); +Insert into REPORT_TYPE +(REPORT_TYPE_ID, CODE, TITLE, REVISION_RULE, PRIORITY, REPORT_AUTHORIZED, IS_CANDIDATE_FOR_SCHEDULING) +Values (HIBERNATE_SEQUENCE.NEXTVAL, 'R25', 'Liste des documents des g�n�riques', ' DMA Configuration Descriptif R25', 1, + 'TRUE', 'TRUE'); +Insert into REPORT_TYPE +(REPORT_TYPE_ID, CODE, TITLE, REVISION_RULE, PRIORITY, REPORT_AUTHORIZED, IS_CANDIDATE_FOR_SCHEDULING) +Values (HIBERNATE_SEQUENCE.NEXTVAL, 'R26', 'Cas d''emploi d''un article', ' DMA Configuration Interface', 1, 'TRUE', + 'FALSE'); +Insert into REPORT_TYPE +(REPORT_TYPE_ID, CODE, TITLE, REVISION_RULE, PRIORITY, REPORT_AUTHORIZED, IS_CANDIDATE_FOR_SCHEDULING) +Values (HIBERNATE_SEQUENCE.NEXTVAL, 'R27', 'Extraction des articles de type Pi�ces', null, 1, 'TRUE', 'TRUE'); +Insert into REPORT_TYPE +(REPORT_TYPE_ID, CODE, TITLE, REVISION_RULE, PRIORITY, REPORT_AUTHORIZED, IS_CANDIDATE_FOR_SCHEDULING) +Values (HIBERNATE_SEQUENCE.NEXTVAL, 'R28', 'Extraction des rep�res fonctionnels ', null, 1, 'TRUE', 'TRUE'); \ No newline at end of file diff --git a/distribution/install/reports/DBcreate/004_criteria_data.sql b/distribution/install/reports/DBcreate/004_criteria_data.sql new file mode 100644 index 0000000..d4d3868 --- /dev/null +++ b/distribution/install/reports/DBcreate/004_criteria_data.sql @@ -0,0 +1,111 @@ +insert into CRITERIA + (CRITERIA_ID, CRITERIA_NAME, CRITERIA_TYPE, IS_TEMPOREL) +values (HIBERNATE_SEQUENCE.NEXTVAL, 'Date d''effectivit�', 'date', 'FALSE'); +insert into CRITERIA + (CRITERIA_ID, CRITERIA_NAME, CRITERIA_TYPE, IS_TEMPOREL) +values (HIBERNATE_SEQUENCE.NEXTVAL, 'G�n�rique', 'string', 'FALSE'); +insert into CRITERIA + (CRITERIA_ID, CRITERIA_NAME, CRITERIA_TYPE, IS_TEMPOREL) +values (HIBERNATE_SEQUENCE.NEXTVAL, 'G�n�rique montage', 'string', 'FALSE'); +insert into CRITERIA + (CRITERIA_ID, CRITERIA_NAME, CRITERIA_TYPE, IS_TEMPOREL) +values (HIBERNATE_SEQUENCE.NEXTVAL, 'Niveau', 'string', 'FALSE'); +insert into CRITERIA + (CRITERIA_ID, CRITERIA_NAME, CRITERIA_TYPE, IS_TEMPOREL) +values (HIBERNATE_SEQUENCE.NEXTVAL, 'Num�ro d''article', 'string', 'FALSE'); +insert into CRITERIA + (CRITERIA_ID, CRITERIA_NAME, CRITERIA_TYPE, IS_TEMPOREL) +values (HIBERNATE_SEQUENCE.NEXTVAL, 'R�vision', 'string', 'FALSE'); +insert into CRITERIA + (CRITERIA_ID, CRITERIA_NAME, CRITERIA_TYPE, IS_TEMPOREL) +values (HIBERNATE_SEQUENCE.NEXTVAL, 'Produit', 'string', 'FALSE'); +insert into CRITERIA + (CRITERIA_ID, CRITERIA_NAME, CRITERIA_TYPE, IS_TEMPOREL) +values (HIBERNATE_SEQUENCE.NEXTVAL, 'Unit', 'integer', 'FALSE'); +insert into CRITERIA + (CRITERIA_ID, CRITERIA_NAME, CRITERIA_TYPE, IS_TEMPOREL) +values (HIBERNATE_SEQUENCE.NEXTVAL, 'Unit pr�c�dent', 'integer', 'FALSE'); +insert into CRITERIA + (CRITERIA_ID, CRITERIA_NAME, CRITERIA_TYPE, IS_TEMPOREL) +values (HIBERNATE_SEQUENCE.NEXTVAL, 'Unit suivant', 'integer', 'FALSE'); +insert into CRITERIA + (CRITERIA_ID, CRITERIA_NAME, CRITERIA_TYPE, IS_TEMPOREL) +values (HIBERNATE_SEQUENCE.NEXTVAL, 'Produit pr�c�dent', 'string', 'FALSE'); +insert into CRITERIA + (CRITERIA_ID, CRITERIA_NAME, CRITERIA_TYPE, IS_TEMPOREL) +values (HIBERNATE_SEQUENCE.NEXTVAL, 'Produit suivant', 'string', 'FALSE'); +insert into CRITERIA + (CRITERIA_ID, CRITERIA_NAME, CRITERIA_TYPE, IS_TEMPOREL) +values (HIBERNATE_SEQUENCE.NEXTVAL, 'Matricule moteur', 'string', 'FALSE'); +insert into CRITERIA + (CRITERIA_ID, CRITERIA_NAME, CRITERIA_TYPE, IS_TEMPOREL) +values (HIBERNATE_SEQUENCE.NEXTVAL, 'LMR', 'string', 'FALSE'); +insert into CRITERIA + (CRITERIA_ID, CRITERIA_NAME, CRITERIA_TYPE, IS_TEMPOREL) +values (HIBERNATE_SEQUENCE.NEXTVAL, 'Classe', 'string', 'FALSE'); +insert into CRITERIA + (CRITERIA_ID, CRITERIA_NAME, CRITERIA_TYPE, IS_TEMPOREL) +values (HIBERNATE_SEQUENCE.NEXTVAL, 'Majeur mineur', 'string', 'FALSE'); +insert into CRITERIA + (CRITERIA_ID, CRITERIA_NAME, CRITERIA_TYPE, IS_TEMPOREL) +values (HIBERNATE_SEQUENCE.NEXTVAL, 'Conjoint unique', 'string', 'FALSE'); +insert into CRITERIA + (CRITERIA_ID, CRITERIA_NAME, CRITERIA_TYPE, IS_TEMPOREL) +values (HIBERNATE_SEQUENCE.NEXTVAL, 'Type d''impression', 'string', 'FALSE'); +insert into CRITERIA + (CRITERIA_ID, CRITERIA_NAME, CRITERIA_TYPE, IS_TEMPOREL) +values (HIBERNATE_SEQUENCE.NEXTVAL, 'Langue', 'string', 'FALSE'); +insert into CRITERIA + (CRITERIA_ID, CRITERIA_NAME, CRITERIA_TYPE, IS_TEMPOREL) +values (HIBERNATE_SEQUENCE.NEXTVAL, 'Date de d�but', 'date', 'FALSE'); +insert into CRITERIA + (CRITERIA_ID, CRITERIA_NAME, CRITERIA_TYPE, IS_TEMPOREL) +values (HIBERNATE_SEQUENCE.NEXTVAL, 'Date de fin', 'string', 'FALSE'); +insert into CRITERIA + (CRITERIA_ID, CRITERIA_NAME, CRITERIA_TYPE, IS_TEMPOREL) +values (HIBERNATE_SEQUENCE.NEXTVAL, 'Type d''objet', 'string', 'FALSE'); +insert into CRITERIA + (CRITERIA_ID, CRITERIA_NAME, CRITERIA_TYPE, IS_TEMPOREL) +values (HIBERNATE_SEQUENCE.NEXTVAL, 'Unit configuration 1', 'string', 'FALSE'); +insert into CRITERIA + (CRITERIA_ID, CRITERIA_NAME, CRITERIA_TYPE, IS_TEMPOREL) +values (HIBERNATE_SEQUENCE.NEXTVAL, 'Unit configuration 2', 'string', 'FALSE'); +insert into CRITERIA + (CRITERIA_ID, CRITERIA_NAME, CRITERIA_TYPE, IS_TEMPOREL) +values (HIBERNATE_SEQUENCE.NEXTVAL, 'Num�ro document', 'string', 'FALSE'); +insert into CRITERIA + (CRITERIA_ID, CRITERIA_NAME, CRITERIA_TYPE, IS_TEMPOREL) +values (HIBERNATE_SEQUENCE.NEXTVAL, 'Document R�vision', 'string', 'FALSE'); +insert into CRITERIA + (CRITERIA_ID, CRITERIA_NAME, CRITERIA_TYPE, IS_TEMPOREL) +values (HIBERNATE_SEQUENCE.NEXTVAL, 'period', 'string', 'TRUE'); +insert into CRITERIA + (CRITERIA_ID, CRITERIA_NAME, CRITERIA_TYPE, IS_TEMPOREL) +values (HIBERNATE_SEQUENCE.NEXTVAL, 'weekly', 'string', 'TRUE'); +insert into CRITERIA + (CRITERIA_ID, CRITERIA_NAME, CRITERIA_TYPE, IS_TEMPOREL) +values (HIBERNATE_SEQUENCE.NEXTVAL, 'weekend', 'string', 'TRUE'); +insert into CRITERIA + (CRITERIA_ID, CRITERIA_NAME, CRITERIA_TYPE, IS_TEMPOREL) +values (HIBERNATE_SEQUENCE.NEXTVAL, 'date', 'string', 'TRUE'); +insert into CRITERIA + (CRITERIA_ID, CRITERIA_NAME, CRITERIA_TYPE, IS_TEMPOREL) +values (HIBERNATE_SEQUENCE.NEXTVAL, 'day_in_month_value', 'string', 'TRUE'); +insert into CRITERIA + (CRITERIA_ID, CRITERIA_NAME, CRITERIA_TYPE, IS_TEMPOREL) +values (HIBERNATE_SEQUENCE.NEXTVAL, 'R�gle de r�vision', 'string', 'FALSE'); +insert into CRITERIA + (CRITERIA_ID, CRITERIA_NAME, CRITERIA_TYPE, IS_TEMPOREL) +values (HIBERNATE_SEQUENCE.NEXTVAL, 'SuperModel', 'boolean', 'FALSE'); +insert into CRITERIA + (CRITERIA_ID, CRITERIA_NAME, CRITERIA_TYPE, IS_TEMPOREL) +values +(HIBERNATE_SEQUENCE.NEXTVAL, 'Avec le(s) unit(s) gelé(s)', 'boolean', 'FALSE'); +insert into CRITERIA + (CRITERIA_ID, CRITERIA_NAME, CRITERIA_TYPE, IS_TEMPOREL) +values +(HIBERNATE_SEQUENCE.NEXTVAL, 'A partir de Unit', 'integer', 'FALSE'); +insert into CRITERIA + (CRITERIA_ID, CRITERIA_NAME, CRITERIA_TYPE, IS_TEMPOREL) +values +(HIBERNATE_SEQUENCE.NEXTVAL, 'Units gelés il y a moins de', 'string', 'FALSE'); \ No newline at end of file diff --git a/distribution/install/reports/DBcreate/006_quartz_tables.sql b/distribution/install/reports/DBcreate/006_quartz_tables.sql new file mode 100644 index 0000000..26c39dc --- /dev/null +++ b/distribution/install/reports/DBcreate/006_quartz_tables.sql @@ -0,0 +1,192 @@ +-- +-- A hint submitted by a user: Oracle DB MUST be created as "shared" and the +-- job_queue_processes parameter must be greater than 2 +-- However, these settings are pretty much standard after any +-- Oracle install, so most users need not worry about this. +-- +-- Many other users (including the primary author of Quartz) have had success +-- runing in dedicated mode, so only consider the above as a hint ;-) +-- + +delete from qrtz_fired_triggers; +delete from qrtz_simple_triggers; +delete from qrtz_simprop_triggers; +delete from qrtz_cron_triggers; +delete from qrtz_blob_triggers; +delete from qrtz_triggers; +delete from qrtz_job_details; +delete from qrtz_calendars; +delete from qrtz_paused_trigger_grps; +delete from qrtz_locks; +delete from qrtz_scheduler_state; + +drop table qrtz_calendars; +drop table qrtz_fired_triggers; +drop table qrtz_blob_triggers; +drop table qrtz_cron_triggers; +drop table qrtz_simple_triggers; +drop table qrtz_simprop_triggers; +drop table qrtz_triggers; +drop table qrtz_job_details; +drop table qrtz_paused_trigger_grps; +drop table qrtz_locks; +drop table qrtz_scheduler_state; + + +CREATE TABLE qrtz_job_details + ( + SCHED_NAME VARCHAR2(120) NOT NULL, + JOB_NAME VARCHAR2(200) NOT NULL, + JOB_GROUP VARCHAR2(200) NOT NULL, + DESCRIPTION VARCHAR2(250) NULL, + JOB_CLASS_NAME VARCHAR2(250) NOT NULL, + IS_DURABLE VARCHAR2(1) NOT NULL, + IS_NONCONCURRENT VARCHAR2(1) NOT NULL, + IS_UPDATE_DATA VARCHAR2(1) NOT NULL, + REQUESTS_RECOVERY VARCHAR2(1) NOT NULL, + JOB_DATA BLOB NULL, + CONSTRAINT QRTZ_JOB_DETAILS_PK PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP) +); +CREATE TABLE qrtz_triggers + ( + SCHED_NAME VARCHAR2(120) NOT NULL, + TRIGGER_NAME VARCHAR2(200) NOT NULL, + TRIGGER_GROUP VARCHAR2(200) NOT NULL, + JOB_NAME VARCHAR2(200) NOT NULL, + JOB_GROUP VARCHAR2(200) NOT NULL, + DESCRIPTION VARCHAR2(250) NULL, + NEXT_FIRE_TIME NUMBER(13) NULL, + PREV_FIRE_TIME NUMBER(13) NULL, + PRIORITY NUMBER(13) NULL, + TRIGGER_STATE VARCHAR2(16) NOT NULL, + TRIGGER_TYPE VARCHAR2(8) NOT NULL, + START_TIME NUMBER(13) NOT NULL, + END_TIME NUMBER(13) NULL, + CALENDAR_NAME VARCHAR2(200) NULL, + MISFIRE_INSTR NUMBER(2) NULL, + JOB_DATA BLOB NULL, + CONSTRAINT QRTZ_TRIGGERS_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP), + CONSTRAINT QRTZ_TRIGGER_TO_JOBS_FK FOREIGN KEY (SCHED_NAME,JOB_NAME,JOB_GROUP) + REFERENCES QRTZ_JOB_DETAILS(SCHED_NAME,JOB_NAME,JOB_GROUP) +); +CREATE TABLE qrtz_simple_triggers + ( + SCHED_NAME VARCHAR2(120) NOT NULL, + TRIGGER_NAME VARCHAR2(200) NOT NULL, + TRIGGER_GROUP VARCHAR2(200) NOT NULL, + REPEAT_COUNT NUMBER(7) NOT NULL, + REPEAT_INTERVAL NUMBER(12) NOT NULL, + TIMES_TRIGGERED NUMBER(10) NOT NULL, + CONSTRAINT QRTZ_SIMPLE_TRIG_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP), + CONSTRAINT QRTZ_SIMPLE_TRIG_TO_TRIG_FK FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) + REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) +); +CREATE TABLE qrtz_cron_triggers + ( + SCHED_NAME VARCHAR2(120) NOT NULL, + TRIGGER_NAME VARCHAR2(200) NOT NULL, + TRIGGER_GROUP VARCHAR2(200) NOT NULL, + CRON_EXPRESSION VARCHAR2(120) NOT NULL, + TIME_ZONE_ID VARCHAR2(80), + CONSTRAINT QRTZ_CRON_TRIG_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP), + CONSTRAINT QRTZ_CRON_TRIG_TO_TRIG_FK FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) + REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) +); +CREATE TABLE qrtz_simprop_triggers + ( + SCHED_NAME VARCHAR2(120) NOT NULL, + TRIGGER_NAME VARCHAR2(200) NOT NULL, + TRIGGER_GROUP VARCHAR2(200) NOT NULL, + STR_PROP_1 VARCHAR2(512) NULL, + STR_PROP_2 VARCHAR2(512) NULL, + STR_PROP_3 VARCHAR2(512) NULL, + INT_PROP_1 NUMBER(10) NULL, + INT_PROP_2 NUMBER(10) NULL, + LONG_PROP_1 NUMBER(13) NULL, + LONG_PROP_2 NUMBER(13) NULL, + DEC_PROP_1 NUMERIC(13,4) NULL, + DEC_PROP_2 NUMERIC(13,4) NULL, + BOOL_PROP_1 VARCHAR2(1) NULL, + BOOL_PROP_2 VARCHAR2(1) NULL, + CONSTRAINT QRTZ_SIMPROP_TRIG_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP), + CONSTRAINT QRTZ_SIMPROP_TRIG_TO_TRIG_FK FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) + REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) +); +CREATE TABLE qrtz_blob_triggers + ( + SCHED_NAME VARCHAR2(120) NOT NULL, + TRIGGER_NAME VARCHAR2(200) NOT NULL, + TRIGGER_GROUP VARCHAR2(200) NOT NULL, + BLOB_DATA BLOB NULL, + CONSTRAINT QRTZ_BLOB_TRIG_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP), + CONSTRAINT QRTZ_BLOB_TRIG_TO_TRIG_FK FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) + REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) +); +CREATE TABLE qrtz_calendars + ( + SCHED_NAME VARCHAR2(120) NOT NULL, + CALENDAR_NAME VARCHAR2(200) NOT NULL, + CALENDAR BLOB NOT NULL, + CONSTRAINT QRTZ_CALENDARS_PK PRIMARY KEY (SCHED_NAME,CALENDAR_NAME) +); +CREATE TABLE qrtz_paused_trigger_grps + ( + SCHED_NAME VARCHAR2(120) NOT NULL, + TRIGGER_GROUP VARCHAR2(200) NOT NULL, + CONSTRAINT QRTZ_PAUSED_TRIG_GRPS_PK PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP) +); +CREATE TABLE qrtz_fired_triggers + ( + SCHED_NAME VARCHAR2(120) NOT NULL, + ENTRY_ID VARCHAR2(95) NOT NULL, + TRIGGER_NAME VARCHAR2(200) NOT NULL, + TRIGGER_GROUP VARCHAR2(200) NOT NULL, + INSTANCE_NAME VARCHAR2(200) NOT NULL, + FIRED_TIME NUMBER(13) NOT NULL, + PRIORITY NUMBER(13) NOT NULL, + STATE VARCHAR2(16) NOT NULL, + JOB_NAME VARCHAR2(200) NULL, + JOB_GROUP VARCHAR2(200) NULL, + IS_NONCONCURRENT VARCHAR2(1) NULL, + REQUESTS_RECOVERY VARCHAR2(1) NULL, + CONSTRAINT QRTZ_FIRED_TRIGGER_PK PRIMARY KEY (SCHED_NAME,ENTRY_ID) +); +CREATE TABLE qrtz_scheduler_state + ( + SCHED_NAME VARCHAR2(120) NOT NULL, + INSTANCE_NAME VARCHAR2(200) NOT NULL, + LAST_CHECKIN_TIME NUMBER(13) NOT NULL, + CHECKIN_INTERVAL NUMBER(13) NOT NULL, + CONSTRAINT QRTZ_SCHEDULER_STATE_PK PRIMARY KEY (SCHED_NAME,INSTANCE_NAME) +); +CREATE TABLE qrtz_locks + ( + SCHED_NAME VARCHAR2(120) NOT NULL, + LOCK_NAME VARCHAR2(40) NOT NULL, + CONSTRAINT QRTZ_LOCKS_PK PRIMARY KEY (SCHED_NAME,LOCK_NAME) +); + +create index idx_qrtz_j_req_recovery on qrtz_job_details(SCHED_NAME,REQUESTS_RECOVERY); +create index idx_qrtz_j_grp on qrtz_job_details(SCHED_NAME,JOB_GROUP); + +create index idx_qrtz_t_j on qrtz_triggers(SCHED_NAME,JOB_NAME,JOB_GROUP); +create index idx_qrtz_t_jg on qrtz_triggers(SCHED_NAME,JOB_GROUP); +create index idx_qrtz_t_c on qrtz_triggers(SCHED_NAME,CALENDAR_NAME); +create index idx_qrtz_t_g on qrtz_triggers(SCHED_NAME,TRIGGER_GROUP); +create index idx_qrtz_t_state on qrtz_triggers(SCHED_NAME,TRIGGER_STATE); +create index idx_qrtz_t_n_state on qrtz_triggers(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,TRIGGER_STATE); +create index idx_qrtz_t_n_g_state on qrtz_triggers(SCHED_NAME,TRIGGER_GROUP,TRIGGER_STATE); +create index idx_qrtz_t_next_fire_time on qrtz_triggers(SCHED_NAME,NEXT_FIRE_TIME); +create index idx_qrtz_t_nft_st on qrtz_triggers(SCHED_NAME,TRIGGER_STATE,NEXT_FIRE_TIME); +create index idx_qrtz_t_nft_misfire on qrtz_triggers(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME); +create index idx_qrtz_t_nft_st_misfire on qrtz_triggers(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_STATE); +create index idx_qrtz_t_nft_st_misfire_grp on qrtz_triggers(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_GROUP,TRIGGER_STATE); + +create index idx_qrtz_ft_trig_inst_name on qrtz_fired_triggers(SCHED_NAME,INSTANCE_NAME); +create index idx_qrtz_ft_inst_job_req_rcvry on qrtz_fired_triggers(SCHED_NAME,INSTANCE_NAME,REQUESTS_RECOVERY); +create index idx_qrtz_ft_j_g on qrtz_fired_triggers(SCHED_NAME,JOB_NAME,JOB_GROUP); +create index idx_qrtz_ft_jg on qrtz_fired_triggers(SCHED_NAME,JOB_GROUP); +create index idx_qrtz_ft_t_g on qrtz_fired_triggers(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP); +create index idx_qrtz_ft_tg on qrtz_fired_triggers(SCHED_NAME,TRIGGER_GROUP); + + diff --git a/distribution/install/reports/DBupdate/003_report_type_data_1.28.0.sql b/distribution/install/reports/DBupdate/003_report_type_data_1.28.0.sql new file mode 100644 index 0000000..a02ea48 --- /dev/null +++ b/distribution/install/reports/DBupdate/003_report_type_data_1.28.0.sql @@ -0,0 +1,5 @@ +Insert into REPORT_TYPE + (REPORT_TYPE_ID, CODE, TITLE, REVISION_RULE, PRIORITY, REPORT_AUTHORIZED, IS_CANDIDATE_FOR_SCHEDULING) +Values + (HIBERNATE_SEQUENCE.NEXTVAL, 'R26', 'Cas d''emploi d''un article', ' DMA Configuration Interface', 1, 'TRUE', + 'FALSE'); \ No newline at end of file diff --git a/distribution/install/reports/DBupdate/003_report_type_data_1.30.0.sql b/distribution/install/reports/DBupdate/003_report_type_data_1.30.0.sql new file mode 100644 index 0000000..b297a36 --- /dev/null +++ b/distribution/install/reports/DBupdate/003_report_type_data_1.30.0.sql @@ -0,0 +1,2 @@ +INSERT INTO REPORT_TYPE (REPORT_TYPE_ID, CODE, TITLE, REVISION_RULE, PRIORITY, REPORT_AUTHORIZED, IS_CANDIDATE_FOR_SCHEDULING) VALUES (HIBERNATE_SEQUENCE.NEXTVAL, 'R27', 'Extraction des articles de type pièces', null, 1, 'FALSE', 'TRUE'); +INSERT INTO REPORT_TYPE (REPORT_TYPE_ID, CODE, TITLE, REVISION_RULE, PRIORITY, REPORT_AUTHORIZED, IS_CANDIDATE_FOR_SCHEDULING) VALUES (HIBERNATE_SEQUENCE.NEXTVAL, 'R28', 'Extraction des repères fonctionnels ', null, 1, 'FALSE', 'TRUE'); \ No newline at end of file diff --git a/distribution/install/reports/DBupdate/003_report_type_data_1.32.0.sql b/distribution/install/reports/DBupdate/003_report_type_data_1.32.0.sql new file mode 100644 index 0000000..0b1e879 --- /dev/null +++ b/distribution/install/reports/DBupdate/003_report_type_data_1.32.0.sql @@ -0,0 +1,2 @@ +update REPORT_TYPE set REVISION_RULE = ' DMA Configuration Interface R01' where CODE = 'R01'; +update REPORT_TYPE set REVISION_RULE = ' DMA Configuration Interface PU R23' where CODE = 'R23'; \ No newline at end of file diff --git a/distribution/install/reports/DBupdate/003_report_type_data_1.32.7.sql b/distribution/install/reports/DBupdate/003_report_type_data_1.32.7.sql new file mode 100644 index 0000000..bf7e056 --- /dev/null +++ b/distribution/install/reports/DBupdate/003_report_type_data_1.32.7.sql @@ -0,0 +1 @@ +update REPORT_TYPE set REVISION_RULE = ' Generic / Generic Assemb R19' where CODE = 'R19'; \ No newline at end of file diff --git a/distribution/install/reports/DBupdate/004_criteria_data_1.28.0.sql b/distribution/install/reports/DBupdate/004_criteria_data_1.28.0.sql new file mode 100644 index 0000000..267ed1c --- /dev/null +++ b/distribution/install/reports/DBupdate/004_criteria_data_1.28.0.sql @@ -0,0 +1,4 @@ +Insert into CRITERIA + (CRITERIA_ID, CRITERIA_NAME, CRITERIA_TYPE, IS_TEMPOREL) +Values + (HIBERNATE_SEQUENCE.NEXTVAL, 'R�gle de r�vision', 'string', 'FALSE'); \ No newline at end of file diff --git a/distribution/install/reports/DBupdate/004_criteria_data_1.32.0.sql b/distribution/install/reports/DBupdate/004_criteria_data_1.32.0.sql new file mode 100644 index 0000000..9cbfb6b --- /dev/null +++ b/distribution/install/reports/DBupdate/004_criteria_data_1.32.0.sql @@ -0,0 +1,4 @@ +insert into CRITERIA +(CRITERIA_ID, CRITERIA_NAME, CRITERIA_TYPE, IS_TEMPOREL) +values +(HIBERNATE_SEQUENCE.NEXTVAL, 'SuperModel', 'boolean', 'FALSE'); \ No newline at end of file diff --git a/distribution/install/reports/DBupdate/004_criteria_data_1.32.6.sql b/distribution/install/reports/DBupdate/004_criteria_data_1.32.6.sql new file mode 100644 index 0000000..aa789ff --- /dev/null +++ b/distribution/install/reports/DBupdate/004_criteria_data_1.32.6.sql @@ -0,0 +1,14 @@ +insert into CRITERIA +(CRITERIA_ID, CRITERIA_NAME, CRITERIA_TYPE, IS_TEMPOREL) +values +(HIBERNATE_SEQUENCE.NEXTVAL, 'Avec le(s) unit(s) gelé(s)', 'boolean', 'FALSE'); + +insert into CRITERIA +(CRITERIA_ID, CRITERIA_NAME, CRITERIA_TYPE, IS_TEMPOREL) +values +(HIBERNATE_SEQUENCE.NEXTVAL, 'A partir de Unit', 'integer', 'FALSE'); + +insert into CRITERIA +(CRITERIA_ID, CRITERIA_NAME, CRITERIA_TYPE, IS_TEMPOREL) +values +(HIBERNATE_SEQUENCE.NEXTVAL, 'Units gelés il y a moins de', 'string', 'FALSE'); diff --git a/distribution/install/reports/create_database.bat b/distribution/install/reports/create_database.bat new file mode 100644 index 0000000..50b0f58 --- /dev/null +++ b/distribution/install/reports/create_database.bat @@ -0,0 +1,35 @@ +@echo on +echo ========================= +echo REPORTING DATABASE CREATE +echo ========================= + +IF "%DEPLOY_TOOL_HOME%"=="" ( + echo > DEPLOY_TOOL_HOME must be defined + exit/B +) + +IF "%JBOSS_HOME%"=="" ( + echo > JBOSS_HOME must be defined + exit/B +) + +echo copy sql creation files +copy %DEPLOY_TOOL_HOME%\DBcreate\. %DEPLOY_TOOL_HOME%\sql +echo - Run database create +java -jar %DEPLOY_TOOL_HOME%\bin\install-reports.jar +if %ERRORLEVEL% EQU 1 ( + echo - Error detected, check install.log file +) else ( + echo - Database create run successfully +) + +echo clearing sql folder contents +del %DEPLOY_TOOL_HOME%\sql\* /Q + +echo ========================== +echo END OF DATABASE CREATE +echo ========================== + +pause + +exit/B \ No newline at end of file diff --git a/distribution/install/reports/create_database.bat:Zone.Identifier b/distribution/install/reports/create_database.bat:Zone.Identifier new file mode 100644 index 0000000..a45e1ac --- /dev/null +++ b/distribution/install/reports/create_database.bat:Zone.Identifier @@ -0,0 +1,2 @@ +[ZoneTransfer] +ZoneId=3 diff --git a/distribution/install/reports/db.properties b/distribution/install/reports/db.properties new file mode 100644 index 0000000..0a932d3 --- /dev/null +++ b/distribution/install/reports/db.properties @@ -0,0 +1,4 @@ +# Database configuration +database.url=TO_BE_DEFINED +database.schema.login=TO_BE_DEFINED +database.schema.password=TO_BE_DEFINED \ No newline at end of file diff --git a/distribution/install/reports/log/readme.txt b/distribution/install/reports/log/readme.txt new file mode 100644 index 0000000..a0ad7d5 --- /dev/null +++ b/distribution/install/reports/log/readme.txt @@ -0,0 +1 @@ +Ce dossier contient l'ensemble des traces d'exécution de la procédure de packaging et de mise à jour de la base de données. \ No newline at end of file diff --git a/distribution/install/reports/modules/modules.zip b/distribution/install/reports/modules/modules.zip new file mode 100644 index 0000000000000000000000000000000000000000..eda6436e6b59f50a94b3bd1498161d64c4e5594a GIT binary patch literal 2600978 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�a{vv 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%0DZxNznH2E@i@Bt4MO=9@)_ito}MK4?M)hZwm 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 z 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

tiPlq4e=^teDWd107gK$ztqBU`-u*p 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 {ezv zsquH(ckf$E*cM!|$Vm8WyzqXzzRwCY`02!_S|dUEp92L$BZE=^3wn{{-Y|w$B+jC4 zuz}{+-5+fC(KM%@JLB4IBP|i+S6aVTy)WLtQGY;~3IkQ=BH4<}2i? zQ{FnNEbBfR%Y{XLh&rH_>^%g2_Igp(tjqM)VOlC@xjlA8Yf75k;-q*Tf8Y`Nq}uSw z4Og*Byb>JH#w1e&0USa!2o!=BwUVRcz4XGs=00E3qQ}YO=9`fnX?OjS8ozY@7)4ar zd8<*KNOO>NwxVE`^U%{5k(V>0j`y5Ad-UOaXJ^f~%)a`J45OV;vyV0wJ-i{!iD6V! zI*dC^wO1&$qvwt4-GFUmlZdjtva+{#xN`Prfmf5Sawg-%{prUTmJ~g5YLTK> zFb-fcwxy2-bB*huE=qKpaUMw&ZWQVmWseE{sSzuCB52BvV&E7WJbVx|yVk5uu?-4i zDt}4j;>%v%moMUmUH;_3rYXh4*l4YlMXupFzU*r1Wi<48Xb z>iXc0`DSlFdG{n`rF>amUKPxJmaBE?CHDzhMF324h29%3#61M7iB6xzx*d%}bERYZ zWT)^POe7BtG3Er5XfKQH+X|!{AQ2lQPUeU(tOv8a*^fsHt2r-9M*-%uLFq$v{{c zp2i9F#8f(|y|tn}7Ne}GKAU8Q_ZZcTK)gb4DhJSs0JnLJ;fg1oub_^nB;L$WGGP;m zS}(%KTSRMTnLoN?zYA}U4@bLhc`g1NknoYBJhS9?e7t#pT_%x$uJ7eeU4~aY1Pkau zJ&KJ}d>{wlEcbBNS@CTm(RM_k&WlGs&29D&18AruoJT>m!_jo>Fby= z<=(7?i}`B%BGe|({CNS! zqJ=L{1c>9#AJkNR6#Iwzn!Gu1{G|KKuXxsp{=rp(GG&Gqq>;!ax7-G9qGCL7za z6CcYI6T)!fnP!!(mN&ykw2xvDyOMRJfpH^7OY&mEK_~}`R@^ed_A6+dg3Zql(W0>@ zD6J3ntvxfKH_W;%WWp2r!5F*wz<_?p|5v`uA8(apPRJ1H}ohUw{vj2>9^MtjeJLBD0zEG z-dn@#E_8}PJRk>Y>jEzXw9e!Xrg0f;WU*0kIvLB*NZ7L!G%OC-ncyBz3MgZUKe5ho zQs_FAHsc}MrMkvJ1n9Uhu_7Bg*aK5JZ1R?mjC9s)*lIIT)uh6Iol3kvlvXI>zb)f5 ztYPnY!uD}M8wqX7IHV#~TN77p+zh;f0~UWE5whnOEF%}cgG{>on3P&H7JFnY=&MoM?FN4w$sGiCjrj3X**GcD4?dW{8laWmEgOb=iU|m!AigTG zACNbSylm5F#217L@&*$?+Ky14DbH2!$-?#ODJkhG-Jzmwdm!n}KjsnEI#m(vh8vw4 zs@O#Tgl#z;^vBp>{ia-WkSe$~Ju53?I5lLweuHiKnlphG%`)gDmD$BSDqWKES@RT{405Af{7)5*A3B(WJd`@XoBCFkPtC%tIfpS9n6cr6|%L_{T zCeKZyGq|dKwKDYx>P@UIvFbsM{i~i?A=X>&jBrnab!*Yr2uXzF=5X@pZ9`-?CA3}4 zvRkFqs-Z39jVH}ESl|xik}8b`&nj8sHS}8D#IhPLx3$j#T2#+_ zDckQRShLHe%8)VWZz?m4_;x@kS7kwM z&w!3TNsrDVL?IQG*tCfM*_4Gbb-RW3cvHe%^7}$X?fmOp?_;G<)p=&>oNRwMkLAf9 zUvfWY4byi)FqC6RqmBVLhd(e-YlfxxV-8S>;P1uO@?^$k##u_bMSE>qI<$#BygL>N zbrfu;T;y(8={5N3=36>^%s8{E&UL_Vsx$~fUwM&lcw{a7bU`IqD$;ih1sK0)n^%z&ZjWTMsVBT@WBrjMyj?d zWBzVJ46cTQGnk!b>V1m?w!Q@_+OWmKGvv4I^6JpHz2~rPwPpqjhcl$|oCOye;`Oi_ z#kRinlS7g-`xy|TRlDe!?YD_`zo7Z^wyWE=eXGVBIJUWUzal=*>agD$s*XF$Oh-;N z45os%Vpb!Xnke}L7{fg@8M=3P9+R8{^8O*zbFJf3xw{a}^z?ZdJD43i2=CvgQci;j zhcE*BNONwx#r#6xJKi8?OZG<%*Nvu*ebl^BEz<-%(fG}+!c`;&t58l%n1#aD zgl_70VcsyF1$LdzS&|>O_)>AZT>en*sq~&_&pCE6ZX!I;stPQwz(2SI?M3#ndrDJ5 zihjftJi|6`u$=rOfX$|0(w zBs!@H5jU37z-+TiBjb}}ISP%I;veMpi}(?GBF1oM!SP@DBl?msC;|O*-t}h&nf?cV zqK;19)()2cf}ygmE&30PZv|IF)#|5>EDcoREI0?WyA>=_d3u<_wCOBpL!k6CO1YiK zkQw^fEE+Ke@h50-#NI9Hti#V<2x5zwOvm0^y}s}FPe@^SPeKf*p#k}=Dw6n3O1qQ> zX|D?2`^P_K-FJ!o#EUJz__?Zi3@)y9n|l%FAxap#9bh8QzC+C& z?r8ATS+)6Wh^E2k%r5Jeg5bt|%6fwW*SmT%j@>gYO+$i#EN7O49lE99FFfvf@CR61 z0rdNOKUTBLOJji4n-RvhG4Gd`gQTCCO1Fo>VdQaTE5Rdr?pP10}!KpuR{op?2}cL!*s=a;&BA z^r`Rk*hR_Z6iT-I;MZ^SPki!xPRX^Ma|Yx5^pGbbLqvg?Sppe8L5@lQr@{?0~GWMT$FexVBa}Qj}6wxso7Rycvh*8PM)>WpyBSp{v{|Y%&0ThazQ%iqA=p zI_8iiuAVWHGxg~@<7v_R{q|?s(bW;*ZfeM)lcJiUx)9mTemHhV#d)CZ1sgO!kh1vq&9J(Qj~!KXDr=y z?!_1~LifPB8|gsCl7Ja+ijm>O!OIZ^`cbl&7r8}(7UcyI*jl0=-hDk6x0w?wz7@5C^{EBQd><&d%a6M#TnZNE^|8rHY?>pc( zY(L4UNQJ0Y7*R0tK8X!#VxcBb5c3PIm=!_oPz{C_N|Za6jTWee0Dl!LiJm+`cTNL}id~TlSfgBR*p5kL%7$C#g}`HN9NxOo*;(yFx!W8~qM6Ik`V${! z5flf2MA3o4!{DyL-Q6L$1q;E0y9Wslg9eu%gS)%4_`qPno#4UUU3V|LReRX2dZ+%? zed>OP=1h&XS+Ap%(W){3gDHmy|Bp^vK{B6AkLW!m#k|AM#eEf)Be0>0>})R9h|&tK z(Uw(LFi`CMM<@@Opaz7&)xWP{+`^m5Uf7lQtC{zBvuQ@%O{@S41Z|aWfe!@#X`uL&(Z7`Zm_simm zuFAU*T*7qurP%?1|vW?KlLH)?(Pltlg%)hxGZg z4~+4Bt&B$5Awp?L8S%g6x^Lpa25R#Ct@l^8$%bxXTUTbP#UP952yyE?tna zU&f9evde7b#7I8Y#iwJ&j%9l8J`*3p@5IY_4QGovtjPKFGxoIiADHZ8=j1dj%9Bkk zQc)YLU&D199IJ~TC-OabSc2e)D{hYB)fd&fVxfx^_6*yK2*iaK=71N8gl*oGEUJAh z;_zwJjzYnR!m5ghB@3|H02lsH>wu@DvbTb*rjqXcFKuG`*^Rs-It=WJ6`3e3+A6e5 zyX%fpTX|{ZSGYl}UO^%DsR*JUWDElcJ}x8M7=8C2DjuXnf^d_&2A*P7;kFuwkw|<5 z@?=S*oi(og(r}Zh`22jp$`nWxGa)+@t}u>CrQ9u}t`PcSX10KI10@LSYiD#v9qfi4fnh+!d_c{9PY?Ds!QSQm!C+0q2KjwopSN z`Eed|JN-|#o7KcgeC|d!(B`icwonye{$?C+Gkkh`R0lIZ(OnyMRv_Bi%-h#33a?GQt^g8sXGjb_y`&OA2f?Uwh3jr9g$G81NcdVpBUY(spn=fs+QsgWF9U} z7mqMJKNB~|apIs`&fX4G9$GN=b&K6FYKgub{JdVGv%)t(f4Vh6HhR><5f0q(N)xke zu`IAboSnjEsDT+P{#lNrDPTmQR0b(Anm32~mMOUPAmDq4R|j6a>5W|+^!$i1;YNLV z9A8#ExVm#6Gf?y1ew1>1&wC8*IlQse7^e?OJ)wTuJX|oiR)U{V{MRD}9+VJ~!7BwyH$SvriNp7(YhY?Vxex(`_n z{^<_-8d9kR+zWM|G*Ty==meMPCd9cE!|kF9izM|wYc+R%ZIj${?iB_*V6FCV0Iu6& zwXaf>+~|!d@a_=*c)PMIo+lV7@0Gv7|F?RAx4~ zqzhSBTc?q;)6<}%4lMnLcOWVXv4{e;u3jI6=nIGU1y2gj{>1EjFx+U)G9g@smh<{aK7$|8cb9KBUZ*Sd-_&m7aaI*SM1#SXKVpgGGMnSXz4F&mn>?FR4Gyyd{ z8az#D2kIzQd`&Hf@Dv3@O*htNby%tyi$;v5f>Gjs@!@uk-|3;n0Z~iF zDuXisSru%pdR}#G`RzmDD+Ih{LN;%ruAs@8>8CGj!M zg|^X}6RO$o4$P|8zG*G)yR)9|Q;~TIl=6PQ5g13jwLT`mMGW`N?VGt`s_VdFAkV0% zL#Klhjqubp>~FnwM{Iuiio7iPm1~W(7LC$e)lA?Ytc)u$W6!zchfH2e_3IXajhm4I zrlym)?b*0W_udAgR_W`rmruwDDW~dgwm#k&e)KzwPo>7$B_nG;en@aBldCY8y*3DXZBZ-2fu+Rju%4*hlbx|M!$ zpLzQ|J5I9mDhe%F!&3J|Y&PbLb#D9?+lWs|pVTWn1KwJjCJ`ev)!h6jX2dTitsGf4 zUPzapYgc74pV(@pd?!!Reh7H3IxKgrF6tOhv{Xvt-uu$qfosoZVP*El@&iR3God26 z-EEfI)x4%&q4q05M*TLy#rg-)zx{P)zS;i(**7$)VV!EbsjU3WZRD8AF&1+sd~Q>r zKTU6Y-mg+=01xixygm)oV5JOBijh9qc4_q6_zi4td{OXs3m){>uQ6BMC>^ymT=5_; zsdadc8C>shZR{a?P9BWQsUIwS?&l>r=H{8}x$Sdo8bWG!U4q;H&?N8QU9VP|m}ztG zJm^_fKV;8&x?Vd`ZS~;{BX4bFAIQ4|YjcE2nJ>*<|#z~t;`uCdNMwF*mOOx#vGF z4^>67>?o#gZeD&gNiRNmu&ez1UUHg?@gkaEp)9r>pt&+60rR$)y`z(0=W~3|b0=x! z`K}!H$RIZjDe*5oM|IW%w{%=CZssg{-WHtBysicw3n~?#79HBhJ;^;zwXi&k{7wF{{CJ#&1UfVN2F+7gxngt(Ahw&oDi>F**mmSU}7#`<1UjYW6rQM zspWTo?=Y2UE0d!(O~!NcdgXr8uIxGV7>S)l%HZzl_H1oCkiUfOTddu!ySJhIvf1b3 z-j(WOhdegFfDF-r+tswDM`(zu5n&8k-uOzgiy)t{DQfJ?<9@GpAjEgj?0OvOu#awuZ%XhtLO~beaIW_W4^H{mD_EXVVe6fTpv% zS&px#kB;=!q+EUrr$NMgw%On~?3YM9f)Aq1AO*S?!F$5Ug)zrN}iDcN&$bh=G9 zmq*y1<~5zAu?sA#*k|jt=w~n1iB`|kbjA#H4RJK><&wu+SLdck+kY1N_P(<)X=FP- zv+^!HBRugd{M>0_Yps8~(#C7Yc(=A{619ZSi7i)@qt%kOnybxqZz$l+wkg~wc6FCD zVy)P;@)yfjl4Vz7P-BZ<$6)Ih!RBue@pW@E8A`j;KM%^ecBk962hlmxv*BNQ~Mk}3%}gZfhfAuHrgJ4 zMe!~raUBhge?PXJ5*})e&E1{Lm*UH%Y-Y82MFw@w<$bZe&pn&!U0<$UZvx@wj-OR;jcUC=kC%8juCm8H z#ZOms`y6pbJaw!Z$#fX8slM`~r@J)z45ZK121K88H3Gl~6wo@XhI#1J^)@VnS@LZ@f3 zcKrp~q_TR+Rq59%QBs^+YMd=r>cr0`=6^9Z_9t^?cE)o5_361cnV@NIeR?!YLTMzg zSU-SWciU=E>wE<`W9*;l66Awvw3K+d%#-XRg3zwpPya5ZTw~k8yFU}<*klnaeav(2 zPAsKtXee=cLU*rb6B!!*!|mB?P@`5SzF%Tp$5P@p=f)RT zcuWrojXmyLhgoaC;*sKG&3NOC3hzkOJI(k++%v~WC2x7LtYa}n?*yUX_I>x+qT|>K z&3oaV82h2ORdBn%(V1tuhlre3Yj@$ktp*3b7F(_ISf7%8QaS&|)mmjX$6Jy9uA{cR z5M#jHZ6lbj=F4&yq`gIFi%m!1q?8>qAlL1qsjt=%cg-CPu|8!~i%=k1*YvXJan9Q< z`|ti;&voepDBHQIouNa$)OqywWw!W??uge!Z{n(4wL+cYZW6!WfGzhkTQsS#n(&V% ziRLdl=bs@R557lUTUOWqun%04CKoBC&~NXUcRIQ#I(#^&@U7K~7^_q?60`3r!uXbX z`i=adn6!E0?~V2C5u1479rlJQ=*r_u+0$z@aKot0Qf*$UCp5nD;l-_D#`xG{l42ui znaw$k*yG0>ogJb3)mD|-op`~mf6Rkcpr?P~MMG}&R9@P(PD>x5G3`-UxaoNK>f(n# zaH9c8KFbQH@115S1mU6XSzeC#cmYT50!~ikpGaFT+I?^Dwih7!sxq9Y->1%(;dSrH zdPlYa0j!87`xXF!4fwV|l*2loC($77OF(xI`sPspAR+@^mzP+vMAG&jgh8ZY06$+i z#dd(83!-o7C)-`5tUpn<=a>L~W%T*UIOQ=V(g%vgq1&p z3R!VxbpY{rxvfLSDLugc5WtHCFszTZDfpT57$5Bms&W^c%33symE_@~4S-St(WQVn z^*3ON5U{z9LYt0SYybu96=K{810K*BULA>oUfBU(CFF&ZAN!O567EQKwzxq&YXDJs zE_QOHI#6?F2WIcsZ$UHuZ^&|6H}UGHI)JKXfY%+m@4lohzuhSe4Z!jQ4+&w+X|h|3{Gks03JayF3jdk(8uc^ z0JnaZCxf!tT7ZSKY*M_d){ASQ%SlxOpc@wZgxk8WEJEgs!{-iPS`kFEM`N69N5`!n z5}mU`xi3A><`l>5D&LMMxFHCT_(!2%GhkJAARvreVibe(2#z7|k);+cKsm7Q))T>{jNCIzdhH(Q(nN!^t;vyp`Th-~ z*B-U^@YtrH-!)jqP^jiACKNWR9)keDbnSMuu^JV1ot&m_iIq*-Ejuv>P;3tdx}qur zT{$RCIP^z$7XbXC{fa!($*!nBgaK`lW}=QiNiW233bSjZfAz$hoyeJYC4`Vyx^S^g z-6+wF2m?yt;Vk}PdTzJMI5%ZX1z<0rB$xXU5HumQ&z_V=r7BD1rnI%R*jB){RFA|U z7Q`RgDB3rmA~kT99@f=XphY}PHtq?!>dGI&VI`N%ehdGtcS9O6yuu{ni@j-j_b7Ezo!sPvzK={IdmJag4>()eF;3li!b(O%L34u)^RRaCiD;K zA}XFR;q}doFek4EojOyHyc-v)b8w@@(R^lJiq3eUXmucTIu%{LMl7rY%C3Yc3r334 zn=fT8l8UrQ+9D(6gteu8sDXz>(yrVP)#KxXS=A0HfqA$a&`nR=(*RT97DxH8zspYT zTLCw)7IJmrAlDa0w3{1*mi*(KIq79~#_G8+SoXIYx|UNpHs8SUjb>;1|kgD#6&nVtE76*0{+*e%=~X zN;q8&_+F{1iPd;=#tnqkvqPKTwHts39-K8v2B@?x=I<9Xe4IixXW1V@QMv0`FrITY z=M%{ggCJ9jKASIFsyA%d{(tH3%vSxU0gHE7zVCp#WmJ(VY>tAo*T}ca`Jtt7@X1jv zqdHm8?muj{hYvVnNHcGD10z>m2>1R9T^|twD$n5BijE(tlf~s2{tV|4dDMYg_c3oq zbGi80q>UjF^$#@^%A8)S13Z?9!fX7PRRsw;75UN+07!v6e$(u)MZin&rO7xhV2IPo zxd`yB0?;kJVst@{69_6k6+PRXv?2ZB!aA50Ve@C@Lcyyj`VRCt%uA` zyHt6^EBx)@{yZixcw)fFHek|?>3tN#zQ~?@zZ&1I`YSNsdeib1Ekj zcIPmb!av{RQh+z-U z^(RoX>|#0M9w-FxjQj}O57FI2F3Wztwu4N6^WyWQlX@+4P@->&Q-Jq1COceqGi8c8 z;EFf66!s4&g19_I(1ZvYGh>O0hRoHy%H`iE^WEjo2UfR)oURO$k8CLczFAX8>ZXD2 zpMY^NY@4gxJp4&H=|Dfip@Q_T!Cw#CKNNz!VKOoBY13pq0|P39zYalm-{II@#)XQc zyF}&8#lnPE6<34$n-e*Zl3l&rv!dkNSK5dScLg9#jzi-s6_n9L4EKNY|Ivx2KZ`*t z_xuc;d=Rlg&YZUC9?&vJEukcxq(S}NiE?WBf#lr~los@7+*?#Nmrr_oImq2+lGIga z-5KopX=8pu4CCjkL?B2z*?{=V&PMg>SNF2#U-OT}hPi_%+=57qzZ zs9!jiP0aqwWYeScc>_*^>+&{pD;ZQ=gFho|APk)9DuYHwmAOnlB=H)L)f9M~RuVAK zD}3PqD278>y*r}ahA6RNiuIeR#RKAOGD}-ay@KBZ*V#vkqiYZ3{yBH#uRTL1?r$6b zYtHA4{M{+&a*5<6ov!0>=J zg>#Ji@Qcvdk!B2m`LtpKrzVH|p0&%#t6`BeXncU^4oSNcGrpdt&7ksvti!m zsy2#>7{`QAz69OpP|g5eys#BrmT*NsH)vGwK{l)p?fbXA_$vt-jHg#-%P2L({ zGvDE^#+M)9yR~oWilX<-Z^Ny7e$J;{le@r@*3QY9?uMO0$t=)v1g~8jh1x!x6PR#( z^S&#n7avscCs|C5{^P=bbVFhFB(eRol!#HBJcx$V*cXhwL-w?Zd9aoac`)u(6xi0g z6np9;i6LD{+<|(Kh08B^^5)7yY{>@{+!&C0eMI@rtf^23pDE?dP|r1#6Q|MKpIL}( z2~3s@V{PvRyaWx46e8}SOd|lN!|o`iCA+Gc{+(+#2|&+wyKwz! zoMRr~ z^2~-)I4L?bo=FL3@?EuwYIV7~EbVfMA80)iCuJ7X(PNVFf=hDYd{D=6$^J+b@{dsd zM~r_s_N}Kt@Yv*!S8LA+21h{uvPQq6^>#p2KcfWY;xigYwOS$I#Rm|{74#OA*@|*1 zM933%cwpyEq#gisPNJ1x^>W`=ZM)3nSqk5u=DP`V_1gSAByCGg|E;G0)h|*9fQs2& z3OTNZl9R>P+fqO6?m(B0W30kgyeQ(iP?b5RCv^&D*JQVBZFJn~9g*cep}O6W+kC`z zef&}X1dloHM!Xb_JSA@UC^h%+ZSIwB?u=&jtQn%g>Lw>F@I_?sq!DuW5^jBk&6^SC zg_?K~Dj0shJW`e7Ug{BeU`L1`5D8!48{6@BQH0Am%m$2 zZZm$0?kYFqIbN_rKxb8t{4@HF$c*=d3|AvGgA2wu1E)NmMjRcUjPA;+tN7haDHlD4 z2ZoV(y{NHN73||PbpKmHH9GPZMwKkE7;q~BdUO>X*^g9G zLR(_d%g)Pg^I3_>p~ZRrBQt%2Q3q1}DRoEQXp%Yv^~u#2h!zbF8_4T3b1~&Asg%Gjur4sNhV#fwSYw+oBWL`UD*0YlPG-g&k@5ShmeAOj8dK)X2c-1>OXmM09P)q3 z_0+f5kPfjI5o9E!u6_^IbOoyKMS@;ZyOmhdeBBURIlK8T7+i!y}zRxEmz@ z4#G44H$da!k4^{>7Vw@@!ar~vYC<6_`Fm0GhNwI`b`TaTRQPcmgbX?qUS%ws)Q?lF zQh9p8l8p%9{{-C1SQe=thgqc(^nyP&B1l=G29Mz&r2jiuVwI}X3pQy)fc`7^S4Sot z3coUz!@mQpMg%G=)K6nLp%6M0E@dpU)Q>P$xIuyWGK(b)lNy#1@jE72gZZ4N!wlnU zk`+de&5NcYaep4O5P0}Lv%=XeUpj_Ceud9*j?vYJ^^Ul+xU=E3^srAkrpn$)+geXw zoYN9hlV^};$cs&%hf`zCNdU#0|BRN00Ex<6co$M!qphhO_ zejhrFF@<25TCx%k?PkB6yk{gV@YDs3VP}PwuiDj5&M)L!7tSn|f%|=I%*!)L;xdKR z;e3zwi=?#OG6NS44ldrhK*RTi<0 zq?SJ!rU-J&qNp8`2w5K}pBzOUnN5Cv<&4+kDfsdguh1b`vnl33<7?{?LwJ&sDnkbC@ugA2LmLkbqsDB_&`CwSB-t{# zHP-5S;1k>t!&aRZz#9CSrP#|uv0?DoF$-IRB1%TGUY31i~R}zTl>vA#1 z=i`(mTGZCwS*yNSO=NTh)p|WOy9|k_@|m844=G4fk}2J(zbkpwXe)MTwAG8Fcy&{l zsV-#I^(qRKw2SQuc1o4rG(EJ@65zF&P@aQ}xhwGC>FVJp7Rapa!Fha+g)=QE6y~=A zPaR6Rl8R_4Rm|0@$DFX{wo`=qqPqL%-XPp(+7eS^5W?Sz1M2n)P1R}DWV>=rN7NFx zrkshHp!q1onkp02;F|f07`izGatT?wjI4}g{E6MB48S5c;ZiE zCn(4y1Q(j1uT;HBf(6EvFW2M^UeF}fu&Y!$Eh5set5qUrEUTblF2fCDv}MW~-9xFc z!Om9ioTyNc)ktnH)6^-?WM(eNX7m_R!qiTd(MvX~$0?1f8jjQy{pwRuz`Pu-$x%i7 zG3b#@MqcA6HbuPRfGt&X0LM&G`-p|ETvMVvhVfQsAWE}=86;WWuEfObh)lN(Zqc!| zUM*lpX{SC2&l3rzKrzFHQT>#k!j;qae``1)DGio1%o%5P>&o5NNPtK5>#ji4e@OW28ALpa=-*DD>2jP!sN8 zCX^CtNVth`Ffoc1H6+Z0KUfH5j~WuOX^wD>%_>=k1*Jxa#xr5Tp1LxSof9Ao(fe?*4*Adq4?$kd@itq=^b9AxW2P)`IAtP`2K4^SrrU#t_^ zI!tH)0x}kvj0+0X6d{*dFnE(OcoK_D+Jy{?iok%K^~r?b9^=2834ZRVf!j z=p;&jlnW-*AEAfZD`=A{SRN&3MuJGQ9Ma#~hBA_XGoVgzm+Fv|inn6olDqWL-a#@p z1N@f{C~a;a5C>jGX#A>r{{vm-bh(Lj7;w=T9xfX!^_Fkx{l5CJ$xG9aons}qw~rEe z*fo>n^J$Y~*C0U#FPBl0AT<$^ijzymVX!ldI<$tF-foYK#Sl82|+Pg9%!XzZbEvr^+ zW@1QfWwzpT;|j5G z9YFaTHugZaxL8PNRP-4r#P>E<&EBLaBi1D4FvPcnP=Q#_a2+{h3mHR2MbYG^u`Bg! z^@!k(X3}}3ftH7#X2L#_jJx>Bc z;(_dP$z~?G^wYau@gFS)5tYsz)XYN*`m!)i!`|Vw_l0lC|2Qq!g8w$(U}MhKGU zHIsn=|99I$+Y>*R)=@R2QoxR2x=gm?E&L^$8bhoV8Hfa@d%HlZL%sf>EQ`$mq%-GD3m_(^ zOB7fOBs$d_f}Uly=?=6e@~Q(z5P6k>BZ$4)!16>7G{AV?3r1i({{;~+p6@~s7%y;v z0JJ9YDgZMOdo_SdiM%SnrNmzC;D7a&fUSwWTEP26UNzu-;s= z0O}m?T>*9W_lkfzM|(R!okP98pw7wOXOLfSFEYq)xHkgyQVxzMdME=+@LX^KDFrT2 zfw{aFOu$_J3u0g{--Qq`SKwkFsoP|e1O25K%t7+N0yO5numlD=ZaSm;4fN`OUaG;h z#1A4sV}Xl%q&H}<0QyTI*qP)Z6&%QY;RxK|x-bI1J8T-G`%U)VgI+4Zltd5tU`pZ# zfv1i*O43^f;k&*{3=_2{hRqkRJM^Q;=q$`LmrpOU#*(ATHs$E`32+X^mXxLyx=LhU z@31_Pc{y+JB@x?EUFkYIvBJAb{=tce@qrHSjYg(YbN&9RKYH zL6-BS86AO;$~;~G8>$S3E7Y$K#;Gl-ggh?QI7*-6RKen^bTvy> z$04pV?r!q^Dgf%QD49_V8<7Kxc?)@~)$MTyhBicN~o-Qt}Nl><%@o1em7UYya0$x6(A@dxT*SHljn;L!x}wWA}t9ZtT4 ze7O03PI+4pNo;~=mYtM&&6ak_z?Qd4w%SIg>xAb@l|YraknrAwym7AZqR5~b;ZBcT z^g-Pd7$rCZmsQMgsG6i;%#E~3JCi&15jZT$oxnGL~0R^&p^Duz->^$xmQLYDbN!u1$muSAma z81Q@gBk)4`3Ur-nXvy@Lsy+Opisl~^!oNtXkpD4~${x5ICM>4NZ>;wVi~mkqf8 z7{Byw2X!U$rQG*BJ=1l#7ngStvW85eHIW7$(JLiYtcfQkQV_#rCq3N;7TU0$zbZ^X zCZvF{rIYq^Ey{E17c-(GUCzD_@?NAgSvS~D>a3>rU~E4M2i#J(&?(C}+AnyqoJffp zn4N3loJk1@fzh;^0+m0bE@9lBbTVCJeQxx}aK}MyW0H902-G~(uBNoQ(dfTjKc*0W zxU|kvARkPZ;jAh8uw7$6nSxT*^@G+>hg64hPQ#rqiE-s?e_uwVn9I@=xYCsVRcC9f zf!b9A2mSsn59LvUpwh$>MKR-mmws|HR~n;-u|+V*ufYdyVihARPFyIur9NkWI>wm13WpW#jUNo%oSrlNV#B@H zEnRW!lNDNHO#1IC%Mz~R^z<<+t2n3rOPNO5AbuHk95@uIQb&XZBQ(44j^l}Fiudp~ z9_OE>XE)~xw%G+!U29jpKcYRHWt$p>5Cl+h5D}Y5FY+UUZ;V}k9?OykbF5Pd+sw!X zqtdqUa&B`i8;NF~#*Aa`}kA#^gmcu}5H{YQDf7*$(9q>;0^gC>K`M@)2Ap0v!J7%(H+{uk0yz~5Xputk$_fn_9Bt_KO3}vVm!E85K19b!| z+eIb1Xsb2e7f|h|X`HQ_>qTzzIUU%&*Aw z;mQ+y9Xs}#gfL@7_H+>YKL`xJlehg74lME0C69tj9tW2^2`+h>jAYJ|#moh=l(|e+FjvTW<~rHL+yIxnL(VdH$wlT@a)o(F zzGr>|mwXKF_=Nn${0Z*(oROIqOljsdQ<2GK{8)~u#R^OVR$?Mpg=xvEOe|~9^kyBI zRMv@^!D`HGwgfYeEyb*0%QLIlip)W_8gq>GW6rWc%$IBk^9^fd08>D$zwWR#m#AZOm3-o3Z|E3*B`a6SseM-Kq@Bs^u%HuSn$rU#-Bh4i$YJ zD*vN*s-nG-#ErG{>%&bN945I*4a#gO$mknF_D>@2dBokOzO z`D8o0fb3@%k)v!DIn6F1=h$WB3rHrvVpox`*=)$4*N~stPatnz4<5CFk=ad*BfEtu z!ER%G+3id?;Ck#nrUkp7X$QD7dw}W29%cHmCz(O)8D=nhjv2{*&WvF%Fca7>nQ81r zW)^#iS-@Ul*05KZP3$#hCwrYaz<$phW^XW`vA38L>`%;T_6`JtyUaEA9&?lZmHCr> zz`SN3u@?3>)}4LKdb3X<82rhGvCr5@z|m|j+m(I8_5z&5zGG83h8@K5dZ3s{O1~lA zkaM>p61qKa3lzNVh<^vSBuv`fl^PTlm-=kP^FCz~qs}Cq; zB>v_!pMNjXIEaq6NJCE(5kD~Cf3b`Bpge#-@}Khnhj0lG6R=@D8(_l_W2C`LfMB;( z6X3{khqH7Qak3pdmc&(rI(u$4r41s+Evti{W)}>jJT!+D#3j>?0c+JnbPzEo?-y6% zrHPaK%mVLqupO(As@cv|yt??pQwy&!@Jxf}By>6I6DCaFNlI!;VE=F_hr4fU($9T6 zJ-Wo%y7@R8!5JHYQzc6Q1rWzUSujxx26dK=+S$8+7zY+m8zZS{BsE6H<`1xq70hF) zX{=}(E5g{KOX`JFx#o|zO-0R9iKeL}(^OKyRK=?TCuR@j&t{ugG*2vU#KAKUo=ebG z4znRUNR~_%!|XL0jbsT|1IbbmqhaP5G`QdbB3!Xv5lkZt!(rl#5un+E0lI1nMidOE zrs0P5Fl7q{h|GBq7tWJ- za9+fVD@`hM<%mC5p48!dNCa1rwBRa}D6T4r;jE+^SBoTZwMl=jE*a0&Clk4bWG>g3 zEaIAwwOlij!$p#fTywIUYfFxBG2}kiiM-^xkX)`iU8_HbdMz9sQv8*pQft|@sW#@2n*`?e(b_F+|-OMdycXEr_Q(P8%mRrhR;g+-4 zxE1X8+)DOmE{A>0ZQwk(EnF3D8|TOEKPWwDkvG_Szm^7&PNnOha*3BiYb4hG2NiN8v+4oL2 zi|AxK-O3*UzYZnD&CMb5L-T0u;fLhWGUi=)z(F8Vd8;$r{P5lzi?|@CcG#v-IO#k! z8BRJEBUi(tPIM)uw`p==@(F!*kWm5yh>FUA@kJCB$Bz9HuA> zQxwTy)xu;_%@2rbo}L97vlpG*))Ne~Lq0joYSEmsV1y+Pos=J@SrV)+nxjR@wl!KT zj%)ZJ&1ES_;9{u&-D`=X=CX`01=Rc&~2?7>+*IjfiEoJA&Rs_k?p z)r@G1Uvhi|&p`eA5<ZOenxk`hXvR*x9iUr5uN(CGKrfI$r;WxZuR)${&j19afou0v9twV?&`;O!^Fhr#?LG4f|RQ&w2cC zS##7^Xvr5yud(m(z((>LD9Rhvh-VR~5xd-MU6(;W(52bB-1IK@e6>_6kc?~uwE&%) zjm}-C^Z2_qOe2PYHeiIiZG?wD!t)=MU>aBtGzbGdYy&-YIxl@-F^hPAxaN{Y6ps=P ziIxh?4qOWE!P#hUn+49v-baE$#R%-|1U|9L-zjF+!*6>8a)6n>oAOyd4(EPz^NC==3IeN`2 zhg1aQnL|ng0>!}Y;A)%zx#^6NKbL9G=H#ZmAGJL4qgG)ekRP`ASw>!FZ_CT_X)tpA zJ#hJ(;?|Gw9EJz-7cKx|)@gVkZ(@+}<^NLO`M+`N|HiHV8@K+q#;rk`x3wzpwA9s< z1h^<#%j_gowKD$JaywxSWrAv!)x4!Rs~-pAmDBvz5(h*HQ1i2v7rbCH;1a zUu6VjlM9-^Rw_<&NU#PPAK5K5>0~NABjHJfr>BwgH#79&ua)#Hs|EV^wFc#ozFLXG zN>|ORuo9(t7FHT)9)*<<&AqTvNpmZ#cxhT;#a?sGuV~e^AXsJ`u2>7QtvSwGUjObT zSgW>#*lE?FDJ%a5UJb~q7m}4?a^9WGtSs1+H~9a#@;-lGc?(Rsn_}F-QwY9>KuC;n z53Q-&)Bh^ng=nQSOEbnDzL~KGe8;k`VgGplE2Hby>YGD+ZKX;%q?D~xF^9O?N)^!b z^^(uubw5ojpG6jGrKN1rsgPq66TjNV{Sv=fC}rCp;MdMp0)COUQboL!l{ff>+Dbk- z;8S1%lICOD{|X>SMQa7ElC`4dYprBVS-9nyRbl!4cfy90@z<)xSuB0|1Zx$ow4saI z#=RH+-)lmRJfV`V3twyX98wbI1*8EBKn}pIIvS1-=(svR0*oghi#TRhVYC3O<>dV# zL0ffcm^F~I2BB96I{S}aLL9X~9@;VkK$ge(yxGo$yjgcp(QbI$blw3L%UaS=3)CuM zF=3ci(E^PLBgT#eJFKV$4AUyuI>u@~Mi1=24{s?AvLHwFqb~qxw3tkFjd7e8$bT6nCW832-Ss*hO+R zeP#LLRy4$|po{BMD6Y@@;vTn&>+`<2Ib^*}I@r*B)fZ?US-^;4$a$PiC|4xY+d(L7 zPtpPl^<)&|phpYRhw4&C*jTt|fraY~%z-GZPic?MdV{wXShxtI7^idL(EaM-8Wb%E z6KR;AT}9wH3Cav)z!n3btrT>P&;l)`kt^8c2(Zg4Ob(%$L5x;qq9tTF5C)E(Xel#% zoE9|El?06$7Z&Umyq|=Gi}+!roI zGTF~pB`5hBhbNFhI~gRf$zrj;kz^a_#VsvK9(8C$1&-AJTrvv$qeTcn9+P9vzbp~_VdZiNj{ai z$fq&a`N7Q3{4nMT{}GeRk7nNSg=&ID2o#)!8qm^2@D^G@YbT+i&|9b^BniR7U?Ef(2E88% z;lgO4rZ7&ZC1eVu4VVY1^m?_i~<_PtLkA()pLZO+EB}59#gyzCZp@onwv=r6} zt%dbM8)1{sPS`HA7xoDqg@eH1n9xl)DRdXE2ywy>LQf%2NTdNm5)Bjj(Plz_8Z9K# zIAH+oBc#w_LMk0245V{}L3ELjM%N4JbeoVtKNAMiGr|yhO&CgV3d86VVK{vud_-Rh zqeVs-BRUIXMNeUzSVb5w1_~3zhC-$oDNGc*2$RHkVX~MeOc93*Q^je*G;yvlUCb6{ zh#Q1i;$~s4xJ#HPo)kV7KNseUKL`uNJHkTonXpLA6&6dXkR`bYOC%p*sZ>>1Ce;>} zOO1q;QWGItY9*|ZdI)Q!L}8sYMEFD+CFDr6g!R$_VT1IEuu<9~Y?6)$o2662R_Uy; zL%JyJlx_*Tq7}qo$`kg=7Ga<4F6@_mg#&VR;gB389FfC?qjGcMGr5g$OztTh zmy?7O@(AIiJWe<*XA0-!>B4z=nee&1Mz|pF7QT=V2^Zxf!e#lC@U?tZ_(r}VT$OJL z-^urcALXaQE%`6uw){%CtN04{m1@ERrMmE&5-dDctim5kP2rhRM|hz$5MC*bg*Qqw z;hoZgGD_qBs=RvF6m8Jo90W{Dqj0V{?qrrC3G{i2BhT8R^R=Z&|%x(;= zVK;|{+byCs?bg#;cH3wjyPdSY-2vLb?mTU1cZoK#yGDFp#C|&+YQK*Tvp-9R+h3$3>~GPJ?C;T0 z_7CV-`=@lA153v{$aI2(7tM4iOD8%6(Mb;Bbc#c5I^CfWo#7BeXF7DHvmBD?Y=?9@ z*I@{q?=XrkaF|6GIxL`z9TwB24lC&@hYd8_VJlthu!DZ$aEoqqxJx%X+@sqZ9?~5S zzti0gf6%=S&*=e&SM-p>8+yc%(9aw>dcskpryLb}*3p5UcXXm(IBN8wqX#YLSc<-K zEJt%4E6}%&)oGq%m`EJ!iHu`}$T>C>1;=PnbnGBXj$K4M$L^x)7$@304iFt3hl);) zqeU0TDWc}MOmufVD0(@b6uljviDez%iRCSfSkYo9`dS>ssumB?&r(7Ruv8F(EWTo> zB}fdjgo-sS^~BnihGIQSOR<3^T5N3TEH<%p6C*9X#VE@_G1@Xp^sr12+gcWh?JR3W zN6SXBgJp}@$+BDQVmTysvz!upSiTeEEHA`fPK?;wDM0M!R8vfKsw1X3H5G?CH5W%X z#fW2^I*Q|+;>F2M3F0)T6mhoGAaS14N8%!<(c%)PDdI{ehzd>%#2lx^;zp-zai`N} zahKBpG2ZE@xYy~fc+lygc-ZN8@u<^t@tD&~@uX9pc-om2&pFHD=gzA5rL&9pwR0J< zlXFG!s&iHGnscD|opX$M!?~+?)47Lu+c{CZ>)cno=bS43>YOG%avm=J?mSX_>O4XG z(|MBk!g-PS(s`-)%6X;u+Ifwb>zpILao#HCIq#Q<^AU-2{!$X1pGbDj&m?>27m~#} zS8{fKCuuIMM4VQGOmdjMBwoA5D*JZ0z&*hBN(B(@h!sUw8#O0>c)a4hcnaevV z%GFMacJ-0kxCTh=T*IUo*C?rjYpm48wWrkGHA#wd9V5lN&XW>cv!p(*tE42?EmErM zL201t*HW76O)10m7iq9Yq>-8^je#rjSgn#YLGza;X`#{-t)4VXYbnjvI!JT1IB9{_ zOIob;la^{Dq!rpYX|*<8%Fz}}>$PlYv$js!sqK|^Ylo%1+EHnrc3e83otF-2SEa++ z57MXFZRwcyv-G8wCtY%*(segi=>~pl&;Lj+K$61ck

!zX|8`@5}MNg3xwxDUnCY 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

7w&~BQue!XA7Hg2;a63x8fs_-MyhJ$ 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 z⪼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 z%0DSAF2_a#U&@5C7YlIqM zt*}4{3x^2ngu{g+!KVejT7{#8c43pyAw=OTDRc^Xp-VVLSTB4<*dTmW*eF~EzSjzy zg>MR5gxiFpg?of!g@=S5;c?+O;TZ_^OCcfrPUsU}75arYg{{JSK;=VWoA7U8yC@0+ zq9&xp3Lzs-69&cog&kszFf1+*P7s$0CyEWiCE`lqOmUTPj@T@mFNTG$ifzJ$Vnn!D zTrXTEZV|2xP#B#;ocaa7my_hcI5{w04wTA)GLHM4JI4I)nA|7_CVat-L*8!V$boW> z2M_);P7a_5C4s2W4T8qRK&37|aJQip0_J9DyBi+~wA73EF<0EfZ7N^ZDz2O{_pzI} zm2+ntyqDX24LA8=Zp)^JxTELo;f^Uk7Qh~^r`6%c@Q&NVMbZ5%k-zneC+FSE#26f8 z59Cl_`4%S&-{#7No4HEi7H)=c8+V{^JGWf8gX;wQM&VAD`G*mt=&&$Z6`E|=iBYq$g8qmSpF;QHI<&fmjry_PGRJ0B3? zJGqD3w&B(GZ0z@d@4vEGUrx6 zi9yK9H|v4@Z|B?iws}u;>b&w4kZ+s+45yZ-psoh+v!p!TRzLq~u55mJW)C-b4JS*t zauV=_<5{4}dF5F%(7f`T6+UN%5Aba`yyQ*nAsc&#g}uXrz0<_rWn&Lp*u!?(GX7~> zV}?J$4u7H*{zOk~Cz;tl*+Mzlj^Y%+*~^`}n>+1RZaOf@J=_@+xW~%R+{>M{9Ex-g z_mvG*fyd1V&$c5x$D(%5sD*j1nS}GKK<9Z}7WQQx?8{B;D{Sm5E$l1pq+G?&uQt)IvC*%!(66=8uVd)fo9JJ+ z(QmNOZ?Mt7!O(9s(Z6Y<-(;cR6l-n$n+dL?@ zn<#f!D0g^JzGI@?X`$TdLAlFBx!Xdy+kiSkPe<(D3mUzsSsworcU zLHUh|@`8o(f(PYA6XmxS%5Oa=zcZQ3?``Jtl7;<}2m22u_8)ERmo4m3?f!=8{uj6Vo2L6)ZuhrM_jlaxe>L6TwUYL(Cux5(QQosq z-t(ZmZ=!r)p?u&$`MZho4-4fVqxPJCn#KGtyO=+;!hh(A;v+MPk1dpsJt&`;D4$v= zpW3PTjNyE4M*43%(*IcK|M5`#uSxL>3+0Q^@&!{73^aLO1y00SC=I>^^BX=*5^@DE zqFBO9yZOMa+zd-Bso+a|O~QHyYyMdC0AiRCtl<)fye!6I?EgTxA(#EMZa_tRP1^ zg0$E{T1Jhv)k(oJ z9(KIJLfU8}ZFCg%CX-`rc5|#PML5>cHkqTn;}|Xibh^nLQ-sX1Hko5b&1sJn>^M8v zaia!{TETklV7;RTi&??qcCh%U!4g)mK08?7sKNTJU|a2ATSsj(Nh{bkJJ_~SW7}>8 zOWDDUrL3p9&GmpXFu#IN@8L7cr7G!ZZcUZ+*bQ8;O2SHfY-x$ORIZdOOK##8R0S&K zCCf<_*~1T(FT0tWT)*i-et=o`^2hJtv!?;Avt<6(FP^W5_;Mxn5AsX)@_FFtXdgoR zLS|ox_8n-Sy_eq!LonKRdF;bzpU&*l(SCx*exg+WAousZ{7E1)W5};_9&XO=TEg%l2@`R7w-Xx3=!# z&)mcHz~sGt?r#1pND}nqsY&z3RIQs<bD+E5VEUE3~LEm{|?1;-u?Xfd-w~M%T+Rb-NKbs zN#Ll{UM|;H$$R*(0?nQG^A}>o5aJ^Egb=&Aoep7<427s*u%a&l-o>akKvWLI)TCPmDd<`tuaHaK_mz@vsmjOkH_Ht;S<(XR;(f|xB z^V7~}IEC%lVG{CBbF0v(;IG)jUwJKe5L))|S1l*vQl(O^o(l-CaI)|xP7z+`#tCn56NNXqDZ*RaEa7c#f8ibOK;duP;lc;pO5yKZqwr5I zEc}aW6+Yy;gpaw6!Y5ph@F^D)KI0O?f4FTT$E8G`8x%!urzmkJiUIBnQRdDT33s8W zaF>cIcbPbjyIL&ct`#S6H;5J7&EiDvcCnJXSDef}C{E!X7OS|&#i`tr;tcM$Vm0@B zaW?m|xIg!XIEQ;%Jb?Q^tl|D8)^eYVb=((XJz?DVsQ(9rFaZ~t#~Z|O|gf+Sv-!vRgCd>ihcauVn2Vs znB>1JZsQ*nxARYl1N@J~H2-rk!~aSg!BHksOA>J*VC*C7mDBdevB0eBoA?^{b5+4$-6Td6mBz{l0MSNJeOMFzg zPkc<+D?TnfB0eEJF8)AxN_<*)T6{)$PJC8)UVQHVA@4oFqbj1u(R0hp+`GLeo6V*H zo3NXu*HEQNNdia>f})@_3sUTY3Wy!M0xC!`Dn;rh7!gDTdjWgF-g{T1yfb(2ZuVX_ zmfyd;_kHgZbK9IcXU?3NIWsH1COs#1U~@^sCfg`du0%{UHsL{**>ahosTc5$R+ZqzSShohD1tRGCO;$yAyxGwA|Z zkuH+0(mdHAT`oJNh3LtylfBXs*(cp0`=w=aK)PEFO83e6(rP&@)yjp^M!8tpB9}-z z0P<4^nu(?`bh35eJ*#AzLdL4-^$&j zU*sOrA97FWnA}U2d8&Mde6Bo2o{e`G%hTj}@^txf`D}TS zJX2mQpC@03Uv81-%6G`;%lF6^$oI(?%B$r|gZ#0)ME**?S^f^O{3_on|0&-lAC~VV9(ft@$;(Nud=Dvjim7gMY@;>sI{0!M6KTDpGpCd2G&y$zsm&j-G ze)5HUfP5prMt+vxAiv9RlB4olRFvPQviu%Zul;+8w(PH^?+Cu(< zmdan#a``*jO8%azqN_-l-cJhX z22w~jlOnp6G^6z-LLVWe^fA(sK1E{m8B$JPCUN>IX+>WrZRtCt1AUKlq#u&b^b69J zenTqg&!ijuoph&vl3w&E>BE5ZWisi{tmH)IBm-H13}Sg?Fv}-Zte6aA&B$<8N=C3& zWF%`xMzOAB4C_J0vVNq74J6~(U^0OXB@@|javB>&Cb98kGMh-wU{lBxHiJxMv&b}d zKAFxgBxkeB$V@h$oW~ZB+3Z>}m)%ItXSb6J*iv#KTTU)vE6F^zip*#ClPlN;vVd(S z3)xn(nAMYO*(2mS_87T=Jw=wVXUI+LIdUs|ncTtllRMe#WGQ=(EN35*yV=KN1^a@m zVqcNf>^riS{Yq-tpX34d7g?tO*{F!*VTF>-ik)m#++>^LC3Q+Jc|^%04N3vosk9)w zl$K<-(uO>)bRc__PUI=28+lskL7q`gAkQfS$qPy)c~KcbUQ))8mz5fFKsklHu1q9v zD3i%s$_(<3axQsSIiI|zTucrsmy!>aE669x0`jS{n0&6>NWN5VAzvv=$=Av~U*3yUM6bRjFIGQ?Kfyel?c{)Iyr0Hlw*}goe}@El}gMP;E<#)h@I| z?M|DieQ68zL>f`6X{mY=EmKF*m|8Z!D?dM0hJPNyBz^JqtPF72dVNV}>x z((dX_w1;{d?WNvLd#fwy3F-s1uezT0Q@7FnYCRpGK1v6vPtp zI!yhLj#fXWW7N-Sjru(ur~XV&R{x?C)MNA%3!|r6taPHqNheuy=-HM$I@yv>r&?lk znx!qBZs|a0S~}75EERONr4OBB89?V+s_6xmljwz(ar7d~DfD8?>GU$obh_AbHl1fV zmtJX^M;BNY(uJ1A^jga`^g7E8^ajiA^hV24y2NrHz1gys-eTE6Z?$Zuw^_E)J1x)B zWtQjZa?8u~9?P3_h2>qk(((zt&+-LbW%-(}wF>kBt3)5PGP=&{r0cC-y1^Qv4_gcA zCTl6(Y>m+^);Qg6ZAa^^9q0~g7usO$O?O)R(Z{TnbeDA)-EAE~pRi7&d#y9*KI^&k z8S4e~S?eYAIqL%Yf^{){(Yl1bWWANXY`v2nu&$u*Sy$0lt!wC;)~)m{>kj(1^-=nP z^)dRPbr1d6`Yip#`Xc?*`a1pG`ZoQ-`Vsxo`WgMo`W5}w`V;-#`YZj;`aAu}M(NKs z8~w%Rq=#&7`j^d5kJ!TWn5~$BttAs|aVFZ@GGgn>oVMi>yMTplH?Shx5>{-xl{K?1XDw_iSj1M#N^R>{nQbGB z*`8#rY6phS`U);r6j?gnc|4X`jqS*{8D6_8F|k zegzwEU%)2V7qe6COV~vFt?V@WayH4nf=#y9vNP=K*qQc?Y?}Q^c9wlFJKO#&JJ-IS z&9uMH&a)q6v+WE$IeEW~=A_rraI#hO~Bu=^afY_($@TjSWu);j9g{fx zguU;)lYQu1&OUOkW*<9i*(c72*yqmO>?`LU_O){_`_}m)``)>q{os6?{pdW%esX@u zes%uN{&4=u{&XH;f4K-d;!@dBmzy1P`4w>GDw3;}LS1bX=IWrRuI`G})myQ-1}b(} zrQ&c6Rot#K6rXE~;&;tZa$K{Opz8u9&oy5OxfUq-uB((n*WF5q>t3aqYn9T%^^j8P z+NhMd5=u+gBTCfus1kQQuC#GIp|o}FQ`);;QaZX0D4ksID4kvJD_vY4E8SdQEB#&H zDcxN^D7{_BloQ-U>El+Efo_X3$n8*uxC2U+J5Q;0mncKs5oMS=s*G^AQzp1ODkI&U zm9g#tN{zcx8Rs6VOmq)dPIHe^Cb=glXSh#O&U8;xrnt{mrn+Y;Gu&4x=eVy{&UIg} zoaeqxneDzynd4rm%yq9(&Ue=;7rA#Tm%4W;m${!%=DVL$u5iDkTS$0S?E5f zEO!5*TUIN_IQ+AJbvYNPfWSX6IYgc+A7OEU6p%0J(PPr z{goA-LCQ)`rLx*{x^ll~vQq1rsyyhKsjTzNQPz7dRW^7oS2lVUD4RV?m2IBo%688R zrOs2U?C`8p9`S5d8a#E%qn<~UU7nYfCp`O=Cq1t#Pk9b1dp#d1`#fJMPkX*op7s2! zJm)#AJnv=7i{4`8C2vf5+1m^6`zvpFM=5W6&rsg;&Q(6}E>b@B-mZM+U8{WQ-L8D^ zeN_3uyI1+i`-1Yb_YLJ&@B7N{-mjHEygw>`dVf*D`H&;9R+o=`)u4)heiE2-O zmD-7|GlrrpbV7E z4~&HIpCAClj`0Lw0}%WLm%H+Fl)~1BAMgBAO$y8aP8{+0Wo8FJcyuv-Q#HZxJ${+64A8h<#h5lgY4=eQt2YJWbZ@BrVDg5P!v5AuB} z_~xNx(OiDNPA?kd59{@ZJpQmje+co1jY*LF#%)A{!2_V433hcFRhN+FNBlTOJJ%x59X+s!{zFgaD%!CR;Y_%oq7$_tJlL*>Jr$m-U0{JJ2F%Xq=+a< zmBPt98yT=?vv*AmA4p30_J&@Fc;8s6`T=gU9rhW{g)K6iu`UPC6ehJsB zU&H8uh2Hpn$f)gEKHE2xNkC0NmE*`;m3SP&AJIT>lJ~u|b`nDGa z1W7&2?}Qw8ub_e(9!v9Gr}OO<>hUjMZpGUjNkRAm3=1-C0fz1J%j=P#8*(9(TC9L5 z&vjQ1p+J9u4R75R8FDR72w5nEEfyGJvBGeR4Mtkrnjk?Ck0Cfs`Vv79xJSW1`CSYW zm64Vi5^+LfiaV2(M931Ch}8>nXTl{?{!SuhmPie%nndcZ0NIdTB1=9O*B%a(U zA?(3-{4j-&q)tRY%cx*co&d0k@ABxR_?2bagX`pk@Caw&UZ{$?Ch!Lm^~>@^KS>A; znu!QAla?~}UQpsvkd4r*BP#i2EQ8vQ`UwIk$p@^8A<=~JD6b5!urnb%#?gx_z~z_u zo7?ftDj?BKI(!9PC}RP?vI_h`mA~5MDq0EZLRqLi_7(rIl9x_?+ReGK1T9H!%B7%X zM36Q%!i%8*RdXt8Zz533X`osrgWYllI4x7aZ$Zy&nGX4uv!S`=9B64d7us58LJ!M% z(9bd(DlK!c_Ah|hmP_Fx%Y0a1xdQI6TnTqs7Q=m(YhaD#dZ@G906Q&9;7Q9(u-9@6 z?6=$oZ(DAM_bqp7wNee1W8maHZn8_|eJ8gVht|6u2AgmUI)Iw_SC|K_A_2giMo0x?^M6)XKSF?&;0Tl$nz@* z?h{;n`I@+^Ebqaq zmXF~}%UAG&N1@E}yU^P5htShV#)_XNKMTvrFL@p@Nj}1+|}w@7P+*?_Slm zZ1H>mukae@_Si?!BsfnT;n3Vw9(y7A9maB7P*dd7a=p%b1Xb_$lQdIYq|3ZR}DK8V{g?|X$0Fa+L|9`{gw1cj|P4g|ZUca|1md4Wg$ zUg5)NmePZ;boVs&A{{%H{z%ADdN@WkJxEWz^l8`&@{vLr4h~vGt76qW<*7!Bji`_t zgpX^2a(TQ?_@rL=bWBi|+HHz8s=ol8B-qA+Y#RsEb}}fo@mK{DpxAZ>L~K)2W1)x) zq!;Op&;ToxH2&+ri~{ zLin~qMicj=Cw**{P#DC%8GEPic$Zu+e2)QOtsv_!f2d$-1N%|4s(Rt4q#a=#T%ne8 zcldJ!j^C6DOD$;r@YjU!8%F}Wf~t@Ze&>$VqT~A`A^gevO0RH8Yj`p3J;r8#b+Y+w zOTifnT6h>beM~L3PP{)Sc|V7P9M(X>DUc(bcnQC)UO1X8G?W)QW+)^=XI>~^s~3f2 zp(qv-MXgX_3X{g7Eoj@T(G1#n$%RCyJ^Fqv$W>Tj5{5ZN&`kISW??{gneYoJ!b!p? z41kgqnSeM}ene8r^Z(9ae+U~{nvjT3i-3QBUtKb3KYHT-avEAGcPuObV zCEJ7WrtKkk$F>eWvu%JMZ5!bT{|#8%Cc$dkA_Qz(g%aB~p@nU`(8g9L^h71~we1ip zZHt7HY>x}0Y&(U~w&dpG1>iac&Gcy(bfA6l9}f`w2}gL;*dIIpe2fv>f+e#A{~)A% z@Bm)^MA?26dg_tmAyCBT&5vPkL(NbCe3nN{zSf-gK#ViVATn4VvgDzG^R_Aq=63f6 z8KSkzV*b0}dh1Jw-A zsCEScb_#);4faB?+KZ5M2_hLmM(Qf)okp@vwCw{2pWazmFWR?@ zHvXp3e8c(K_D3Jts+Cq!p;gXpS>*NJYEo3)Pz#eNF1c`D@CCqmFZ z2}1U15V6lpu^lwfA4_U<`bGGT_XkQe#`*S``Cepz8;5X`23L6PtEu$R3Tu?SVHve7X4Ki|2iAQKu!5>F{e(<&FsZ{;`k2i%TT_%QNDXn zzI#!=`ygyz1%>uCDC7Om#$F2@?GHd_`@?8jo1wq`Q5a<3iDtD+livz*kmMW&9RHo% zC{Mb*jV0stAS$Z&c8joSSa=k&4DE!oKJ~cdWG-}0TIh^#f|fMgaxXO3B$V?pMpD8U z7+Lef^kT%{$tI)zJ|Gj!uy8=nRF93Mh4Shjxx0(8bXcx;ajOo{qlI-_Z}wbPR?Wjv=V| z(M@aq^rkd_dQ+M|y-CeaN^AaqXNwH$EwYfeNUo9NTBKt-D2}th<2V~~9OppLaUO&n zvrsp4AmTV5+BhzNj*bhVvtvGVbzFhExef+7u7^>M8_g~9bVJ}bIW?fc$WzwjX@hJ< z_JJqbAePi{Z(k=ixS2q5o9@yS;QI9QgoGACeCQ=>SCPpi3kA0PoibGq8ZAKz-=mcF;hbid> zZ~%zoHPq`HP~>!LWSd7=;Qbi1~`6#!H!=w z$$fkpzLb$^hjCzJ<7essV+Nt7lNownvr}IdnXYkrT5OA0o)F`F?O==83h(&J!WOZ$ z_O1}`+Guyl1sd3u(Uqc{ZL8z@;Wfc{^6(n5U4@*_XG>;X-lO)|CsFKY+c(yxHizx_ z6GX=$ppL`P$|*uurvyEnGW2#TP~%i#veOFFoHk7^H;}`SCwSe5d6UgO1O<&kCC@t~ zXG0MRcaC0Tf9N%Kb<{QMZ!HZgv`X8Fw@vJT-65)=;~2b;R@EN+I>c2X%$m0p93id~ zyj=#t5Lb%!wkX84qTOau3)XU{lp%L+6kS_la|VDqbHU-vgIs3_!p?jsbQVH$XEBsH zBhcDe3LTs+p}R8%Q=M&LwzC~v=xh%cJ1bzGvpZbr>;a3Ny)@N0fE8+5ndW4EzuQ#V zDGP3)$7ejU6VBG_B5C>--m^ISg5vCFXu9X7f!FG5b_1iX+1ZqtTB*}o2ij5qEuza( zV0h`O+x<6bZ6w5sMrCLnfwK~oQH{zNhRPU@$~Xy?F&dRI7L_p$m2on(cTRwA&dJcr zc_#FAPJt7h(^3vk7v3=JFD5fn%nM!6>u}~*aJC8dTKvjZg1i}7>4p!;u$y1_9-Z=9+x5cx-q@q^OG50;k4;0E6L_Sny%lW1U zOGB+;?kj?Jt{RW(TVc>&+4#g)IYscpLf{9>-VC>B*QAb4hg{UrTyQzh2exoHxNK&YR(M=dIX=ZiAW5JKzH6ov_fk z9IkQR4L3Sh!p(SpC*I%dT&3yK2^JUR`mJ`qw~~?bYz9l3MJjY-h~XQqPiwu{FIDlz zA%YYAo$~=uoevsN%>FMZHX(}5h+>NY#hm|wVh5sl1W_~?P|QttNF0Tvqe!^}6N;x0 z#a=|Q&w%3m|AJyaqBwvkUNwxq&QG_k{(8go>8%RQ(&f^Q;uHIuR=%C@V;lVdaeWF- z=NI60ewFHT)ePiCQ9oWDRb=Wl3*ze79cpU~NP2)esOjUxh5FjqCTM?I$k2eHXGz?1Zt zcV#$Zqv~7^u)3V!a=A>HQa*m6o}JM%KX(wS8DlG(k8GkazRFa2;^dIaGz;#m!vuS=a%CdjfBU5>Kbbh?o!g{ z-=mm@D5fKd8HT#M?0;Yd7orthgjR5|0n@xRGwpOuXJBfAr^SfrYQ%Jn0n_~d0j4_; z)18RvE(4~^(|+OKOLsqF!mhyefC1ALEmT5uF>j^FeeMfa)#+zq=Sh?h+_)w}4W21lqVup{u(k^l``F zM0Xs9yIaEqcN>`GZVP9+JHQNgCz$E(0++hGBGVPH$lU|3b@zfL?h|0SyARyw?h9+& z17V|kIBa$ghOO=@*yXN)Zb`s*CdPF~c`wJv zO*ld_^bj|v3`leDvhLnfgBhdUyXS!Ho{I`P-+(9V4= zHh^2nZ94xm^vSZee=|^l=KH`IZ4gJ-MC-&c+qJo^=BDXiH-;4M<=}DO4LR<6kn~C@ za^DB#?$xR8Kj<-dklWK8K#A@_Xf(7P%1mP|_cjzMVSv0N>-u)gT;jfZ4Q;;!e#$nQU0cyd4eo4DUPsN8u4mbs-AlfM~ zO}i$mX#lv9&AAu?l681rw!sny>kkL zQj>&*8U2$f(D#&p>}d`TPYdvRBH;J5Oa=OW15fv)ttMTcvYDZF28erc0DQcim70ve z)7=2HG95dX=-nCBj;}YFwWlu-Pk#gCePmU};(M||#IisRM#xHhvpQ{V!*qRxLigzU z@@3B2gtiOCjY`wOPne6|kA_kEH-bh@g65kAeHjJakAfaRL0?5d-#|g%$|h(rc_6Ex`DT`W z#-b0Rt(xl!skb)OmDhqp4I7q!D4VoGYZGcOKk<59cGT_6sLK&`D@47XY|yncK_BAr zIj0W$KoKfyA;j+=+X++nV5)-@leFi0aYD>ANA0Zu=IstPZ*TB>`#^JVKTSz0##x6U zhmo+sCN`3XvowwNW_d;%^t*{{)`2SYHQ+#uvsN9G;!=z=6^-X7#8Vn2)z0hoo&nT5 z1)Scg$k_}-AG#%lQQ*T{o`(A-pFZla7G8)wh9gIPAaHkv&%}s_t%5GGaJytydl`@M z#`07D!>!gNPpfgm3UkJncDng99Q9rpnMBb|N3l;EpLPhh+Xn%TFdUSV&)U&8PP}gy zmPhi*fwmf!z5Ip#%%C85JH_?0E+h_ zaCk3+pm!b=c;`crcL9`o7eTpqG4%3Y3sv6hV1)O27>)18dvAtG-dkb1_jWkfdnerF zT?Ti0m&4uoZk2Z>Z1b*#25&9w!RyoBhu{V8M%eG&3~zY1X;u&cM-iVSZ-0nSEh~a% z5f0BGu;L3h|8fZ2vTUfEt!YQddpRLXhwFXH0I)3`5H$(#3KrY`&v@TA*lHqc+iPdG z)o<{rE_>VSXli>tKM)^ptMyq?cQm2)wZNwx*-@WhM%@Qd_ro`jWG~;(Tz&|a=cyVE zSy?&3%*qsedNl3ln(PUEbMR^BzbJPJ6p_csF1_5vdNA3WPh{_f!UplwnpAp|I8jUF z7x}LR)QP9>it!2X?IKT}DC5Z;c!_NnC!xuUWsTOZ#g@K>z!FwL##C(CEP#CMPV;e-zM#Lj!^qbr=tMShnOTmT%v@@glXG*-P_SmPXBE@`}r8=|} zEc|;dFuY7n7yHn(V&dD23_lI3?^$H{dGPyQgrM&wDDdrvBHsa2q7}44x z$M1lk-wk2EFI(bE5qT<2s*A2C>?Fid$+eJC3Gu8(+}ilj9|GnNqX(V@*ui03s{St~xBms63K)1cIUI+Xh-K`Z~6(9S;vD*V&ZgJYk;9A8R@y#Ksv;-86XKMz#@EQ5S6 zlLP;I0BI@GnI97NLAsqkPw(eAhK0->d&czFSbf zTT#B-4D!83Ue{4f(ns6Tze~(P^v1d1Ow(C`;@pQ0Vik(A8uI)t(+k_N@_KPjLY!L*v1((0?$s_@%hK2L9eA@0dn=&5*w$PHHa%(H<{Ef>j#j9pXhI-$t@YXdKLF zeTx4Ru=+p43jG2r^6OM378~fiOWxDzEY+P(JE00Gg_D#5nw&`r;>D;C@sg@qaPgZ< zF>>J7dF7il?^y)Rc%m|1W8!6o3i}yE|Ldr)3iv& zyMQb7TI{1~w?~?ZWFmpiP(oN-g%()IpX8N1F&0YriKUL@P4WO?K%T$5X~r>74q~7c z&_HYO1lpi>+d{`cJ7ln9YUG;KW+AfkQF`_-qr*#xSD1RFzzIMCebY&qA8UI8IMjJM zRIj9gWEDZYatwZLS_J%V3Qht;!4((=1%ctvK5!EB42(><%L2~yC+Ti9wGX_R)SVCL zo2}Ny^(7%hZ%f`J#03il95;S!CNTjlfm6U6I2H2oz9cZIaV=C7f;fCb5}&36{WJ9h zzLrvVsYia26c2<-@{yD?l)Oub3nzA8C?d5FLXE34S{xLZiFI-w*aEY_AD9ircwZWr zt7o4`M?e;Y{3OlK$mcrE&-FpWEu7r4BspEZ>C|wfxd>Z%QkDC7u8gJ1FHVTpjKTW4w$b1^fgOdr5?EjX>T)3( z+f}H`tD!^S8mzW!VOZcg7#Fx6&I;TB=LD9({J>3cL*Qmja0aAE2!*^_6aGRs!<+Ob zJRD7?CpO`Vzi-0nuMOgLHL*JJ`hU@aH6I+nt}SpMw%}FRg4aN=zymNS@E}wN9zvcs zq+4&Ux%GajSI(_y4%%2nYrO+f27^6B_4s6*pwOh>JTK`^Vd3qi*$?ahwSx9u~(Iqy>i|Jn_#Wn*gTUC=6R3< zFMvIOqo=@2Xvi-^m%uB~H}INn(4v+;h%AMWnQzilV#D>;%KI#q>Q+xMrhc)6c*A;A zQ~d(X>uYcazJWmCTgVOkm~E&ckZ=Dhp&Lzva?mDoByi`*5Xd2ro1>tTby502D-tmEC6ERMs znQC1_P6haKx~2H{A+DdvFWClBvZ+tW=>sIEAC~_$`;5*qbNRtoz7os-mUTvFnOVT$ zSoHVosF#{i*C6VXvHTxdQ7<*4o`~=NOeaJCfGGGB>lu9a8_#o3h-0hc@(%G95#ksr z-6{f)VRwkP@zhpZP{!NaMX2JFq89%C4gunOp){_qS{3k}#)eO7@>7uP(jqGctzjS% z9EhX-f$7@Nma%fCf|xT6$E@R}7m8bG)Cv)7S9x|->7L&iy%YnW15jb)_$u@x^Q0c$tvgCY+oPCd+{a}z$rbNf|y54V|jILzlJ~%0~6sm~(RA)YG1GAC5iP%vE zCjwtF9jIM1lH+p@Ba27Do-2Ysmq0j|LL`?#JXeJ-xpwHD>wrGFF6fu*h7<9*5}!}P z=h3;zX)8Y;jNm}z^nO~Kuwa|`6C{JQ6g%PLf@);lO~gy9iOR%QJ@Q?yc{leA-wkTmEx^Q{;d?Q_+alh-U0hv@ z6~9HS#XF89AwJO94QW{sxlv%b<>1Q2K|*dv)Iw*7=5~QLxfReMw;S}#?E(FBd+U*g zbQIb!stAJp51b?VTeKGjWicGPuoGGYD1rFs{CksB{;HkNwQ?mjtnq$Ib0 znRh(~^9^vPQg3!R^X|4_rHP(Thuec}Vo(cbHi(;eki5B?ACF~;C&Vqw_>6Hv+`1`0 zJ$u&AID3YrwqcKt&*IkIVh&#!-7N;TiQD-eLK>v+)-_i3SFmC{@AkYl0~uTBmc|d?ZGhSNyrKEW1pTz(Vjuk zo<-4Kg08_=pjU7|3=STEF~QehLhyAI?G2b3e6vx!928ISn#9X#O1y^u+v4R}z>;T$ zoIE=ef)`@ z=ZD5cU2{$D=R#u^TBiGH5Ff3n6L(goeamCX)x}*Iey2R?WHJIEZB{O?3(&l7V9)D; z67_`qyk1a{*AH6c4S;ywAn2Gk1gi3?U~Jy7^lXg7#Cu+P`Zv|fXXU*K*U5Ru2DrN_ z&HUqAu) zmw<}AdKj740JHKQ%jWmP+5LV&TKIqV`+0AGocAWEd2bnl&%$&RFjzNS96>^Xyb`=z zb)lvc)$+arCGQ7t=luwQyq_R9@7JuOVOoR~jvvfHfhnvCVQ>(_5d$sGmbL^1rbr{i zQ2r9yOfT9k9qDcppGxk@#T!1)Y8tQqG3oVL&r_1EWL@{@=h+BmvS z+`C~?+A<6;Z2@OgQi4bMvA9)k6G$T3%5luwiCN=UV&{A5KQOSS5^&&I_ z^0W&{Q93Gs8Lr0${hT6OZn*NmF}3B=HEXpcBn3jG1r&{1&ZOW?_; znx;J<9pmkmr<`k!2?rM`y6w|0rAnU)=M$(cll#q|uL;$OFKmaFwc0+kmZ60BqA7zS zKLjj441xUSP>^4i^7{e99#7gKEnJ0OY3?KuBCby+QM}YRY|^YUzcZrk0&0Fmww-gu zv|~D*|ApoKW|pr- zh>Zu9`HW1H4}oFvf_6_INAZswkt9d2|1(EnH?Xi5T;TxZhjXAf9D-OlAKHY&&@No^ z4;=NNJ=6Iu$u!lnq*dgkPr%5?HPyH*5Bt%VycR?`8mae_@ckJWi|_Nd=E}Vn zc~}AV@OtotH$Y(+oj|xAEB6uT6@E0eNLHx&v1{v>UU}-3+CryoT(1*9tU{Ce2<_`* zlj8{E2rm3Iiueqw^7)kd+#DJ0|98kf$%gDTMD{u&djpZZ-H1$}1JcOO)a~9Et*P3> z2Z^7SKf!Yr%Abg9`$PC4!49o~yR~a3`u7n1K}7#PR>y~WXe}P&zJLeT{Pciky#G4y z5HC$nqyu%DZS*+Mm)67<@iX+IpYI0R7#V1hYxpZ5;ja;T5FOkU^e0=yFOtx*8TxmG z{sZM5l7=3q%j?$UMX)c+pV*{Hs|%ZKo=)wW;oHJTP}rkj3m?-2^@4DWx8mfsu%wts zr;?^DyQLn<**TY$F_bYOeq~~>Km}4@L9k&>gME?(%#UCJY)8ZCNf~kD-|s9dh~ucI z6{rP;!Htz#MTq+1--#v&^PNg z2|Ds$?PVyy%AupuYjg{B`{rkiRbV95B3e_qN54-q_04vuh;d7;iantXJS)~Cn2l#b z0nctM)2Xq`?}*7){6MV#IXb ztUTR57A@Zn<)(Ao3eLpZnF5xAX(-g#^kQ36^S}iQuvpDMpNv;N>g|ga+~Z zng;O)?mB<06Mw>itN3$yi2o$%~!7ck$QEsR$g9Dg|4Rk*(k; z*aqH$dI%QmfR+W1L%d)QbS`)Tx)(eJJqq^fzXu>$l&Or4KQ8hHIw7rtZ}r*DAwnge zaHx#!7JrjnHhG8my9_a}_=mR6$P;a%F?}7exJvAa&ua2HyuLzidE5K?V zrClquDsQD-E18>C8=Y#5Alb_z8=i zntkb+n5GB{4x`x~1^%O(y>**7O?R~Ang$avb}2MNMgPe|qP$o+KSlfIrQj-;g%Qzm z{BS5C{$+{^3awx*bb_nU4F!chC@Bm;tT2=^#@KPyE6~%@#ZW zYnog+kV15Fg>Ar5h_O#0#yy1y($@%1@UZT~Q*D{9>xOeHtWv7;_x#Q@*Sqrne!T_vIe&w7Dz#-j` zv^?4*SK)XN3nzeFh(S-`WQZ0{gSLg!p=;r6=utQa1{9tR0}IcEA^1ETpT`wm0H+pS zq%T*KBhWRuR$Yk(#@*Txv?gtBPBeIdNm-Yxd+5v6$F${Yo{QJRG^J8_8L-0nsO2lO zE?3jZS*HoQn~b#ZCa};mXv$Ac(T%i2p3AZ-<5+SDb)J`;Fsww)X8tgG>UGT2K@~0q zTDS}i?`~*UcyDUux6{` zm!LXcF9``rO#U|e1%BBpNoVnsdtKen>O}p-PhH)oPUgq!-`hB!Darho+iAU|{kn$4 zkA(J<=tlbWUbj=9QF8Df@s6rMw^QqZTE75Nw6(Ah&QMgbO!8q;Ly1 zwQbP85If4k1oSJche3sp!0f_ZaChMzSW);CtS)>;(@FsldJN9uCz@#|_%S+F;6DNM zCzOeQ@_MDy(k3!Uub-T#S5nb5_!%rV{>v{j6O!flDmVa2;p@oQo8T{e$M9P(nL|U7 zPEV&#&eB(TyJpmainXv3a?`4^HvZyDrB*f32FX?vuaoTCp{Lm=e1*FC2Cej4C@uUR z$_sylE``6OrnC-&NARJ5Gw4~mfIXn`+@Q>c%^yt-pa@YEN#HD^sRrOQG=Q_Sr`mKe zx!$52AVonee@@nDsf#HRD8d+#o|_%@a5L%(MBN?B&&-N?xEb{jEP5WDm9enQJur#Y zi*roPwkX{<3*R8nY&s_cNNfsdrU7Vfx+|Zc3vv8jj?^ruaY8gBt}B`cO3~%uDY^o3 zimrrU(Nz#GS_~ycS7+PHA<*;xw-CJpiQa`omm<++Nc3JLx&n!=%tlnD7tjlJ^^ehY z8jM!Pv`#IyTXJkFuZ-=GoP4F^*mp+rEyAd{XcNdq+mPaRuou;#z18cJ2qF$j7`+Jp zVXLAS(@V1S^w7y{6T8tS_F(x->1F1q(|l?{(LO9UFI}#)UXCY1cG`>KAzn5`&8^}^ zY!xqot>~4ME^MIC`SfxfNgv%nTo|_T&3wBhSH0vu&UF-hjDmj-wCGE46n&T3htn&N zsVo2a(CMOIvD^ZhI;1C058Xv|gQ?sRgMlofsl#}hirI^e{pVtuvZx|m?@BDXL-L4V zVyM_~VkEr=M?9%B?vo-Y8M%>}aJ;v=mR_e*DMdx_AjR1rd26DvBEK9Yb&}6aEMOpZ zExrD4!To0N0t5IBG^`6qNK-a28KAFnMQs#m~fK*i3dRmcFa0(&i8|Lo)j3QsZZlCc{?#nJ*lPD_|loR%R%M9~z7C&n=CgrKpie%=Ee3 z@L32Nc@Xjq$b|ya=VIgMxao6iBl1qB&s~h4hnYSPH-7GJ`rOm_xxMLgN8{%};pV0UjYdp@6(|ux03~i}ZWAvyU4_bT+D8;vdulNoK7vBXfiQWz7MV{UJYxD*TR#+I-|8UGtBpDwJ3aDAsCQh%?{ZZ$yf3YPEni^UVWVZbRmq2akh#NE>2izFDWa z*-UoVXU%!I+~hP$DiL@C-Dm(7=)-i=zs>?F84Ger4X7pK3@A3!Ejo&`^^H9IJdb`j zw1_37*3q@8lSh_htgZax-Fy5o`IxGcS zgVeF6yiV$rxlc!n-Ab+mOUVLomn=dSuWpRp@)$K7p-Ah~REFvkkl`d1xlZc*&tz@} zYsoF(DY*?oC3iNG37N@kr#m2Z+(42{UOrg~c8-}#)MZnWDk{9IDVi-=1*Bv(YP&Z3 z81E6<0I9_04))HlaMI8d6J~WaH<*INgq3&Xb+8O zPc!6B1LQ8cTZfG6#^{bk>!n`R4N~u#cofxqf@!s( zsV2Y|n~-sc8SnxF;7j!7;{huy)f{lB8PKrvg&v@<9uGLICR8U4 zHv_IQ0lwA*;7Mk{ttPin!6xK?myC!OttO^8rB#ocGA zc9yDiDq`jliVNK7lre1@sQDP6&Bubf`8e=29}oG>CqPm2Q&Q7F!x=wW%fX0o0{$cV z@$p)l$hCHwS@v^GfS)u0c)A(zG85pZO#n_Z172?e{HzJU$!5UiCcw{|06fDC_>ckc z3;N~pedw85A3DVhxx)ncRYu3H#e_*ntk9`u(C1B{UpGZ`ni=vP6XZ8d5}j@a{mumX zZBs;Nm?4jtAiryp=vgMv7A_O$_e~Ks|Ab?ULKEZ&ox8#FhKr9 ze?Fe*%$jI9f}Upv9cBXkrAg3PX3$9{&|jMbooxm^-vs(wlc45l_ZHWfK!0x%bgmin zZo^#4AM{VdcuSy%=wGHG(_K3GlS2gPa!i z5Ny$qeJ+1HJ))BusfWjUA$7GzH`8Tu( z(%LOuXeReQlKT+JeT3vbMslBJCC7lJw!n_lwb-&rat+c&HBn(VOsSJD-Ys2XruZvT z{2eL&ffWBliifjP6q%GBrzUfxx<;#FJEThm*ezXFT^?TxEy}kE3*&ssi=S7S6W<1x z?gbyec%^w-Hh}pYcCCAi*g=dqz!q_(HclSlzbkCVe^PJ5V4cawpS)|%gozm0CaJ}H zVTitXzb@+$Rk6KL%9kl?DzzVn55?-G`OC7DOD{5B-nhtE<(00`wy|r!mB=Rq%ai9V z$Gp;&n%q`?#CEq@a0lhMeiXBeFZibQ0={Wo%Lnjf>|#$Q1Mm#H8n_mg0zX=4xpqw| zZX8w~L|TCyX#MUj)>+Q?{F5*Y(a@wyVP4@Ji5Yrf21n*NPYMwZ#D(;M22``Llf^n_1B zUqk7i{DmF;XNkhGZQ^8pbRs{KFqV)O@I1mP<(2xGguIBGAFNo#zwy^UYG;-=PPJ+K z^dpmjM9u_DWGV_g9R)rM@*?LzLF8O$7MTStBD0|^G8f{J3!rV}B2>b~P!YKVx<@XB zUXgjwFLH&RnMbrO$Qg$a8m2-RV<~A&Te#OWIkz6U5v-9V;ELRofk|d6v;6DHp~yX0 zmG^=gSz%zt%Jf~lf|8tyhC5- zpEsI*kN^$dRj?-Yb)9*;CX97ESEfI&H*E@xm1Bf@bz@zf1U{5zJ+|hD!57&K;mB5K z8QBi4BME31*@5-Z00SdCp*r#y439hx<04PMnUSa9tjJzCH}VWz6nPE}^98sr@*>-R+eF;!yM@ZpBcIV$75Nv z>u=O@}uyaw1=2RepmC_!e8__fQo15smXFD2@Dzt@HQP1e`6;Ac!-~!oRSU zV<4AeAX{qaSec8tGjzdHx@i2-awC>fCy-JXSWAuO?_u5yEJ_Ls) zEX4*aKIYHBLQ_~8Gt*62;)tacVliZ&vH%PICoJ6&OAo}-(}X4Ozt~9WAjC2lu?#U_ z39;0Ezw`A4(ysB{(zO+`yc1{z!FGW7r0e*f>-nD>f`nggOh`+Dgr5#%3(EW^A>Cxk zKq(y!v~(=kO2(vRF+-`qe^ek1SsKo z(4#<2W)3k{%z&aSjFsSD^tE9ClU&Upm1>vVs(dN-t3n0wN_WMzsKV}*md2BPDvDEq z@kBSTv@HE*Ie*jAE8U%ba}R%$6UTw|y_)4nD|SmO6ViRyT_@{o6|Y8YC40dYq$vGr z)D;$66Qrge2`ya?Qt90&|2>dbx&lf{S3-H|ebAwF74$4!4FgK=hpN(A7+3lrOeuW` z&MI9Gvr0F>MWqkx$6#PMnx`qCIdi+c{6`O1=2_@PtObi?n5vpG)y7|6F`4S)XsUbA zRG%wKXu(k#+j_dg_XLsz5z;%gmu;omm$h#da*k{on~g6~+eZ>ZSDwX+uJ|uBsMV zS0_8UAB^3+{`N;xQm+0{TtQC;D0_U-K3O^_~ZgKP-q$nVab-DnXO*cwPhQ6vdgz!(q^75Nd7Ut6mP z7Hmb@o_gAH%CYMRPRb2Ac&wDEA{Q~=lvg^$ ztj-W4%9)tWYAdL=ycvtiOMaD^u}|eKoi!j@oqL)`Oo<(h*$0NoGnq%kR3>5u6ETYk zn2pldT=a^~V-Y!Hd2$OH^BLU*h#2?b661dKG#)^2V=>5Bl3ViZE#+_*ORkmIo%eWR zJPNuB z?O`?P@AM42##88HY(SZ@$@7})J^P9zm9mYn%d=_HXhgth@^JY23o$#5{Vc@;taPus z5Ev;d&tFc5SWbtTp+`I*s?K|*!g!xSe83=%yFgT52o|Rp#Aycci3`Lid4uE024E-u zo1|50Rdx_XM7&@H<5Uy#c6VjM%HqdPZh0nDqQAWkA|6?r@k8r9ZmKtq!rW}dP?REW z#ZZ)@nqL{m4OW?F)ERB?5u-_LSdbqP3Lr`nrBsYKg^-{^45W@2Mqk4S3Zs&W7|UWz zpb|?{2dh|}xIMJWZ)d`F&Z1Q6omI4syW;-@>}c{vIojdQL4Kwf-5e3Wagrm()4s-( z-+Vr)w~F7^7U|*Ov~6OKW!x9ZBE1g1q5-o=vc0~yMm_M~QHR24Ak1UM?`oDxt)cBm z)bCdV@QW?tC4s2FMZBybC5cCCvAa4dEq<$SPs3E*KE?6Dwy}IJ&vT0vMqn`w!uKhKA5%G2(h#hnp{S#)QO|X0vJYroj$j+lGC^x% z=x(_lEQ9fEON>!F0M96?^;2h2xT+o5U24hB*KYNkHlD6R-U>^mK)a3HBsw+_oOW3y9{TadgmEa>$-4?t{0ro`1E4I9S zjnxUilB}%@2|cG530p0K#Eyd4T@?*xl4({X9Hkg&P4Mj~MgGB(J5wP$0jH%BA!Q{B zo+8#@6LUb72bt4a?Or(e>uA#avWQUh%}PXhcKoNN{Q*+)O1 zvL9LbO}CnMdedrCw@U8offn&9|D&7IeiAT)E#mh+B&8X4>VmD}U~MAmXW#v`R45vV zh}SKbw=5cp>P0ddWRLfaQ~^cxXhB;1fzhhQpTU0GnsFS*>L-%+QPpWV2@-5=Ol%7zV#z!yptGwQMd(*7*rbxw&K8{YbiU-=& z+~e24q_yZz>rhU0-0Rn43_ZajeiC=n1}vbB+~YUlhx9ZarDyO9+KlyVB5kB5?(J#p zpl0l%7Q9H$;SJi3W3&Uu`TrBN(-QG;1kSR6<+wJsI18-Kd4}(t@7l_A?5J5j`FPcT z`#DCk`UzD0L;*`$JA)p1GQHIQLc0gfm3jPI+Q(XROS^$MDD&74beKWB&FV5Cb5gUm z!U;NiS&a`7@wS~Mw<>OD$&IT;0ySeM93@(yG23lDQX}_XgxOSohda88yy{t#&^=X0 zb5#LP)w{VW>8bj2wyL4+5hu;AJyrM4Ow}c+fU6=iB?qk4j1Z%$6k;>BBBvPNV@nqF z5%>R(x&NQwDdAt}NT0C<{5dY6f1@w`2SjIa1^pL;=nGt9s&g_lj5d9^)eK;|DKX0o z;(oILOU*(oGdo~~c@b8cVXQJcVZGTI4Q2$J`996}+xdPM-@jybv6O^R_=R-@rINhf zk)1cb78jpEu`g7ai;N6;LL=owIVroKoEK8#J-g5B2HkX>dM9s{li@o@g)Z|fubMqv zjc#l2EKCgb=$&c08r?4MKqh?C4qa2>n-y00W?CF;7VkA#Vciv;osH%INHdAf=Ad@N zH|3PKVwr$(?UE8*;q>@y{NzL25ey6AV z^ce%;(jL1SrlW9-iOVAch6Yo~b3enV{ee5Pii%{Bp`v|Y&Yb2`Z9XRr(gLiz> z6k(B9v1gITg&2>7j+v-IRlq!9>OYdEyQvAYywRX=d%~@ssJkiB`G%L50tSHs004jh zC=OlBJVs4IyS9PHh1B82s- ztMG1vM%U4cxG-{(SL9EBo?B&qz&n7OPl}1`Co~NT>gjf`>&wmdm(5PUpNG+0fEM{k zBe-A;Bnqlk#oL^K7gTF%_cDF*7%_JoF}%)*YYPgC*I$ID5*9itw6liderp_!bTotY zn>BYuE@bQ5ctVex9o7)3{!8IaV)Nvfdtpv{o+VeFf*mPFo@&7T2x{MhyF*!9_s_LF z0!0^3WL@)(hb(@UoWu%l-1`Xz@f_XjHj@{Vee7~Q<1hZicB=1z)D~`DIqfPGmuYfE zORhm0t~d|s9-+te7*HOBTx3F)6-6cFHmy>m!!P`m>=mZXQ&vgB#W!%gli9{hk?@#A zpKaRtw9g`8!eGfd4LTcz+0B=*SW9Q)ye1H8@3;y2`39Z)iE|!O;p=$kKz&jq#~gKp1$yS zWl>0Nkspv#Muh$(XvpG};?(MjbyWm`BCz=6@*}=LsLIIdgV-?GKKykK%NEViF-`PA zEHPPoPNlM6ja#x?yjRR5KYAP{&IC4%Jm(o&@Y4f@Tl)uF`z;>IM~i8O@gYO}0uE8f zrO`i!&Eo2;(2`m^B|w>Qmx}t#{yK1% zlKOh^mlbv^Nw<7j%3zz~X63SA1?a>73$XdPi`ks))V5SO0x5Oi*$^UuaH zhTBGXdE0rq8NH%OQ<{9mtl2xTzEJPXD(8B2Uny;o@X8Wic?NjGG4zIbRb%bn6 zQJJrE3h|{#kmfJsGpJ;Y(rgd=coG+j^B-5@8t@-9qxYa>_8=S{a|gkHUPk)?{=Hf& z{#>m>3%_C!zyJWo|9nOM|Etx+@vpTSt*T>>tb+1wo9LQZS1hv*KnW`F$9!H>w0z!C zsSOm8O#WjC5r_o)_&l98yGbWyblB%uEDs0VJ_QpOOpLmisWJ*wA@f*ZU<`B5>v>}j z$3bHZDvw)ck|K11#7y@K_esu=(+2*HuMhMe5Vf5OflqYSe?&q%&7G6Y9~04B3Uae` z)IrWdHfY3!5zI=t_eW!fMF@q)trNv)4c92?Z-AU7^lg<1OZRPTosPiezl*TD8m3}b zBBCF=O1Vo6;DvCi=B}5+FAZ#(`>uEJbG;v$$O7-itQi-@=imC$6i%22)O&XZljm6v9jp%qd5Tp6;2 z6E3`Ob7!9=b~#IzUlz4m{)Id7>*`k!9#wL-fry}@pd?VbgB^}+IdF=ogCqg{q$2#W zmu}v3JSM$P=KRB5rw5r;$)Zd~Sj#bC4jnpWYCQ@dq?gH~VNaAt0L|b6(|caL7t^x= z{~NWCSTBrFToeH?N1r@nvpJJA%tT#~Fd8MM5C?@3h6N_4e|MB`M>2dsMn#QIeM1ob z05ua_q;eP40YuCMN5}z^ZlVJaxk=W51*V)n;NXA-lDzq>V9qDJ4APNdVmYa1V|Tc` zQGu_E(qKkONOJhhGe)zy5b$8Zj{-j9vnfVE><%o9$Q_%&K!811ZZ;Dl*A7}X1&7e- zor`O^q-SORNtwR|2WV9>9#erVHTxg9ePeZ@Nfcid#TlR)A;ovE&bX|shUe8xw48kI zh>ASYSi~q16&v3qEP+i}5jhyGstFSr3dx3!lqKbdWkXOxCf@Twb~4vWN@(S@b1H=^ z=Z)YgEFHlka3-rgv{narK_4hiaUGp%%}^Tv(dryTV3UQYo6=U4!xIoKePlBper8B$ z%{E7X`8Bj=&SixF6;mq&Bs-PzbhQ|SAMN)o&XuXa4~76coU!vil-1_*+~wzClm z>1AK0!{Q5@&rFN5n74wu57G8|z$Ui+EH23DvQ&ZRq6<^j}ku1Snkru z@$08e)sijL&z2o{jF;@RqAz8~jlj)`0kKc%>4E#jRwF>~Mv6kQjfuXGZ3xw9iPDw$ z&=w}{3C|+x!Y9M(Ob)(K!%g!W!s4`7st6JQAg5by+jcg{Njoc@aU|IW+PumD+H{nVa1OT@@*T>c+SYL{=RgG^@Vc>4-l9up>2oej}g@y zCy-ksFz;+C@6>b>&iV6u4+%@@Jy2$|6cZL!8zjxVF}ArY zoSSK8A6<4f^!D9DPagDtP+=iKyyT<^@hOp#>nOg z#q))r;)lt`?`PnTF#6<}xkqjrliO$F51xI){2baDqW`4vE%xetXuSjHkL`T}-8{Ns zM*sP>bQ@_+*gGWn$z-*M&pg9#;PqNcGsthm>6?SQr?%$co88?nw#Mlj*ge=QfcxeK zmcytlRfa!^#1=yI48P0>3H$OpgbI=na+XQ74+@f+l%?Sgete?|Pz0z;?CXnT01n$Z z=_~x6$iNCl0O`5}T-DH-i@aN$dtNFz22#@BlH41ob|K0GAeiB67P6?xB4#tp2 z3qg28t-Oy*#HpL`%DRch3;jPg6%?Js_Dnzk0Cpe%0J{I(RD|s8JuGa^{;{|CD9BhT z383({zQvR;sa95(pVF28P6as^(+Xm#mxsW*H$<}yk=RBkmEN%;PyEF%rA&Y9qyk&*(o1SQ1vW(CTe_|XjV}&e$G5V9(YO^wA*=%VDgoZc|Ws7uMO)J?@Ux#2hHiDBe zSVu3k$+WdNZrf*Pa!25P3;aq5QoBDKsCKtzlOa?-V~~^jHv8~tnp5k?=Lh&(P(}>S zO*LLbLr7#$CnR(;E2m4X|IlVgD|$rfTaz;frHhsnpJWXaKP+9|Y0oL-X*-_T4dyHe zc`!y9LDm)XaR$3`=YKO}~lGSMmUx0$=fjf@h-!I&HGpjy8+#X(eK?NE4Oke!$; zNsI`_m1YX-b<}jdP4NZ8nf(1}G{{E2ry%3vxmId24|fTA^`(cSf7!-@x`!dZ_^*l| z^LL83WFpBnO<_FH5b#vxo5?k9i}pDInj_A!V?XDUjPo8SckZ0qW#n!5mId#g1@Ebk zEyC!^wINdYNXhw(E+&?SM~Hi7^5UJxuB*bNXUyH4y%V0Ya%Yon22 zB1l3~3&~@0lSSeqVqSR_n-7S8KP;?-pUOlmn`LoDwWf&5QYe*5wK65GMc~KQT75TI zVS#3j*G>D&6z56KP3Or>kJCf+1;Fw_K#12|jRB`2Rc4#@^SEhm7B_(ye*ClmXsB}8 zY21L=(K;~}Ur11h&1sTTiFJoE$sDa%3OojOV&Nc^=b>{giXs*aj)J}NOcCoNVW9zJ z1JpY!PGB`5xY!^N3?#@=z4qO5*M>5e5_i#p~+Ih|Q=I$m8tx~-LbUJ_GidC{4%jh!voN!jMXqbD*K zxhC!Cqp(Gx!C3u0mq&a3O4I03a`=e#Ph9r-nG4dzO3hZ1dE>P4y5wT%Lbxkurc{#_ z=Omx43pt2sGY(^HCaVSWf)cXRrE-Z`lmUy&^^UL;CTk6zAHM~K?N>t$pM z=#3XvoAz2wi^Tr$Zra8kT}qt96mJ=O_8cpVRB}VXG`rx|C(NLM%29BX?PyW zFWfm~E!P7jb5$5C(Po0z>5P&eo+iE~{c#v$v16q5Rbt~JSEM(J`L@p7;DKg_>a96y zcB_G#J9y%V2bSA%E3*<;Pe3izYer1%0jk9fjsd;=Mt5y< ze!C7`)=E9vMaj-1?mVSDU-bQ<>F0HnLa7K9AtV>A3w1 zX<^uvO?n<#>=#QHBE@;wc!>fVY|XsQA%Pb(bKip%nTC>K%AgS8+CZRpsu`tUg0od! z9a(w11FZj%n~|74pOm`tGCB9SeHRg%u1b`$!1!b;vzsqxEGV>a2)3DE1{eu7*?r@} zlyl-ckK2;Ul2QOh>v1rng}(z$4wcMGTmoUTc=B?bMDL zUUG4`OZ5>PP4RNUnZ2cc4(C{VSld$HmN8E!eY)0-ja1^tmASrl7Y90195+|IKe%zx zM}6AMZFiToGapUx{dWA)@2kpgzWpcaZr|jU+UIvxUA=?n2NOgC{A05*E?vVH2kju( zB=!PV!R;V`kLkAD1Fjf60R%z|W=B+_hK9u#v2Sbvq4t1+u>izZB2j&i@31|50RlyX z*I`r;`i|B^v=-?6Hve}_ZA{?I(LA*ICC3hJ5q7Qi^U`a!XPP^Y(tUx~O@^A3-XQrR zZxG2tChywzOb`Fq*=Bf}1LQ;IzEY(L#Pi_o5Kqi?hzM#5)ZU2pcpQb^g@XjgSTq0+$Oh4K;EC-#BJn?1&(%ut0piEY zinhJDja$)g?X0Lz!n=f$@J8U8b?DU`zqUAnIOaLR2%UFP9==#w9l^-x3+cK7Y_bf2n4rqKomTWIM;zXA2kL-Wr4`gLlntEd_Yf@8Mi{t=oT`D9F2U<{W>1-I9~3(h8ruolTgy~Je_Wyp zF?^-h?_^nXhkQDT@b&pF>gq%9}W~Aa{gN=iE5Q{;>7n?I)2_MnWV>9L4h~s5jI5z)c4?O zGI%eA;HtXJ(DM)SCpPFVzZ%4Mz_Q}emI6%`bWEZ?Qq`-oes%Jzbs8AWPq+dN*B{kZ z>h=s(!GUV^uV{<9*dvr@&f_4=f_xSdTvn6ZN~783^J^3K;!Hx!EL_wnK-s7tFw-U> zp0HAIA(6F)7XJ9jzPh;saI94wm-5hScQh#tUy#MQ3Ai^2xcubYz5;!|GOnK?;2*7@ zOHX)y&R;Q?ue|Wjxnt@4iPV1mocljMpSXqEy)k~fVuu5D$zg2llq*E0< z0wdxWHWdkn@bbD6!G1C(@?oeI(Zn9;H1?5n2neZl)(s=zM@`s~**qyRX222L*jrSU>6x{XW@5U;gDE66~2+Z0y1fdX`_E!bVb` zh<4{=#H^jfIKDlQ4yKTu#;ox;HEWYK7G_6{X>K<(Mf}mJ8SK`+a1t_7r^vPP(P4Pz zs#M+q*DXjX7-|lj>d6D}=cvB&5c)B)JDXfb|2D1VjEN*+ zMLC6wR5#zoKBPFo;$fv*HJh8Y+ZJ(u1053%<2W$@-S)GRBS%`NlCy57ZUj z=KH{lZ-?LgSeMMOf^*h{yua^Xi6uF%~WMK?@0mmbrEL3G6o@| zpW}IrgN?{@6LdRvfgu-Q z37Cq7&4-4M2r1boX+~BE2moO4e+=@UW%wTrvX&LH0Lr(l zlb%xL(|U$#Fdqr(CdqC!tsos*Q1P)T-aC_YgHRUJR&}C85x^h@@|3%*`2p!t4JD2}a1TQoPRu|w;xXdpJoSYdKL?pDv|nQ+tYZ|SajN6RF0 zOkyxdE_7g4HP>=M0d;uUL&bMdQD(o>sunIW`9xKqT#90m3*imKoQzQ@@FmCW3)myj+$y15 z{nWjdml`f))li|bTrL$vFC3ILQI+b{d5R-wEt6w~f0T`s_whrLEAcmZmRIdCKfIU{ z@RM9Q;oIN_PawI{<+sdczlW-FHfc7YG0%BZozK2t(LZC!3DQiGS}yJni~G{?EAE)<0bc z{~U+0K>`4f{Ab*MCjHOmCtB4;30V!rm+eLa4e}H%K2KF4F%QIAzylFhBCdH)1gS8% z#h|f0WOy2k9Xsed=sV!OIGbzXY{j)=@yvNWHv5d+Prmedla$0DBfWu}(`$CkY4%~$ zX{I}~_xtV14S>C#x&Xgb#QPT|T}gWyq#>GH087TfKAqZ4xVU~!r39U#c2WC7K-h;m z3S!`Z4Sd^cP$Uex6j4h3fLNt3&!dsdA1{jg5@g-p{H^NhvixWS6vk4j(;3wnuDYz} zQ?Rc)xK7&RMPp$vK%!9N=QBOUsjZg-)AjXQ!KhM8FskAhq6X1gR>7>QM$2^6s34Cf zElWDAwq>TAInA_NG_w#0C-{`<%7n>d#lT}wx5vv!<1C08Cm0C3nM*QTImC71CFeo0 zcBv7XUB+jfQxW(?rZ!8asHW@8lByc9$Dr;BOGwDS6X#@Fv};k)la(UDG=?5?MqI74 zmruoH|M)aESV8qQ@i?_*vYJg<#3e6C92W!f`^$j*f>}8f|IhC>H z!g0fFbPJw@uq;HrFf;B(RGpBV%b>ipS>uU0-oXdw`Z8cU?F0xv(AZm&ZxYM|)CTfz z6OJ>k`KAhm+B8@ht_cEuK!~#H@@K0>kVWPSlkyKN+!`Rmc($qJeKy8i1+KItb3F7j z>zh)eg~&!{_}_OPF)Zj{640$@LXSn=(g%PUPWcu;agS1Mn~R~8NT*5dk_T2S9l-co zEY#1?L960r{EN&aUhumS<2iNq055Vg>9~Yz;IYWtLc4@O{8GOZ8r)BPrXacIA>LU# zPQm7@^BjLq2Zp>43N?s5Pw=hLgC7zQx{K-#a#K$1vqJ>y5m7|$sojq6XQy>a^c^9z z1p$mtg184mXp>@+jv-1Pa8(Qm2e`27<(BYM2)8p2`_UQFrRoNKa zk^Nu4*p>I1A}9d+>eZN8yv%kQ|gBh3e#KKa5r!iOga$% zJ(Ru**dcVUm8IF^@GEDO{d?E-Js6CgTzki`DgQZvOKg_!-38XxM%FXL7y1^X)FjsJ zp~LHxc1HWBe%yVre1pgWKJ1Q3)+qSAOL97q-1H(XkA9BFClKuvIjL|K-V873!Y=FK zps<|n9?)BQCP2tHEa&qcieJd~DRGuDRYI2Qwe|a7c9HvBjTO8=0014p002b)`HB6v znQp@tNdZNtR2%G6o=$}t&AfY1xqaBmMw()^2(o_jGLSyepEG{}1{f0z#_xb!J=xs* z7Wk7e*LpKlF$(r-@RHXoyP5vt^6TPpR1N?X<#V;KgrODq_8^Q+###T8cSgl*8X*v!f%(Jb~!mAi6dBy3}?aZ(LNt0Heh^khr{ zx_#5>NncVmvZQ<&luQ1?yYC8dMJ2@iNFCckL#dH#EyPF(RT6R4r&W)#^2qQ3R;X^V z5iG`(Gc<$qkdFc;$Fy6$fckk`B%yDYjb_k5yrkxo#z(wMQSJmLKf>Uyb$9@+Lr;sftLGM|%#r?WM zw4CyG^o_UFjki+E=FK9&qX(FJsph#v&I3M516Z(fR@b(1TCOW*6f_VWqShJKuRf+x z<#05~KGBbTO@lhk)Y5vz#hOoFLhsNQJ!j=d zHK%@^ujr!;@cayxD`%e+LIGXlTME6sHx~E@s5&yG!aI-pp(JtTXVCd^P|F}|!wUL0 z^uLR*{LkY1SeY~300jU*gaH7c`mf>>va_+Vv;CJ9=ij<~3W+rYG({W5{l1hBBp^&) zKtOW{K?a&PAqD87Go+R}4EClq!h7)oe6}ms7jTPG>49^J-W5v!T#Vkv8U88#pHI^Q ze9LotW>649JSFpHs?#jzpAYYet?$>%8Z^Mx>sTmQkoRgRAY;%lgSvktM#b)V!o`7F zt#0^|i37sjo=z8e%b=i15s;d_$_Oidg~L{;g77c{*+B?=a~q}fh)LH?V8q3MrQk?W z6eXlhy}hHuFq7%YrMjD$ncZbY@i4L{O_KPKXfO*Z_L5RZbJ6S&$s*jWm6Rq!etKhn znGNQ#buY+HU-a0mzBL1jtAd~khee6?bd#NBc+>STEo4spoP3(td{Jb$px_(lAj{lbB|!<#-!$euibf@+JetVlyb@2b*)WF@qsp$<-7j z=eEceb_pW666cj>#DEjlL!ApXc@?!YV}%uShsXt11sq0+Y4zcwaF|-@$x~Z5=}=Uf zs@Uh+=X^^%L_*Yeg5`im$g~VxV^--kX@D^;Z30E`?~t{QP-g6)fMgWC%ay<{0Vj#$8Kqy z)ljkqH@eoR$0=81MUgZM;93vK^6P^%znd(^m<;nDt*bi8mpw{qFRb-e&Q_cI8C~tv z(A(V#klW@i2C=gV@~tg@P4^6{hRH@S)r_Nd=R|0Yu-Fw0_s)?PQ~%s%Zb`|bH60NO z$xR7I$DS%j$QRK!hRM(}wls*xTc*8Tg|+ZhWi~$JPzx_I)`oAL7(j+6X+j}p3*s)J zzkwlg9+Bv>UTrG4)ev5MDFKsmCD6uCgt{A(^VCZpNGuqSbN?|awWgh^C4uQci?}Uc zv^IxJX}W25=unpQ(eLkF@fCn_JYvOh3$`@HJRP0w1<&a|anF}TMigQ4~&j#!Lq+<=p2B-#WzE6{%e!DTTue=pxS7o)2G)GlhG==aWC=fCagtlp>k)2C|8jwGwXyYXZo!{XAuPcS1{5 z$U7KrK&*^w;I-Z9p=#+4b?p5eB)M##=k&G0*_*Z8c1b9-;ar7UIagC+^twgG-4jK{ zBaCb53xH2WVJnuPQZkl%cfu%@bCp)s8_=+oF#vh!LYThecWffW0ZVb7=$h1{WQ~mf zozEl~+sxYZoBRQ=J8-m|JYHFHZr{cuLT3h0fegc-1VvL# zKW+og!7SW#zoM{fMAS^`tz;%c=PNQrphqT?zeg8BV!29`FLrqu6sB`sF*h6t=-SjW z3J|1KDTGHsmfHZK|3li-Kd4B+vmU-nx`a28>(Cx9T~_Lq<{&T#oWC!Y>C#DAS{mQ< zIfvD1dfRGtR|ktpsHo|NV=m3X2f6_4?9uo|i8kjroTiN6; zDem0uLZ+vn5u_DJ@cj?)bzc&amPug2229V0y3J*Ou5?|P~AS@CE6!yf~#ZhK47 zb8#{EJGaGpt1J@&! z!z@}B=Uqx6ch=CQww7~#&ATykh1?jCtLn0@ol4);%Ik;))!b3F>iefpO~0k_F@*f4 ztsFI4va3{Z_Zh#WeFIYYFdF-oa2heemrzmlkDDhWGuWL(QYpOIrijT12e@;t4+;nfhDQa3=!T-hTBN+2c{F(E> zpE;BLSI++$hr7h<*dYm^gzWeS+o;uPRznFY9>7+ILzDP6M}whdS_@jf#YG}9!*wEW zc5IOj(vA3;90Z4>e*^d>-Cd%!o7>YJdv`m{Ff;f5e13xFg;xN=!n4JTNQh~S3Wbnw zLYe6$vwxx7nRb5%^ePS9k=niS-H@+w-b}VDL!UW@TwS-TLoA^8FX9MKK$nEVh<KxG)G1YR&C1*jBZV8YOc@PGk{%*N)@Uo5u zckP%-fD{S67O%58Cr1@(ZfUJKQc1UMayWdI5;j5@nTQ|N1yX*S{ardUt1dHzwj$6-PyR1jnkIF&u@Q zxrV?>0xTHYw(aD{#>BRhiEVpgJ3pS-wllG9V`Ezrt`F-y^r8D&^7q_oIjvo6Ei( zlCLPRC5{1}93_c-f}-g8A;*B|bv~o(ftg}qaI6Vnx5K-zvv~SYWgBCLU{>PE-MK#T z?C0~8z4dXPYv>Qo5_Bza($9g+i)w71ltIgtVP$Tf4hy*Nz+XYV-9_vgo2-I%Nw+W$ z1eNQkkHELxL<1;?q22FNr3&EmGA=)1*>p~sgpO1|Q{S{eGkS(|{F><4=fAo^;dvM- zeRzn=FIt{@8J(RSdI=(xsUScuxAu)}Hs6zVmf&nTG|d*cYt@W4G>+5dR3a5uL-hrwfPus!AN(RY9kP`^+`D!bof<6T8)t@c09> z=^Y!TFM-I)ML`aG(M`rRB|08GvH zb{679>b{M>S6JdlBtyI%=(D3?FA~v>r(*Bhi*RrFq;E((q;F6-zaZuft|0aesOb?J;!j}kW%yI% zha{N>!0x z2s;Jrq4oTB^)!YU{qMIk`EM|+HI^l|mIXTL{pZ>)DsxE~KQr{DF?1zS4b~>i3Td_} z^cQHb7-t?dzzph9d` zyyznZWOfy7fzPkVe1fa_$qX;8-4MxYrj(6pMVf4;&T>|&ZAn+gdW00M1exjGL&=5d zbOPbyObCVL0+Q<(NK;_~p;R7nUK%AxOrl7#2R$lByq5|2JJBWL(s7p3qV*a&&3MJ5 zWI&&U1?`q?<0C!nW(qj4?#fhCtF=pa zmZ2+Y{hX7@Q=6y?3HI~7h&ld@EtKM8N86wLeKqKKdbJn4!ChoK$0SA7AhK*i^IIzN z)E{RQ;W~H9+?5r-C#uH6G<^jS2srFDsNYiOwOyuWeJ4kJlbH1A;mQwG#(`zs&( z@C1gg0XIr(@Ip&(W$utnuX9zs@Q#80wO31geoH)RkiH5d!bowY%kY%KEvO0&m!^Dw zpq$4lI4#AZeni&F3x=H4Eh{EQ*#v)VCq!7R^l*L6{$-szG4f{Zd!?a>H2tG67)Yr$ zRYv6#miO^(NwV2Lo6?hSYYl9RDiKyK?z+&X+Ar=5TuM9FM#v4@v*9?xJf(~|DP`gt zm&o&>ddwd(nC&^#@(+%nwHX&Q-uPO)i|&IH`&;Yr#Y7=)T- z!{%-}-NGEt0N$Kb`Pak?^$EV(5BPtSidk-^LUu3^kU?+|5UT$w75`Yo(pAJ0!T6M5 zf^UNbP;s2(_^cPW zx({0+-mrIAac8^&R5kJMT=41%)br{u-Cd$SFHOv>AmE4ncyqtzX0Zm2!|#(o;Jb~m zvKtZN;1N3p3^E3juJE!-mYk*AD=vZO79>P3UcG&2ELbjYIN;7B&JaSB;1gs_Cs60H z46f^Rix^&rg^YuV`Hr|>?jnj6sReYU=91SY0WSAz*cjxaM`m{u7wpD%19{VjErxK-u3LV>V698WhtR^FEHCT|0Cc{F=oUo+zD&IJX-0rjm0t6J<=o zT1>ygOjJ~r(ZhKZk5WlL(nbh`Ff%0i`2metjxlhj5%5pOMEiOUE*BI8#PCntWBjkY z`#0vqO<7+NT?9iQ&7WBu0}}!sO)SB9uSNa_JVM%vlGQ53bw%)oEyI0;*L2OUWP|Gc zPv&G8+W&`8l%s`+Z#iZ#}LAi`pOi|1j<2zsH!d|9uoX~DF5N>{@a&{PNQOW6R%9F}umn zz^Gec^*x}w2e-kUrGHq#0_r);Rq4_w*#Wp;Y*uG3Y2<(@-V%cL=HkemBl(-jU>CX* zRN|^p(@fS@wo^!?vxntbpu0CXW$^eWhy2_w|HRH^y_j#!n-0wR0X!ohsVh_<>)uG` za*pF4k?!nrN}l->(&K+Zn(n_M{jc_9#(qHA zLAVqas#^V6K2H^a4{VJd-#T~VtA-ju0{0CFKZfx|36I((k^ARGE1+lX%g2}Ag%Afr+;JWNcU5`!+@p@HOx1`+`^Z{T$Cwf2AA`#^s0YJ zj4SiRoh;bWxi`=4m(B;%HQuyjSOczP<6vx3KK}F&o;3ob#rJgAL4~_-pkaGPD3D{& zVZJ67qj~A|%s8B{A{2r%GsB|1SKLK0Y)E9ee<+)a2he;h68m&82ZtuSQXbc1sA|IP zC~SVqj-=tKW3XAo%^=?xUzT3aznF{p%bYITB0e7%u#3MWav7=HF|us!R?oWtyGXcM zH}jW_VQ~oCRjQJ3;va?(m!S8uTm*|@2X3NF-rU!KMa#*cTu12J+xt@ z5y2nduJ$q?&@bcJ-bcRvX#QZ!ILA^NfN zA*j_LpvBfHD28`&q{c#Jby#L;I6}UQp-WYa-}Oa|CXtV2%m&P-DU|k*$OTR|0sJP# zK2`a)$np8G*E4b5n|-F&COibI->!WDt2rXjY zJoMYLz+C4c|E@N{yX3dRaQ(V|@bY3;{YyNnmBH?(kAU4zuSvf#nam&e?E)XgIrXlc z*<)`tR%x^$O?CN4Sj|Jf`&A&az&ha0@7E~lT%)m}K=ZX1I6r(+7}gY&tqr#D^0|$d zX<0!9coxhnn`IK)A-gRTC3U>b>M9)2pp1N}Nfr!N8G&DiUMDVHd1fQ}i++CFEa}Iv zZ3${iiW~c#GfF7?zoQK74&qZYa;w{O_Mu88&PuzmHNx^LwEc5_1C02Q_ND!<2lj{n zCo(BV+azLJ@*ooCh?Rj#7D?18cM4M+s|{m~j~v0v^lqE@{9!TYZR95K8*KI@Q5=k!CB4M>b}5cd4BI7T$YT4}&Q! zEm|Zc3UVkp@|*YZ&hiQ{C#wc1j=#TXMKJd3TBl?=h;JH>L-;2FdW}+=?B5ox>dsxE z#x8&}db+J}Z|du{>FyJHR^96=PCFLV5+Ui0!ko&D(GdeaQQp<_lmqp4dy2ESj|*pp z8(YtEVyz8Rv4hQjXyJs5sBQeoI}(fsH|4{mvk%1P`V-t)}!! z>@hCdZaN_FFkSKtkxXn(wi|S^@<4LeV&i)95Hun3R4GET z2l{sO11YC{m_G!AM5ux2r5|t;<_cqQ%>~n*U1EWHg{vqmz$vbxUcQlV#5PKtc^vE) zFROr$L{urgpO6-@*2K?s%joz=)9VrL$z^^91gf-7{}T7uKXuDYIF%+QPpu*5Uy+Wx z56F9lB}|-mxLIq$!5$)~IprQ}EPp^fXnW~c8>TQ#dOjs0MscTK9K_qQA%drwMUIvC z_Lc(#WJ$cMs@)(k`N4bIY@vMi>)~(>yxavNmBIvjhl>^QNriic`_*P?Vvr%evNtJ+ zJ7y`N2dM`4(Iu+CAYvm4@*X61;V%k)Apc`l1a~+ZBY*?}S^Lu`s{fG{)m^P@|C$l2 zH8xz()d@Zo8pc{CROWT65dT1zRuo!-UBjp(qe_8BLt({wQ`abubh&JX&Y1=FT88{< z>}5BaH*bG5W&s*Q@(dBz(Dh+T(&8PQpmrv%@N?Q-Ix9V9@?;>V@pxnB@@@J$``}zi z=oj*L6l@GvBdy_xm;pGV5mZ(J_1%H87!x?tn5d!jn0+{mdK^hn5o9Wzv6~PrK}tP^ zC{o(6(ji9~2^pO1R40jHir|VY^Nz`%7msMnfEQ*1IkpGu{h@icjr5-`O?{uA;Oj-z z$MQ9?86~M$mfEuSY^~UyA|@wNQ|IvBn~T+Jp2PKsHtr!JJc2+u%BDdr_aLK7&pA52 zjzhU~^U&5^1~HN>BK%Uti=f<>AX3lOI)q~yAWEz}Kx%&o%t9-TjlsXf*(+>A+wV{C z`fVR|3;?`3rGWR&L#}L_Ml_PD;;rK^zD88U%&Ws-t@}B+sFU0WZW+4MQskXxK}(M0 zW2=Q)r~tUEfTt#dy9!mRnnSNK)`;2|mj}O8woVS1z(@^tT=GCZ*c>{{GBOn^!+JaW z!&-FRAY%Jrwl87!Q{E=+Z0saRx}7#tM<1S9$ZNi->bHI4H&X4rCpF1X9#aRr7B<)@RjXFL z{QFVRT-6>koDmuoAHt&SJd=zh!KL*vL)eFrwrl+=2ua}8sekVYeSVm(75pe&ahKx#_;-s`mVpF7v&Ze9kn;-T-YOJ%=Hk%u^}UhM(J<^OKfH51ZgVGu`qYvpBAONKN0V-4pRM z8stNuU_YqtYTDfE4|E2G+~?2>k7)#Oy>kkW54ZVpd(+NO{XhatVbKHvePGaNR)QH3 z`v5g>IhaMj$rSHK4#YmAF}JH!4WC9OY~3JUf)ga)i00!?@Z8SK3&#Ks_11TqxM*V0 zm_3XJZs_3Y)BDjsK(TiP^9%M9{33avpG;<)h2t6L<@0ct(EmiEofoT^yWE5A3Ppnf z>TFBudd}{&YL(t{G;A*n>b!Z3;Z`%o=5Jh_4>DS04OQH0ICw*2w z+i-*r9Nmi+bbqV8)~2ZsaVzzJf9lj6btve8Ac=xA$cHm1ergjrFev1&T>w6W$*Ki@ zA-}91?Vy$!$)u%eP9b#7*-u=AJv@nt5xUER2s>1znCXKAQP21RLcr2vinK;y)xSnJabAhbIE?$H9q)c zl>}4?et1+8P+ko9*ZTBt8$H$Yxe*B|1%WS#eYJG%^vaU{2Dl!*2Py)ycZ4#M-;*=4 z4{FvwgyuW8zUWB<@ea5|gNW`_mn3RLLgb^v-}RbdA#F(5I-)t2I{QrAnrr{aO2C85-NA2`hBKwD)eTIA*V{XRn!W zrCrpeDl^3sxGlV;#!L)`5IIZ8&2U|QVRHLooeO)_9UpN<-8@Jo`7r$^f0!}FL&iaK zuiY-f;EPPeKp7^Lsjw^S1!m@JtzX8F>zpqV@}^cU=~t?W%afb*msEuCO3dYUX(Mp9qx)wIpKC z9Hwc{ZvEi+qsj+RUXZ*QV<|ln^y?H^?5J<#UhJ!2&nec3OuC<-8rv}+zvF=SWHd$c$T^}K(v%up>(14)b(|KyzFGrpPzRj{MW&HY_nbPsc3|=0+1nMZ8tkfLl)w}NjUuItGDr#cM zCSjyAELPGvb26FDHHW51KgTf5^ds@2GU7|@WV!AO3EuY`RoIwDOfo{SiCu0?&5hAv zWvmm2K*EAYE5qtV`qGR~1wXHDm#=v&ZK)vML^9Qhff zeI`uS!$%`uNs6n~_uuX^_1BI_!iulDH5MnM)?MAjRWAjsFQz_So=c>_;cju^UaK#axsPL- zhrTTgH56MX^Hz4al)OmIsL#^r_)Qx0dg)>3kxNP%|zz~tXG zg3$`4&5PgwMPADpl7baM3f#hhtE-;`OM%qutNT&eCSlzC~hvfaIo;KVm-`G#>gW3K% zcK`%3|C!1YdGYB^5E6vsTaTjO-e8CS57Y@w0~ zZ`EGmLuP?>QpSS%ka=?pL$Q^xrTNJ#ixpB?l4pka8tp}i@ezW>YUjX~y!w){#(9Mg z&Q=fXMVlEgDYcFPt3$P!U6kx&))IsjOYnQddf@sNbQED*Eq<6O?+B-uJ09OwEO{<1 z3fcur@|{sP6jXkJouj2{w1n4El~WkF0TA69rU8985Sckv7R@F+JZE*CdnAj}8n6W( zWk#Dtr{73G_J?k0#dXPVf>x=DvssWgv)*tb9a5bUHX;!(3yAN!O|mYEGt{?8)f~S& z2Xlwo2|op1tOVj&1UwcNIGX0us>qo8#F-%AKnBuLj4MZ@4dx_KH&It=gh$GB zl&0;Sar5M65}U$*#rB<)ltan(t4lMyKx|9hK=LOd@%slZOC9j&2uv{dI`9;)=p!ff ziN82TZX%;Q7M@U-!)Mph4ujBY82iebPdcW`CaPZJ6U5pMV51oJ2`zQTw*1}}O3(He zb^NU|p{e%Ug`j|#n1LZ)y%lL;IpK|C9XkRxgny#ojgnVIK+&Tin!8MTaI4^=#0jEx ztp{w}F=t*Y&-dDhfNg%17x!)U4q4&0&9j*H`dPX@>Dfw0*U~N)qIK@KEA$^UbVRTn z3YSorh)2&BsOUR@l^U>M3Ek)MfJ*Z69IoAV;@KxWNo;Qe(JIYTkL&=6D?yJ66fMkf zub9o2Iyb3BperTd# zO2N!iS%-W}^c2|>a^h)3%+G78pv(olP4NJBeotrYe7&Cv{vcQ;=MGF^cTr|Lg*m#l zhEUFqP124a2_B+p7?r-@fIP;?wwUe0FIe{3xk~Z=NZi_DSl^0s#4V{1SZN|iTsv#3 zmK$mI2+8uQYoBCs7tS+3q~tcBhQ0SIg<07ms44Dl2voED6oLO zQE<+vNe9%ZSGQiG|GduRr;*rL?sUlX`yztG#?UKzT^6kSw$oV70+~iL{#x4$C~qH; zAuy=V7W*~l?Qo)Fyp^ghCls_Ew5TOcG(o3v(-EbbuHvXYL}yH=W|cDxfU7B^$t%k% zDv060M2|==8)3OE-6L*!B`-%SbX(zs8;~b&HDxfEv|v7LJdUkAgp!xwl(lZv5f5Xv zVh=!qy5`Av)mPLlWfD^kK(^W+`wD|Q2ahxdO+N3IB?8zJy0~f$kViy~9)pw!DlJh7c%6y4^O0BbWjtiu7kF$HB}rvmrAgZn)gOXe)zypAo8<;A!X2&8Ep(NPDWUIMZH%2ev`liLC$eVC3d}mw=_Q)Q=0%md5X48|`>Z2ON9@A!u$2~*R{vIlc zon49^#Ge7t+Mk5eH`h+7Uq1+ThA{oH9c~1=2A+*>!6#Mh5dwws=sgwsPFLA-o^^X~ zzt`N&W&w( zedqQx+g8eVhJEm1=zt$zqd16-*n@++1Lo$_IgJ2|r?>0c9gxMkBhp}KBBDKIP%Hjv zBieAYe)zc<#pxKLfTjYCa@$C7a>;zOM-~kIaD{K0@+leR!YEi9lFn2gN)jeL7O`=| zd=Ry_pZb59UDNIN1;kNlNVt;>l#lPjk}g~?XZeZ~tMJ3YtmzY4bxKNAr$L9f0+29_ z@~g?0GKi3YrxQk_QvMzo2CUr%{2b)XwS)#8*|)Q0=vHd8jq?>Im}_bFZDjT)q~R*4 z^jeH$(FA|+%7%F_{LXy`UT87?vh|_{JN5U|H-}DDKCL)vQ@? z=iT{g-q}Hmr0Zw!y;(-d+=;<9JDBs=_bb(gk51Ugo`QSu(`m&6zMhx0A)7TBGBCCW z-145Js$gV2H|A6Ke;!wgA~$rJ{u9>2f5MvPzhM0@{h_1@g$-ehu&=SH?|bv}qSBda zj9U2VpEot)&f&N3{I(Sv0NdDr z{G9PIMa)4N{!zz=gXFSJw7_Qa1~U|R5fYXRp=seNi~=V%>F)Y&+*9Wh z`w2rXvtp_hGdx+waU=qu)-h(2pn+vCvLp-Rz_^H9E8!Rf-uW0ycpgNsW_C?g14I;E zH<6+TN=)fbd5HE>(sxsof6X)Ss9}(nkr6}E!R33+78v8}sJ|!)(@ZeASo%6Dt=`SM zWAfFh4l!kHhQT4bqh}VhpvFb)-UtV9bAQi5??*CM-&({cL`~(P)T-G;FuZJGF!GRy zsb^&!mMNhpJ}1U9@^`-_KJAGASPI=mkb;F@9v@d(yPzoK$J5NyrD|^nH)7SnJ$cvc zTU_8hPz&Y2=oG#gE+|LIfBHfega2Zs`%+RcsG>d?NusJ|_Hw_W6J^~%dwOaFO11w2 zo7bOkJc*rfJd3^V4bNU7AWOM32qSQ39uQAUkk#~L(NvaL!GYGxR-JYyq*G~X8pmlB zmK5sUDz&1&3DNU;Y#nu)93U*EI<+3>zkB@E>ex0t(ScT>Eo`+!{^Bagqslmlo;#mE zVk7pFim)_I{sJx7%@D|A8Oz3gkF>3NJNV3zW?;q0)&j!e)#-=IxZWps@IY34#nMDklRW|-6H0L`oM@4{9 z=|_$-y+COY)RI&Vo_$u1-+Tofe$J$6=A^N@L02T{S4*Pn zhSu}5=b?TY{$oTvOkwP|p@M)!Qi6cc{9h6Ew_PC}SYO@4#N5OOB!LM@f{jQMbowxe zTqm?3v21W#NhB~ywiaV!XqJW#Tlz%GLUQOsDcw|kIM=`iJ=s7gnYI?hKyFYMw^l^W zeBo13Bhtgo7T4AbCdSYZ)32R{KTwZE!XoYX0Pd%_06UYu_eTry*hm7O7^sYUc6j=- z#B1d_f>`li81XyNBg7c5g%WIj1+%&ADnoBQ?DKQG;)QSo5f7L-tI{?SQ2+wJxC*OU@7Zd}elMxOdsu@l$f6Sx`_ywNv_A z!J>I1p!AQt6~M+?zXs4Qudb+mGHSeH+#SdPZ2Zp8hcT_eEqSOHd+(Xq{~M3-@YL8X z@CO{`dbML>KY*S0r-gM>QZ!~xu`)V#v}ELXF$u#vVH}fAvqG=fxp|y}Zl!|X@Q@dXUDl*}7)r;i@*4w)UFlmfYfyWK22?~pPpjC> zyJL$@yN3(atnlp^w}8o!2+dNn*YE<4GXZtg465%k`UzUcEy{gc#;b!IVm&<@RwwNC zoZ^HxAQ$uJ-Ga7C=VR%%isl*Vwo2wN>9+Fc_37+1PlZgK0BBfJO;EHuq;4$os z8=Wsx@)q`XSvVN>IVx2+AI3cSlt=)3g=C<6_QILY%7yiPdp8l4JHU)9Tx>2~2;=+# zdcOnHOI!}ncYN#Zdl{R9)H<;*TZ?)>sTT2jjG9r-D_w8t#AY&2H)CAb!HMH_xuuie zz;I-}h0~#PrkO5yYFG`FldGu4-s7z!vpWZg25kHEsf81+1;Ib^lp?sNv3{w$!m0XN z&Y`n&WB1(Bg~Q@zT<#G43G$Xm^Bz?Nvjlhd;^giHZ>4>Gqx%wfVf6U4AM}cY>3V(g zasz#X9fKV&XrsHjT0VBl!lKTKs>NhAaYzlK07*c$zvW1yZ~v*u6JSmVOTVE%wXLA( zW1?C~Z^D~3hKJx_-hc=R6`sC$BHkC5E>r?IY_-2}xLbkz$nWcj)1pAZ(+g{wYkfE+ zuNUSXOyRpA#szKHj}O~V6lAD>4HhYBKi3^V4KP%y-I(3k&|D#gwVfw->sJ@O$s8mb z<(+GEkF6YA+TOQ2)m~U#K6h6JdE3&HYbW=y3hYz`WNjlDoSTra{q-yr_2U zjNi=fY(W2IiS%s3)m|N#a21LCe1@9a!vzzC711H)*XP-@ja&ogK?z}QqUncUUrC{8 zFSWyfG~1SIO-HqmoY%MIW^Ugmj(9d#<}ex$q}KE$RD`2n)Z!-1D9Hs9J4GZ2_euu~CYr9Fh#h1sc*9(Tv?l26#4m)idHe4d`M@Q$zH-UCm1ILrrxA zcxngX#6t$TRR>xkq|$5_JGS#%^ zolGWK*P?1`|6bL5U+44PTlc!B13IvtHI4W1l}~fqf%h)a?$QQOlrl)P2!(7`{O1b( z`x0WMSEOy}WZsLckiRp&M`tN$!6JhLs{~FJ)cB9%!BR`1WO2EiZXLO{oKY5BBa9)l zu6gzB3+;b^dWgA2oDe*uq5{b)-|@Aua{sAEiX(^}E5?~;fE3fpw1Eo)?H#t>Ud8#8 zsEc=TpCB1Ek}517buS6Ce__-#sO`6;iu_&vA9n3eZ#RhI-a5M|Q{6^KHS<6PL(ODK z6GxLS4~p(x7^b(Bdi0BN&~F65Vs_$Nsq#mp+CZA@sK7#8jAHI_|2GuHk6@nI<0h?D2V7b<8RcVUQwaubo$)!Al!BYMOt<@{p9( z6P8skuI{+2@a#N3h(GrOy9qd?M^GgoO?ce1M4(W$2&S1_vcJ*wPhHpt^i?68Hlbb^ zrX2Gt&F3s0G0P3p`@CDK;$ZGx9OTqMCC=Z6u3T5Xsp>lDzpbmAike>I51$wu@3#Pc zWG%q2PcwAsAbq#|BQrip8V9nUm-6$(0h(oX4ok6?p`pnUGhY{sIvs#t^Os{RAR1JF zbBSy@Ul1q1IdFf^o`n7A;^3_O?ZjqD64d1sR@pjWR8Y|R$3L-h6l!O2uS&SCgp};i z≥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%0ASVrzC4?r!@p(Mtc*E@k&ob)xy}GR+4ji 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

!_0v0moy;4$>-WjJembas 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�PQ9WB5^Hh>9)`ETLCL*Wm(x)$kr0H>r$OGwLFAF zD-<&ygL)X-3f~1d_n;ksEbYIDU|&Fv_9c{SUn3m9ftdCKoT(jzdR>9B+F=;49fiqS z3rt5nW`<5+mhORtI)f#;0XOS8aEETe3OyGd)bpT855tqX4IA_>uu0E{?Ro+1*1N)9 ze0QH-4Ey!&a-Jp%UjbuXedeD&WxTx1g`Yi+RwHg4vG$qbJgNMLkrtThYVDb?q+#k_ zk9mWxmg%h-U zX5o?G*GHv!YxqR@)GfRQxraEdd8QQb&P|UCq7{|42kkyzg7(1Cm97BI_9`MLLCflo zbGXvE_fZa&>3l$+0;)b0dvZR6_32QkqnfGDflB=n=&fG{{q>npt6vU7^;vL+er1wt zl@HEPkGm=RmCxM1zk^dLY~Tq>%-^Q_7ey;X-*MV|+8)vCixRX~y)yueme)IBH0D2! zHEa2WBBP|aZjcK<`n90w*Mm>L0kZVpfUVyG-St~>9Jj%V`brq6-vKrH@8C3jIgHfr zhB5j*FiyW$j;Xujt|5@T`gp*n{8!#%_#8jZy~>R7exY39j`wDFqI=;0R`RkdAA(4m zVV{+t6-^KrP9Mh)8u!h#@^O4UD22r;85Y9gw(6t48iM*Gpy^FW36J71)+04M1`+*n zoSrA4o4yW;^`~%X3EA~*P=$GhGcu5pv@U+BeC2de?SmRy7bLZ%(akZB<=GUBdo9m% zV8(s&!7sl9@;fNMv*dTS{0`xFR$Rkxe_WR-OvX7@L9611Ofr>NPGltn)mV;6dk<1# z7XI_BhHq`JWj#gvBxv6{3c715A2if}XSzvhAQ{ zO{`KE*SY!e^!$*M&sggV13Rq1gZWvORW4sj(39(yS|}BQ<+g4!o7;wM+G;bcQ4u_r zZ7GpDgoABaISD!_mWv5hgIY!6DJTw+Pw6JD#qUUhEHLS*u87RDa+8K4&1Je;-A3$W;&#Psf_^m zi!5k|H?M{qF=8x?&>1T8_S@lgK*tB&k`qyN#{yw=-|BlSjkCOTNG1AB=xrr&{R^}laST=c{g~$s`BVV%$@-6F5 zzGtQ6DCu@iz%;NVL;4zd5^|vb;omosC4JNG^R47o-^lOpFhYbkQA!TO!`%u)hrn|T z8bm5qR7&E89_DpQ=Zf$KX9(Es2)!%iVyQ}N#hwmHaoNG}E1L`h z|AI@|0MbKxu8B5}49YRoi*Q0A)5VtKKYE-PZQoP4yLcwTd*&UltQj(hqV9 zYqx8xhEKy#d8%=@a_4cAY-TTp9F_7D!Rgh0yIY4oo0yIG0#fFW(+;Zf5{x$A?@@Y+ z8ji4r60MCi#w&+yu9e@g=fS8puiqf&LCpZa0WEX}S%1MdG}r92wBw7Kt`0<9=&y~{ zhc&D{Iwx=cMe~U$b;gOp=RzCP>}QJ81*^trW}3YxAHleGG6j%WAWnb|@+ztpH~&R# zF-skB3Y`wXczC9=BUhdDW3ZAq^?RXv58ttDkHJRo0DCvIzFOyl$D)7kxKJ&zi@FC! zY>(l^If=3E z%?%a|g=;rvB0O^Hf#Tj%F@iWT19YdNePCA8k0}PrUbZ9LC_Y?iu z1;e<7sw9RVY$*^*v&9;J?h6^PF4K|i7)o#`Av`s1M<26+y)JMLtb!;yFSImFta?AmK(v8-|)jfsD*0(;9U8os}EDCwNVl2pZxrQ_8=JCWVVqR?EBu5+p(K`>`Gbto#YhT-3#XQUk1Pgk~XQ zWa2#CnkH@-zcrs7eiGQu&zHY+v&V}=wYQaK;)rZeQVANV8Rb?IX)vlz1OYb6ITa=A zCM8I=zH?ZftOX~c=x!k1us)KuxD$|K_~3sPBOYtmDn~}=ghCt$Xv9ej2Q`UnQ!{K%8DKOfCR-#VCJ-$ow3G=2WDO=d$rJJ&NJhhr!vygbZzy1YxUz^>b=t%gUo-A(55^hBdskb!5 zJFGl&sJA#l$eFR3;hehU>4S?bMCY$4+D)2ouHA7br7#(ZU0&in%dFCliBIKj=a9M) zB{#-7%O^4tB8wj!YPv|?Bl{{U5aldqhTp`ArO7g6*^EkX7??f{z5Vr z(j<($4C_N|RBX2dM=YXg{sU}uWVd>j zVnxb*2X6HHI%=~GWzznvbqDvhCVkPrZe)BJ`*V#)gJe(dwA{a$s5Bfr&pW&*bj9x~ zULQR#9DiVRg^I~tAJ?3ReVA?-sX5+GtO}FS!4#^Pe0Xd+ zizNT1K@;GU+C2TfbW~1-)RM~Jcx0s^Xg?urglWD{pPm&8;iJ%zqOgKnn()I}F_t$I z)2ZH+YtoTQo-DE$4eOF#oUFo7G6&6Jf8k*h9~7e=ff&{#w6tRgGYDRB&zMh%{%>CGW-kr*X?IxN)YVaJyc^@ z5CdI6vTmL?HowY`jq@$b*`uHQfJ=C}(^Hajoa-Flob6K;ux_qW||NSZmi_ zi@+sRXO{?A%GXqOlTvQW;W64@=B`}Il^Z57qUPy}t^%oAE9(gUh;!em>{KZ_sd(eo zS;n5NwJThz>?~O24x$^DCb!p5QTGi2_y(Sq;|Z4Id1}5fRz3`=C{)(|l%bd6KL1v& z4jcG`E}am^Ia3|sM?53G<3mJ_Oi;&E^q_(T#FowQ{@f_}nngY&89`g)9DhR9=y_Qd zN4zG1O|s~yGv^|{v^9}Un$M_h^8kO;$1i-@UqpxUL$>5|gjf?!7M!m`{7L>6N))>U zcpZhFElGc2;Eb^y{xktBc^c?Ff&%3}f5}0B1=_px0?l0t*2o&v*98}{poq@LrF(h=BIR#KjUefn_W=yoebj!3?sJ=1@UdRAkyNA%yM0@ z46V12vxt7mkz|_&>(X8gHSIIet;7)I~LoE?td4&S8u{fpS^!j+dU2 zU4UIe?VMggf{GvQ$hqD#4;%3)2o^}t33UV`IR-s=xOihU5~cj>3R#RKnm3%Ndl}sR zht>PqH@Qfgc909ueLh?_bu-$9P>(LJI79nfy|dzVE(pH8-A2I+M2S&WkZU9C$g`6W zPrDdnJJQ5{Xf784!%ZUaXT55U{_s4b{ifM25HU|w_+}SjzK2-ZKz~F$!uNgiL$_xY znuA}h(=FoFpp%X_6))n7wT^Z2{CxYp} zontQ@^6W=GhxGEz-vJ==662Rdz(sJHu9M$L!`qtZZJKDi$wy%l$r^bct`7S@QNCH)Kw5(aO3-Wm* z%xE?QmNMj$G9s4}Og+1nuC1?W%z0Rzve=dt?A|vn_@o@YoA~pNm^%moWW`12X$?1{ zwUti#W=x@W*c2*R%BcPX$)bef=$YQ#_}W^zd7@jMHi~*DEQ(M(NBb$JUo{b2{400b zbZ5#7vZ+z?fpTL_<;IK4cbUiPmBMhb`Iv1U3cy+z3hKRB#KR}rafu#{pNeIr^F&S| zo8rXe`mA7H2rjq5?~#M-j^kY2!HzP;YZr)C))WuCapcyxl688JR5P5}rcdDv)@&UR zOBHz;>{GR&H8Y~l1$qesLf^Erp{NI7Lsy-|Cn$Y#a!&zZ(Um8VQF#0AA9U|w4q{cA z!aWyB)DSkP=~q^o%#O|6zB_vP`8=-Zwc2kDJ_`B^p_b~L5KF^){hKsrvOoZ=K%-8E zIEG?IB93@MN3iS{zHT*nwpb#3Qva1Ov62|FE$DZIIqdL7XNJ3~Rx@tLWm6Boo{D~N z?RA*zW*7hv!i5$8&e(qF9vgEz_~=XpkLELFx#npe89YY}`|Tdt^h6JxH%b!C4fT1qN?u?8q zfR$M}rOq9;41XSZkKvvu9rG$TE4A_6vdU;h;(2ld>uP~`zeklsy~!t;@{_(Hau6po z7UHGukhEdkrwie@&W6h9S8#TWl=D>4Ssiw6aA)U&*uo|~vlhl*@&Mt?Uf45=0~WJV zTRp@b0z_TeZpHIGm{DSA2Pc$O9C+ZIY`)1Jp7Y!Xe9M?y^fGU$8p-5@Dp;k<3fxX3 zu}u+OU21jHK^1{VB;M18l&oXiqh}^t!*8S>YSbPbYEC_QUQj&OA<;f!p8Ma{^L2oi zc!+rQBla%vWhkraq%c@GIbbj;AnNf56 zLI~-^h|HcFgm;VcGnWy8luIv4oW|2J*zh z%1tuVznoI2F8Qri;&HMLMKW5tWlTz-2Qqz5`d>F>z_hjJ9)Gsw8aXTpu``36b7~_& zGdqquByH_Bsa|;vVv%^Jx&Q}1)ti9d@3p_a#Qtsjsh1!WlYiO955t6j7^eMy-X|$D zcdP&QsILejxofVp`4x3?d2x2i(@N5s$^9iz0+SrU4jvzUJZfNo+7we%KHT!}pE7h@ zF4mCHZ5lQ0`gK7p(VV4oFXC}HaE!m~KmSgI)5_aLbJ3KCpxB3|2;d;^@e6`B^p)7=3f24GV|A zHM-}C^ntWB*eh=AYJ<21bZd>=MPY?3Wy+4l9dK zY;^;GMdRQf{X=RUD0a9{h5I5PJlQ*j{}DQPh+Jr@T-5p(4B?SIJ5o_F;%5y(VcP)P zz7D7G*g+r*_#T%&1P{N*HZrT@6J@D~8T_3^4YeVAe;5DtTKENxtH(Za*X8-y`Xvmx zLC+Kht07p7bD;>oXBNyiePhGbGjZ6@?mYznS3s!085Hr8;9~~j`1;Zs_gZ&PY~KiK zK}1f;rSffL*Mg?DCW!%r#Lp+!vRtUp!o?zysd#UxgUp^~iGqtL(-xvd|Ms-g$;4}=c zy1u?t3sb&AB{O5L@$_BpYs^|s-A4+KjG1tBxik5(BtUU)Cv`5+J-c0rkYOe#V+v1) zUK=nNEQ=D6|E1C}MuG}0zwU1{NK26NaQO@nmK1T?_3ht4FNPqvL!y^zjw(&XPYdoz z_UqO^MD2D63)y+>n@^D3oH{8 zNH2+F<@x8!u8^s)kA*CPSS)lBC6#`^2b665rE!(SDYixT6^EI2INh^4UWPzpnG1%RH+^d#C`vo;aL}Iy+wF z1i#TBL8HN7&h)!*e)%5I+KZ7ZCoDD8jiZQm&mRT}UuWEulr3kj7X~?2?WW5dM$x+? z*(!_ig@qa5j4_wN<;xL91HJd|3<|Amvc~Dq3?UmhMq~vq+4XBX0ri)(ukC?uj-V41 zeFM5fR~Vf=1%>H_KAkLi7GBufn>&*8{+fjIwHG}b3%cxg{F$BkSw!9;m^m<3LM5~<=*o;i-(P`~2 zdPB@leM#IF^hb(w#i>~ANxpY)avKJ%{b6#td#Yync49-)OLnf7y)K0ZBp>YM({;^ssEJZ{=wZC|LPs64cOdSDfUWZ%1{TuwxXi)AQ9x z_|P5DWTj9^cn94}V(*{Lyg*c=(B`WI)Q|wP7Kvayf*5@u1I0RJ-JZ8@ZFwJ%!_T5` zwCM0K*FjkNay}uJ&RuC8f)^+!9LZH>`GX@oN?AoVJNs5fbv{H-> znjWr=igg#)>c6Av*S{hofc~I3-lWj}30rY0O467jss_37RPBF}OWTAAon4jZNe0FN z?%VlVIm)_h-_^QOQq2Sj_=Z)qGQ6!|p@azEw@9_ThEem3FYSw$LQv&wYSPl^w)1qQ zr&bEwz27v0ygKMan|&o8KSfPe{-P|5WE&!@nE3*!IQExpcQZ`PG;||rISp=FnY1(# zOBxG-^M`J^Kl)dx=l-7uEy5J)KbK%7j_3~#QDL{C{NesWKTYO$ATTCwCsBtG@cV#s zyhZTRh+|hhf#5uxdZ*%E8q@A>q)r*((JTDmIR+?rHr9(}se$N1sS*6PY`Qjuka0;^ zPYm|f&*vd6iAU_3AG|} zWlA#^#^wZLNO?cnt%%}QASTZ8;$3#!dFU25clTJyx`*~0{_+N3cQT@-F$y7R4cVs9 zB66e-8kRlxhr2+4PE%sm>rH|Em&B^*(0NUyorE_>tvsBH+(Un)+&( zhAF0JOx|(Y%hBeRJM~Dyx~Z_cNrl#@4i{;A^7BkSacXVSNWsTV6-9JuW7~v3`L1KQh%${$xKlMTxnBJPdVo-!v+<5*w+`xqQC;n%O#=j7@ZAN!T2d@_j!fPlcZd+zuTKi36 zuqUQhCinQLiqH0dO*f#l3)2a*;V6F0JME{4WJD5zC1T{RSD7s?6~rmL3GLF+xa7Mb zbzw&ui5X34YJ(MYQEG}4flknLz>u~^9K*&idfqUXXt|}cZ*5psPnU2)RJ8&a{L!YwOs?(Q~m3b(p%t|#E%VcIwz<7K>p9T zy=MmbcXIHzbZ)fl=-Zz>WQGvk7NP@8^eNOs#B|EdPinS#XkkY7LFgBeVd0a3geNwv zyPu8gBe}C&=-g5imB|K@>e#eN`q#yCJALtc*mYilgIgkMleMlRv`%-(d66+Puk(g- zTXYWjciDw~Ad$-{J>Gz&ie}wWX$DR(qisQNGLObMIcTDH?V*iOP={^Pnf?4X`4NV2 zQTrZDGQw_%yfcF1(Ufhs2`bW=T_=8hS!*w0^}esd77@Mr^APWvtifNcH|BrN%fz9N z)IIq3CTQ=9b9sR&_~Fq818(>~pbI15_N@3J8^G$`M2UmD`!@RHoCDmT7dKsHkT0ga ziw39CCpJB~G;4emD065S=TQD>(s&~=ceg^ZU<$U)uo>{ZY-#P@rxT1CFI|!Uc{c9I z#z!lu>2$zaV)>M8WUT2_F^imFr|Rc}i00a9vv8v9={B9^DIYc}Ej+o6)GifXalAew zYexHMz0N|Yl;WN5{^17%Tw1?L@!bt2_n@LP?MI~l zCuipY&PIPjYD17L+urIP?F*LA8{5(8&wYfAxh6-`aX|!HMtHGs%^k=Iv0UQw-RmLg zTa6o=J2sthw{-{4AIk)8`6qeno(uxkWC9nXo*=;eBFGZmV_g(^Q zw?6VDWN|*kn}wa72!`C_rQrA-oQ6=mDd!mET_Q*SQp7+q)`Ywr39aOy{b{yo5lFW` zCt~GVBKIupK7r}U%e^FvC-?1KvL(e%UnOOQy!FJ{%6)~%KKw8zriB$z1oU~QW1zh?WCZ34E|8lG$Ux6HWNS` z`LV(X#l#x9-T|4pr=ZM&5blwxQqJ&^r>;bEOl}2JUixupp|t{H)Q4)tsd?uDW$b@K^V1q%W#_#90lN^gt3@-EdO1c}hExzRDK>2@! zzu0)R%>EAfD^^YU*m>*K8lMN80Og#5l2;VBSSQHs=(HOd{M-VX?>t4s(SmGIVAUBsG2s{@^t%UPIC&QJJ|OVGz#D* zA6)VTC(i+oqI}4)8GyRUOVh4#XMb~Qe)>gBMDE||2+}v;eKjK4s15#5*-+cK#KBp3 zQWaf5O`Mw!^fL`}&5EAGJXDRA1$ zQdoI%er8%PWq&++NPkmscO;IBM8VS<+mPeH01Mhf&|CqeIEGFZA-LHkY7h`FEsVaN zqu2P=74W9Ue$SO!LXI)jZ+SgOk+ono0CX^291Snxff8u>F<(X@x~_=oL9f1sAE7)U zNk&#e$771b--uIjs7*iQ*oeMajJ#>a;aiNUWf*F_6>M|p^lhmk@3(|5 z$PGA2`yK~q-eKNYLDV~g0S5s+dj8SxBM9;Mt~bGEggZ{z3D5YM`@NB#J#+IBQ7F5k zRr?U699uDBJi@VK$lv$DkzThL3}|F&hA(CAu%a}MBd29f{^EoKS!HpzKNk~Ts@;jc zjJuFbvaY~PbP=9sc(g zU>IczAMvgm=iZ^BB{0F(8_kN?PNyTTST~OasZDch#jIDXm?wh7v2$}r`~i9NJeTNJ z6-?5d=fS$>T_*WXzPh#SpAxm)y^PgLLD(x5Kcy1Rp_(QiKvg^i*fqz*`|0l{uNben^L`76ucAN!?>@m3(O`|?Gt=IWc!re?_g%w@${pLAvvQ=uCwg^%389M z!D(3j*`4duOt*KRpP!$@Wt|<5`zG@cbw>K!Mtr93pMboIx*&4nuu5p|VCS^RHzWKf z&%98Yb+YM1MVZH*{FI1i_~WlDiZB8Kb^-+Xs$9&Y`O6amAW3#Spb7Xdi;C}WBj5wk zu-beN?%d=|4uY(5UC|#|)n9rZB!*;vO)#YqIee+iH@Wq*XDhq$bGoOfjr)vG)54En z(SBFAtv5lB$eck6oPAkq_!c)D*pULd+TZ2!TFMgS=6?9rMzS18{9RR}J8om{@DlGf zGsxlhd|*y|n?jFcc~TIDNSdfvfWa$*z8qiYFG=LNEeEKVJhox!t!aD7`;l1aymuy%vklfA7_4QaVmg)fnG1(-WWi7SMW)K}xX;PH zVvFfpVSraL6^tiiVVHYu!LM)s23ggA2U+k6E(9l#5D*1$5D-lN8)W?>Nqf6nIl2AI zUEQl?q>3euEds@2kjbWwA&!ooA`#L)?u7wRl+WeXC^5aUY5~$&O?dviazglENB{-4Z!16!Nlm3i^8cf*KIs89y6s4Udk;otDeaz!=C6uZrg# zrXIEm4=>1~IP?(eY9u#PAHtNBlGi)tGGHU^ob+dIuLW*aTRYR(;ZG*s2u`AUbp#9{ zA%ejdO}?cvC@ah|UPcCdaR{)l+s3rrARz6%U1WW_m0-Pn*L$`4J_R!u^u5poc7S=2 zK7#>!Yu%rUD<}5W$jT=INQRmL0^jDYiCrCqsIA$WC|IAa*sXGB+Ev4CPJ*4tykj;I z938$=flWrY&6Uoy>@IhqqJ%SLh!p!b%|ojuXX;w^hw4Z(yXq+~BSM8OcY=1XUX6a( znajRf94_!Pd~;!IA?JrfwK^VaTF#xMF>WJnvL;-;mMbq?4KLd===@pBVdt&jOjS<-#oFB1`C@pZ*tHBd+@T z;vNSrV8ZwFgQ3S$JdHdp{kP@g3d#2Ztj$X)u|m%Hw{W^qWfy3t46|V}oz2MLIu4~b zaIT8V0M^f;fLYgRGCdtA4A)*P5$^%^{iLVm5DI?>m%L(0gZ6rACTXic`Ix%e5uMe8 zI0YvzRT5fKo3k2`*=@A-jX2A-?&tTu&tj2IYN@cC*DyTgn}mK}L~Qa;wyQf)8IYx)BfV5Hd6PLz!W3YG7#yoT^fW?;6vm1>^L3{W#6fK;7 z^7lxU?^=r7ku^~qk3|2?ePL+KQOBVnAnf5GAn5*QyU05^d$b~crgsK1>X#Hk=8cqX>?hBtkUZ3asA@QTIWYAdK59nFj4mj&u4;T+p zvyv?}P_Z-w2}Ubll*Ae1xjD_;O%!dFGK#S{^8?x(>aDvKbG7*NofXNmP2{ZTF{c7g;6v0FTa~>uOa)VG zd^bmaDM*WGyG|>EV|XZa-Fa4Z`G9;Wjuq*P9zV2e1Y^!p|3VI6A%JugSmHhT{YM%+ z;UFECpRAWxV~`mvhG}H&>|QOFzrrir1ScMQs~S{JL{vX90HZ${nYZJL!U~lF*ZLRcjJ(!AE zo=#tQ>y2ZA+!bBVz+I&gK_G#=mT56Uc6{ELHIc8R4^)!o!$J1I#L47$Y6j;Mv7{T8 zwmyO}=Ca?%Loek+XBjVRD=%v!Lo*=Z8YiGq@n>=4Nt{Fckq0d)lZi`p5|QkNzMm2P z)?2`&?B4QU9d4-~1E8U2dEES4nzgt*W(0#{`{w$xN(Y*JXRd|(B^sHmbYULaomSNs@eXyVt`z5!kPLEGu*vmWh)oTcr z5~+BE+zWFYdep@ssZtD=QkA6Klo=BTTN`pSGunEYvQ9IFyMLtE)=!jZbgppfpadvp z(QTdJ^W4W^m;I@!fjzvfDe}6K z>$f9``N(5pbC;EFQT(+DdX~zqz&9F#Ft9`O%Ox8-irBBl8xv^R>U=6GdXVLBQbi*l z$RP>IUotG9U=d(Bg?o=IlKj|v9OEJeFT(~f6!Hkc*xB8}+1R;!esH}M4*nH6q`~fs zc+fGZc@RnYAt0;#ip*LZaya#8fQ@#zUX zvk|UlvXAbMNLlL)qn^<>pcKvDFYfzzhXpmPQ8K(Ub-iQ8y1}<|?X;g7MX*JY^+q z-2QWMYxS0vO}%i3i2(yHWl^So!A@TO(=DdnzQ$DtCwu#KF z?VFtnZWtKpzl4Rrh4FiGd1VmM z%52GzPc*Av8DECLWJyg%h?(_YEcp$Q`z}F=-5#(5qPyT_*?9H5bs7BZNr7m>${aJURt-$x(H%l z*`D#Yv1lg(NE?{6Oj4eN$nB;OTgmCzYmVB;E0nLq%=ur#YQknfOy{ICzc3kddLCwS z$ev}nb4Zwg;Z^C6i3JxXQSSU$?s@|+<1)qSxYlfI>R}BbOimzp!(x~c5@&GxjkI@g z8A}pnKOILEImK7?PvT!1Sr&gS_G%Rm7b&eVh@|{pnBf3NyhF!!NwNeIV)jO0bHelU zjbYs`vbBw~+bs^-Gi+6Ml4lmOoZMv^nk9JjpTQWFIvbDWiJ6kup#eEYt`-sGlc> zhH*wdr&U@Y#FmQG<{2SSrT54b&l_wq6-zPDu8T5MH9d;RCX zMe5*{ol#m7-apF5;n_Hhcf|RIAy-B(>CR>SQ;Hz8tSvL6%2uK!7S~^I#E0Kxq;qXx zJ4#D<2r7y56)~-$G{;n(BcuWJB1j6j>4>Fzi43LF^v6nLEF1dS z7Sp=rB7GN#3mQDiQt~`-9a0!+SnD@A#KGx31Kcti18%xv`EDv=clTIu`bRby1EY3p zIv|K(dhY3FLEZ@YB6G{HCo8Q6w{lZ!YGq9V%~u}@f7sSK`WTvf>+)2t-yX5W2}IuQ zTPXbX*t4D>r$nhEU~tDXZY?E?nZ6r|n=oOCrLohzZV~6wOjf9G+Z8#?UPUIk6Z%N| zD3Jzdi`gY6PFii&D{4_9X0HslECGuE`2WWs_&QtyW}ODru5_=a2|+uMH)qp-WK|MvM%@CzY#M&U#|zn(SnyqevY zI{3IVCGxtP8JjH?ey6iHs_ zRDl`yfPh(VD}IzI@WBQqtB$;2LQ_1JnJuSbPCe3mJ5AU)ew>Jaq2z3~u_w~?Qkfd2B z>bmEb_W0#6*K($6GEKT{nC&tHL%RFAECFJk37r1>TZ19o`sZvNArHhS7uy79mhi1} zT2*@+Z2NyW&&4kqXUv?kGzvwt9)%vq+F1F^UcnCV;CWwcwTj_79pvka@tGf_E3ye198dKjh zI1&f%OFjEolWRl5&b3erA*5(ZP!cwzP@oXlr&%$LmtO{ln?WK2t=P*-Ef}YLiNv^n z(N;WK4)OYG-?C5xODhlLbqW$H2tGCZ0dP~86r;~ENwM{WpX4t_>e%PEqts3mUZ8x= zNazbkfH;8z7-6O9cwxrD*iR2KH*d}9!ydvR3H8GIa!9x1jYqd2VtyezDO0BChDO*p z0Ka%N$-hV=_!*hIk|ba+J)o%G3jv!qFFF4%%qIlyM5+O!OEDZSRK5%uuepR&*cvZ* z^_%bgy92Lpj!z8KA2d8Y#Rh|H5nAP%aG-_yU9ub`KV=uUix~ZgtYw2S5{xp5_z=sb z=L%5X!In@uJrN9>7$B#Z2MPN=rxND6La!}!3Kxc|gut|gT9?&Z%)AZXS6%GLx4xzI1EH@;1P@&v|x)EB^usU-${% zpg|upLmwI6erpcisPd zL*(cDEv1a2MU#z4us!-kI3mdc7tzVkiVE20CcWj7zD^@MOyL=*#2wMdW;aRHFpbHY zMjM%hOhB%$#}8$|!#W+azjyX=RHz$~nKP9rX&Ay*Qn4mBdI4LpHFDNC+)>f=n=hl&rv(b8}h5GozTC~;tf9zY#(yBbGq~aI>N(J&ka$L z-ABQ?Lmzve+qLl#fisuxCxO?m6;~pQ;eK+5uSJ~zCEKu!-3|iD9SG_3MD=4MUQoC)Ug`SB!)SIeylRYvFGMU zbA`3xkOw!H=7vf+Bu|8%wh!MRL#75(azK$v-Tw1?1U5Ey$`R?&!071{B7V`*yhfjj z`Wst_2f?}76@Og!AWo6wP{hU;-~X4epTzNBeAg<~*9)6H{n4|#;zxEyPQavD z)@LGK&uHAXJr2s(4sYJ7-`%+SeYiaqqkzqx(D5AEt36Y9x~Ie-?@vTUou+Wv*wWfw zi);jLqcBCtEOfo2^#ooVFg)6wZIogA@Wx32=Bhh{tQdn8=#c0KCF0V!)F)KE92k*9rBAXkn&$a2@o(0(!;_^t;# zNGsqMiIcU^;GsPD?lM|?S?ULx#C)cKPsn%narsg2buW}ev0dX`G@?l>UrWRF`G>EU z+iTDpE((moq}OSBN(@0OKz3+Pi9e-zj8s2fB1+2qz7oY(wzFtAKL+f3aOx3MXc2c} zrZI3L4s+j7^}AlB-8h|_Rr5F zsyS72knDd)AkMExC9H6X|HSt5U~!ekgPFg^+Mx|yE{BzYq0}-QdNZrYjM8S?!D%y! z;L>rVH8B8=QaPEllbdB7!xS!YnMb{_5Pq6g`^FUec#jX8q+k3>pm@)a*dt_IBi#pk z`crh2l#kr-%58bjs47uECl+7rURJvD?WbJTTdY#-Y{gp!mkJL8+=_Or9rarz=N&`- z**!??S#TF0n(8fos&C#ns>cLshIj5bBG=FzNcEQd>LY#nd+{FCQ$?@<~zl|d`2-LagiZ!q?iPYm12x4dtl;pg_ReQgeV*->eI zYlyOX79iIy?6~F_R0)DC^7Gj)gTZH98;d9#`}2Z@E<-3WMe*6*bsIQ+oQaa2z9>{l z!$2`7Q@%B{iwPZ#A3GBieH5}%0)pX35sj9r-s{JiO^A9Ldc6qR8Ax z7UN!eq8$lV_8ACD7a+gbH+;9nC{%(ByQ}+43)^IgZ)XLgGul|1&OCnb)i1kRE@p+} zqCtHL`MFK;dza*x9M~wp_^ftIa5a}JSqdIOeWXkpe`O2!?L8FuN?ssb(ZG-!fsQ-l zWEGF41*y_z8$2=I$-Qk#n*F_mJ>yUn@bOvk(J(c>%h9__D%V8|a*OR06uDswD6k`E zw^M>^J5LpmehjN)q87nub6*vY_?egZEn8N}bThZM1?H5tDRCua^u9bn!^6Cd7|vDY z&mO%<`wx$fT+TQy*yLFJ!=otj#sB6}or_`?lRtY@^j|%iS^qbW_PYlJ?6_O;qcDC> z6qjlGyGO(4|LjpjVR=yQpFPS7?E1C3AN*&JK0xDk{?(&d>9+g-hJ1_g7a^vUXI*Pq$vmf)v?el< zSfv?aw)`P0lBq9raVIF+={*`;&fo;Cn*}$K=t=<|jj92EhRu+AB9}$CUS$tOQ7Z{36Pj(Ra!EI{u!DWpk<0l^ zP5F8y!u`3W&{)w-PHiHmRhV35>7EyS>+hi#tQkgU^_sH?vSvD5-CIlCSyT+1t*if;CeQm zKuEuJ#TE{*I3Qt%N=O#>M07SXtO)L-G?cZ3iXxW5BikXa$Qh4!Kg*nIu+(Rqu#W3V zHvfbm&{9(qV&Ys1?P-cWGCX-mdibKOf?Zdp|7)xdr&aFz;p7_qWT~TBE@C1#wfQlA zMl!j!tJjk}P3=URo(BbNix@uC=2uT&@(BkZ4tjaYy=M!Cdp@!Iyk|$2@-JfH3xU6T zloVlP5Gz2U{?8trtGZYJyGQ4~Q=R_JqZs^R`UPdjy#M4;c-?4%?ZLl#H2PmXDn{X% ztHd2K&t^wQ)G(dInnoLug-AfIuf~q}SC7tD2AY{OicT|{Nfk2-XU;EPP@0vf^05B6 z0Lx=LgSfBeH!bPe!;5DquhfV|JvoFYtJojmv&A-Pr|Bw2``?LfnrODAB!fZo2>iu# zC-8cqX*8Gm1*-ljH-6vb&(2T!3EP7}(=gk`Ts@)ZHynoVC|3h{)CB$`MNfp_H+Qd= z?^)b1q1aSl3}8Dz%;%GnKN}bBj$H__WH&B^Nh8l1pMCl?q9ibBwR)MTL%_IM)ft7$ z2&05OGgxcHLQ8vsP=J?#p>icEGgB=xQ9}h--f_;Zpi);#{8g)FMfd>|0^dx-Fp=FWBz;QMs?Vq4XG3?KJ_Vsm=M#IoDGwYfVQmHm;M7Y6oEP?8l{avG z=EZXHvf4lPuN+kj8~cU#7mns;WMn`sg5)m+xr!G*co%YuAEd2zCY!I#*YW?x(XGp} zGabQUmz-i`m4D-C)Ua1_gg8A8VS_Ro*k&%qdFUCdL9SiylVdm>7=&KRbeWTmm9`(T z8agT_N~VTT@k#A`82@l{;YTT^;g5V(&og0LvVEBH~bDZM7s>~HC zw3#wL3Ku($E<|<26$|RV@c#!!D})II72#j~C_h0!c)>zIQ2tkp%KUjOY9?#x?DAKH zhN^BjZJ3~aU`eH3@JL7!hL_5b29SsI!1MEvE{1=S%`RG!O=5-S`RX$gSXC-}3*>@7Fc2|NG;EDnROl#l@H>iqQv+ zoON(MT$Y#`&m`A0(Ks=#AV8}%Ga5|pGu2rbq<}Src*4kdHf%FKW}epcT-eL_l^Wq> zYQ@^mU^$3=VXIAS!b2{=D#N?<@Dnm*!plReJ?tNfN8JW-KikiHA!~| zwLCh)QZky~0c=z7swtJNI0OQBhV}QdG{+yjw>ZQv#0&H$>f8J^W+yf+)+o_mFEdYZUIA5 z$~6!h9rgfiN5;m~q2`xfmjzpi1;3GMk2bsxj#Bvz@{-A)s*3^QE z0~JU^r_3znmf&XxGAAdtY^h{6>zamgidl9l@;Uac%7xU8AaeEEYwuM4V~20PFEwv` za!rlXHCqRpjxh#ov78R}4$cVa6qR(I?!%d`TAcRgua zDqe4#4(hYh9>EJ-4hCsY2=KV>vU|ZTDPGw-4saYmG04N+5#JF-ps>~sVYbV^{pK2U z=?&ymn6U?A+@g2OWx5a4Nx;4bGG5|;VsH&Xxy0KueDdm+X-37E;}yLoje0#9!pgBc zVfZa^z<@@w;8hC{njaz`%X}a#7DVF?a-yv)coOCpzGr*+OeRW#Hm$73ea5V?gcCnN zbZTj-t@ROx6#AqRMe3ZLx67L3PVFYngMC=~Bs?uDsXP=y(RjpdG^ENxn#V0ZEP8N| z9^bwmG8IZ$zFEE;GsLg-c_xe287Xx{Gs^0m!cHbAs>?VJ$Ges-HL}&0Hi{dAc~$0V<4#Hh8Xnz+92ZC5pb>G7k-9pv^y{iP#D+ zQV(r+pe1>HS9?Tr1fk`|yxm0_Q>b1oI3u=gq|<)aWq#+;9ds)_6I-x9?T~qWX|%jA zJat#JtdN*Z|EYlECw2^mULc7u8=z5m|F`TlJqUxTMuLEV#Qk5JNV4{J=KmhN@E)p5 z*dO-WQ{5ThFBE~0e~8StkqY?43Z-bLZ^y`VkicnHj}&rY`Yj^|^p_m%&L^OdjX z$K|Xbq(Q~Rtr0Xm;1@BygtDmg5HUJ#^eUZEUW5!^J64+Kji1j~uUA)H#-zGSnGm*Hb%&Jl8p|;)o$q9L>m=p&(c{@e(&f?1kwoBhIJA8ySb%T$a1(ZTz0AdD zU1r)49X0Yb?{?3Sk8Ceu)kAg2-1Yt(PtoB5;frjj3gKR)BA1o=)rkeFh8qQ$_mrq< zeWjg$bPA8~czn?Ey0(l?!^66-)Pfa<2mpb*hAnkPpc-yyB?JQjx)dA5H4D<& zeIh1wI`flj2Yj#oWL`#np0jovEmlAWaOx z&=RP0txt5%MoNZII+uibR5wx5e;vleHd^_L7Kg9-%?rxfp*FCE?2T;MuqO}(o$gjZe4%gO zLwGa^CReyAkZI3`)U!s@W4$lUp*7H4)JJQmi7RW4^9GyGe7DMDyKm*j6>6uC6WIrG zXYN)HYDZ+XPsXSUd57}`>a>SG$)9>pg7tpXW4KS@rZO;Z&z#54ZWs5dWT5)i(PUD%f%gP-~C<5O^~AVCCJ0p^1~`VD#mshhI*W2tZF#vST+-#O0* zjrV(6p#LD-4M}$aGqA~MN>+WOdO|zVz`Q7f2;3UTX?meU=0-LFhyPS}@otNRkI=r^ z2g632&Cz?j=7_IH@BL#Heb^c!p*2(0d}IEsb=aIy-)Z^h7xQLYU4RL{R-?(ATI^)~ zt;V<+-I_Tt4!Vie0W>(Kj!n7tBH2B^lUy<_m|IruLZ#<(QH>Zkq+s~r0pxVMY)apr zoBP^?Gs9mIh_IlN+98f1fYvc&6G_qaY2Ib8>5OU**IqW=O-NDmZQClDOaF(V9hC*Z zGPvJ&>*$t8OT9m0DA9}zC#p0Y55Omlk>Ccr<5I5RSYm9cLO+ikB|u)!PI8P{O1Fyc zl25b9MGUmr2#m3%brpB_r5H()M@4!>5)_hI6cb4`ZKP0-(Q;aS-^a~K%IFo=kTwK+ zX9&BKr}{E;emN7Kqo%VR((WlJSd%Tq2(dS&MsGadQ13$WCR?VQv@xKJcXnZ2qc3Qx z`Yxs8nE)maFc0i-r!SrQHqc=1ZY+(H+!O>W45@{7f)YAiZA?+d&b%z1@@=cLA!Ntg zQQ@8;Su*4y)U%r|In7M%s`LSH07m%DMVs}itvlc{!ApYX5}%DyR%m?I+hu3#yY!+xXITA;T zzq7oOVI1%sEiBGo>;qSapC*2V1V`_{TdM!S6g84P90#~HF%q;*U3iNZ`G%S(ueCuL z)`-NKV9+=#j2nQX%&w}5>6YwFE02`;1gp0Emm7)ll!Dk6R!o&_d$_${6{Fd z6;-_jJL^!x`NqY^d`8|Y!djC6$Y^FrXBPOoh)JL1U5qKP`}7}l!%8$`fHc-h!vGCq z#MFM1E=+S$vE)b0tvgFYm}XMDof_ll*qZ7HX$iVINPB}93f(?Plpv=9^THylRoR6@oP{hna6D21n<+Ozps-{$$!tBPh3_23^hZQ6R1BF(Cb_uiYUeP#G8-k{Q&qnSO8&IdQ7p( zow6=*Z_igK+*^~r=uMSUgCh!39BfAI2Fz}=_)@?zUHSR-PV-)NK9bdF=wBMuxNSb^ zvJo}1SWp#mz;G|ge#Tw9^YdaY3K!a$k24x=g~YNBZ%I*2z0v5t^i5`D=*dvYEN;QZ z4o+VSURcXh%Wl$I%%secMCJQcsn!agR?7Zu{Zb|L!9#B3Jd=EEq{gxzool>B(7H<6 z>1qTuRHyM{o{AbUUq#*bqg6zc<3;@1YpQ3H|3QPx?n98Zw zmKQnM1QC(A0CeU=#F5WS#Xw1Wz)B&+N>kY8kZ1=!a4tBsJ!yPy^2{ruWnUod+Hd3? z65~Zk^oE9Y->?yk?z9J&R7|o0c5a8%Hz?#A=TuM;7_=|0yFonhR12}Mf_{p%8j`7m zW~xHGA;%uBvO@K%d;sH~Df|6`D=Qt~KmE?7U(v>_(-V2bX(;Ch_4XP6Xd%=D>xWQO zsdHs=O=6KS+HRc>8e;6~Z>9K4&r2WgoRl+tV<#tG9-tb%q=2-PKP~djfYOr`qG61B z<6>-UQE}n=`11Jju=4RmDDars+Py)wH`W_WQ@i}S+mcuLi!6M$C7^_F8qRzi8e70u zCrLrD`zxIvCxR+(BRBKx@n?85(}Vyw0ETNBz?G`#$~h*iIYB67uQnN1z%*a<(5QA| zkSryRRxQAa9pAiyrd&;>AvMra8K^lTZBUtUqU`KYlNkq63-eP899>f8rN?$aX&^pv zo1RQjmVor*$Dv+9Lj{c9AkIOLidSj&S^+I~`rsrJJW0#e^$r&01p{QFGB6*7nR=6E zaLUO?>n%FUBF1&+ln*=;J6yd`32-c@vfI29bPkNT%iSIg(bZrTm5U#XoY11V??(2` zcrs3jhFpncAH?Y4eW{5un5wLW@?JmxjMhB_`dkUo8&10%j!hb^OQGI(xN51944sly z`dnp$WJ|>)6vbt&q-645nIlWUC`1QZSt(ivU8R{|wXBXVM8~L3IA>MDqbg=vRov7H zK)Di2c9k0t3CA;UNQ^cV?ar{P6Nz`p&!uY8v7r+~qulxi-Ic#qiF4o0mGDaOaX;F7-33?BfvWFU3diV z%(8tENUc6=lVqz2nE8{i%%V9#6SKn-0NU`w}Nk}I`@J=ba;`Z^A zrT@%SxcKq}Cdm?FdO2u_{#Rp9EDSrHH9Tjh7JYJ$Xrvx31QiRnb+dH4Xbq@fdaL#D z6R6%gd{60-tk+k5?l;80{=v1V?Vbuif`AyrfqG4~gXp0;jQv67?tXpc zG>(XaL?P^%j3)dCI3dUisen#2j44J@47N2J#_@?p!mF#G{>mloyppBX<)A1U?IMQq z&+t!Qm8?mYwJ#^Fs%mU6yOx*N!2e85*if7_<63D9P@&VoySa9Dn-J*%ygJ7x0;{Fugtv7)SX?snH^}vBo=5o z=}~90ZmrhsA}wpEJ4>@$g&<(*%8)fkI#meE-AckpS))mYB_5dpQ*|#MVc$rs+B42A zI?p@^YqC{D#BHsdt1O{KYLuMBRWv;o&J@e|TXUSgj=rn%nZMjw&hsrGopLZ0@1hJDX_e-AiND-^X_rR~MfO zGII@tm`~!emiIFJ$UyxIc9aXT8aKBn*Q3F)0zqs`Qg~TQ05cC2GBN&~VY+vq25oy< zND=X@-G@hJKq`uZ@RQUj@OZJ~Dh z-I0Az74V+~a_4TV1CJeg14$yQ#ot!@6p9~J*4}`mvy=0A`_NEKd$=%uk!dd7HoF>6 zEdvJ$a^pWDG7N>X0yS<3p$wbxpK8Y50U-7p?>C`Q5@gXEDk%R{k&hrsD1U6d-)6h) zZ(DumPvNot6M8$$H%!fV9+u!QS8oItaEdNPo;76E&kxVn6gZy+~DE7$en`HNFvM|nRAgeJmv*4ia%9bpdJ{4y= z7<-}d`$?qCv=yk*Q>FN#)T+28X(X4Nxu~^NV3BOenW)*?S-LG-N}p*jH-@k_UOP84 zo-1i&J5X)NhUTuys>O8GBoip5wU+SV)i+=O;@T{YiF*Tw_HcZGl?EHQj*(;hA*Z08 zySUVZ9Xf0>-G0OF(BX&s7Z0j4oW^QJjr11%f?^Lzf;#J-08QNsl0ega{pjc{`S)Eb zA?V0+2U?zLxb~`95U7W?-i_T*VE*ImO$VxID{Vaa}bF`9iR;=RPZStpmo0?k|T^vN$A#b0Z#_Hv# z3S%3@UGu8?#CQ7Yy>^%?*pZe8cvsEA5AKT|c-&1JK|R*0`my61Zd9R^@}jY`Q1wDD zFxnoyBj3ekX!N%tT(3^YG^}n`eDI@6&M?s>-@b&ug7;%cU}u`m?@SeJxqleAoix35yt4$b{AcRRA!8_ zGQHn(WXzA#XVL|an6Nih(rg@nK`G2TV%_Qb$+cSTZK0pqY%7l$23dDEUumZ0TZ4ct z5_@3yQT$zspYfBfz}E4Dr_Z*?n1E%|k3ZyM?39BJlAmHg2f2NsYrPi*loK=Q)UShb z%^1(cOE+_(Vr)}bnHDf|s^XXo`H`t;7-}3uGo^zXKU3L#9GA#ux6C`4z1GRP~zVnXEU@K(>bfK(}yi5h2XR+vd#11@GZu?DYsmR#OS#{_5?$ zp{$7iM)0qT*p_emlUXk>#IkY<->fC?Mjye+dg(i}7yVNOK1{ICyqCdznD(JpCxIea ztKsm-!C|xwbG?CP2$;OK<+}_TyMM_1JV9r3L@n=Z+kYHCW-yYImZmRYhRx(BTl|Ae z`h@4Oo?*9e7r7OAX7JgP&_sD+YeO^#$7Y?Z! zpH}uBQ%p2^sz>x&QMwn}0*dj=JY-97!XzmDqDkqX$8hJ%KRitmdoq0&$? z^Xk!tEX3|??0KUmXtQl{Z1iMZXY9C|9$4LRrH`z;0J#GQJ+L5e)dE~DpIR;1LrYPv zXpZFP`&6F1UiVb>CquMy2c+S?QD2lGgP&+4=~PJB7w(BBg>Y&NX!3gfCW=SoGV$d%_ z$&ZF8?%NKVf28Z2nk!MTD4g8*#hQx`(Lfqfji(4RTqiUR_xO^fDs!aJrj>*zA+N^<@P=j)`aJPG7b znD)-)uEaK`oIy`UF~eJ3INy>tux(FUW^%GMslv0hLh27rmuET9I10+;hGWx&u(Tq> zszK3UL*=W|aahAT+8_9&3PmtCD%p)uxH9vskgu09jG0~F=vKPz^SFZbRsn`*E)cHN zITzHr7K#Bw0#EFCirx;APxE%}hmNiBj_!zufWB*CLh(LQ3Wkg$>|@6xGqrOj1#EX+ z-TQ1oRE^Uml?VU!#iYpa21D2Lwrj8CF5J*k--?8~=0k*|6zg*UAx0fTk3C56+cx|Y zlJ13){yTF@1*I+dwxMDA*%=l_EHXyspUUd}lw7xI*)(ItPbrSb0prZY8%L zMZEefbU^ouD4(Nw{kIaiihqI(_Bh`GE-47ega`--`TqqOxnIg+01GRC*}o7b*Bi!1 zZRP&wrMs)I`>G=_0esNghw-5#yD0mA}l0-xZcoR`X5G+lr_O=cc#0Yt< zOsM)_81SpwR<$-ZI(FAZD^<0toh`1Q582!=y{Tt=-;cx=xz6VQ9m+T^C=j>(uf(|)r#^r5_)@rskscY*Q zyJv65u8R98?Z$Dm(@bM#&dcs1eLCh5WfeNskvIKD-5SI8)Ux(|G|ViZ&9=_Sh&5v` z`6RtHyF+7Gv^YanJG4V%TC_RCs^h}oh*+5BtypDqQ))DPw@$W3OLVM$Hx0+VrbNye zn%?%s$*MU(&o+X7d&4?Hrke_L3(k@Hg^_jGjqxN3KdgNlNyDR2NcVh1*fEvZ%}eRf zuro_%jj7D0CxhP2@$z!JQ{HI9@(Wq`4H9$h@d$qVodUDV^DB0{Gcr26qdhcQr=vYK zdaL6V19R^;v z@QLr*I|T}uh0E-J>GJiD1nYhVVEc@tgby3td?!Q`I^H)B$9XuWo*e_JoE>6x;vMcy z7~*gfoa1SbKn{Ikq6HY_ne0B=+q35`9YsDvE-A4#6yWbmi2W!GSJyODYpMkLq=i)f z9@c1Sb9G~HaizDjyhcDu=0Xq2RM8mtS{m?Eo8i03hnZp2pZ@X#o!V(`3WG9-@vthm z_`D!jdkPUwd8~krRbO7EJ4TKVSZ#GRDNr%gRP&Y)F|jE)D=K4;6_dlK&j!O6dqSnT zu<~*=JY)kcrJpBHzz-?bSJJUi68i{)-?5{Qh1a9MwgWHa_}ylQfh92S);txdX6?dL zusRy|+&P0U1BNeZgnz%hsJ^y>Y`IRv#0DuNS5Vz#XX2jDI%l&LoD01;)Ze}!?-)dyy`Lfv>80VOnn>0TAIzAgRK07=vZ)IwsY--UIu#0?F^>+)i zI!_2$lI+&@a~!u04j8VM_FtiDnC!Lys*4+IEBd01(VMt9Asr1R5siEfb?%?2Q-;6fp68I7_IvNGVwS}z}>IjR4Ef6@zZ!@N3_<^l5m3#7I z#u7x-muHsi+AE72VoYzK%(wS;8WmsR0?C+@bOiPZ+yFb6 zF^DnFiZ_!FffkEa=KV0fUNSl|YqEhk+l;Nb-KAtH2~I9Jz*AFkgI-gyUFCCCzhC;g zL~-|AlM;}%N0acJY%VT!HkP%tlxiAM&@KDtcXucj?F=|AWGDq8pftsx6rz908U{ct zfRudp8d_*w12+zCP|CCS-KNH*T8oy~ zwA92h#zLdb8OiS2iQ08@=65jo@d*P1K>vi5m5J$@y7bQYAg6FqPM{Ef9(x{dYw!Q| z!3TXV2GwAi4oS&l3=t*ZIv4Uh+DCD3h`U*_+)uJ>K!F)eSMg{lsv90?37{mwREW^$ z`^BKYpJxR}XC*FOA@f~X)K#3!FQ>^@Hy8q?n<@ndzno%!4dj&}?a|dDSi~MQWrykv zYBpNDJk2p6lnPxAieR`5obcv?GUAq#INfn8EzX7;z#3`+Um^EcXEU&hFc1#{M`U3~ zIoy1X8*x5aZTz0ZSNSV979JPOHBfHns==mHM+bjM=U0^^rkP1Wb8}N|Bz^u!>2X~} zi~ykoM6fMgg2XY>rOu(QJxi}cH;7#PIK6wfnv6HHjBJ(i5qWl7fH8fb64~M%Jaboe zkM_9CjJ>6ebt!0I_jY%^$Jl&Yu7Q<||Bc3W;@oJ??)t^Mmc5?0yM&1$0Co>z0&Pe& zojz}ARkm$d(>x=`qb8l<7GP!fx6A9@-}>cSo$c$CdB}4(K<<1Gf;kmpeWDKZCB(?q z_I0a_k&%J2wsx-Vdvr_*H`J(NKOYZ-xuw)2R7PN%=q_ZGj8o?-d&{xxtkxk_UAafJ z!l!fz4scE29z~?mP8mOpNk|@yP*q;XTSMN)TgO?xpth&W6MrY07XBVL|F!lNzt|%Z z(rFxFEDm3$7S{93eR`MBmn%r0FwV&_CR(EXl^Jua!y_ento`f|2=3kS`9r*TcR=Ye z7@mJXou5Hdh7B~!_YnKsrTiw+e>(8v6KYFU_*D9w2q!!+%71NsjYbT=7YQs11e@=C z9(`H>-D!#oi^V-}8MX@3c28Jvh}9t)WEPY5J3uy}aWghk^4j^_g_WM1|X-^wk;n9G!cnsWp)vG#j-mj;&;Lv+?V4!?EU)c*2u1q`Yb~lcTws zU(#IrCIGo%WuvET31UG9%x*^Ss6J^ZAeHRgyqEaUbewRT{x20*Fh(VgmX-+}1ASj^ zFtZGJJ$M@&9x!Jfp4T*4D>Cw{znAT-V-vJCG1%6K?O5h2%3VQc z;Yd6YC$a-nxTqrCWbiglzXX?7O)ZQ<_#IK0`#aCJxf;1KHuj0^Ov{+L#D~qX8coO7 zTe-ucej($ElN#{#`z0b7+)dww>hDTLL;JHs2*J;Q%FjS5YR2VLR}s}u{0#&j+8n{B z*K6rtTb#H>U=I{R6$DkZm1a&|94MeMvNnbwSJ@9~rQLl0?dAp%p(CT;5u0*9SwOa0 zP_Bl+LsZV&#`te%UwUy==t~-O11qbfUOE$gq^9VrAW2 z5?`d_gBdtD7}|n8{nziMTfhXNCH|d2AQ?fprXN}!S}EqmJewtNQc~PNfjr}M7C|?D zPFs$r{q*Nt@S}i*fPne8_rRN|g#fj=pN50LNTxz;rU7P7TkhMRjJLOew}Dw7@oAqr zUO_f$i)=@@Ot_KO)o41XGezm=!hH%6tBQsO%%PSVS2-hS>U+#e-2gNi#Da`J)mbf8 z$ma`?i$$>|yqpQT_GGc12`$G+=i|*Kn2ZSs-4dtYjGv;zhf;|l$wlA_(UEK)w42nK zC_zTEb9X9tSg);o%jr2HV*L1(;TIE$;cR5sUt96SV}-ReNq;_lDEPA+h+$qPef>gZ zF^BAR;f9Fz%8cMTv`H&NFwdM`&0s#ange4&1AeFi{ZIcAl<5CVESd60@tV97$^7o^ zs$>Q#PL5xcXl0HuS(hnSZCXG7$~k;c6jJ@LbNytFDN~=s3Xiq=oB_^!SX0yR$1%4&e;}0ux>M%v9%!Nvj5-G-KnB2FQM~ zPP5)EL_*(VKS0Xt>brSni*~V&!7$kS`R_3wg*H+I7*Gfj*W{zD&K<{*@dQ_C+B8)ni(})}N=X$T9T3!wf5|ljmx}(9E9PxL-h~C0?9^?Hk9)C#|=d&jG6=-l= zHDB+@zFP0BcEs6E^PH_4`$##lfa0HoM{uipzff6p$Xxj8ps?PQE4lPE) z6C%s6voPa*1xUFBs~CDtp*O2Po;~7Orje)`CwtD_U_W6 z&0r1;>8yPI&b*QbT!`tBHF*SCkV>Yxk~PssV5XBu*@{%H6NvskqcgP+PtcP!si`FW z$_xR}Wm@o8%kvzbfQI_4pbYA%P&ra6lQGG@XW?n_wud8qAaN4OUx^pBLudhYu*Aig zgs)QBO8S@PZX#zzpgCHwoTzeLC$JB-bJy}Sn_PHdxmWLQh?Sm2YriEdUD;SiwBcAs ze!y6JhNnq~r%i^Z6(TanA~PxbP*_u{x{h*0^aBuCW(Dcsr`)bCMjkW)dBGapNUfjw zg~vKp++Al2-$tUJ;60eM=H|BphUwWb(!Y;JbE?cMm_OkJqw@uk1?!Oo?NJ18kp%5c zQam`*2v-gyVoA=v50Nj7xj|@u0x1L{wcqN0exVQ`cIR0R6Yh(+zd5blEIxcZ zlV-k^XS9r=jg4nP}BF zaVB`hCK=^c6D6HttUyutM=)S2;^=Gk9Ep8hOn-=!TU}lQu1KT99FbWf4Jp4z+;P; z1^koSi6vTT(lW=4Jn|y6E?GzyEn}P`X`7PGcVdsFD`%G}a|@$Mw^p;ck`7^5t<(|O zbm&(+Hdlkvqlc<$>wiyJFf_XA=;&2#c|GTTDLkZ*+!8(upPECZAH6g-6p5OeV%%{}6zdFzis z@gvY^r(_@eqmtIzsW=!np-6tG z*k>zgnWtpR`4^u^bL_pXwf+S-lsk^;%vuOMfM%rRDy%1}-%xD8L2QKUVZ1adlv^6l z8l6y`HWHeOdc8nVv1GkHWS>z3QpS^PkPku(t;*B7=pFkWbH=l8>J4;J`J{WY%)zOO zLS`p1$P4K$4h@)T40v9_Xb0=GLmLN`dXf45gsUYIVQiVu#~qY?l~O1?64D48DvuHB zWchpJ?~O>7Fkpl;Q|72Sji+YCQP)PQ7i44@$QNpGlJR)i5?t0B2Pe_wod4hIeuRlx z7^~8~U|tEpm!lUuO2P9v3yFrXm3bK)<0Y2toF;s`%1Jhqrw&Oa8bjLSBga#t5*9+g zQfcLr&=bA>wO~r(D6)7(-K6*Jt`02a&!K>BT}F0WHVED0eg|wAD)GY(SsVNVYNp zn^f}&Wj>eH1YK9Ia|s_bjjDOwI(--VVm0cO!OnqgJs~aer8?!A)o0T1l%X=bvRP)t zMFb}tP~`+TJ!~CZP_A|+XiY58aY$hy8+@})+UZSMWfLmgLaJ;-np_v2opD7DlZqw? zlayMldfgza$zVhiHc(odll6wD_IE1cPQE;<$XDN z`pOQVf-9H*XULLcw0i4BWptdl?ef|b&Z?c+bP;nnp@Vlc5LM2my7fZGA?3gTWc1vubL{+V1AfxpFoy;2x`<0L*_=3tjKksbe4o) z4xjI@{LSIhKlsyh4Nuc#OB}0uG&?RmwKu=gYOe#+&BtNki-KESU7zGiy%4(rHsuR@ zOFt@*spe*vN&e1NnMQfgg)7jt>8hy|Ya8!iqPyBH#le!7Lg_W6d4?&drt0y@lpiqX zr*mg_@=25*FH&$K*979gxRniwhbHb)OLUllhK~51hKS-JzGM?j<4O z1KBLm+dh1<2<`ZS3caAkzC50A2*BkQtOKpOJE!xb3GxH;bXc9(l)SRECO^!kKeAh& z2(#q$_~MJKYkH%Ic3qM_IME7}_vq4;@<39JabZ?XA9J3_P-+RB>QY1whS z*e{VsNf`@j4x0tjZwy=H%s1r+>X4WiewxgF!D;EwG*rdP_jiN)4ESIyv9jMvuKXnkpK2%B&YDg5mFWy`HQxm~o ze(aMet|5f#ItNOe#PZidL7QTD`Y{6+7;s8$#5z5ALo2ydiuI#hPdG6e?obAGTmlA` z5hbCvFK%#P6U2}t8wTD}8&`W$SA;QIxg^RvD;^6xjpOX#}f5 zH~011(J=#)&(bO%xQ3OK-`7$n6yAP%2RMh~yl8&xwJg}n17?Gh?h^+q{83Eqs<YVp|k$JWm zTj=Hcq2hQpR?(WR(8KEm(0a2#j|FV#h9@u|W&V+xWrTN`Sh6q~!A_{ka$ktbip zuq^J=S|Bc33yghO{po&RFMW>`Zlp-!3P8FXmXDYR}&{@V|#auXD8<)&Zq zT0Um=<`+YyS)LoAbjt_xuMf~NOF@@>sd0yiaQ$?(o6R~e3{q|e(o4$}Z0zjR9-hAV z#k$YlnzDKCcSD_0vL$s5i!Eyv#!mJ0D*i9~E$el(qvY6U)}mW7U~73|34gH5wbqf% z92Dz>$1{nDF%=d;(Y{4V*k_&|stjnfs=4jXl+21R7GBz=D!quwgt;Zz=ATM!$=_^D zYIE}nOrd{sGa-1aPI=YA`J7B`7IvpF;8@n99@`@w+an*}5=(r5Kx~GSEyOb^eK1nk z-L36%hx=EI$;w?qY0qb05zF z>=^P5114T05!p_?vNAFM&jrP5bw~_&r3MV8ElPk^1yyVK z7v8=>=h*dz7t1VOKOpMENA9;DWz#3w?q8vS3_9i?w!W^F3J1EzHQ*cZ%nTqeWHAic zav?jEIxYRHFVSzmt-YN>eh|9py@4+y?!~I(aGX-1tcn z*BcM{q0XXQGv67Ye<+idd6|ad+`laiS$_N}xC~rbN)vwFYg+jz{3QRKD%o7i-(aee z_Jz1vc8X9U%Ca7eYnRJHJJExDvg^>nN%k_D?qJ`(jf=dETVjgvGK%SF4>!%fFkze5 z*+pnwx#E1%JXn6l!Yqa57#ek5Tbfg%Xe42P8`VFe+GKe)C%lkP>g|_@b`P=mfjLq6 z^*1$-nD#rZ>7IYT;+Fze{`CA$Aj_9tQ|QZtl)upP7cs{94+ZWI zo``dLJafk_Bd)(BBN6b3G*TrDQ6u89n%2uvE2G8>*2|IdCXwsbbf_9wv?H;jp~m(1?2c^DgHFa+Lj;3hL7_& z8HYWrHzVRdBD=)9xA_G|cc_JbDN5p0KL8D9?}dp#l#+wpM*3hKM&f{c5AnsP00Cyl8WEy-~^ za`GXcORUeu;q&*9z`8z&KtHoq>f?ti<=l-%CO*zwm$Tvid;` z&%!|ZS{);}k8`N-fMzayErCNP0FkKh^UC6=kFYWLaehN!85du%zZ9WCBoP8p$Yd4n zO}5nB2TOkm+LU{>lCqyfYR-Bwk~)R=k*t(*GLH$Tu)$Jm&Ld3`0FoktbR4$J3x!cpw;=CCv~f2nzRhWDoufc;s}- zYWDazUV14OPI|eP>X(LGC91Uo%7mT|+Gcc$`##8)z;yhVmdwRv%0w&f!Sdni-WO@ZH zY~@n_NC~NCz(hGhh`9scb-;?6U|UACB|9R?3U4w!FwPlXFpn1%dBP;i9$q|+7x*}> z#I?rJ;S7n8!Rk0qH^zTryKO%^g6vEn zp8sp!qZes;fA39ONob`08BGz`P9 z#|TNk37lc8b24_lR>02fu+7oo;tG^V#BsX9V_S(5Bk8UWgw@F{ISM`yZE?97sr@;s zzAK)b)pR#I%xuW*ie!cHYAfFPGt?I_udU*d6co__s=`77ugPD?MnOve~i%ax)nAlsP4yd({i%pE!r zlWJO-ag_8%tKrU5%c53R{TYx&O$b2E4e!R)w2ETQ=2QWK7m8+Nf_nQbjA*v<;$ zUUivnGcTH~>i^q@BdfM!-E_vi?>AOCvn;w+RvBERuPqIFGQK{)=PX$3I1y?i#eFOO z$Su#LwLM*Gy=}S*=dOCPo9(HF|5BXPPA!~FUgGgK_-b$_&2hl*s-4gf*=vNDX0=1W z5ijktSbai)vY{hf6>dzTyf*EAaNl_}l2VkB4z~8*FI90VcST5Q+5AmY9l66d*SoY# ze#!B9+o|i)%MB@WB;%d5>iUe5+ZL)2uB5uhJs#Pj_MpXhmmcq=yt;6OBe(B$Ky8pQ zyHML|f74%BrtG9!ozNyV>S)@ylE)mzMJur^HmoOFm?nX(_^qqxTyvdS@~5~Z%4;Uo zu3!wUfD!anyY|&i{574uLBJ&lp!sIl?^1u;;%PtOiT`ul3&eL-#AB2vq)$_DSg((2Cktn*4ono!U4{FH^qAUaZ{j%LQGSC>~o^%`I5z}e48qF+sYK+YMi|{{V0zf4@ z@jgfp5H~mw5c>b?u8}vgGc#57boj5G#!~ekXWSL!A3m7}sR!=+^vU5y5fCWjDF9km zB$zz(c#}xHWTOeUya}h;>|(U<#9PUBZW32Y7zUN1Bz35tR6v5VIoy(4nb6fV6Skl6 zYvB1@?l=5bq+o!t+pXz{)V35zY>)lku6Ngmo1p!k-~AJ1{$FQ91|;o>g62ico-9#c zlC0^G`yk>ZSR=pEV(-~-N4OB~*I?4{|T98N+DF`At_;Q+}hmaUCYIE)+}M z^m8TsqD@yGDdTX?&9ZP5lo>gyhBO(d5!2@uON&{K77!s6iup9!an(9EA%HZq{m+Mo zCLss;&Q773l+kX0OyI|on9f`_i(?T}t^%6vVM`0@A+K`g(Ru^BiKbJVkUN7K-OSeL zbWQfs~Ly_oeHO%dq&F=ywont4xVBRyN8o0yhsstG1>xl4o0Y?@n3tXQ z+%903R3dPB@s^C;b2NjFMvY-=^=hl1rW+hrUr@4-HexQ`*-QBsv$9uL@ZaP5*91c> z+dY3t@UHzG(Ph7uv_f%0~ORw*u5YX`6K zNb^2MsG!+KIgk`-H<^<*oE*D0);!vbm+=J~Z(Uv4RVY6>^!_bL_Jo^W%p13>a8N8f ziX~azMQK_sXA~RVg1LS_C#w9;8A74@6=Js91F}!`o|dnE9|E1xSaC!~vf^ySUiE5} z0G+Won4}(vuI>ohr`CvBU*!R$!9}-4iHS@k;t#0-S5F0HW-g+WFG# z0_*KrJ7U~bhZpD@T(7Zq+?WFCZEAE)v_1s3#>uBxJ9@vjpTnWN2(iz0GI8;7%6S*I zXdB)TxREWNS**}dHzmso zv^F`#+bdbAe-SuNF3FRh(&uh!qsti1xz{WE947BILpR1{BOZV;8FPi>WtQ=ZAeEhU zsd|ckZ8C66u6)9iFHti*=n+(C47i1-uTpBjs+==V+Ld#ZzE#VJf0t0h20t>Kaxjey zx{gjR{j!hXqg6Z&Z)UM+iMD7W=V#RDVPaR=&;k7XOtJ8{zAUJ~FB^jq2toB|>R74= zLoM__MG-RBMTl}by%jd1^Rv~}d=SsH5i8}|Q_AfF#XjRBJ{bQR2E_zw5C>@#ENU(( zdOeaA*P!7{8Rt^gm3npA5pmT6eSLz4J(-8`Xa z4&x=MxOYUtDtxdb%KgPQ3c{q$~UIKFg&AwJobYG;NyTb@bbpZ_`H;%kwuk`LA zc8*r7C1FCcyK_SwyE2-h$%SDRt1sfL=F49hKX!p}AM7EkH{6L^#^JTjghWbu%>-lb z96}#`r_woLiW1x_#jMc8lk^#GjM^pH$m4`gKVTAV3G=x#_s)MlnNb-7MRRtJ_&yz` zSBM@-0y#)uIF6g{ThSV#Us7lVQww$g5dyY01ZIR{Tk?~(>cBBe2)30rFD}aq8~-F> zxqj3fQ|B!>ChxyOu5jGbC^-|tDGr7Ti{=~uq|trj9|2CGPFR$6e&`Y}bR8~$aKmjV?ZS%_(5_tg>}enb_KO36MEv5Aei z$itNyBE`Q$hsV}^NZVTTUU}@+Pjk;<_#{kHN)BJy^L)Gid$aI7&%%$N*Q4%&>J6ObVR= ze7b>&H@0qi>9ktYdK9i0r~XzX7A?`Q)r?u==EJ&Bbc?q{*xSLfe$8`d!*)#^ZE1Jr=po;a zrtFj)O*d@APDgmM)VoPVHjHDE^el0&b=?ITQWdR4odb4z825cC_#)1w@!Y;8Un+?^ z;<`pB)FQovB^X$4dCs*;bhNfR3tpmMDpPnNtTF66y4;e^Jt^T`4h66_?HJ5&(psb^ zycs?7lA>RV;d$-}4g{=(UYW)_`x!lpkYYOKA-&D9ZTt-n_PWj)&d3`&Jml?Xf=s9o z?Y;}gXGjRNeLvL3Z`FNjMFkRyfes6bEaWJS}Y|#oGbcm&l zZRR257~C*}2E+THWWO7{ zb`FbMb$W5hK56w`CWEG?0|`o6Md-Jqt#{O{x2xyM+kWlXks!mFUKeMbPf4!~!IHD? z;6jv$+~_ek1XmlnbwtNkD1J~>4Z1N<{i-I& zj7c~Mi-={i%TlO7F#O&U0gpxehudb0uX~@qT!aDjC-8U}Ihr$PGuGbrW=8Ea24K z;^=4RBJxi8u_ip8ozvm~i_zyWu+k$llJ9O^<$HMI(-K5Q`FrWlsd4Gob|h@k&wSpA ziHkP|7=KWES8m|m)draWpCLLPU16eU&q$x8yJUc^9|e1Ph0F2ZPo7(y|6tJk8M*^( z{Wjp7E!cBN?55f`%DnyMe1-J#*UWeqnukC2X8h1228oP|;s_ll@2FW2dJ@8B#Bqu= zZ|pfhfZm8MHV0stpirhb&oe%6i)?w8BGFEGAV>GD49e9`lRmc|5L`fwR`FSTXJnU6RV7BXh}WYyh36&;A&tfv;nf zimxeOhGb0d5h(VV)adnh4RS5ms+;v?V-reKJS0vGJ?FKg<5Y&MD^MEDT+2J@h!H~| z%W{?RStxUHJf-z>5pW&AqK52^d_u%!$-(Z;#KRuav_z+-E(UjsiG@MwVy>-{I4+g3 zhzHN#nDE%X{&W>2(8Ab}L{`7aS~SnZsBqaONTdq|4F#69XYgXFer5!6W*;LoJPA$A+8{+>|1gv11Zy$Nh3I{OUNY_QqJ9z`KL_kRQLQ1FruI{?Fb?6 zWK5iP1E0E+JFmQSL!A_c(pR>=W-n&3hnQC1(`e2e>04+ge^v3?z3;MbM-=E@jE6~6 zZP~dpuRJS#=iB!F^&o=Nt7`8sX|p3SG&ZI@+^$($Ki<{f;W~A^TuS=APqyNP%AnTP zWb3~ak$7&9%6`L~##X2O9B_fKOblGna*y)yoE z=nO>y5}#Fyt0or7T~2j%d*jK719d`d2+^jy?ma8g>eVeesFThQx|i|LgQpg$zVd&* zZ53NQ>|rx$JppL|Bp&WWTWzl!AasDu@PgP)5yJXomLYBS2? z%y#*G3n}XFl8nuAiqb`mgkBi*Q7DELNqjKvh^&Q^EogGb1z{5vman}a0Q-PGh#qjW4da;pJ?*}8eb z|JUvMBh{3h=>9rdwwM2F;ObL_Q%tiW(yobqoZ_U}M7kL>qiT?k?ufeJjIG+bXx^*{ zJYGYaaC~#wMaV*KJCf%_oZx14d+ue-7w6*jg*D?f(-;gI{d~ld=v<`h3%^I20JI0y2);7?#HYdL*15_Y9 zMA*_bQ|E+BpAz~OEz33UeGdVR?Ir^=iU%`1E|2yWoyl3cF023-b zau7Q+@-b-|r|-Ur%CO^+1;CnYcn$nyp5wq5JuDi#)~>)Nuy2p9G65Z6AWG|9(mZt{ zGgtmH^iH(W6Ji?)QMLxS2p&dP6gGLxV}qAtnF&J+7ADrCQ)qu0htYX8v*Cc>v(?R< z@CGTH;odm3#+Y>+?UirkI0RJ_fF5|mjMIcYa*@$Vx%C&M!+}V7xI5Z4P=X23;KcaO z_Oy)=9BaJ1yEhj`(yut4ZXaud*4Avn9eElre+>fq5`8mPM1v+=;8%9k48!Sk2Q^m1 ztuy@oHgi)(|K0bN?oh!yx0iQ&nCTtknQ-m-OdXODd;cC~&Y!F@sn(?W>3puw@4Hjy zMQhfYQU(ZYM_15y8~>yd(y&ms!QG-sSU3gQHtG}`}p{`Nt3`*aEVQr z(d*!Kyu~NuFwwhk_05s{-?ku=f$1uPe*REf){CM$gbx&7t}&($uB^VuJS!3p@_s7! zmRqTMCs|HQ*~>e`?KNr2DECznXcwqc<}5Vlu{Gy3KWX#Aq_g^)y=Va-Y*R*a z#lwnj6=)|vgFKK2u_0**cgQM{0~}{DtKZYCd?hos_nTVU z9%+0N+VTU)eo90od&v$OLxizAxrn^@sT1X!p2BLj@rCQM0_ z2`=igVs0J5yr7HJ2Cj>F9O+l5T#me0D>S(x5Fh4k46)G}!&E73?q8Lk^_`wYJ_wlQ zeXmykY!gm55Kty+n|g5N_|+(56I$p7$F9P02X`$nl*9Q0CJIE{2a3|;|FMAGX!BPz zPNT(NWlUC}e+bMD#kmS$sQk2$Z}YJ&k?DD{K0oU+b@=?f(L3pqROL77pxe|;I-6art?`eWdfRlTISZ=37Thdgzn@yj~P#k z&$NORzdA0f#jKzU2OW{1mOUKp^qv>*I~RuAp@EXs3J3a379`3^eGp2bGaPpva%y?a zA+;MFy1qQ0aVzPuf5`qb|Io@ST@mdcqc`UN6E`Xz?*APIqGRW5Fog5DoD@LwlC|ox z|GWOnPiTmBPTT6&oZ@GU;0R*42|4o8(Utk;YI21`d1YsBQA7ud*`y|uFBCBPc(VOJ ze;3#yI`}l-Z;CSnD1uD^3%fdH3z^E{v-g5JNi0OI#aVM}jn-Z>d*DXvr=Eu^EVeJ@ zBYvb+{ni`hgU#YW;=ZByr1uomhN~!8ACAZ-sumb0m$y3rNlSNG3yxigcvz?*8|Q=s zE5&AU0tQ8A=sAXKaDrN9tIqu<{bsgM8$m0)S7ib?WP^1d)#X-s_aDoRZ3d&lg`aMu z{-oco^I@LGj{`WJ@{l(e_5&%>f84)0oFz*(Jq4A@P>=8?r13XXh*RHaC7 zIIf+YSq1{do`5zE)lmboNU0`$*3s9OdH|$dx>#v`|Rz z*!Bbjr(D&JMQrks)(a>UZu|rV)`Y0^*r*0K37N9bX1lVZvcoJj)z^_xQ2HoFE2hX` zCLaGa=_e*l047yWq!`sY0aqu)51SY#RS>5MeQx3&lrLm@&I^tyo^u=u2Ndn{Hs)le8(y@(qS9|J> zQhVktF}#I+gBJ3xDvJjN*h~g%IIa}t1Zf)_nOQ<%Q z=x%soa0zH)buRf15XPB)36a#HZ_$y4c=SwHc?cvS3kX+>Lrq?{BXBFE$YoS;2?r*v z`BJBGS7%^ckdl-VMKw#HWk)99oN#GS2E4}D+kslqppV+H2&6)u6ek&Sp2iw8h6}uz zhw0Ccb*9R^&vtBrMg-RZ!igO-qD7I+(8RI{3QHJaM5A$R332h_v3_j=m`KS;7W|ts zQrdQlvef%kHNOswV29f&sukIeetyJ?PyJ~Oxs=8w!eG$W<53b<;Q)Q`e_o;!|a}g($%` zro(x0O(>Mv2i>BfBr13I=%oipjddBgxSJzvn7hu)8O>H z)Ij~B!u`m!a3I3Cac61UhzKoud>xM(|C8#|I6ZXhGaU-OVNE@$ltv>^$8M3SD0FD3 zy=hy+FM*XQdzdD)&Uzj%S=5se@Zjl2a-(aQNaFoO{v^h_U)p|Lf~Z1za}3<-U#I6Y zStsL=G+oH4_}rexOuOS~4x33f{Pa0W#2tqj^#mEB+AFwV7=%WT9qnK~t`yjI^pZNZ z5Y;8VmyPkLX^?`4w3ZGgx~BJ3wWgDQnU8`Pr-WfgFy3g~8BWCc<(S&Ll4&c|g7mpH zAp71(2F6LYsbqa(sH-|2*vdx~$M$YW;bh@D(4o<2yTk^r9~3DGE{YURGNrkFOBT&V z&Lp9oHbdLL`l1#StYzeXiNXXB<5`7Zl~1Pmtuo*@q6mzW1|R19SWx2)ZS*9rFG~Mf zu~SdB#T22$Q*TR6dqKQ5!0wALEy`=k#yS{qo%m&ZhmlcVSEox);>~uhaF>&&$wKR&LeQ2=)6^p-ijJ8^0GvC<;8L)S&|1luodL0Pxb zx;lCNky8fjnatjZKLcA2#m3p-ulk%}zG_-&jYe6nBai=Tgwn#OGBa2()0_E|)V~#L zmi=em(oEYzLpSRnXetKW(io$-${01SG5F@-qSxXuvTIw;l9FtUgwjn9NtfmjHBGzi zv=j)-5aysgWyffOe|2;>K_e67bA6n8CvJyP+mJuGXe094G2RFbXoHJS%BJ>$Lfg?g zKVmxlYioG$nQQo3C+?F3?t;bOM;D|czD-F!7s899;-rDZhq#LT-8Xx^UFjvIi?uw) z+L_5MY(-_YT~pSP*Cyy4(m?Q+hTy_6c1u+&hnH_O;ay0HELKRDzC=;9VtciFUF#f6 zF6XY$qxY|s)Pec4CR@kgd->r^>=P13mZuKmAZKeoVO|fx5>b?Q#V99=`5gnD!3EtA z>&$@}j*C3&3Kh&Ks>ubs*(sST9)9_%co(?1Jz5dRt3&YPUt~@3*9>pSWVLk9W&yEI zi;Eo2%z#iK55gy^Z;kazfB5-{wow5Ij4)SN+fXfhh`=pFYkruV*eLAzoe(M&OG?+pH9u`D;}dd)Ws{X@(46f z3zB;VPajyhu7ycIw=om9=U%qCC_ekbU&tay^D>IAxZXYoD6fB#ysVkb`liX;$(~MTy&4e5!!4w=)?9K{)b7HJ9<+&nCuK2IVLvipFOI$#aD?6o0%^-W z6t&jBW6plRdH0V%x=y?ZN18lD;=VL&kqX2uW)YFAJJ3JYCIMkKmID#-uzkM`RIoH_ zl&`A2MU84?t|#2_1LuvbYzK$kv)CB+Jo(de-91+E0d~X_@MdXVl?Q$FjxDbJ)k5^z zFS>>9%vw_A`)YQo(X)l}-sfrg3aM+qIuqRx6%e+h8V!$Hm0pQiX*4nKsbjU{23az+ zlz!O~CmE&AjLP^u-=8d$t)6vH)o&mA& zYKG1tDi>%DE|F2@WM_AhBXQs*kEQ%FaEDj8_ zxb}am&!Vhm;YGl~(8R_jD>qs?Kzoz;+6wUL_8uSfIhwFL<^z`rO8H>>E=7$`?5N}4+AWkCCc+gaU zEWu_Za}61!+n`g+DTOZ{T1w54)867n{e?hzjJjqRm~+r2=}(9(`PxG5h+wCB;_Xm$ zx)h-zO(LUGG&jde1UD$G;!4vTTAxfi3I`yYj8#p zsj;Nx<%;#Ot93l~VE$(9rlIwtMUv?N3f;Lnh7JN+f_jj`da?IGS7u;nHc%?ohCX52 z@Lf5^ZBh0AX%VB&K_eOSx^;=F<)jVZhIre(6#`Wlm8a#r)yO+#RHU^A;c3lo%9G?z z-CO8K85>5O-TiXs&3~mhk1F0N6gTmSMe=rFS5p-5(s-%CM&q`~^E2;8gcL!&s7XaX z0{1=ndkh>dFF}_oAgzv?`|QGE@B*l`stMtFbi=xlVb}6+Pvhlj(+PYz=SxMW>-=yW z(GZ8l7!pFC>c`AaEh&Mh;+_beG2LJt3!xB1f(d+~Fj|6ded+|Ykc^l;e(9UhXIkUr z8-TJbKf@k&56x~_^@5aNfLd>cF7ncnRJ*ZEF{VRIIHtl$s3SU90 z1DwR638r)*!}k3GS#u?>hlwN__ryb*`L%{?^8&@pIfu;>6PVk{6w)f7Zy5_>11!aMBwGEzPaa(=mc7Dqu6oJ_M$Br<9`j>?;v6Q7h*pA-*{=4q} zzf+EPyrE8k6`2upP2QneuF0 zX{$wTYTK2zOCLNZkdEfMw5-T)PN0gSaC!%Nm8HoXXeW@mfXBpNQ-xfI$w?w9sUn(X z_o0g+TAC-(y@MLM8YH6;RT*uj}&LSt}nlf5N8P;q9WL3;5rd>&BCxv|r zNa*lUQuomwZnC@Nn3L7Df*8TE_G^`^!>YdB(9j9D$X(3-@5O3vfZ5ODWpHjCYG+fE zdi)&Nv{>eMQ{j%}3=+?6wJS#{2)OFu-Rkg>MrR1uT@nmgOnnpQTRz3|jClv(K7ySEl*MS7EuV5i z;tAHCatD}`8~3nFF?NZ={1)g*`*10RgRfD|)TcMT=MEd%DQsEXG=_1!@TbLb!qqto zZ7W1Gj3`P>2dz*D!0y!HAyfG+2yn3wCy*HjrDiCMG0=uH(Z@9FhWl2@5b>HYoz@Yd zc*hyvcu?#8<)y6bsJ8`+(2uc9`BOjAM3sLMxlQ&4mJ5yo06grgQSYHkJa@gNKEf}3 zZbhbCnG*>yd^7kx-WisZv*gFtA#rY7pPTQ1ukjIc5go?x!{9(brTu~lVar;*vMRr9 z#elze-V}q2F;^0sSVDk^p{|*ov8go%)XCE6*qd9G$xELX3dd;pQe|4YcQsE;fnTBu?)ZDn%;u8u zuBpU}I_-|w>V@_!3c<|bTwu@OkxSE^XU|^J43^vPup5)m^fi&%#$;FUS$6Hb z%z=yHkliyn-L(qj6Yk4E7#Agx_0Wg6!ShXA`AGh1%##!xYs5txwI`%uHJk~8V~ABI z_o-xvXYC?^Jcs2ELl%K{UGNP59hYp64YK`Q*%ldZZ~Q)`{i7FrxEEFpO$KJPk#@Ed z4jS{Zq*C31{KCXMrQw#fDPD8KijVqZhFK3!f)2r&e1}#BE3Mj8D)~nRsq9WRePiJv zf3D09!-&rpf!x6B`;EvONw(Qk?ZejBMQaB-lngPk@;gNNB8I67@d}nED(%o(!N2Y* zT=dHGt1)d@v7@e9JtHg}x%#5F%#$}|OSJ9?$)C#CWChpWLzku_XQQU{{H(&P`7>{t zvXt7DU7xJ5PF^}dQ(B;^IO5MS*tC22dosPwW#ibRhz9FPap3(3`^xlY71@i!V3PJA zTM;YUC9E#J%_V0j+wS%c+J91#t8-WXAlYAkNq_x+9y?W6OJ`G8OA8HmQ+G=TOGo#A zd+ZDl{56-B{^Y$G-&)beqeDr+%jsgXhXh2!2PHwfvm?>|4Owk4!H2piSurD%To-TS zR6AYUAyi+iY4{SD{39%ADav5UF|RqV+M&7nPdYub-1Ig|P8ce3kgqv?Ov zZCPmKJJVCb+bR_0G)GKV3u{+4`fWF;DVmS zW}g@gwpMV6%RZbJ0!`u7eeDzfTQv91DhDVPk>BXCepShO7SonBbv=_*UwWd%C+$Zg zOclB+ZT^N5PSd?Y_zYD zl5UabIxbZ>R>x43{hIy5Q!E6=-Mg(_>Z@diObHt;buLs3B7{@S9_zPfFzeHfdIR!n z4xEE~sF;o~dfKBFseR%t5Uo)C@;X1c#(9p%)pdo?Jr@pq;v4LEz2g@2rwdL;-lqso z=dR)9FQ+5~C*EURv>L3*YSInz13aNNwQ;aeo8CBBxJ_$ZP^c~TG6g1ZE}zZEnQqf| z)`-+!F2T#sxi#g<``VJB_q@MbJ#Z-4C@$slp)SR99N`l4CSXb8X>J92Y z_w{$1&M_JGbwYFx>mph-s(a)!S>mP4K721lvs2W0FU_ix!iC`clMz}#JZb8>ITUHS z={6qg=KMJZ#CYvZ#P$;JIwbs8u?SxDF;W;9p-eN3>hmyx=P0SK^ibfZ ztaBw!rbcgFSDqDvskDYqo4FtL>O7%cmZ;a|i4xCaMk!8#sz&v_bT+WM9A^y(lLgUeHMj`2+hR5z0Y>eQ_QXjv+jwjH^7=eM%&6us$nfoO!!Tg0O^l7mdo5oF**7%- z3w}kfzQgmoOcM`rB~z_cB5rM(o-3x{>GtGF1LL>N9W93pkwp$#*r+h*0UYfn0n81H zG3ZCm$2wj;aMj^-Ml&O^T>cBRZr8^LvkI=$uoctt#`w_&v12?8Sg=}ug3Kg^z476P zN}CXN+;~5qf=^%>&hEmvL%rE!q^4JxxMlz2k0EeIpG25`ZSc{O@0VTqE#J`*dBXef zp!B!gw|zjP0Je^yicuTaynQudRL#L%uD&^06OKtql%9jOpM8t$Sbko{y~b;%oT&AW zl@mPL54`R^;Nt2r*9i}yT!wq00uX}J1)OI)@kkD&+3AJpqS#r13Z&Xm`dcr~wcx9; zY22WD3w!Pbd#><4;~w8&aqF=|^5@qp{CiQ_ZiTCi``&vz@vXi=)-&WVUBxbf_s9eE zO-w-i0k7>Eb@HeDcdTo#kn@i6|BI~uR8ax%yCOa*dz zax)wNAR|1v?~rEHTZ%MWw!98O>9}TCfnlkuLaWSI+>c4sQjm1Hy+$lF*5NEtDIpEH zPM;0Wu&S{}?2uj9IM)(?suLvsIT;u0ZgOli9*^5{%)E%{?~tfb*6SSWA4q{_XSSHOtZtFmxv zfdHGD(MtrS`jnGtQR-b(u0kF*G_sAfr2q{U^Y+SvQh-95AMY36Z`JHtnT&jzp&)Jf zC;GKT#=jlG^Xt6&LupsuDQb`DsOryoEF!c z;H*|(kohfZT6dg%jUfBi*dVbH|o>+%c` zU`boUh_=lEss*Xdu2s9`i=&%e2&f7}f$%mh^J6@r{|>FB>@UU1Wl_3Q z$UbB>=Ddobxx?kD29+Ou4cHQjdqjGtnA^z?3s*A z*D`Pa(NRD^x?PAGx8j3~>iA*rqYcPXKWyFOgTNdObDV>{CvN&K&;O`U?i53{Ut}+b z6xH+WdNS?&UL@v^OU-aJm^%C$ew>|Ib($<-HOILz^15!Pt=^P3UV)D6H$Bhtq*6ke zXPg2_18*!?R=VT~8z0{rYvqu|0Cy0VBp!8!PA?QX(uW($ewEtkbgrjRPxQxdZ5`P*il*P?nYRLa`TxJw|f z;0x3Cl8KPZ47@Z`1>;4P-~4R15`<79h9 zbNDkOeUX3Mc{hv997qPpvu?>b$9;z2??ug#&)sz6mCp7id#bJO^yOAJt1J<=xlPNv zM=tu((4D%jy}bqE9uHNm`#9Qdw`v{zQl=t~6PP;%Hu@FV2p~16E(8!ZrRgu~bL=gP zkF8yOUG&+pJpE~D7nc4KRbO!`Q+lP4iz?f>2G$SuJS@HV<=Z*e&#%xo@MZpHwv>dd z1^ZI^DzT9}6c+nLGk>UUbrXiNaF98}GLC=MbmnqFv_=86zp>#ZP0RDjURl-6jQLy_ z1el|WD+VT|Impo^pT@=xboTbrTIC%q4&P_fJ~;o5QrJXoVmeKK+zxr}kRHkgrH{tw zvh>?9Lqw-P%4@!9sTmt(i_B+hOyz_s`Ysdd)o_Y1W3<)`I_{T#AY$LGI zE}*bDC0@vl-SEHWt*)qB^Uyh;#)`c7C1K)z;2JTh0O^Sgd#GfB`c2#gbVXp`*XVx9?4dv+J9}*K+8y zGw)mVyJPoGOpzHCDu7ZKUut91! z5pjNYEhzbJ?bo$`s+-ib>-m1dQ>&JY7@#;VvZUO~AU=sd3da z79_UdVd$3|VL@BPQ;jBv?eiZSCzeG0X`+}XOC88a?vFsxSbaPyll4FY2Ei}LJM%DN_LV^|AwI5{-B|9MRpI-hm z1?0$%wSXM#tRO!<^hgk6`Y@>TLb9cqLWQLuq;#A)(ywj)w`_|l3MTc@E@bLBaEfU6 z(Q=}ecjKao1qx6*eLXn+>uFGfx@Th2AMzC`+%3G8GfjQQ(&^!^)?{7#W{B0|(zf zXM{z%kyQmJV0be}M2(bWpd9?kJcoG}$;+MgC!Zoi zcps?TW#xY4;Zx^jQsnW*`)DIPH*-HXQ#>~Z?3WP@t|?z>WOq0!UEEbUIki&qB6R@( z6$L4s?RrkQ`ae-vw=r^7Vzg>X7;EOwU7e@SdMuKJYh!qb>$+S46%xxH0(hKBv-I|h zj3#ac>n9VAd>f@p}De&Y@sEHr?MGi38=$naAC&*r^CJJPy{DX@gs(xk90fvv z>R~hctle9%ruXXT)mw1jqf3rN2({Drw=wqWOvwq3?4kWl z-%_F;)P{Mk+YKR!agO%Ay&P+^2j$ykx_w4cQ}?|)cL3naffJcVLVl8{ z7%sfLyoIP+r`5+IC)6!?GZo4h2(hZ`4>qCGX#i=9-q>v8bL7vCT-8w=RGK41^#I-8 zaA@u{CNs*(oex@70J4=*9ItM8%X08N+zwRmOnA+@GZEu}Z9DFx)4L!0&gpXa(9Y18 zQlHpUrlO1qg}?g3LO#J}Z&9Zb)8hC8>{w{D;?alsN$T6Il>=^8pcG6H$9$}{C1PzE zQG0}7oX)Xzdk`@o)3-egWtZ*_%58S)TFr~-apv-hv?oU5cn<4gm>x)Q_S}J2c>AvD_GjM z;5db9Q>wJ8Ytp5UaG{0+%qTy!N3=Ayr#I`|J-)#M{0>77z2UUZI}#r_@)xwYm0IEP zd(AaGp8@$DxWR2US+Wpxr?uCGg2C`x4{Dx;!6#K`nTH*pjxLS}MEb|Ds+RYK&JQc! zKJWBDYypi0bCTFvD2+dHp4stLERYVTHA|n^rViUH*_Km=ZN!|0ngy$EY4Adbye5Y- zfnFPe)pe)l=Q~FEP?)nI_Nf~osn9Y|TAo(n<91*Gc~pXMg`m_>SM}h7q%B3%$OP+{ zE2A4w{x}Zn@D0Evj(zCUOmH!f{rEu2R;0=_{b*eMR6PE^Tn`%Nve^Ordd7&XHS(TeQ>-vZ znztE}c0oJ3Ats(-OO9D%!gqzBbcIN{AGNgZ zt*Upc&j&^AF4*a2H#xQuNrSRpi0PA(cIKEL4gHkR=k7>L!%J;2x8vM#u$7oN!2~@P z7k$!9#)8%}P#(*}W;4o|GpxPx2kFvuS}htzXgNXPeIP5R-@R(sUmW=kcpc)&JThtrm{ufvMVEH!T-XGQb$%w<6`{HCVa?)L z;%|tR+?nzwxhX+!NLZivb;i5Rl{BaEp8V(x==1=!9oxO2_{Mz-N^RU>pO-xzlln@A z9jm+)upV1-MCLZt`F|NSiBa~1CciBu3`pz77+U%Kh`Hr&QmKU>@eji2GvsSe{$y3= z--`|%EnAWO1`-+n=L>QGZ>oN+F7tX^)=fS#M)-$BczqElLQ0BPe3ugUj#cIcYk#_` z`*)rp|9dntcMv$ zhB`{{&`s9|^%ncTURbS7Uyazi6$)3hI{Zof5m0oDjXEPEFw5CP{QhO$-6(hoP(%#k zal>UEIknsvcAqw_0u&zPn!*~VF7;S!(ASOCc4F7uu683)`tZ=6@-9-Iqj8D~7&0-> zWiY4+1go*?nCXs8IY7ldvzd=4dd}Mo^HRC?hf7dnc+Ws4WDoLIT&u&1KD5x!VPEgv zIAEdj+m@?{M01^t3Z066dDcs2XjX`Clcfa7EYR3!bhPWo3=*B$kSOk5`>Op;o3D84 zqNPx#+&3DcqrL@1<9TxWhI*b&7n?-MkgpFpl%5|Wy#fCSA$MPT@IzfU{4&chz(*fq;UC4vdnPd{fT?JM;aNeiom<2|A&+;H=D>kQ^a@phulDtMQfpX zsspRz$X^PD*iO5unVdJ|K4;PMpU`P0lB>enyR=WKIg^&Jxce*oe;9FFxklT11T21} zF@F4Nq$=Vi)NV!Go(QtCX+wGo@B6FG;AnRD#+Q+c?OmHur(^uEF-As9Eq#n!mzC+B zIZda%J7o+mO=!O{Ye{w36g92Pd1Z_;4!TaIYXk)@f8pkl(;xL=XEqcaJ{8e6#{JF7 zBBDyBXNSYBpd8f}nbM72Fa1{=;>+Ji27)Bq;2;5lHh9sIaFAQya1?RyH&;ua-bvwG zTP&B7rR4~of8Ye3H|!xxDyP9QZgcuGaI43_@ud4&@4T-h4CaH8w@)uc*H{J-(K+x4 zhG`!`xMv}Z4z{Qkecsu(-HX{OEWcOJn7U<&Kf0pT#K{R(ifSw6))BS#ypYI^ojrcS z%Ls74)7f8s3fl&A@{d#rKUtR}SS&90HB7TlJ z|0Z~bAN^99pN(53Y+UWvGwd#q*_@lVLtmSV7&8}hq{iV_HaWCbN$jtF>LAMzuZ%P2 zaZpBvl`mEqf?XwJ5o1-vyC95H4i}ny#Cd zyR&ws^Ub#_i<`$;kaTSuRWncufmmA=c>Rq*1GT~xg0_&~Thdy7S()x7>nrS9#Wydw zP?D>iJl@54s;07~4s%qQ_g=m1E{F9$=%1OtbRT(Ep5CvE z*Ll)5DAA#Fc}ag2(`omTls1==3UR2^wKpc zRRo~{W=zD1O}QN;26efVumY#?)w@Pt^s*(Ly_&JscpjZ5ds5e?OaDyE10`#40nIBk z+sW6Mwv6f)w~9p!f5cYFnk`C>x1Fk5q1IZ!?YcUF1kI-HdOERP+&$eAbVH0aP+cvw zI;q)~(L8|*XWoOUcu(%ancJ}xWDEzUM}GpzJ#!rn1b6u(u4DTeFvw+GK8o&lvkH54 z=W<;BM0m9GF=n%MUe^%&@XbKL?p{|LjMe4Yj^(V3$#{+h?^dI*0B~J3uU{8I0oai$sd~om54Ra zcIW8Pi@eNAQI5M#FkmPCZOj%c;p}TfFYpg>GHwyzo__UH- zW{ST+1l%GLHo-j3IHhV6{Oo_w`FW@D`OS1HAEjz@CNt9PKA8+X+4YMjOqFIi*JD+* zYV?C<{YEP9dBrXL`?XeKtJO)2TOOFyE8-fI_#(?6@E(qNA0T)hs#740b$`jnZM+Q- z;tO1NrTJdj3+|f|NtF9N|C=01*rRJ~>pj_Q$M~H2tcNcd)^SpWq)-agv5IAkr3h+tu(|9nzyN@P?xY>h-%}| zc@_j8b5uKbm^wns`djj(GAn?DyNE~(Mp)1JZ2HoPxo!G@#K&ONy^sj<`^h+;<(Obspl08X-GilbPuhB7q+8&=EHZh>*C}58 z5FQ%Ps)L^6adX8QC7x{F1E4}Zck)}_u2Gwy-wqL42ss#XmT4T?(f4J`?$&k+f_lwy zAe2|&|1gGU`u?JJb<7uEWiY0*83OeV)9cQ)%l>XQzF^-^_O6~?yA=z5$tj<{6zTC} zT0AjmYU6^z+uJoeIwz-LzY0_EG^of@9Vz>b%HxiX+&<{0DC9yoKbu42+WOLriM-)q z7S!7?)G8`tO(?rgCE$DYg<^A0!DaCsHQ~e_`N3X%w{wGLsB-^g4ZiM!X5EX+=}tfS zSYccC{jbscqXubzgrj4HBK1!+{Co2TC821!mne%F0};tjmb{lSA4uJ{^Gnro0iOaI zvBjtOGpW6twlc2XwR?iJ4z7?>@bzamPGcRv?4SMp-b0zd^1g}J7mUkOz5Nq^;J0^x z?BW*i=Zlb5mC)ZRK7OP+p?AuDVjh{wHY{C+=I&Y8uHLxzf+w4pB-&c#u_)M*6Lh^> z|M+?Fz0rJa5+a?%+L%oLqA+L^J(?cWfOmVY#Xfvn`}PUrSWCB8*O2rNzR~dny}f(( zp<%)}2@xK}r~`Wcyo)v+p3sby!ZQbgL+Sf(*t34bmk>Gll1$A#UJv|UCv=X_Q0gD) z*`JSGzoRA)Wl#8!_2=jN{QT?R)c_9k(A%xZfBp3n@2|h8|EC(@zn1dqf?Yq%4cuEg zMG_BM7)Cf-12marTI&}B&#;)EYBBeySp0EzDP@1>E4hg2OCrW z-up{BFeww1nzQ}aPk4$Smddm2a#_uCI+>xR48@+!U%H>C)>E2U$+%y71^!vjo6Yvg z<9w*=d%K>N3pHJy`ZOK=4&4p|8@x_$A~MV%vPr(Lj@D80SKD5kiAPwx5VliU{Nu}& z;9JBUO60H}Gb;N`=+@`(NG8> z&W+ZOJd7J0r)~^E{(vdO=RhQd$PX1k*_~$8rJZOb1-R$JaX+b40n6>`04BP2ao|rG zBU73T1c_aBVD7PD@sG^N^EPGVjZ>XAE_XXAq#^Xh6oit!i1L(31rR#0z{I$n&F62z z_oLYARMp$Zh{}V~5(5DBv=;ky>0i}{s?r5CrXfY=Z(2VE-0mD_po}=n+$k{h@Z2Qs zWo`YfoovXk2#81SxN7yf3i?C|7PbiE9^DbRHnuEFYUcguR;L(5ya!%^$kz_W?EzWS z^!O*%D_BS^_iY^R_63KFCS*DA)T~{=YsayuGR*ajoQWEpaJu~M6-*frYZjJ>+HKC( z;${lGd9@N

  • +I)|szPcBMN;!lFrXK6cpfGK(OuMM)><1w)y~@J?(HE<$8i-MP-o$#USL9>60LdS!i*LpHjqIf?5+k~7UEGEmu@+Pf&IO|Rp>@Mj4VA+#p?oC;dVwRgoECbtR93-hR%FrEdn;RNSuTq#$Z zk^z)5vXp%pOl%`T&L4NKltU_L*4DCrV%I;syjFQyTyPsaT+kq^<~so?JDx{N1rl=e+=`_x%E@VaGA1<90-LrJxcQM8u$mCHoD&r;8OKDjX{x++MQ(-Kcl3uCG zz^s;`Z9&_oZDLHKOeL~Bxz5^`;K`_@DHu0S7*L|4((rM3z4I~nx6f5N&RXxIL07qV zzO~K_>ctvB@iC3mWfYf748ouQeUdG*AHyQ?u?s1vs;^obL!&!z?y0=(!Ua zKk|(k|5ZHzd0spt%#dUQfXzj-#u&Ruh0T7+7q2uqv!Je}*n4SAy09XPPq%84jp{GC zOd&ZHsao@A%geM@N{ZoB<~}j@q*cR>(tpKF7u*>u zbZohW?rxzfJ4z#7J;E_=^gVR8As%wLcI>P``kp!Y8|=qU8qS=PjGLOQjLbcCV{SH9 zfk+F3Bk^8gv-$X3bN1py*v`QLG`h>0bm$t6`H|=`c9Jth>E#sAEZ^YXb!tSb?r%j8 zudgF>?DN=*v(JvewJt-u1yX{QOXW-5nfq0Rr9>)l%-Gg0&)Efv(+9(D&}|3Al(Xa5 z7*s2|FK`+mC54IZZRucOzqQu)(zk_vt@0DV%1T_;q$5#1ym`m%du(gFHTw@dhLdCh z_Tg)GYlT_7CEN_BKS`vFEHk)KFLZf)(sZefth7GBh0^x(%amk0K2CC=#mbFu(<>;2 zOeoko5U09r7bgG8$WaZ9_ztwIa>46TMv^v)N32LZAzjYh!#M9wM_l^GBu|SibSoWB#F6$JxGOFqZbyGlO zyyUK^KFs{m=3)ntszg=3%|^QPZ_Ym=;OU>{_aL)^^bj%Gb z8gyNBN09GwY;ep8T(jfnILK9D&YgCBx0_YFN?a_6H_)OC2e61YWMhq)N+#;WiC2rE zQtBr6$yfDls@JJcXOlV2s$Oy<)b%-_Gp>E_8?t}u`3Ri5(*G??g25@oGWxXmnW z5~2Y2NLPFPYO>F?uV`JdgFl3UkILfD7AeJLh&N#%c3Wlnp`FF5}%FsVwjvOiT0{rdlA5gh#^M&)z|89D!)6ZnxF|Y!+i3mGp$S<7GC>_+#C&k zdJsX?eD<1tXp+Eo5C^qUXY7E9jwCfLp$3-bzQ==|phY$>FJjafJ0YW-51FlG@}}Vt`yRR;N3bWy#%>4liqcM$8@@ zN~6{TKSYLW%W<)5hBA!Soo9u+tiD@Z+x#7~KfCKO5@?Yek`lWyOYeG-i^Ywq1H-g* zss`gvm(~GmqQNpilrvB%)e_@dlW1Wun~>xju_}WKDBrJVdd zhUYNWOCYe$Ln^Z&ufatSH@9-`&O=Z=*!euLmA0I;BTc# z8HrY0Qoa#Ro}hi%scj+i&XOO-QU?5S;vz95CYA&#4RApQ+N#N5K~Os0JgX>b@fZ5q|q65Sljc_@Ko6oW*P133&W3&Xn>32-H$pccNWe^QSFTvIbO~GTP3SR7y?3Ha3!!TF_?UQprH)B_}j zHb+bR>b!p!jDGO;Da=8oMVs%Mamrm7=KoC%sK}vN4pFSYS1ej2%U>+e;vg$$lxWkQ zqF??d107!ouvg1+P}B>FE4RL4SqR*N=y6xontl&mc)eb6B~X7BS65Z=$CRGC zPMti~U;Uu3$rAZn=S6~qqV7?1m&$T|&jl#D2C*HVRt|(}*pZq4xmjd;Ez%Q&HjxtLiZUkgIJfba!EDfxlnTQ>aSuoq=_awtF8mfHann6+nGx6N1QSGLBDEhYKrHM$27a8eN2I<) zM?k~U^tl_(RDdbTDGfoYfP=N>A_8$17_Z9KygI)0q5{B6hm(7MQSMwjLu|BPJ>o72 z4Zwp$xeO#?;7+sFH&AkO=uP215H+Z0+aG2BxJ?!+$Nf#-kSXtu@i-KUa}pXbcZ1a z#Ouf8Sb1;#&Aim&?Ap)feS;^mEnaqA|a)f6^dP1*sAy5e7rS;7Z z{@%UriY#NaKVltl+*My3KDL`Q3ny~)R2F5*Xaag|A}WR)EbtC#Pa(7&{}K-GB=D^o zW&;O;z4)9vd5j}WE&`zpB#w$Boe?TgOvlkTlV>!TQ|OlQSWF}-GI33m$Dz-1Kl1^yn(HcM~M$0E2zk=N~e7}$~HU6TV zB@cC={Z)48)~+X(|MZo_FOD~O0es>?Q{=cEW{l}8bI(_??&2M$n=@0(X9WG3D_Z@e z$~cRss^oXM#H#kv0t_Q)R2!7n&S=bL`@%Ni3fE!I*_i>GPJ4f^DRNjZ5`pP1CIMdN zLD+(}v@7pvzN2wTh)3c2-w;;)^6wDvd$PnC(MhzN>+F1g9*{5BZBKuGsCpda=sSQR z9^oH(F$~Cy=3u0`;Xx-eqs_$lnzWK=nPkh*1BA8NiNeTKEcrpsQZY-Ni|OkR!8$A+ z+sd2;T+FlHEJ?1qeO?CR_z|ttVN6Fq3pQYpGa^c!Fq^tMf4e7_t?K^V=+`h^$5MyJ zlEuR`+5?G#Q9B+hO)aMiHTkHycp^5}A+*@QT)sk`5C>oBE}5n0=Dyne*S?Mc2W0bk z6AE%SSuUP<0wi-o?gUJ`elvIpSDhoc>a+CdvBYoV%BQM)A(mzHX=}W@Suw=4c$4iw zJLhyMA{8edZ}BKm`DteWUa}?`Pf}A-kmygITVB&VYfp0LMa&hy2fDh~(qf0I23`Ul z3a}WoPULm6+r8U`2yLA?C=*SaMJ%i95(d53d+iDJTRjoq%%uAa;{|PfR*5o3sGZv6G!rYwi^?0{suY*KLQ<0J7M4`O@JDYU)-SwV#s zu_~uk-5~4^7;P-WKl#~giWlG@sT11Sf9k8B90WIGO((>^>X@xXouL&;JalOc;CCWFj&(Uj# z=EEcP|6$24nWyl;X8bXgY|Ae_fvvi*#Pth5u9Ewzr@1hYNY3kT*WPg7ES}=SzHBK| zB2h&IyhWeDwXOec&*5=Ne-fgzyx9}zP4UWT)#;n4C2Z0Dy65D9{0q~E1?CEg#Xoi9 zAsa^=D_O@w5v*|Ww|B>1GQ{>OhfD>%=d@Np>bjy4e=j__UeqWHTLl;2uM3Z!YJsn2 zA6%{_l5{?L2GPL+rRLC&iIxfGWhCUb_w7J1&{}_+Pn(WvzY)mQ5KI+EM{IBns_Bhr z$sMy4=m-5?T2ZtwB(^U?yF_1kTn5QhgI;}f1r0?=SbO5W4-MJWD_m2kYvvK84+&`| z_}|d&$oS#-9P}$8`tLE!R~~<&IEq=)YZ#MQD}~^~gvWzSVKttsR0V;)pO)vpse4Bd zgY=_Cp9GdjOQ^4*{2o1S`@a19!K&IH6*2lpCh8{6|8p)Wn>xGNxTu)A{HL=U*+*po z>vN0hL}pgQ;%7nf6=fb}2_`Lra{emnw4t=M%BV$3JXIWLI@JLsbYy48N%opa)*O$K zic+>KN|~fiHWWbqTBl6q$RvwEzU`UARfS7vaI%9*N~K)+_Vr-hc}n1M)A{2u+xgP_ z%>R)HN|6@ftQ@QkExa>~ms2u)6a(3z<5>CgokvdY^$dM#kQwYOSGzMM88CM!^uN2Q?*5J$7S8nxSM#sft`9VTPv?8@q;kll zu6+G!RAU0DXHZ0+7tP}6DYi6{(^K2Kk@Ti1WI$6STTRvMW@BV-a^=4F`gt?>?pUJ| z1+okkJ3WhhgfnSYN8ERl2+SnDfEQa8n341@@{js$VT9P+p69v_CDxm1p%F)Hbs7FD zeKcjT&$f7{76R-QPaX7$(UzU#vKG$!gF7YuY347rOk&A&J?N^P{?M#Z=jLtY+oC2n z2Hj{~n4q~%62bKf+{na2jhB;)QR5hs!<6_wtcxERyqf}*JCNY9|In!;4?mx6c2hxx zPoXN|Em>dL)g(8U^=507xSVE>Y@v7kJ)>lM2`YwstqnXORJSHjxY1;3wmrb>pSGSn z`>Q`Fkr;dUWVYxF1GclozmicGMwUe$v(2DU;g?ri+P@V44l1VJtJ;R^SRg7Wk8phg z-lNs9NFQ0yX3vQ@%CVs5-^xS|Cr7Y+n$;|lJl0JY<=pQW*0csxS6^(_3(oivSxvztPy`QU~}PKX>kng!6eZeNhG9i7{Q6>IY{VGpZdUVZ*)h(l?G4J{j;r!=AT8EdLtvVRE*OK}8(pEo zBXh()oj<4y&KhfKw~aOzcuTAQ=MuBKeD~2q3as=d3?{iYhaOVx4vdfNyCJjnPzwn~ z{#F~gx4IZdmeM;kpWsG_BX!K|G3{%@Qy%5-ZHlY28c~tZHjjHwr zOFZEJv^v7#ORVz4eIKphz!0rqe;MsZ*k0vd=QK2ystNrdit)<& zcvG^ZKj;VpmGzC0F%dbYTH_V6jU$RI(pW`WbYW7Ap7ev^`~g~dp0pJ}7k9Ui5gHbC zER;>}>|qV1IGBJH;H#4|F5Eb-xHE1`1l?VHU1isXhW164zxY4U4Hn|44|0o~Y6doa z{x>P;l1F|8+8XH6Y%($EoBeUcW{_SUC({wgWG_<_2$Cte*hk8@;@K?(S7_dZNFz_B z08onq(~OPVd60<&SSo#Y`f186 z*(8c3TT)<*L3nC8+4rSc7jo(HA|WWJ>xvYTe<$Ruo8kbBC=R5-T@H753vR*PU4y&3 z6X0-%!`;F_KY3kwNWU*dV54zLs5fsdALZg)1+T|JIJQrm;~}=KKtz zO~R8W%;5GGKz3-iP2{&DHY9C`aivK{SYn8As$Qh(nga_Hc8vSXQlV~_{>RT0_XR{K z^#iM-bNQv6t@C3gd@LF3gpQVEd+5OwF=lE^-6cX~&EJbu#-W%{Y)$C!Pc1pzYsP80 zInn~GLBQz8i;mtfW@<=HqYS=BJNz@t)V44*=|OnBW~32yHF>_FjDqd{@Q3(!a<~Z| z@~F*vG>j#JJcSO~{NMcSj?Rvr$Fso4du1JI2rTrARk=qwjvmBWN zH0%b|UVO`oS2~kF9`Fvr_QM z=+GqVPti2QoG(rjOPM8`#EzdnGX2ArCH<_4R>J`_WYqRYegpdOk>XNyaiJ|^&rNaE z5rjov%6+{MJ1^}ELqx9@QlJ}*PWO}}D0OSVdRD}fNU?)8eZW&7SiWFEgR%8^6y~@I zlCg7FSdn+EBcTq!E|D59(Z`XDX8WmZlW51hjLz4A!t?iUr5`hlY4(UQ+9qSapjq6h z0aPK~X-Q12s-yLy_C?$dKaEQU*?3@B?59aGn0S?yn&hb)qfWCX>to4UW0VjRfjJ+* z9ZsMl78B@{$7p(*P&Ltm$!l843>7b^TrrIjD!s{3$+#~G2~h|3%SR2PE6;E8Ui)jb zGneHU93c;ggY<5!H5d6Q#JoKF>n++}Bd7&^0G(zS3@0?gXG$<4{Sb9palF%6nMZuS z^JsKo-5f!9tJO3dA5GcvQ@@qL4oayNN(7Z)bbEVpDp8#`PA1tlj|)VS-e$%zlHonv zi*1d|yGns7Woz`Q6(37XsJcP_jtYvIMYqYoVxIk1^%~*LP&dG7MMg- zuUsLc3q|}(+D2Rfh{EqwNhorGD?N3amUY1HBl#!=v}%Og2NiZC5utWQ;gU38<)Kw$ zpO~j}?nCJw`U0V#ct1ctD*tG;D{D?Yf*jI{{U?z^cpuCL-h+eRwlF*6V z-bUor78rRotybVsh|_9}W?!h{#Frc?00MicD7QsH1uzd^3aBwW8L_|6u0N?ZZAs<_ z{M6tUYeX(YL5V*k<&O(!A{%e*c`>WW{s@GlJRIZj)&qM-%G`8;h+n#)ksPNJfT2c9}Q zo_J0MGe&G7I9G5qc6_*9uyX-2kFR_PJ+mdMJWyDxTtbe zyj27Tel#Adl+EewxxB;u>rIJZ;)kOer3gaV+)ITQ1&?_P?{=IJx)(W*1x;@ZzoJ~` zk?$B@b7zCE#>zkGhyJ2RPi4}Y7V2jVK#mlFD+`LQ&m~dKf-s~ei{O2Pha6kk5J!v} zG)Bf7lRClXnJO0yW*Iipc0iWFnQ=@@H$yGKQ*pPgC!MBqH%(5iM2GGamG3iVbYGpw zAUsDt1n_vas|?6d5zK$zeq)QOuCcVkezo-G)N%RWQ#Ub=DB}0=LPMrpD_QLRYKnkS5|Q# zAo>~pwp;PvvxG^&zgaD|=Sg$ljeS1UW~rDZIoa@p$j_34l1%J=uq)phF&l~$ek zx0B8Eafuhr&r{!Ufs@VBS^tOILI{~*T!X4nE`F^rKHO{LwoI#?!{t_- zYooT*JwfK{(J!0cbHRn&$Nf(HLrr1rui@C#w{}E+Ageg13#U+OoSwlZYTTZS;%iko zpNu`+&>L3Y+&yigcgR-%)8V*V6aNEhIUfZW=>FDWh}+XJ)RX(2yY-V*mT zr*3WR-$Om_pgaO5Z+E(eu(hv0S>9szej^4LK9e_gneHjtzomceokIWEAO3L%AJ;We z-OGA)gILRY<>r5bWZ!MIN4)7ZDNYw6$jyB^vcZ3gJlKhNbN4KSyWM)rj6e*FvmrWP z*9UsZu`DA;XX2@C>@F-~UvDNSV1#3;GSFO8+vskt^Oa3fRdZ=+g{{|rLdwNYREgx|Z6>7p{c65urboYfZ+Y9U(^#J{AGVk5FIn@2 z2|3l{!ZFL7-Yj_A+Y8u&Aq3lNE7;a2n$fC3EAF*lK`p~Ja3Fj`$lxw|<~;(J%lR8`hm zRhJ_!cQ~o^VcAwx)lmA_@B4l4(_3HKT58qH>#^id4WC`z#6CxGK=Js^SZ-6Z@j$F^ z@dSMzb)KUDcJLNJTmJ3ffFc>3{{*Yt)y&5?(Cw#xC<`S|>;RT`dt1@d{9Rv?(mkIO z>&T$7vL%f?w<3DZ8F}tWk!P9D6VD{v(&>n7wAdc5DC@+8we=6R{ zrH#`xCk|s|)5ct*>2}>nLBw z+(ftD*i8!7#@H6&D?i_9pd_HgD#o;{S=Z}M=M?e@rUX)srK=VSV7t3P`y@uOMRC@q zPZJ$Qxc|i`!&9kGo*68gxuTRrNUwu;W#}Z6`fbQ1GvSI4JHWJ8zHcVhEkIv*!6qzoeXaEz%VuVVVh!K*J?%k427jsOf~VG0cZ#9P;zjMerM6CE z3r-H(s!C-(vU@7XOi%?CBG^d=Y*l()Oqc*X@y_&lDJ0xe*S|DCZV%qCy)+~~jQ})a z*$x5i59Dm?=6_1);#eAIOaiEyfy2Azw|Nn70|0{rV+7qI9kOY_nTQVAARwJ=60kN< zFCIJA44ei0XMA=6sqrY|n2xQiZI$UYw2hk?6|mhnd&2SU>Lse0#k;jEq8j{4z#a zYa`-XZA&)7pNuu^>}$F+8KNmgr6CBjL6rTdu++3M`&?cIf4_Je#zIi2)T%3MuBVc! z_w0uX9RDN*PG2eO$)JLz1SJMQ$*DfSwVO0n>=yW8=mJE7_x0F6QPZ+rzkUR^x`wJ=a{o{Lr)KX0bZ~;{`?7sRh!Kt!^rqx!| z*vidOvP}tl_L|Y|ik-0Hh57nfl3(A%OOMw&oTTV>keGWqdT0~KxGEFQKo+6dc_q0A z=X3c20*hO?%IWUz^Ov8K1%+>RU8sXzIq*G>cHbsCrZ2-o$MZ}l(I5*NPE8aN7+6Q3 zZ8CK2&mzUnJJh=|ihfJQVMI!3Q1sgsnbicPAQs!s^c8(w_KudNQddq(0IKT^flQ?- ztke%FQYLJaOcPTv%u3-M;C{Qs!z?DHR_{}_)BONweU&mA`d$C|p!d z(!0w&0>PjYVel8VcC%m)+~X8S3o219(s zDRP`C{Vha%VY;M>Ewoj-On6fc-1$d$@iIn^tq80${i%uKRDqHR;@Fjm24#+uw&v<&82DmhjLId*_FlFW z1HCGmqvt#ziupSgH~Qjy{RVGkO%|`8lHMX@R0Mk!dxPxkCf6KsJ+D!7q-(}+L7fjj z#btkkd>+0>nrue?8F%YQyl6_iygrPl<^d%h+;2LfE)ZOhQ1M&`k4@jPkS<8`gsU|R zbQ?iTFGqj?0;5Z-#@x#vBLL0V()wXnl_xHZ)%GVRxeBS|^uTWhrIo7YM8Yy%xKfky zOXWQ6eM`qhgp&D*r$q^4>J{l)bLyG+_UiuP>->8)O1!fio@#uNw2?VBLt#n#u_o5R z)+6KT3r{k?uWf=OO`C=zaB((ei;U>YM}&*#(A;tQ{<0K_@}qXFC*gShMuxZUHt|=G zag6vKW$?ZXz{`jzySMzXWntXRV$az5UH}vC$yktSROE6{B0Pc*>j3G$9Rfb|c8e9I^c=;OMj-i+wo zW$KFTyu<5>;Bq3~9{z$e6zu9HK*#1NcevM<7K-88>!ViHk3kk)D)tw}C<9+bJ>X3g z{p}YgLVpJ2eI6$Sf2y94+^DcyggZokTK_QYA>HR{^L9iHvw zlmme)*RERRQ|KadBrs{qvmsv4$I(p@@+n<6%rk0b2x>6qYd1fWSfbgnq?YX-8$#-W zC35sL4eg&VYJNXEs`4B46}5YaW!(+cFdqRKn8a1rtR;qdeY3!06GHKN2Tk$mEiSat_`$ zXW-0lB$##2zi29m$f)!S5lwtC-wae!b0e@xh^#;W&Dq&O##SNtZr)coEjW#Si8P^c zWn7Ps)=BzB$TiA}99bNznLoPwp|p#ukY!VL`I9>i4#6ZU@)enm9fZj*eE zDAOCfG#ch+DrB$0Z+>SR#W`=pb0*ZxoG-_$pJQzsw;qd9^)iXtUj%t6OceaA#@ute z1R8JtBA6{eiuHrgb|C<8r8k+=Pb1#+g7oEm;Zz7n!v3%whi6*dw9aiih<9@Xshsey z-eI$gHqg+%H2v;e6r>J>ni`fWh7j!^8Q=i?QN52F346C73-B)lIDAM%vR$sr`*)ib z@6eRrcgoP@W>6jhj(Fk@@+ppreKRkz8EBD+B!6zGhGz2Apgj=SwE4{{`C;#%CHwAk zZ|-ne@nsftJffA55+q_F{it8iVs&<$U^% z^B7MeR{C_p31gdm1d~}9JD?=wGX(HXM-|>{l;KHOypIHL?U2Z`J)pgBmqouVTtyc*ZT@d2gf)%;imi` zB%&T}f*Fr-(t+7u&l@vSsO4nmm@9srl7W-_EBN)HKS&okmy(!sJ@g#9VpCv|0VtUX zt(zI^S`FI{QpUD)QLdSmEY=8JXcm`I=6r~YS5W>Dt_@Z zhFsZ%Pl_w3fVdGg3$ZKf!CEUJ>V}C2IN)UKMYlG8RcQyi(7az3lISO-WR4i|a$VKy zHGX$+(G$*{2RP!ZN$a#m5{wpPaT7IOd2E`Q`Jy&C;XbvCCyritj-KS>W`j6K2gNgN zN)M8M{nqJZ?&dtzsu^T~aa`!Z-1GdBqewSttS$SyW4}R;vhw4TbaInk9^H*r_nD$w ziVRxNdr6wG<&5}L1KJLY!H%O#4NbZlS$o}EZgGY}aU&XQz1?&{qiSW{F%%#X)k1h; zy#;I4y;?AgI`5wMqZ1X|imzUCBbdIqyG^1Kk;^*u!2AlH09-SKc15>Yt{>ymJiBjn zg~wmxhpcGLwg2@B!oQZV2>y!2VA;O#{1Vn+p+_WnP4h0FlSJ<7Vqp0i^=y61IK@3K zt#ph2*ajt%?W&AsB{l;7s;z992;FTRZobG*H>+5Hj?+dl{AyjbK+{KOsL5i8=}P-3 zj@l3fEdDLIlH((SyMn=)XNfDQGAMw(LN!+g$5>i&otEJo?hplh<$hTv6^jhEy8{U) z;4nO3zrZNp-k8Pl-oS(woMcAuHe4*8S~)!&ZiIb11F3UdV^D>N1T=_pp{TMJD9^-&U_U%1#?Xnv!E>zcJiOgt7)v`XuvXSxv{`h^$?~i_ z%0bsr?ttaZ>#9Gn$iBDKm{7}?CVu7Bp~yImq|-s(nx#1F@btwJG|Q}#15 zO(5o09D^T|uQzMSDP>wAbDwWyJ|v!Q#i)rL-UG@W+nA(9`25kM*awPCgnCZ0*3ldP z41Xec`V4Ym^vbi*@Gonup=Tz7BxmY%kJfT?HZ1bB;t@UG(aOk_$9!RJe}Wetf_@4E z?h?Q!huBRC;`bnd`=WNA@xI;3KZR9!4LRFV8r)w}w&gTn!Fu>C+78mozSL*mUnJzc zaat)8CyR&TB^vngk~{y%++cqExD)ao(CvpCae5^d2+Gon!ow8dS>{yIBfxpH5u`>c zxv(1scPHse=sM{ZoZ;DLEFyZ|Zyhwiv=vOGE>kC%olJu6LW+5Fg2$Zr)htW6TatKZ z^T8eV5ZWeEHf4D(Na3~^#QKWK6)Rk%1P)N+Kv#prLprRX|+hJ z2TnZh(A&EN;{`O5FA{7#EpnybCK9cG7h4`64yWF8n{lM%;Ut2S6|Y{EcfgTThcZ%;!zGXY|8J{U*D>qoG53k}8A3&`#A=-(@ zQn8SaXs!H!AGV7D6f^SybjB~gjKeIDl{zROvorNGqzeFlQr07uyyoiSw@g)R4i+eodFkC-?Nv)?^~7iD=JB_8oLD zW4CwAm4nNye|YV2tV@|J%jv&%2k`Zzcz(JYAAC-h&Ua7U(5tTaF4Agz6d*kc+i*S? za)&88DhGQ#=t}g;%pi_5K$>>Kg5{xV#dn>VCy5PycA()HSW3VH@U6;N!1YsOL-6DX z>JrG-(QsOJhxs$N`P*s0#}T#WRm?Q%dM%s>Y8oNLxp#fWwbfcd^FG*i#Wr16ZCqQ{ zBB9m&znN^t5(fAdEob*z|EgsAu+d7-u8dI|&o0i@{glceMlh%nj?s%ZUw0YJ`w&m0 zR!=sK>;lfNJ(fkihFUHO33%3!pfte_%WjHcRANgtl_)%5>qV7M&V_nB76ZgM)COXh zAsE$ciltGD0tMF;(wO;R5lpG~C~&E=7+O&Q6V*V~L(YNnhA77j{y4`D{#?hl!*c1@DS%uJz2;(?wrp${~3=GqhK zC~X=OcZM|jo`Rk-$u=~jAj&qh{}|31e8589x%KAHgM#Oya%r>0$n!VS8NLz zgZNzt`(5ru`@zMg$_M&ddg+nH6ITVtHdHP2Tc|7aczl2Sc>Hku^e)RGi=1KFSo~!C z=&s3_1&v|a5KDS~yb=7MTBsG`0W}c6vC874urZiu&C~@MQHmBTD4C(Eb;4T9 z1?fZ?CTAKpAAX!A!nq~V+7yL3RzILGPht+ZfvNPERpIbW@r(-PsQE=@2B^}7R~gvh zg4v>O<5fTLl$%qse3^R$p)R;Oxa&9~Y;kq^FR*;3f<~nb zB#4vJK;1*rf$D~M$IL8|RmxKI9O_cE9OhCCi9^JJD`zUB)-3VW!BM>@Fpon5_U&G( z@{uPiPikEpdEjO0FpzHyOZPBjqS%8jb-P&4yVdzD$}n%nj-F^w_yk@i0{S+9{<6LJjp`AP4GfXVHj2>)7-2yceRlS4s3n0)!$ z+3EkTM?|dbP0jvMj`*qQ+F%Id2rTGvO1H}6RcCNkSFgBMwktc>p@D})NLLf9{BF(G zOv6kk-MQpA6S`i?V9COFdzIiKQ9d97K+p2tg=sJM)4mon={GO0v$H=SBF7|I7!@ z#>`(pL^we$Hm`_L=@ne?DSUN!(^-_4g4peh8_jL2T5Hq>YmMBZUDlm%UN?39A@-aE zA_JNCVWo(H(TC!knKP`Yl|BOVhZ`+L#c|ea7+ogt_Dg;XCt;h9jSaA0J=9I>3Pc7g zBI(;Ic5@f zrro!FtCgpVk0ODjZbtNFC?9#EM|HfxV4Ua8Jti+c#9`I~1nU~7g>|=VNVD_ScHq^q zG?McdOAz(m@h3YVR6FsrasZuC9aMtfmt~8$rJ{6J6qEP*my+=~a;NiIRCY2SxiK@5 z1|TbMX|tFQY{~TQBPzxZiB~pyr+v|Y;JOch>I`;*{C94&v$%NQ9 zU9K~U*L00?!7fH<^7iLlKbOh352}GJ@w?(XqvLHJmznoBx4TFDpHxKLV|z8hW>uj0 z;ch4m1TAv@6a&|n@r?N}EzXO_llyA*!S9nAsAKj)v1Xca&DqvJ&{KFvtt&Rahmf~o z>te({!Orw|u4K2^whqw`bYX`aXoWca_==%FP^o=Y{IfeWl`BAh7L$mV9r?07yJfi&|YyjcCKpHyc4BfrRa(yBppeA zKm~v=1J%dIu-((3Rw&as#=ZB?Jyxe%UqqG~aJ^W*75QBs^Z|QXfYZ2(+FcX*91R?} zxK)%}b*+(P zx*`$pJltM6kq(C+*5y(oBn^xt>9*B`!8B2=-d2F>(Cu( z&NX-WDve4iDnm5V>Rqb-*%q4d5fPFmN^O^UJ;cl{QiZkalyUo^Pjb(Vb8+Dz;@vp( zS^EV&(7E2!pEQpdFY}ojAt8TA%L41~gTZE|%3$T?yZAlY)`6s183jR!F74Xh{nrU6 zzkc1G*;i@ziC1H~MLEwbqh^o8DS`!$pa`CD5F*tEqQt9c>&jks%6m?}Wk~-w=OD|| z=Xx!X5K@cZx&XrZK?dcYq`l-{aJ$XMmN`QaGqAjajEbqh)MFFJg*0T>E8^NQe2LrB zuf{G>I!@qnmscE5S33TB5{OP6i@r_bOyb~D5JvQ(3Fm0C;oLzj-F5W4uvic)$?FVf~%u@RsD~C*#0eB@ceQyb& zbZldXrX#rX7s8R(`_%E7NakF>Aaz0WS4j?aG?>@esWq%K#r2!w=ii_I2FEp7B@EqH z2nY>02#9b06%JJg6B{#EX?sUES5;SMGb1}qXCp_)e^QdH{_2oqhUvfkWYgOM(*Idt zUx|o$rlZx490;j93Qf2LeF3qi_Pp+oza_)hSvv_p3J-h^j*xioPotqDwTdZGl*5^q*V2XJtx?u>@-qRB_l?k(XkrC9~n+09yoT~~8yML?k zukSFC6hKXGIIpozj_HiX$n`gUVS-%+n?S{lI(w0)vkq!6z*~$CY?WY5#{#O_lDT3U zeQ=UZ7E@l82g}9SvL;GLr+wQTe02F!30SLhg4AcY6SyQKr};6i%AWztx$sTt+fytx^vkC^9Y`*M4ZLH4TWq{Xs ztbuN?4NsK1T*|^Us*kNb;;2Eip1a*9&{FiIYm&*UTyW9h*u}1We%vzdr|dFLIOoH~ zDR^EUc&A62`;8BbF6@_n)|CPZ=S0Ro2*tjr8;_E_OT*?Udn`cqXC@lOV?N*eWnBFY zzg}804qMW3F$zM2*SkA>vI_#Q>om!n&mHy~)6xYD8tft?2XA09x-oY)f~3!cA9k4+ ziB*ovw1@?e7*88VxmYlRwLx_6`7q6_A$DWzBxamKmkt$i=orcyeb5}dj`5yaS+*$s zOgc=ti!+5eGBcL=yLn2YcDM2`uCYc~zP@&qUJZL_I>-_NdNUH$1aUe%q|MG!*7}ti z*a0hhaL0n<`jPax%$(2;B7Ygiv<0sQKhawDTVwY)%lDHi&KOGZa)G^q@1QQMa)UBk zzT&kwwGv{j3WN9}46!Sl!NkI_c6$9dfkY;pNz6}z)Gb>|mhViniIcyEJTnRv(A^@npTl`xPI(ru%8S zXSd3s{jhX0SV3JcB(tSV>%7s_?TSugQY*cz9AQ|`>O>-aRm0PY8upe_ZJ)o{H}Kpq zWW9R`vL}+oU{JVA!PtQ$u$2Yaij|LN>7h(6M;OD7StT#2CAC5G_KO?dmZ@@bHc2ft z*tnuiBc)1Jzo(JJ3c+Za>ixSR?+ThnWw&%?^~mH2lZm$7(jS*;yjgiMah$O6++X)W{lv=4vx>>uBs zN6+E4AMoOOhxi|9Z0|t!u2=={tlC zF3yB6%>Id+AD`kg`Nc$enpuC`rR}-AI>haNByOx6x@T@)JF4uk9{VUz999hhiaMty1`#*B|=Z{N?yRvscm0^*;~a5H%YI3`tCZ1IcA=P6|kPE90cw z=(Rb98_6UUG_C}|5#;J$q&%xvFdX+UbuKt4f4mUC)c>G+B)!9pXe+CDhI}h)v4Ex@ zv4WKCVRyOCcA4#Vx$+43`~&FY@ii$xac5?bqxmaeR}~Y9f&^J~ad-D+ad%kU-QC^Y z-4=%#90qrHhldR^xG(O9!{YXU(~rAc?vhTY`?r&-bf+q55B=;0#T>aKSH-+RJujh( zBqG6vDL5E>R70#2lg{Aln<-FN*V;yM{1v1&)D`X($!zXtABFLwy;3$T2Zn4UYS{b> z+wGq@p3sDXV#9iAH|m`Aya(naaxNb7g%z8I20+XM9h;>I)bF=&yo<|)L?+mLIiD!t zDyuL}%39g#+y;2}rY^km@kHdkr94JMMa!+xJsJwClEfb58;&Kx=#(c!4(W- zg)Ux=`IlV?rdPfiO3zfdBOZ#ZiG{t(Cu*RQ`q)*NKo5U*J%o9*ZtzPKCtm&hqNINp zUZLz(gQ@VB(}&{mjoUTOFM^^wh`Qe!6h!mgKN0pFOcSuz#$J@nz6Q+C?h)-Wgo){U zqn{1KpQQ_zaz6`?oWS-U&K%|J=CpiT9dnLhxAh_5c}EV_7^2IQLJ+E~zS7 z9M_m0tJ?j1ynJc*lSA1|Pc%=1Zhg2_GQl-{qMKfKx^I7>Hvdl7(E5=; zsnrOmZ|lG*I=fO~OD~DqR{nBLzG(49guF?7o4fs%Vf023na*Y90^%Pib8VNOW_&JO zGjYQ%Sp9UH9!iwWyOvWJe=suR0irC=cNi$2nVONfT$^4rePFlgsPf|&Y0isw8$I-5 zuK0laPk`oM_{$}cK|xUoLqXC0Z-D;yH>kAbw$FmMpb1{im#>s;krP8?C}tXwp^oBM zb74Q&5Gi0$C9GwoW3t&e#azM1#;Yr3Lp9JWrOsL@uv|EX^ZIpd?b_$+HM90@`gQua zYTNufyxA86Z+$6U8~jh39SCRO^fq|l-vG(cM2w&AxBGQmMQs_vxrSNz1%z|$naJ}d)LDFL%o5pZ-)7eBG&X6Oi(-XplUF$C~~ zUf!)42WXhUtEVreu9#|GjZ-1Zt`v8wK9yo#9&bHgr9S2D&OTOXzGfWj*s6)~7kP*L zR%PJ6Cw@LfL!okNv22_g{4~BbUME{J1lFO*(K&UBDf7yl9wdfKl_k$mU8+kJTBgqA z;r67+kb!)I%c0Hujj@bR0m=rsP#UTR<+iI40722e99q+KNZE zFhgAys5Iun=Q<(5pDFS{Me4%9de+AuQjamRHEq`m!_;dWEc9X-fy44L>sw;S=aD7# z*$b>9HtJM8dtfnCJVuNlMp-`@D)Y=2JMMAKhGKQyL#kr+-1}a|>b^%*#p=DMZy=xf z^Oh&}ki~00WZp{M@ak|MDWab1#tq9N1e0wW%PEqu>a#lvgnr6+&O>9CW!G#t1T=6HIac2-W~MK*+x{ z1LB_u#by1z2m0a0Mn*=PZoNYNO_V>z8|qo&C4<_E1|mKFtZ|^16~sbS{MIpAO<<#J zx9l12a5V(hnskWE)S0IJMrk!lpDsDH_rpnu01-Rdhw301eifk@yP7V&^?)s%otri_ zI&t3AD5%$ZKbBs(swuN78yjg^bKJJJoC*V3auwlE?#QWTkHGUFZ1H~Atw@M37ePI? zbX=zIq`ZUt@mK1gEPtjeEDq!!|iBc0Cw__iAl7e~BWizrFBu@!BE$4{9sMxc-O;zC6mqX}>8^>B8}3)sfVzQslotwu``ZnM>}Tp(jMBljA+9K~Hx z0l-Rl)vWsVN=byR8->>5%2OR8rpdHfxAj$DYaLLetr&E~yyU#xylCUc3h`hNP}eQy zjK!lx)d_#Yxhi*(e*;O%rzYx-l z^bRp^h{=7!vN)^PubQ<*k<>G&;tbz24a75Z6jLE#sox<$UU?NKo%-dF>M>P`N^9Ny zojP%TeW16HKvlHeuf53E)QN(GoYkG}l-+-G#KSk=HN0=cSI@k+Z{%4S8*9{Fo$-?M zboD+`OeOoCOW16I^PY*arp7X!ID#^S!hS!Xce-|DB?=FA_@jt3CdV@+AGq%a43=Oe zxHkYAmu4!ylJ+?+T%Y0sKPbR8>VKwwSS~o++pKiTHB62Z-`fB`sKB|cW2GII7f$x< zr=+hnV%ItMy#BL=PfD-kVSyCjom1Qh5w26}*BCkSgF?B2ITqjt1GqvxQ2LYO!~@tr zFbV&@QObJCi0!iH1ne*W%(_o(?Z=hh3DXmz0Y7>EDkYCxNp60|gu_QV-LkH2a;6WlGoDhJ`swT^ztVVg&Yo({ggBD@=8T|-{ zpIIHB^pt87t!NW13wYw<_h;x1|J3U<@(R z?_f6WO-*Xw9p3_EZuNEm>$j3pJ~7;^XF(CJWm~OrmUet}gX{SAf&t?c2-RLU&Fa)| z0`GTW3zi2d2SGKGHO~A?p5)lk!=Xfnjd_1Pt>>EGpw*;f)3VsH+zGnc(MS3IUiNLX zoC`-1GhNo|bJ-BjSw8S!BWt&t@wff>jsrY0)DEtNabBq&sf5gySHwPm(8boTuOmbf zZjV)Cn)-J1JL|~mZr_?;vt(&ODgNx2``m-7F%SM`A(&(6!HjGt6!(bb0%~YVtm}1O zYft$~bk?;7+rISAuJVv*sK`w{zl<$uVDTU_N#bufyQS zC38@Jqjj#fzggd@NiP?O_jZHTHkvjpP(si0%>W4mN8o>z@W*oln9kaap{WW|9L>bT zJN$)fWm%D_n&0iL6{wu;y>OTVF4H2J&G!UEjv6Pm`WxF<8(xy|w3+N3)y$ebv=c^g zYif}v=GlxDS9eRsLGlsXb1NA4YmR<2E$q9X(bU%Dx4S#wTabjFIr$fn?3@qfz2$(7+zL_om zfTK=_w2@8A--#Hv(RF#1aSTmr)?WL9c6AAPqtoE|A5>`cA_y>o3BJQt{knnqs8dJ= zgAy-9f~0yRv2fV@TJmh#-HlW7#o8Eo{gJ7hmafUsTa*#wrX>kF<8hdTz*0Ku1%hJ( z0m25k1w7Od;*vcu0Ktbq*<{*wyRpFHy_0+Qic58^vpf80@{Kp5h8ck61*XY7Nr5SF z%_EeYeX{hC%oQ3o*S67BIaG*O0DM~vcyuRKqv16?*`V0efuB8o@7&O&%sngo>QU!1 zThK?2aw(2p;moE`Sajj4~-M18u%P2jWo1l@v!*1J#t-a3saxt7lw|lT< zt)-JmOP%T}VX+CX=)(IOHaj@hd91}u8pdl-SLjSIZjH4%M@PT8vKXeAPhZ*PI4vC$ zWG4##bH^Fo#jEM*M0q!BcmE7Ih6 ztud=4OImKB@K^Hf&4q)^*A>LJVOU^O?b}H3*Yn}6GRFd^AV1EV^;yJ8zOWW&CZ7ri zD)uS)%Y(Z&M#0@Sqc|gszLJ1!mr+6C0;`ct52Va9)wE7rlXQdgYZ#%zFhIe>^ z`8OFehM{Y(wZCC}m;A4)6`aiUOeTsvFT>IvhrjqHM>2F96a0MplgWxF*R(b-!loZQ z;&>5&ijz?J&U7xRS+7ATd0g zY)fi&k&*b(J7hUhT zQ&eW>r(kd1#V6T&S1?@2?qkgl2$XRVdg1iM8uVhFOIT_TT#~pwJnmIAWJ$l!gW3vT z-N!W03^^gVwE{QkC}4NWvyDP2l$p(7&W3fNqRe02V9qC-{^7^Abu>F$3E_Jugh{@Q z{mn(X+S&`AWQ3q@+?9A?I|LtI;gW}rOwzx&jC(k!OH4^-doL`EbPj>;Z!wSHEj4=< znxFn-R=(KAON!hR<5~esu5wmAk-dg*W9ev1%vKwwB^9lGxEnkp)>*bbD|O|3csaWJ zN)@Ah=qc!DIc}uO2qdZDFm$$gucpdOaqCfMqLQ+^YGsyn5|0(m*=vna>d0;tie-Fmft?h>`Vlr$$4?TmUU6*e}<(a($z z%@eLlSmj63%{}r}d>KBL@0L4Rqazx2DSX~syGM;rX{1=6ZS(*#G3{}Fh0}!ok$}tc z%$X#5V8ABkD2u~X+;$=Ecr5vmw^W`V>1cWIXLctt{q+z{Q{O}}?FY_Hj8OF09%fQ` zt7&zN(i6@+*qRS{%Wk^2daR9j@z+Hzo0WbJs!f@$D{wEr6>n<%>os`F>4bH}M(%jY zddgnBn*MS?Ic2?)pBsDe#r7Sukc#QBgeN;$2a|&xmp>~yaB9eoFP*ZbiJ+`<$guV> zb@?|{AV#)VW*)NPg<5zL05)L%RJ%ExW@ycSJe74 z9XH{=B;pgJP5EmJGNxy94D;JcwQzhZ6XVFo@e2=!@PrWNYDYxqZZ`=BFVjIimhQLiY z`a$%Kzg?mJc>E@3%QAb9gm5PW{k0XwTi-eJ@(WDr&=LIwM06M`a3<-A5obTZ;SYf& zDBjg;noRw4-LsJ);cpp0!Jf-!$myQ7TtG`}AHPq9S4#CRmxaAi)UH&Z=>V6676jEe|qNdb1`zpBCsW zYLCbTJ|SBo#wJXF?AY|z#880tym-!X6i43DkokA1i~yl=B>d|Wo~u!Y1%I^cC}#;1 ztEFoXZVO3l>DC7(pNWs9qPCYsarE4Yucuv!hLa8JhthNti5H5_mOAd#*#BtK@;An@ z-CuaR{-o*pbLQ~22QaCUGN}TX%*@|#JwJME>tpw`kpcL4Q_MpgMvEmqcp;qHPHpv{ zk~%xl*~Nq_(Osz6cYqYI59h2SgN>|OD#6Tj37#gM0CT0is64AFm4TXw;l;^$|h}bjKrioxu*-yE7P0{X+5#) zN(&acJdwE%Ytl~=6xs8N zX7^X?L?IO3t{9Z&;6KKoSD(?wA`g@4u@D@wS8roXigP!QtW=tEb*a!yBXOw9#>wxv zOkR=4goHC#>A^D;_!7QD7$Uh606;5fq`_?NOU5Dgcp-guSVfA`Y-5S<%Ki+hS7gPv zM-cpnOx_VfOjbz}!sqq#++P$xLrI*8a`GcoIkTO}(c7>_jPj`j2mWOG-5~{w&6tVY ze@rF8mHE-dI56barMM3S=NIF5mAZ5ry?SeM7bS04gX=BXIURIlcZRX6fEevM) zXOM<7x6a%!c8YYWV!cf5$INBgQXvMJ!QI<|Ch9I3Y= ziJ-JOAlRNUGC5d@4Xa5`8abm!LvTUGNnpW{&-#L|qaT5B{nA?m0lHB1w(b$G`I&=M ze5YkqWa{yi`Y*R|UK#3qI(EM*Jq_#CU8w~pFCil()#$-Bo6ni@^y*!Q>cdRay+6MM z+1zacpT&VWBaDK{rqN#WgwNvxq9}omJHD{{v~!%Yh)i%*AhRE@j@HRc#Sx~S*@#;M z^xDZ|A|gYNzfh^msNq3o>~pBG_{Z@*K(Tl10y-D0X^#7)AD|cX}nyeZe$T~PW zWR3ITb6`++?s1VzW(G#Py7Y37YO?stpSGt_)Dq|I2ul0w{dix1VyHYU2uc8_u=i-g z$;M_@(I=B*fq{oi!v?cIX$@CBKr;{e^*j3lLl0*4*%|AD4+8ZKM*@%spy9Q3zI&JR zU;L3)nGNp@*$UQ|4MWDg;6k>KXSeEfyLwf{j|?aGF9Tj`?ULvo$~S(6_iE?$_0GkW zc>s5bzFa$itFJhNpx3wKmbb*(pu3xKKduTxLuZs~JIXiwy`Wh zEjaqBFcF$)F7B=;g2fc0-vJ!8C5Df90@60@?VSUz6MDv86v5@@H2#5`=^gW_gB5JU z$a1dy>P{J?$5?-Y)~){Ip{}!9@WlQLvm=;$OH34VZbaK~gVYlgdO_gOHKKdzz2_zb zxX%}L--lJ^<>H2!ty%NcN#70PMklXYbdzMJD8tieuPzm8OQWkf;?k-s1y@IZU$z&} zcws0$`&KRPS%kERhg;-S9d@P7{#q8d2s{(=mjJ1_RK=e#w#D|VWmff{$){Jskccn>-bc9+2_X9^elVXBS>6pD4mIU{o$`GT;^S6qt)VXaH(}&t^H89 z-Vm&+Vymj+5V0i2tRmcis>N!jv3%WjdZtyU-dE17CFL29(ELWDk$p-JO}zR9$~$=Jmqy;?nIhKihE* zWA|-6>v3|lWxI!RUWbqThH>Zj-tg=yE~ox<97>78Y7h!D@SQe@ifRgQ+bDJ$8t8<< z`t#i|Zi7EJ8UcUTTzSCpi1mmKcKruI9;dZE|G0U_>AbXQB@Y(8?MqfgqIkM?=(0Yg z_&NcXdr+8mWITUIuVij$fi1RMi#Lb!DxFz853WI*hHJ96BVxJ++N{~sv4X8>Q&`Bc zCtx?zi4uS3k18rLEW667>BmWeYyU~>d*-DV8Hd4;cv26Ajyq_<`@Ox$(9S=lIInEa z+jeKH9i4{qn%NN`SmA^~j41*<#awGVQYV2)r2~>l<;-@cQD0}LKA=S!o}eZGT zy-<(qDu?qn^A_Xde*T&}XxoXN5slKd0Y?yU&gJx%IqA$)@i$DB+|)&}D*g<0xwP+h zGruMPZu^#+jZ>w@Lvg^IYeBMj{kFRCf<{yc1H=mLh!1@ziB<~b6_yc_OR6*n{1S2G zBK3IF*mg99HiAHX>Y4c!>S9ogS3*bZjq?J}p7te&_WseYBBQXFR>mfS9;8|O)m^wt z>)zt6@YU9h-{p@Ufu&BP73+9`bz8C2>)P(NKI+}=pjU?{eTXRTsYFsEqO0y(cO;{U zoDhv!9Cu0%0fkq481INcHUFQadAYefy8Be^S<0igUK?&2jK6gGvI_Oq6*F|ABHO4c z=!Bf&pEGlBvOr3g`)49(->;8fx0y4Py&VTx9hWz&r<;paXQuDlrQ;&2od!?slV>g^ zBOwgh$XBc`*H*O~_Et?!ThVpxuUK0rJcnm3STIA!EewjJY8* z!a`O-vcY>*)SJp}p*7p+&S3ltGhS9tHnSYQ!kPItOa&n*hR@G=s4~g|-SY;1qsKoI zlri}VIQ(^*7k;`D;x$q1n98&2C->Kn9G5e*0<6{4?(K@A2aZvJ@@1LRGuqx+~J10o2=S0TypywYd!(-jCv-cv;>en)* zHh>wg43UK9hc9U*=%qqI7^o{PcCGmm2lqnX7Z4UbgT78L-7zof$K4N~jE!pAgL@}* z=+Q*}i1EP~>)k2d!A#=jM*dE?qLXn-`yIM`(uJ@aZL-| z9E@YZuT6)m8TMuBfr}?sPj)qaZ)K8AmNiPIU`*RfVD!{jap~9s(EklFL|Ji1XvAdPGkfdY|3(~`J5FV6KL7KEsb%Ys z+MxDOv%THb5skCI1+gW`n|p#RAmBr(3ENQ)%e@w1SS)Md5h=lLisGKY(4U&);m&uG zmr6#oV0J5tPwWo@`m;>a=6*zt`$;yfKcLHAmn#<<#?;?!RvzIgtW<|Cd))}S;6L1d z@~*l8cW8HD`~N~C&$O$49=>j6qH4iwaJ|#JEK{c6Pu!z(Qj^nUV0y%3=>u){>D?+k zNv^PZ$qE3Glh!sQ9lm-O!`=bbJ2*_ykzR*rJ*+ z89&MFF}G;F<-l>mRwH^?kudgy;bmNzFe;US-qaCtf`%;cTjF-muRI+ahRh$jE_vUw z{!utiZe3)oSI%sp)-E&rruc$6v~ zjwrhm{JVhd9^@6$^}aYO$t7nJQx&s)QRM6&PwsMe0AlM?xQ;pvdJVl9#t6bGPNqHM zP~t9ez>;%|^*_>Yo1fCj?FzJ7LmSFI)Tf#9D-TteaLi#i0hFI8lCqq7*kpBUGYsO~ ze#5pn^PXTMJ#&*=c2_(%gwUas|LhP~v_4D!1}kspHfC2K$X6pcSo;K>exUenY%XWx z7=hpZmjoww2B(=GaiL@1oqefvISwaaC2=fmqN2cFEIVh$?T8{IONx!jnzQBrl4tJ^ zX}#bh1bmySq;K_vFzlXcb-2AV$zRdMk#q6G&|_<1eR7 z)VUM3-Bqs32r5I&$vNc-H;-A8x$YW1cKm-R=VRs?SV$Mt(;U@0+s;)Vr>2&=Gaq_1 z=gjZ}tSvPw`kSjJ<G5!VV9hUiuvo$Uxcx>+#OFUB;35)2MWlpH-;#ITpsP9p<#65+@3+9h0U#Y}R7IZN6sqTYZ zFBdvzXwF=Cr44i?NwQLFGwXi2Pvi)hC#sMZ@OcOBH>S&Fo!pJUegJ0@+?nGv{JHgF zqpy~~Fh#jfccy!Fq)NU8mgxmFT=vHx+8=o_5f|*T5K;3J4dGWIY{-^h;*@*+QpWsP zS7q%~*?rgz4&x2wMe0TD)!Sv>t%G)fal!Y6YL(ap?TUr@gk59%^7_i|3h(woU&CDE zKL`K*5=IV%jw}RChU<&+XCdon46Ml4BqSlU{NHOTuV)X94I(jtFXWG4AIaU4U52pa zu;j&9Je3IYo4SyNjt>U%f=4j+9T@uwO#QYm_q?wb=?mDEffIqzh6_ds)HXF1rTvY< z$INz3p2*>oP;hrt^LEP___la|l#847eiZoTwKC>0^xC`KJJ7rB7q<3!0PP`MfRT0n zQaWHbi~P5SIjrjs6~sIQ)~|+8_;BrmD#(UI=*MIxS6D2gc~R80QoP3$%)-OGE)&M7?rhYNvE?FY|80FDOQ%9*kc5FO2=2f7>Nq zNa@GPE2j$PxKHDbPjQ6!pM=I12?Pl(eJnaEJy2~z2G@36AJOyPk++;^+|%>#@-E#) zK08knK7NF`7-;n9GQgR=3ia(~UxB;7kP&ai9<5JC>M=eXG`C{jQ*og2JyIKw_PK5i zUN!6#vwXHXb$&yiQ#dr{F#e06)#PBPMf?t`iQ!u$BI!L+-rpK>JuY#YjEHAfd~NaH2Pi;tvl}%$a*G=`yaLl3IlQOF zXPkmJu2~W6Ase?0a39l^g_~$Rg73p1hDb~dfymVU-Bb|ePnq!N;?Vk9PpWK?q5^be zYv^`q{j!oCr_G_g#3_XjT!4yD>a;>a5YNn!Mi<`!8nKGyosaH0h-an(utqoiqxpQKQnsDCBU$h3MGw-BE6lHsfcoLFhb4e?RffycG?YqM5TQpL&(cTp>Gz=EEK)cm7clGJ9@m}K5S?N8t@+I_dc z>_6KUOhks5^w)|(BrCVMs#Ta$5xD5)lGJeZPN##_EMrsyiRWSJ403^HJv zfPrE{wEK2K)cbnY+Im7U9#s9K`+mI`Bk@$mLpeV)Z@e%YcC|2l{&s86D6Dqiria#S zdku?6WYVLw5x8i^S@7b@IP>%QpAXK%fHylOo%jXhdB>29mMum~gv~6x*q*OiMOqOmoH-j6x|O*h@f7=N3;=M( zsdcbzMUO-`#Ljn`jo(Y%pik>n;S%R;sI3R#P~Tr}id~w<5sES9A}CB@lZr zSNPH8=GPy~7N3QGCG4zXDq)N$ytunN6nA%992Q;N9TtbXxVyXC#ogUm;NtG??sjqb zkv46UrhVzdBr}tFnWyvRWRe;Aq=^3*ApPs+e$YF6ByYpu`e3 zgd>qr0H0p`7Z1MJ<9i8|MQDV|!R#1My;KoE4e(s#Pq6YEv1i_9*+r zS`B3BH-zUNgs(9O4m=-5LhC|C!fU%iLBc0qjHoau#Rtg&5Y3=fdsXDNReM)t&nb$c zUDWpKlLN`eNln0NTkt96D__Z;oJ~quIXJI0%p>gOR|SS9{o2e=!1Pbkyt0%(-w||+ zpt}|PdV^p-PB{XH`;cr?y_bo;kC zJ)ozfe9P79va20ZZV}gdmGAU{U&<>&IEUS+vYilaN)S+E)qG~s5Y+Fx z0aLzX^!De0_19D ztB845=CP6K{_s0bj{QW@k$UHqd|y#JXRw*JSQVqJx=jv?TUnQZQa~gzS1Yo*tl9X- zZhJ(zzEG$An4T>KN&bF&u9DNpyD2|D(K1qTGB0@ZY|Tq5gm6b+-7o@@je8 z>HWg_@@+7qot_e;x6N*LI2!~ccwJy}6>~5{L#R;AWJQm4MtitNG zfwpg4?OdRw*YM3sTp7xnDX3tHFyYz1i;F{2pesZ8-=Y)6?6~{pY*JPIV9dGsE62I# z{vY8y9lP^+!)pXrk3o&6DN#4XU{0Nxa+pEIFL%e16ofTINbFt!+a`OQLPbl(Pd_$7 z-Jy}BEc;sz#UZ`yI$<}N#Rt*-$M1BiGO7-}B=6z}Lp+h#nZ=|{+OZGS+W;!GA9o2< zX!3Uv>VAunBR~)RK8(06{Mc7$NtOH_)~XYvN<+SU%c!haipWN3e{!0iI2!%FAP=T} zqNw3;NH`cmOYnC-KB`%+i3sRI%3ui3S(aIWi4)(%)qK`Y<*02us|Hf=V|ciDI9-AK zvV`hyHq00~Zw+kb##JQApdOXm`Wdn$Rl(y7Wa$Bl`^IN_YhY?f{~jG0{G`Q5koObE zCc|V4mLL}~-G=p`{z_PXFi039&!xsXmyQtsNow4$qr~c`;X-l)u<~R{k|Jj*^EQY_ z!?-#e#-=G*S1HvlFpF|+Gej4j2IgEfR9}E#{z2UYXmzRmb4op-DIs^ZQHrphY^74gS^=HT^qydaIxt|-&tL7 zHV^`;VG%H2Pnhpxj7^PD>KaavtRw*pu>>kfwYoSfbI;@Eb%a|C`i{sD!rl%(Cgo9b z(aSBR-(qZxNr?sLy*lgVjaz6_xE0*V6yvBnlRF*&%qt`ti!$!6Q%*kKD-dBT>5B7R z!z#KfVNqCSx-6w}7NY=~rp6Gc6wjcd&!7G(pF}9*5|491S?!)GIb5y=ffXS<^!CR& z9!bAw7xn%0r`T-b7u`#m`xUY-b6GOWHSc_onhwuQy>j>!6{W-0gsaAB732Sk=78f& zztVU#4?_-QQCv+ch#oC+`SOU=PthVXa^E5?RYe$Iq0#_U)Yk1MPt8K zI-#F3Z>G9=VZubr9dcIkQ34SN)$PKJy>?R>_2J=k(~YG&El094dLXbezC^_w1XSGf@+pY^TxC571Q7(hM za=G{kvAY+kam*F!>z1-P2@nnEO!fQS zy({Sx6|@ zjEb}^*F6zbNBfUa-$6g5Ys#Yx_9tSr;m#5L=PcV2ypG=-1dMRu4XD`{erlxb zx0q`neLS-e+oNr$K{!uGn4MA4+&+5O4B*de)PWa$vsm|>gTIBWXo{z5r5Gmv{atPHmA&9)Er zvkYuRgVRcueyR8)aEI&Ku=YQOxmzQ+Zo7FSM790t4DoX8Dhh#h>}m>;cJx+6P~0AB znXh=H=JKw~y;y@;)DVs5sh!&4u4%>BESvM1hSwG7CYmZnn~Mye3zNx6lQ}yzb9n&Z zE?_Zb(CR=dgH7^|2Xc-NgeC?>N2u~Zip2FY{JO46%X~F_Doal+3qER|XiKug_?Sn= zRof=@ZkFfvXB((VttAUqyd?JEb&I$$;BaA6%nT2dsCrz1SmC<0zH1u5h)(9|jouWC zF3tCk#g6gyl_N(m&R?}U3x{o4m2LyuI+k1ApEGv1l$?Vjlkb7Y;Dub2e@ z{|6-ShHHDeVK;G8PudfX-4ie57m)lyaor#9M7C}6_z_}snYU;0PQ35})8Zf5cFV{! zUN`oN;@&%S^YVrEBK#R5x}W#L>HqUxYV}rYuYX69_LD_(kIYo~lbYvX#}sKBXXQW` z1i_4oK%u^eeNZTU7%C6McHK`Y$9s;31;=8-A{kSoxw= zNg6aYjx~&)0p8*KC=Lxrmln{K?DplV>L(=B?k?zh#3ViR-2&;ljZi#suy% z_@ClS=UT@Vwfhd;^J2u>M-9#WdVWsNf2a@e+Zf$Ers8zRuJdwanWZOcg8#;oulUf% zT${O&?^e7vh$O7Tv2#XL?!zgZsge3sIppc{vMHp&uf-{Ct?-WaAGD|tClpOK-^>2? zk8%a$|Jb)C0Q-O2w_4UNdP^9e(i=@jzw{yt`J$Q}`JzZhlt%aYC>p6_FxP%lQ71sF z;Jgm~OrVxYlAucwU$b6&o}&7m-N*|e$Q+WQnwFM^OSg6AhFVru7XAchudJ6=%6TKK z!$7^ex|5SB$mxE)ndxn0_%Xvd0?~Y+NV|UfYQr=T3WZlebZC~U z;iGo(az>b1%y!*f!a!S?9;REIzzgVFymql&>A-Ag2i$h4UCqD^U^|IB{3g9qdh$xU zo>)BFGyEo_lM%Nxpf`ChpieAOnEW=sPXe*$JOs@M>o}or1%?#&E1u3n9b^XGCQ2Gl z^S3z_yMl~K+%_6c%B<8TEULwe^UqvkBcZvI8w&*2u|?Sa z!zg-xa&(koQ;q}H8k5Nf8A`CMI~9|f0d%^*a~)IGX*3lisNO$&RP0uLH2BwJc;Tl9 z-TW_MkZ1_3bCT~PZ71cN6%6J`))hr1PD9!~@Wvl;sOr-?WUR)v1gMNpw8 zxwe}VbTWga3A3Q~ru`{xw3LL=MmF~&t%g%-C6GF(QW>{P+U;uoj%mhrNTro7I%M+O z69+FhaDrBipr)mscYzS?5!MXg@A#$bTw=PeU(u6q0oUB^uQGxASCRxF?V(xH{97{P z;b&lAx2EyE^%pDCSr=pJ+kJ;AOX>mi((&CH$b~2Kj2Sr$7Jk_@&Xq_WbWO0DX+ttv z_H6yS{1WAmt8aTruQ8fs&4SUz5o{-ta)>=C9O+pnN;r9ELnsI+{k>M5#!%{PCwfB# zyM-lS*FZIwL(~&6uw|go%&OPQfH7x}`KdsIfn!a9v4p7Wm&cQ^`w;R>^-QhDId*Am zTb-f&3(jJ$mbt)*9OHH*Si=Ko953^+r8>UhiI#I_*V&$1UvSn`^qTU{wEd&r^#u0i z^n9Rur6;ix#l6v zS6nRQ0PR}YdH_>Q43un_w4zGLTDwaWQaPfaVM3#JDda5m}PB z6oIk*4wwu~v++|5g?|&2Hx3`2#^r;Xz!56hw~nd6$K#7~tbD=E{Rw7@tMEV_(eNRf zVSI^;!W(?)^7tu*%Ua<TYZGQ(tN(Vuu^+Vy1^gh`8a%O2Q>wOw(c=y+1}-LDPReqrXr7_U zbU0+WxrDmZtc%s)$GbZ&-NE?Eu?*EV-lf&@fbpsx+A2irBiFKMwwvD19mZk3z7a_s z3tPw6bNcV_T#NhvjWkhfgvND(na(8gEGW6f_!V|ef^baJ0cdtY)K<&H9i&8$ohi3|U8y@<5pM+X0}Viz+_@6zGx-Rww{0{;%>Tl)Y|bc1+?U8YCl zA+e5d_-wvN$cw$t%-WyuzKcye5lt|@E75X{w6xYd^V4Ea5b>@f#Z1Gj{>5$tXjcDb zh0K%ZitJWEEKU!p(R0kM{#RNI=tIt8$RZp{_{W zQhk({>VaX&BU6`L1>KMfFoY8(j-laTFQr)&r+w+g0~!U;6tGW^4XN$7^>!G|C$Sxf zqr63Gw@4PnkzGI_9=%BYgBe-&{iO zOYe-X_$)Kb4Kk~FWmhJ&|26>bV%q@%NXSMeG3~iwnotX*%{85;Z8Ex0oZUk^y81W& z(Iw+O5sfE^rvDvh)_OoLkYUFL(#$Ikd{Mt^ufL_70oMI7VS*%RN77r;r5HxKIjLL>22hl)pe5J#Jr^H|Ck;WNO+Dn^{vZ;PnX zvfgUI2*nTz1yy)pJA?7%b9Z$;l4ic(+ivjN4u2lL{Om!WapD#p!MPVA-3@=i=pJmU z+m-SQFdC`y2#@|SDE*A$z2)tW^xva>fp<(q5iMbOk2$|}zT3q+9AdTR@sqj-+v>)& zRgm-+EWMDp?msWaimJfh%v!!DwjRtB?->vddpDE$mrdNFb&`ISZh#?T_bI(HB2bfa z%%F@q#^Fx2G&#ajv51olKy37@RbR(CMScD}*KvP~rz|0C-5$WXJT$j^AXpQW%5n*+ zW=wvBU0Ph@L(HrDS&NIe!}JI1al;Px*3_uUmA>tfqDacX0xww+@4_-7nqa?wisg;Q zrhSNMf2ao+z&_-%$I^A1vG|r*q;0&eQ(RolB6XP?>X;o7XBw$bjz!%xtnXDaWkz&_ z30^gSgf;v#AoBCduuJDAdMcENrW(2MRiWXtW@LD1$K*MpWxyCarvj6^ZtLQfVY?F0 ztgWT#T`AlOcU#^zuJ&iKW$zoV*H!NMQ#$*?h4C1jqb%MiNtyghE~m>!Uf~7Z8AF)E z3dH0SL#IQq$Zv_2SC{clVBHT1Mvnkt0^QuCG#e|hqL(K(i2w%cFFSkd8#m6s?^YYv_yqHJr#eJ-30D?-?I zK@P4QTX)#$vds1b%RPbXG(Bt7>wM4lblhEZ=EIv$DUYbETTJ&^y~W9`CT#yg&G*pt zcKLO%2y>aPt{9819I38ilNAbcA*!x;&Z5$Vc4My6fxp=Lcfhc7MflSKO=n8K3-jZG z1d}hYb(Zg|?i58JeA_bCUo~l`F@H$xM2BWB!9w7ODcWjvUdfyJ!m5{A67THKYH%l- zr$j4SgOV|hZ$!(3h#l>VE8vITUHn`c?A`rpkNMs^)@GEOGvP}>uVt|X32@SPvsr`B ze_t`DqPILCCs*9|b;>y+gT->QE)N9r1@qthh^6p$b&C1z+Y!_M;YV{b(|_?}i!PE6 z_EC%IFH4>#!A!+QIb3*2=pzhFihzXg{fx@m@CfEm@KGjBnN&#GTlHvci-qO+i+GP3 z-wnm=y)KG0nk~RKnZf@gr4E4}Tm_k3G z<7o&Eu*>%y8X+h4s5%g)6qppSX}}zni2A{rGzgXo=DAcwiV%1-6B&g8*`Ae3da)(dB5sRZX z7X9n&sp@%o`F>?ULf;Y$%!GUt0|PGq4{e4y*|fCu>Qme-N=im~TxV_sifKFt)5P#-I0`6D3&&@2}3=-gXvln4<4() zOGJai%k$Lu1Py~jM;la+b0YC2HCpBA8lFydJdZz1sZ1!ES~gN}LL$mmsQs%kJu#J8 znv&D^*4GImHxqgF#9|D0D>m?v7NmKaqz=_{kQ%jwta4Pa;-jZnWhaNk$kcFLZPHWl z&K$MZw(5Z!H88=S-#?R#Z7I zW}UVpIF3Zil){b&5}LS*g;tw1{$fz_=i6QWA$*w#-A^8&>pn##tztqpt+MCm@jcXg zPXy;W(4Jv>P>A4O0~p$*0StE50EWXb2qDH-Xh%pfyrZ{{X;+&fT#DfX;yg#SEBAf$ z1DwYAPm1Ot4IlKEEW=l=^HOt$f(<`+jn=D)^wL>S=Juq`s0sPS< z?czgKP9;%Q9yVG7q&RgZjagMI`z|eVNoD5r^lny3p8 zARdv%1BfSN;*Grngmd~kD9R7kYM=cg6FLK$fOe2dK_hAa7KeA=wVC-L)~dRZjt0f5 z^l06E=coWWK*hf{;4da9o`&I@oPlkQ-Z~N7zux?=$nDn8JKz4MaN4C;Fmi&(mG1RX ztKz;h>HNt26mC7|=1#ihe)3~w_*&#+GVhnOX79vbpgYHhMYm_d9c5N#{HHLW?xf@! z*p%Jg4$6(;;mx*_^4?b|cIsrjIOF<5sW^cLzlP`mcKV&j^U+~%UXhQ;#A=45i0u-* zY(s3X^pOq56+ok@Xvb-Lyomg*Rivr6v{^hA_Mvm*-+?xLcDYqx?0enm@psv=j2(s6vUn|`4x9b0Q|$qdn; z;?fHjX2rWHM}DHPj8Qy_<@u$F1c!Y-5sGA0PB=NKPR>P($ena0L0n{WP&#%v=DO^8 zKWH4&NZ8<~>{1Doih2v2Bd{su_9P0)&^)+FC}XDxGqBe60GExr95RgLxk3!a_A(Q z#~h95Kv!R^rpBAYDQuJNb)vs6$Fi1tI_jiGnG%cNIEn@H7%*+3WO?UsDpbB!w@RMK zrHhDf&MMt zM2z?Rxc%P4n_wjfvwGm{J;x5`gJS=hbu`9iS5Mg!TYFMN~RA^1f zth|<>+NBWXW8zpWk<+$Kmw**3K1*VsMJRT#$gKt^~*=bIP(T&eA#2In2lH&bN!ejTa*8 zuE;kCK9?vJuxdlb_A~&I-?*xJN_irPJFH1nkn7olwgo&W=d@b%RSi|NHB}W#ERLeb z88uTD49^hK7S>tqSmF-561Ad7WwP3A{kfkaTowH|=A_HA1usivalsY1hiWx-dUiL- z3G-!EVsdkTJ82xkF7D~qSJz45jJ0I1?&UG$P;B{i#$&;xKiU>fL4fpE#7jRZ-j|;b zLeZ{eJIptAd{{jbBJ$1got9mmO2_z$uYmKmk;R+*w;cAzu5v$j1z)(IUMDAxQtzSP zPoDdI1$xOy$pwHnxq}PFc;H$Ulo0NC@Xa7)H^2ZUNy3`6XVGCtZ^% zk=DpPU{-xr!@5lEExThl-8-%p|94yvv`FrE+?o_dhAeUh+jeizc7sPHV`W+Dj)VFLV3P*DI90c#>o zeE$a&%^6HRN!a1GiOlR}1Nj5l>&p|g?i<+}@` zh2*dVSL+U99FvF&6jg`BhL$E_UtWD%Z4se(fK0Q5mp&5HWtLGKziy*s))DS#6k@6s zy~wZNk`T@AC#6mFbBE|+M4<_~ zzNhJmVLD?^sRc_Ns`DNf4aI;+lK{XnXw(alcIq9F_4v%X{ZJ|9Q`(rl>FUO`Ho z@V9btwq;Vrl1Nv<;`{v)TyLIZ_JBxELAVK5J)4e_4GmoZ7_b<1*MO0X>L-3%<>pn^g}IZ4i1HmXxIpU(wcLd|`nF&S$(G zB+Pv%11v-UqTsd&UWiea{R_DxzI_PQR~E3u_i#}#&wf0HBQ4f3x~Ky1`3MU`Xubf* zW$7}+f=^1nhJ_{`M6YT+D%VVVOtoe|@27IvO7-}ycs2Q1EJ!%>ud$~?U~%{kXn_#Xd}B3e}JzakjJ_E4hnY2X}tqVfIa$oD3I zHKl6E%^nHgkDwo@U@jg4NyP*v3dV5oZd6d`y>dIo#Jr}71G2P*CptL;m%nyZ#a902 zI~XAkdzMzBG%)(3^I*-M=T)&stW>#$wk@zpqcbro$Z(zfsCZq?EpRROH*2b0P{WSz zoO7BmZ~nboxiGie&7KYqm}!W!yXrc;;0@QdXnY5G%3t(bf%eqnTkX0lE|tN%j)C?T*YhVta&}IDfE(x5tD9;8}}X=WBHX;F1b2ncH!;EWk#kD@6!@G zC?-CLBz7!mV_fqCs*I>LHWJzaC;-W0^bj1eaHjHENKWRmnCXwv!sXOe5(t>Q3_&7fG)|07vK+oDsioc9WMIZFgH zOEC{V`=A#6IwG5XlR)cln^^8$PUP1tdj;*hp|l6vxTr(EG(wchScXX_h;^e%d)%IF zx4G{Tw}J1Ow;evxFa377Jv_9CI~mEL{#jT3^!H8$13nc_!$N8?oHLjf_p$pb_gAJ_ zuhxK=*9gAlcSb<>D>WcU3g?%0Sk!CU(mv#bG@#;$X3lzzg{5he!qCD~Vv&g~5+!YB zs3k3VUtmI1GOsWS!XgD<^KK}1d}^P^BD>vSjd{C5h~iqs5cejsEs_~ru|EK=8Z6t_ zina%%MY0ZmX$z5l{Q^(D^hP;WEeypk5$u-!K#(q8b6xiQo{5`ew;1aSr@vNrr0wlmugp)FxEg=ce+-k*ly8J zHD9OR)$}GD>-tmT+^rxKKwA1EX^q}CgR{eP63{As`A0{z{!L}+1^o3P;iXIlK$Ldr z7fj%|MThnsELV~hsJjje8bmEW3mHUGnT0_5+;J^07VG?ml2d;fWT~Q*d>Zg7P?FaR zg?qN+7h~fKXJy`a#8qCNzjvQ@w#60M>6#{g;O7l zZJ~DU3$FaM{{b127eIh2rgsQ+PyMbK{;BZ7wYm6V%^x?E6#Ufc<{K^;)7%v(?j^Ig z^)ldT{RQ{mCtM8x6`@wtZ{I9P{*O;)>H6=}=^PytAN8eF(Gv>}*39njFYr_e-yjkb z(8UYy63N{-GQS%q$ytV>S92>R$>7Uc_D@p5xZAp>GuK?{*4Q(*(CKbiyH`Xdd@o6@ z*|1r%uUcBJtf5;nc$Tp3aB5OPk&+)HFQD0)pxt_Ks%%4-VRU0DKWt`=cK*-$M@8L4i;UCT@)4ofF2i`LwVFE2QQ)>nejNZ zpBXb6557&?vO}dgEuvaKtyTSj!KD^E)Pln?)ruLfR#$z(Sxj@((AK4P>Gf}=cD=n* z8{>mwr9R3`S+Ze8V{uMj37MhatO|Fp9=xFWGJu~nj-yRtDy`)4Gh`2l<0kVTB41wq zYRP^2OJ|PYHbjnMHI+`zogn5Zia@oD-yaaYGb_7Kc9fH!vW|`^w4sRXr zcoF?WElgVi7#E0aZ`)vC45__hYxF{IaQ~?MT8Hqp-qmPri%uIUVv;e>U1AI}ytv$|!+-B} zwz;@m>;u+;u%D{AfZ1ds0!flM94*z2Hwpxc#p^ED;3B@j_)dx2Ba*1dJ3O}{ttP|9 zBI+}HT|YfquUsm+zhbx3pa`UHD?$nc*HoUMFE`lJoku=q!Ta=YE(vhW+7BlNqRcBQ z=&%Rg`!sm8m+e$<&uwg}Z4t#IXM@jYhjLZQ2|nOEF?hWdWP`_?FiYDrt-YL!W;Sqc zy}GAJwrhz4{a`F55*&RkQ>l85qfm6ip z$qgjzMl|L@wGM|>8#Xo7Gh8ce#}>{iT`UgK2FK!58!JgU=Bj{~mPd&EI+J&>m#8Z)3VW;=`ijtpRVi8uCe;AgiaI&YR|*eyPa$w#j;&1 z=^IJm#nzS?>bN9A4r`zUvlLS+Z z-F3P%8rOC>%U8jagS^#ShE97jDzJB!4*5R9z^N}T(dOLB;tD2EdmSYtku>(i-VR8z z{;!nZ=F`|k=oOM}=i_7t-Im=LWL&36WW2UgqYPva;%pXx)hsmvS;>K51D6kP1Lx_+y$V8LSOCIGQR2C8 z-E`)cu7n`V8>=_$u#dbCNt^b5^b5|8LX+6x-xA8mz9Ggu9nz29`n%4S8QOl? zRfk>a4D%adjBCy=IZ8a&T`@wDgRbEn9yk%ps<>B4X51j2jyzaFM0AX?%^b)f+Ut6I z_<>sZ#xBOTxeL8BuWF#E{VaEJ5WL|S1@71Oxe0`KZA%@u%ntna<$&+UmD#lkbk!tD z;X($<&cx0xS)J%td&Xgaj+}Pn75W4*@txQ2qThPnTCXzT=9^0y$rZa6~E+Oe0&p+h;z?D$t_c< ziAjOs@Jybf2O4*RO=zZrz`Kv+QZl=S!u#Sy(`A(9Acw?$-V?LgGQnr?P{CK9DHk9PHU`^$*Y2XtaUvuBx-Ftl!9f16xzu)AjZ4A!ujTJuEaAG+HvLwpfF zdiH=%1L&u9Q%jeN&}pEX?)awa;#E?u3;WgRfZImy#}!$lDmw&6N0#RdS=N8@!(Dcn zi}eGFFx8L(oNd;zRNQ1~Nn*^2N>3&nM6fja+on~aHZ;!c+>|Q0HYFeXkaC+qZZ*LF zDg;<@w}%k^m3!Jqv}(U};P=|3;_3+-XtVf&TP!b)%v!j}TxcZj5oo?`+dw!oSqT0< zDg`yXZ6`3M`{(ut^KP!@m@s1~1wSV}@*iIf&+SJSDh3te%|zI+jwXp@=mlJIH17k? z^t4DjU-#z2I1vDwb|jiga3t}${OW5cdd-qiZd%Ey?hnkt_&ZK<>6YjKpNO{66U)?ZUqfByzNZz=|;4%qB4DnubA>}t4l;5Q!AxHS=K)*)Vwiwib{ftNd zWWAwxc>c1hvVPOrx3YG#1O3^JehvSDNb-SqBTDkYb7SN1?6*6!esl8Ua}MYX_0fgC zgA|a89t{0#P4Yo?lj-n0(bv9uqx0iw<3=aMxpl7rnxb)UP=psN&8;s z&7cPAn};vh>Tstx`wk-&lf`#3gka8lHsOhIZi_Df^QN1RFKy5&AtT$P&wDq5Rm zz!5cgw$NnhLJ*bK&>w!bqQ@M(qtYCu({(O>s9sw1JGVtS?RI&>K3r29@(Mquf<31G zh{bwR80!3TYaD^JViAsr;ViL%A^U+x?auK13L`J*Sl!=k;BN~}ppi)anpXVL@!RBl z(_u7*Kh8ZP(JMUhean;xC_qK`_SYoJz(sVlN1B_g-E_y89un`IL7_ACvkg|H_g_M& zYct$6OcQVv$~j5Qxr!Lm6AqP1bq8ZjMG4%xBtJETbVHyln^aOv(~gaq&iTb@4U!+q zN_di@GF1fjNoPNTi^cgXUMd|k4mLPgGd%v^aPmrXYs8@3MkTQS+=T{gj9} zz5!&Nv$}R6_CZa*ZDp*gnZ3+M&+btiR4|w8l&xFE9HFC;tMj)ogW?p^QdwEMqPwb` zifX!*i*H`@s(`{0qhC`CRP~IN!<3jfGfNpr(1<7-tW6w5Dg8923D51~qj3+o@hz#; ztp@XN8KxAI{7nP49&=99#urLl_*+dswb+aXV5F~q-6hEwh3I5lwTQac)oL-VI9FIE zEZSdYush(%IG)`4I?S6>D_4&D=jXwF^8K;31EW_ysSdLp*$L|3Zo}VPr^gnB2CL__ zMWxo#`R`vCB)oUc84pZu8ASoit%8nu$1*bK9ts-(CqHTCWNm|D-l{eu5>>aeomkS; zpq6SA{j*H3_BPp8|5g=75iKSD7({GWPOIOB^S+dTBk9WJ*fah5!oaS$o<1!PRQ8JZ zu275{X%EDeIimpNz_1n7nDaBNhBE(EfNV#I%$nkpJ8s_L!~I{*#gVJBiF+iU6`RT` z`^>L;+X@xW#C{PC#X8^|;}gewgdV@0L!|C0p;M!TpVORdyW;tSuK6=7H|jkZI(MFi zm_5l)Zrs-ge+47#?7XfX&fG%n^hpL#n@qKTyTg}z{GIu%-IIrTL)jBA+b7m%auWH% z7L?WtQMqZ~Tf6RSf4a5ni8R?Ce50e-YcG6ZOSA_E80PfvEGaw_J0b_0)EpwV=!;e@ z-G;3T21&X9#^lBP)cr0IEcB^#el*fb_7=_uB|J1^-}%Dmi1~cpcP;%YEn0SYLf8r$ zpx>Eiq7Bclpg5gWzo21b`<2jf@r)33H95h&oHyNExqJFTE2#I83gTA@OaF$Qp2bk{X&$cBf1M*e-T+{RWNL?LNht`3N;D7$Nb}%yCdJ{M^-{jf5TM?9BVQVh~ zKzB>A8(0voj*yo<;2Ov4XFBFee(>9i7#-^#@bq{OL@|(yG+5^ImnkTIU~XZrb8zzF z7JgPuPXxdJ*R=yVUEu2|3=|Y1{Qs$X?JO<+C0o+iP{vimGpZmH&j35*qI0 z#3CVP4=pJA zCAWgcJu~}O8Zbam@jN4%G+{l>$F5O>=8(|OX`MCf^`oe}MybkloyXI0LoVmziWY$~ zOZjiKR_wt=ieo+;Ke~E4^>EFjNp#-Sz_N0p3!_|p+zsv4hss}imU2Zapq?>iE9p&q z*Th0y!OXdPy|9tIig*qG?(g=->8@ndX!-86$($%+HovSE4`Slze5~Tk45hve!_iqO znSqMV0`e?7X8$Tl&iTvQ(h$N6B(X}Z9Qi#k$1--lA9-WduHLgMQR?9V^h5nR-*fXu zVLK9hDmJB+-h$IN>*k6Bu#l|q0!^rvXv9*wrrwcfmhjk?-fb`Y2Mi^+{rx?NpX!*yHg_xqa&z4WcUVSH(ifk`#5q zYAyS5T})H7L86z8A@RkbLEpp$fR54vaAnBwnn^mYaEPq?*i0kJE7f_fPi#QECmT6< z%?()cCvts8?Mnfm=46Hi!EA6isNJjW^ZZqm318;kyzYk$A$80M(_RZEDqDYZq!)^y z(SVp1Qqwq+=CMIjoQ6Q1hCyE$?D^Z9k76mtslu{3a1nV9+GZ~L^;Db)HmhWVq90ZY zoBorLAn6<0_ZDtO?nJAueiW}8qU+J%M4RUyC;UUGAlQ}8J2=U>CJNhTWU;xvZsnXG z)+mCNAp|LTMN{_W?_dAZ5476Ip~DfOptjNfpC34T{ae0gjq`D48}FlG04F?5Sy~3L?c02>5@V{_ zE+za1M+9(>HroqGTnNjJHpy|*2RkFoDL)1NzJ}c|b}M(1?>_^6$}hOiWe$EjLtKIO z*d@d6~=bD%9O0~JG&wRgo>06mHg6tv0yf*mgz-py9@!kDgr(_;+ zZor9q>U|7t%_K@wk;A^GSCpo$q@#-3S61nEV48${SyW*}i+ouyM;_U}JEkPZhDL5a zZ_6z*^M>oq?wmufqa~j{gC*i~bvBtQU@1%Ow;u49! z%FT>Lj|WXVdrjW?aoZ5>p>1~oPmqZOae#iG!2A(VE%Ys*gx?X*z1j{#7~AH#M67vP zYmRh<;Y+d?ia^xvnN)4I-c$0J& z=o8w2_=%o`6Jjr?-TH9n-Nqk;H1~TsIL3!LJrS93T`YSWKGJ>C$UA$nPeob-H9mm8 zbDW;oYx!qUHslVLJ@hWdJ=QK(O1QhAm0zdSCVV(g*#|VDX0~g#cETIj)8rQy_F~IR zK{Wn?`Q-!Ooo$jFMOs3L8srky8Sva&oFS~hk`K7|vX5R&^ma!a%m%dpLEgH<#qj)< zQ`I0)md;2ep!Bkw8C1O_#wW9QII8S|x(O1nt(F%IGkXH&MVnpwIcf1!eCg)lby+_A z8U@yJW^~Gt4KK3dCgaMXT9z-bUy**5C)ew=*B*kC+H%Tyx8U^CRwe{YU1e)7YA_Y~ zTnpMfNhA6_xW-spIu2=7Yqq8L>vnFjBURQd8eaL}vfmEXOMH|TpH$@}!8?9@PPLXB zR2MNvaLx0@>lrqssX;XT(Zj+D*<^Lw7Z=wgq}`gPearq41weSD|&R z!WBNb0DO$uxBi$H$<=-XqFd3Hg^r)w;=d*Ny9C8xLWVgKaCYQ3iTQUAy%9na3c}z? zQ7iX{`lC~Eb$0t;s$ntNzWM9~T_s{~MSdwR5a%Usk4Sh-66YdrfyGQUNKB&U^hlQB zHNq8duk-H;D4P+D=20 zs+VXhul82@$=w);?kodaw6B(JP;>M%7O^&elP$8jLzrD&El;RQcL6-3#wVkZm4JDG zsDLLv{qvMqU(=nRPD#UD2LAxSO(Tir0sg2wfh5VcJG!|F6>#zQyjWoTSdB|V?!JlZ z371!@km%Y(`?9OIlPM}iF6ydZzoL-d4Jc2AyxYb>_-Hp&A)2Uy=d{JCn2=j;msHt; zfH7A#pL|7LI8mVM+h**&Ur)Hs4Hp}Bw*>o9;?0-(xz}fCk;LAjrNrn@vh5-Idx;O^ z>-`2F%-}&xS5z@;y~hJ+uIboX9V*N zbf}e|0dC(rFz^!f9bLHFgm~;u3g=E^8xtE|Ri*ilyAft~vT-QP*IYLoGst8^2gyV3 zD8IO-GX0^hUf97I2u_r}MI4`_C+aIW69e^{hEh4ImKH#E7-c^TCj+F2Uoy$QBi9?; zG`AfekN0_K*#6Kstq}aXMF_2#c^neo>7|qXp3_rttE<=AUHfYZW6BC?y2eE?=%@Yj zT|Vur8)0>+>}fK!VxrFG(5K;r&8n-8IIbKKbYel;2m60caIU4@2%+Ghphyw_j|l%e zmz&GK*{qhlJBb$7M}Dh*TqZwibR9n&4)p~8&xoIE3DJBbKaXfr9C91c4(4LHrfp@i ziNPr((&GIhvQFRdbqujIAR!ce4SP!XioF#OlxWma(ACP${r0d#KrF zlqu5J*XT)PF7_dK*I)SkRNJ_RUQl%fDspz>T%nc``fT9=NQ!95OO|%r-`9CJ%uV5e zA+?U+d~4qg(AuHsPaCp2BV%rskbBN>+JU<2q(HQoG_v}Q*G=rK-Z1c{C%VBp{OFb1 zyxr;c0)nJm`?=>-HJ4JAUgzy1r#+?!uK>5Z(UuF()}j46&r-@aqt+p#tBc>&;~eUn z3y-bgReG&bYwl<@d@97&Z77gjkfP3=*`^tirox#+zQQkdm@vu?Q(a*DsEdGhOWEs? zv8RrTCRrGlvZlHo)8_s!S@5)q6ZdnoS2{NuK6-4!*YnQJD%(yv%Dw7tO6C%VCJFIV znL8DaZLD%9qzOt@3Q5l?R|Q33*T#z+8VJg4rpHuQ+Z3A zvp(!Hykh08TMmD3`q>AgWiY*{bFz3DJL03Sn0ZHF1gmV+b3?&|SJ4e;kewFQOl8sD zG^G%2*2r4xj30}m3esMoWAv`Lp~_0xMX^35z+AAFbs?bVkRS^e%Adw_t6s-}O5 z;=d8Ih~|n&?Syp2q)H)DUL8>pZvjKm@(!}7V9oxpx!!s)h(40`_}mM;-AckG#L4c` z`yoQJXuQL_wZ(WNA*bx|)Xy@Czb8*;Nz@Zj?m&Vi8b7fp`_FCz=R_%}SXLSDy+c;~ zJWX&+)G;ZXAMDe}gXsf;F~zD~a;%Yl`I)8J7F&T-BLusowVbG>SDeX(M)%3JT?)1X zzI|dg#U?gJCf*V;f8cOa+D!o(Td8W(!|EH5QmLN(S_2b{IKW`MQ!Q)D$SBpwBV%#-ww3KD~SJOC|KNoa3tIT7nsN1jf z%ttcF$S#bTj*f(5PmbfOsAKHNxU;l4D=f&7$*^q&36d7)F!DJ5yvCsuN_3sQ76&Vw zrfv{@Xf5#zG6X2go+A5f@ZP=dtb&83Qj#gE7vXYL_|yp7G2N#bN7CuyJ}D_r3pmMb zGQw!QgHsftvq#`Q_xVH-D0>8GM`O9|In;*wkhwuX91eS~GU2c*VjRJjD)@Vp0o|ik z)GfmaAg|M3#)v6nh~fE#!o_9K1{ByITv1I}x+g|oXA^n+I#8PB+5hOyQ7CcUK>sJ8 zGZ+EXLH`6Z0q*~$1TQl;w|^n3X`r(B4etY3Z_u8WgHkzR#MX(b4z6U7qk_XRy=^=H zv#W8Ipv!P6c*&MjsUrIPH^ogqAaL0*p{0}K(SdfTXCoq@nFe>nfD3y&#{!IQl7qwF>2ieP{X zEqbzB$1Oi{v0&{rCvGEg*#jjs4Yhw2NuJ48PFBfq^gFKQYLo_^rd_W0^GKQ$4@erX z(z3-}JYUqF{Mtlun8{N*CZcLK&gbSSb z%(2-Y21ej-N+ z=Cu4cp~OJ&!Qne*R_$;l1FzkDZHWhwpRzL850;r9tqvlwjphS<6`i6$YUqX!dn@Dpx7j`crl;52NVC$g3{qZ zxiVTH>&2}f#qJ$c+KLodP%0|ECVP0fXmT*wDRlcpqzLJyRG3aXdwfQ0nbik$(gcKn zd`lYhcEs$wvh$MK3p^ z-!Fe}`(L^rnFM&fF#Yg+9*WTN>H5;XC&!!Lml~Rn^SdR>W=NR%Sb$R&5&)R|ZQjFn zoRvj5)WvX2%ejN~`zLC{Zbz1L%u7a=4y5aNU#0<7aBqO*xh?BD>ZSg98;_g1{I6qH zPI{~Eb~65>J|PrR$q!R+73T^V+S)#{$x`xo0vt+kKjglbI1))8! z-CrCmi+1zIB`e%3B=cu6;4%cnh;6a<7q7r0YLwhRn=TwfgZGnDWGEnpw{N{LnT5Lv z{ie=R;;o`RGdth~QXEngcScO5FDTbdnqy>f>5-j-?*tY7{;$O$Tghz3V0-6pAtJc3 zBkuBEr=~PQMTKTmUK~kE^lxhp7piiKiN_;&x^yjS@PHyEJ^~dx$Ajp=+cqgafjX-V zs`IeUw=ko#IZOTXUHOA-5B=Da)a;hf^a5^5-7gDfq*TdbmOqjgE1~I{LC|iuY0z{S zIQ(c>UyYg;H(NYqOhi+ah*q#IAC*shGL~&QxP2LNNXaH-SL%#9IoB&FSpQZjD-PSA zl16OJ&B$BEQInzMAIZ3AKd#TjmPoCPJRB zV*sEn&oM(2ChYt##PY+b`XK5YQRfl4(n!iv-R?+eg=0VJNIHR?d8#fyCK2q3<6)YZ zd$e2s9HerY-6J z$N=3o$E3fI9AsjiRKs%zN%BgX2sK_LN?AV34h3aG%?mrVV0SL+pZD5%}ss`#oh>0 zP-rvL^j=pCYG}-U4n!J}t;)w_GZXS2lEpk)^^Aq6X$X;J3Sv67dDex5`N)YMd``5% zsOa?sz7ALMPoGZHm3&mqo&G|fYt3nEao(N}QfcYs9MPYaEOi)^hesu_2(VC*ReeAOg6qD6gpxS3F6j=Gu$?PJwN#-kMe&2)WK zEu2u}=Kg&`8N0sb&WZQ;mF4#}5?zrv{I~GBeZ^*!2^S&I%l;-M1$|3WL;bGk-7-oL z{fiNP0J^UMyoutrasNv4j#2+g>W)VL*Cgkma^F|y`rV(O87OS8-kL6J!QbIC-`llr z{Ku|qcArvTnSFlbLKqY4H4C?YA{}YOUDDaWpR-QrJ4^bBm3lq2tvI|+w(aD8HEj#C zCgIzN0`DY^MLu|eHK{jpnsP2TUmlaLA%nCZ(u+-jaB6HHoi9oj(TMU?pUs^(2TdnM~6fGaB1| zL?WLf5f?!Z*h?VzW%Ed=6iJ!}8tu`npWP(+qS(^a($}*0DW1}J5bRPq{N=#VXT7!T zQ;t`3)VLt3;uR-$Vr*J!ECJoHPh-5|YzTWE{QO%T3|uuTEg|A==$yk#tG%#RAX{E& z)Nk{fQ0%<_XeVyb_@mCJS@p)q^g?8lX?w~kqa^%^$Ek1ABzI>NTF+I>y9XGFt>nHn zAM-|D&MaC8SFE%Pc`O(-6R1-h4r-Ny5N$0QN)lHeO>L?ZH|tva*R-rm$;SQx)a*#9 z-aXbECoN*#=jxoX(-hvR3}_ziAQad{*H0o8j1<8#tpHRrPRI$qxMYZn%6gCkI!4bj zb&s!qH-RS+4`2yi@KGKmQGPS!56Jo?n;hak6J76qeH;BG=pClG5qd-J9WlAJ35e<4 zyM9LesFU499qBC;X#DK0wSLfE5Ec55_v7sFI#H1%tf-LcgqK)k6mf4ncOoDLZ zJc1B%XyP7HxJTMKVCGBycxm)+Q;$rc)Mk~fst#U;1lVN?P3rM-O`M4g)UxK54wNmX z0Mgq)-aJnOx3NAg5X*&?-k4u5Z*B?BG_UgyBmM*l&il_BqZr1Y!k(xj?Jix37g!W{ z7H?keZ*@J(dMt#VKObVy9I3vg3?KYvEAJf~|MJnfGE8L{3sDeqQoFLA$yDTR*{&@z ziB^}+X?_kxHnP(F{w>lGp>BTpU;qt-rkUHX4jU*~5?gR;9)fSBRF?x`tB zw=)UNv;Gd8ftLAL`ZQ5e4TKvI&agaf=u;Y{p*r~x{kY_FS<2!>Km0i_T8GifsMLEc za`nzwdr()Yg3)GWlc8(A&7WzDqXC!>TrXPb8MAjElXr^$Bt|u;$5H~cP*7cRP*5!Y zn;3a|*jhPx*jbo){A=-IcK~vL=F-C__(_?IJvGyk3(Hg&HYS_~%QBjSB?X;mOvZYk z8Ys^dK1YMgjZ07$mHumqO}~aJCPuN^lMp6mUmex4)w8bc@kG7V^ShC~7GCnsQ`eLA z9ZqO#@8`*HosOrV8Ih+=|9?KY?mMd=S2>Z7*mIgk?sG!>V4gpnKKZeP9X`piVs5uM zgzQ2PUc=AmSTXlo6vANFm`_(Vpig@Lcf+nLiCcvBk8wy2+iiwVPHeC1t#^6%V4b%S zk8#&X-4pl$n(%XXzd-3VsVpE(Vpt4gerQD7AW0)21tB4r^ST0*HT=-adz(!sx*}CY zhvFN<-oalPjSGHKL@=>4$61NwxoxGRbN}5)7t`?}gDY$3QBMOv$xKrZVIU)7)Zob; z@2iS7ujd8i4tav;+HB25z8Zm)PV`qS5mvI^+lkp0cxPx;QTp_Hjs2$ggQ%jo>q2j&Mt|M&ggi&32kJr@Q}Ykcv>2;uVs9G z+jVmb5{AYT5XWr>PrHvt3!8`%!Yk`lj>&^`Cyi2h^-7}^0LpViIDq`hXhDGCP_xoe zb_Mv*Ltv0Lh%z?sjwVASb%je2R|EX$%9%6f&Lfa{?rWGkDS1+1Ca`J^Wbqv5%4EsJ zR|fYLk}0%3_2k_xgI(T!x7%KqqK8Fx9-h8hzuaV?w_WP5kQw&1u*SrQZPrF@n@kD)fHtfgi{OCi+9>rin!$H`uZN_$? zBlOS~pN?kMd2)Mv8l7~MFL+Lvylud+y|#pLTMHu}fSx}oVGZkI3*S6BK^pl6QB7im zP>rPHH#@StxpEhlV|H20b=JHhzGixn&Fw{S6E(RL1`9!{>^di=HK)+S4N#P05rybS zu3QV5A_{LS8+xl((a6%`7v%Pl4c6qTWPbih@%rQG(O*M?!g)lbmw!8;=tQhbvhFDd zb4R7ygfBV$f4TaQYzXJC66HnNDYJh{p!mM*4 z&8ebpD48B?W+dMjiU@`W`wPJ^!yJ{-D$QJSL*0YcV+60Vc7ngj7b?sJhU!&R%%{Xl= zeT79=B)n1II=xwyWoZIB97C)dH-VigzE zXaUTV)<1ISaAz7j%%vrmj-46Ukuzu-n|^`>8*NBdP2znyzkAASNr!4TZ7OryFfa}d z2wOMfY(?iGeX$<9MSQ1CN4HArbR0}3!!<80Jc|BW=DIMSk`_^BXnV|59=sddTM#lJSF!=48UYKVC!4h0( zs2k3rv6sc2xa{2f5vXrjhIA>Unr#*9{`UnhU-VJg!_o)s19EiOKM1?0uSx&}j^o>; z$&)ADY}-w?Z?6y(VLtQ;*3_ z;Nz&JF@z{WM+VEUHA;$4YPKfoChSx-$Y~nKXv>Q=vxC-=?^^oi5AN=5Jtx-EC(~!Q@HTBg%mP0#Bbs07 zY<8`*#*-RowbDaDbP6G_u||A2Ey|dTkzy_0UpU=G6vSVcD~lTnJGx+8^VaI%;i2FvA$&h{ z$p}QnyoQ33USze3d)iuh3g!*hl?}UBZ*I)m+>+s##0Ow1Z#H^e1{~?L{^76f+soBb zIypl~%N0kW_kBSR!FPEvl|wD%H8_mDp2mE|M#zXZowk(X^H=3cc+r z5tU~aPlyDiyIsqk$#?hPLTWq(!m#&lr~l{{XfpBAuAyQI-a=hGuM<6v-*q(6*o?j^l7c=-RY(!m>KQTNcdfLjt zj*iVWws7aZVdz}6X391lek`O2i45IWmp7|Cip%xI2{FjAiN1%Y3!Q9fHG(qa6w{^98?XEgnihmUcWI36b?ewdQp4DfD* z>aqAbxiim|w%5oiPg4G)6XvmDWBhcLMyjG7qI(J+-DstFsn*ugazsj$tIVWMeF5!e zpQ)*$S7V~0$MCYtbOi)tBuN6W;cKK@G```dWW%>~Z3?qjn7#F?lGRMjb-6F5&p?HJ zePJ}M>f?wLZ!3d#z9YC4_ExapBa5vF_~@_ zk7zW{PianFo@D`J1G_ zg%cSc5$=6XS<{Cx7csF^SwJ8ITpXQs$n5qKv%L_iXn49;=BA7bX73VxlgHI`Ik$0+ zWomJ8u30UOK0mP)G5r`Q2{v*LXR5{BaDNFhzru_^yQeHoXr18ChJZV|Fp(ilUad^m z#>;upRc>B&T}t4;6Yy^Bz^i%l_|2LLK|KK);`u{^=U+_3iLXxB=d$DP7bUKr$?)@s zMG)5Qqx}va(GSEq(_RKgx4hyp;;%1NxXZ85(FqT(>2s(0%i?^9(q5`%Xmf@B3qPHX zq)LqVe0#e;4-7`I-ijs+C*C84EtNC~j50d}Nc@ZTFRdd!?1QFqe{-GOBgnm_MEg76 z3QYj~)Jl_(qxpQN3E#!aQ$x-mo)B6+41FO+|LYY0*+X`Sw*H&sn+AAh>{unD491sj zx`{;-Hl?GUb-jz#Q=zGuvqR_z(Jf>kAT|-iz};0~&3M6g5#)asa~QT9PIkKq;%J4< z-q-7E-rbCwcEZdpxnykr3TRK%asc+@g=e`Ea35tZ9HdF`^E+kQjVJ3L>J!!2mHwlB zj%Dkf6Hxb%tTQ1*47b{g&_j_FS-+K$b`VO9A%A8SaPa3II$tkYkg|JY;_4E+ zZ)W8t5(-kDv@umYE6>s8P zu~*y5Ci?mHn8QlsRD?sUTZR61G}>dZam0D{|+QJUp{updT1A zSbx(At&V~!>>B30;=b7D(vJm>oSuQ6tAVjAO9;OhIH4p0ue5O892(< zFp*UuQ^Op*P{BkCWsOH=6{j7Uq@|mmK2msxKt3#zczqheNF$)-rELIMQ)s@AV+zP zf6h+is%mkHW?Z=*(GP`J;wO{>J@zKAYa4}WSm;kU*28>FQ5?ZL#rd^I)j^W`fyD*Px zZp%CY9-@vK#1XN>0?=2-bpiTMi=URNrZhN;ZowNrCl$rTrRlh-v@?IL^?5;;-suQr z+@g)$p=CqLIHb;PCY&1dFJ+=L5t&m$B8!w-M72{NY4GXkqFb8Xn{_KzFZ@JW47rbjdy@=S;4;zui>ATlRCQWw!UiE%(8b>WJY%GLGc?l5mR4pBWUHq1e4yS7JbpUiX&&==2`_A(1r?$S&7ft-!{@mXVF+&5t za+{PbEv?9Z^S~UU?SS8)6OcX6M|G`zJgjB>LIRktsrPkpES^|;46&OFwCn_ZDlPap zO5$atjG~F9!8Yqc7 zdp9xKnm3^0;=X3(-_0Ol%i!2=`HP9oEbHMSUGE;cUL@h`C`1ejxwHl~IV)(!uoH=4 z&rMr&S)GYaB{IpUXIh?`ea*c{v}kc2P=1?Yh-9|0DKCOfqp+Iye6cX4+|$anF%I|W z7w)qX{`<}HkZMzP*E2hY-PI%7%lyy$ME!P@XE5)Qe&*9v=9|7(LXKYQ6X}|1+4A5d zbA_*#?bM&-_)>@`UmGd^lH-T?X1Ip&d;=d}5dl}`HPeDR+S&UlkF{>3CsST4v4o7P zYZ)twu7Y_J?P3Sb_@B^lNggl+Y%aa}+G%m#u3UF|?$Z9BZcq3y5{=scqV%z!&P5SddC3hqB}_XIG! z^I!zV!pfkOT6Rr#$Ov)~1ct)EP3GY?j7RNL-a{P z0YlF;?fUF!cWXTbSZ=(K_qy7>y9OSw-Hi3#*}p;UU=SF5(X$x{?KS5TfNt9i)BcUk z^^6pNyM9Av^cyAbOV=t_4|Lmnm}##%*N4pxK0z(4fyw^$m)geNhh8WG|8H&EVc;*! zjk|}v^mhC2z4Z1V)*Cv4&x+o%wVTsk6s|6O9YxoAH?Bo@P`KV;ZX`E+`3Rn}{XX`8zQ2vM zb9Es+b@_dmHKOF9z4;RK`~wti@7GdByvmYy9LlAK=97rx_>Z2|mfvy#%+0&RUkoh< zeth|;NBM;DyDKaGJo=M?ypFwRDd}4h>d#cmc2+gSDcQYLS%S; zPV5q!d;O>#0R;c%T4&J6vS;CpwB8y7;h}ZOM?J@R-sbS=!u_6Kd068Xc;jB2uX-VNM=4fY$?IInR6>pg3)UUZH zU(=`V9p@B={f8<2pmtlM`Kx1nC1_VU<`ka!$J+CTU78*Fy;RW73i|Z$iUH%NRPi!I z{i$Du&WP5<23{a#j|qR_eJdjW>XK%KR$tP`!wPPF19%fHoV_c0(o@g+2 zl~Y1#1YlG^0%Z22g%@t(%gN{}xH~wDOH7vfm_xGE6IUF_e3AnJ9?<-X!%t1$YC{2ElyC|^|6dw#&G^99$N)2N6S;m`~d)PnELypEQv(H~5jw5Sk=WLd?k zF-rD0ROl6P>BWP!$nhoQIim08I<%U4qjPCJBDkF6t#Fy6QEw}G=Kd(C3(fN8IPk}&Dx)G^(dy<9a6w-@dWHgwk}b1R^l2O+xa5l<@OL#oA2hE^=fvX ziUZf1C!D z-@G7Y`MWgYEAxY};q9i{XFFAD1-ir*jh*w3`0PpTWc5BFMyB z-Nc(n_bl*{&g9$PdVqiOvOAWZ9R0k`0DMc`SCW~?6=e^zr)&1On^sT7<2j2rBsDk( zc%B3$9t3f)$OR7Biw-sy>S??W`YBXb1wOYVdJyvT7gjkax*rN_{Rv_M30lGUaSni& zsQR$g*!w*L8_{gLS~XW*oD=?XA?N1$heY5MhB57?m~EvXqY!+RDaD1cJagW}jw|J} zPh60U0Vu6`qD8uGc>_rx5x`f3DC9M3z~?Hl>tJ(P(BidqP|kECjwC>on+D*Eent|= zfz3@v8AcM&=W46%ZQO?AHqtQ#XaK&94m*%yuD>_bi8_{edNIF75}B+Eji81s0r>cJ z?=K2m>70psTB~Z5Fk z#O9sOvFRPr)5)$&T`KP-v24ZmTqUuY6Z2Sd1PJ~-Nv@bmJrxuBZbGf|Qi|IWe~v+} zH3jE)lf53>LancGulGyIpck3=ZFqtWVciolo7R{^?5-yRgC>}bnT z>fBIjpE&$Mq{T1ZS)j1A4m=gxJswvJv^L?erHsSV_k)yI8rlK6=IWQGN z1%|ERbKc8Y4d=FPQ9h<~53j{gn16GacJBuVahTCC90py6vCBWH7)ITcAm#y|I6B9k z=Mf(#1}1yd{jL;Dk+Q9bHW`Nx`vOtfXRf`o^O(1?rm0U9{1@e!N;AR*7YW%v;qWb6 zH2yfn7{mJ9&4((D2+Gl$N$ z|7AOwOgNq5NG9B_=T2_Twy~2|^9G{z*81qQ5}MV%toxXzq7BU8R_s-0GfYPreF}8Z zP*0$5Cc)Z%_TK)Q0H-pZ7*8E*46X65SzYHd)bUg6!nW=(#QB6k38X80`Z$JhFHDG> z3gGO!|7@&Yx+spGlXX@+FOch?9RgoYsV0-E-F2jD0%IO$(K;no3_9#2uG6>f$qm!E zqlX%10WbA4mkL|Q%X}@#BQ+UQM-$QdTPc-M`n|lhOW)4#OX=!>P-1k$oxH%eNM`<_ z^Uc=f`t@|J4e;L7cB_X}9uNW&9H#XGJXri}7Q6>Cv-4&0l6MHKD)`@*UX@uUAGwC+ z176nl-3~SS50sfN2eadrhQGiQAaMxiQSxb^HAx=>UU;wF4aap1a_JrqKmi`gMcniw z?2K7L+Xn)#5R=xxP3ZLB)3nh}wk}yd zVh&)(asGpi1PJ$YgpcMG_&WHG7~=k{)Fh;44KYn+{-X&z5K*s9sRYu_mI9mU!0Y+* zOH?Idt-LnTBFcW zaM$*Ye_3ML2&Rn{l^$0(zE@n%I?^oA0$})i^V5L>AvEmwEK@E~-C-b^E7K_4G@f%b zv>mkR=-5Cpt(*E~b7JWf{-9%CuFjJQzYxgS9TDyjJ%)hUusoD3P zA<==4PsQUm4f3Z<8x`=L({ItoO>WB`IRQIK!{@K3!hm!c(C+)1e zLEb-s9oDV|$EASv+wV1l#D-@E9e6H|x9w`ql8SI|=ctuqrR3X-*)i5xkFzzUbsYge z*!AQx48X@NfHQ+-g^}YEt@Cen6R{K!+=(tGi~YEJaaTDwfg?eI>q|kmaOPAoyvKVv zQwaa<$T5fXTdWD935o&D#kf9iz7clOPEvBT=TX~@a2CPpUeM(4qn``nnNGd9W!}vy zyr?|JAUPc=;(6+uq`bXeLIg*d4eKv#IjqHMOhMyXvcP>BIU*?lXKq*}0*B<`91Le7 zqPh^H8mw9!qIG+wcv%G*VpRneaKS1kQ${x>-mmy*j?+eHt5o)cNnP@9m5aBy`fS~z zsJAR*A$ZZm8%4me%H~CRX}-*+;+svov^u>+2cJ5!YFYGLrHH(QAdoX^sB&xc(N88r z%8K-qg|Uw}Pda@mM{!<$pY7sY&Lw`2kmYVQCSGgh*Ntw*>Uba5q*sD!TrZ*i$lf90 z9jVI1&`JvI3TI2aw%kYjr9z{k^)UG)^qt=}a-gSr#>3WU@rxahutVbogN4A_S2 z>M!rqFm$AyYZ>#D-31%+_gFxPOi_K-50%@2fksPi!4t3Y@W-n{i7gP<_rdVjZ$KZs zWYh#pv|aSSR_@#m+F{4_Hgz5Wl3KXqcRaP|{#gwU$w%%)BxT14dGxp11+!1pEWA+E zcsIo`2h^lD5DG=sn?(vm&YNlq4}6dThAkY^Zk<GwT+~xX)|swnW)Q zfg$PE)JXv~Z^f3_Z%IG(U&)V#a+)Ca$Js!@3(9eI?w=N%PL=oCCBd>Ho{e?CxK}>> zTxHnp{FP&2bR`k=Ee;M5zjeu@(nK;!`1frRBF+;uu7;BJNgu}}CKoKH=ShIK2b$pV z1l!qhVui&eHANeIwLs+6p&iXemc5zST09k3&bQAXFB=>BScL=w4jELB1b>dQ5UB52 zkgh>g_Gn#Z*J!kjJL=>SWfKX}p5qxfru~_Sx0R=((P?vDeNpfnxf`r~$$8TBAtxWg z^r7ASBJY95AM!dr@Nk8KTK;s=sSW#-`tib-2j5B++}?_}6#S*bCIfvLaJlUXn>+Tq zmcEo`d6rdGM{F&Sd%?q#7j?%z!8D^~CYa??qmaM0HUyvB)Fx zwo+6?>P+tu{!FUb1zG^wx)4%5o`t>GVw-+i5GF1+$jGJ&{mhQ2;8p?9f&Za8D?&+5H@ za=nr8qAh?Lab?qG);>cCk#@R2ih*zIS`kmbzdBLC-t1kVy}a-JL+1_eN@e!x)8mkX z6HI&@cjQ&Mnz+BiRcj-H$}~iO<;<EV52PdfONNqA7WwNOn7!*Z83rBgXHR0J>&=N9@NW*@4Hs8@XYr|$i?TE|4y*Z{9%8${cFx+{l7Nd+~q%y zw?@E2>`z}W4tsB1L|EFU&~bK!KvfvEUYo4ar1kmCVyr%G#|1e8>1z~jnR=mgK4SSC z#Vs|rp7bo&D9n;(zEIvAzSeeLZtCe%w~o`rXTQL`>Gt-iA{=n=H=V{L#*J;nY z#XxvZXsr-vMZ)mtyI)^)@qEC2l*mlxPI$rBtZkc-^f$hxwQhTKdO1=TXz4Gc6Sc-p zjKSyM?e;^@Gdcn*h*{mqf!wU_?7_O*2yx;ipJWOXFlLn3<=qC@wM6)63oAh;V?2&m#?hP9<9u`YUXv!dMrzP{pDk%=l~rRhRCMb4^n z;sf>#On(s$9Mjx6s~jEt30R*y#+3A~qG;rKP0<+-M=CwXir2B{LDjffEa=URY!gjYm5mB<7)ZKw-Gi;9yyb zT%deI_jlRBL+~GN#P|sM&3BU>^4mB$-#sl#ifcc$2vm_7Il@* z;7rZSM{ge#D085wirBdHjQJT8SCI8M7ThWn0`yuY=Ncd9rY>zu(b9~gvh1w#%Ehih z)q%5KHpb7)_jAszYx_yarS@sr?EwUDoE=qAmxj2~Ic51_n>|IDtk&(WQ<|PNPltI# z?4AiL1{qdKJX*ys%DqJCT+`}+o2EVi5H}pVD+S*2PoTFdFC(~6+Fli@B>_qpb(Lu@ zpTqCTGL%yiqXuHEba?++AFt0%sUI&5%spY^ElqFq5|!3GnG94&jFClcLv?-f^#$hP zjh;N_TSYC0lcVR^2r!92#A&lG#$)(bt8BBL$4C!522gehxU#Wg6BdgeB&@H_j*vwD zAOV+c5t=*gV4KInWTvyqN!ukRLQpAW0DueL|zAV}Q_&}~EmsW!I7rO~I zF{+CsQ1B^?JS|~yN{&2DWpRogt7CJnirkR*X|TTLeh!EXF74Xd^lu*XOb5kADzUDt zWP);Ne=H5&Ao^-vX9=|*Z78=Yv!#*B1B zCH*|ZW}qhuIZ%{Egj2CfdhU{oA_P-K&mVx2vsofclCyatWT?CbNvPrzG|>tvf^(CW zb2F*r7F1G7xM`K><>lz*mFU&d4-$jZ6PI%`s4Pp|Ez1NaWmH|WriS*bn-9%5PUU4< z_PCWWg^)%ebiQTFG`9}w=DMQxe1D|)xZ#T>LSGbo+!ud zsmWpi?_`aR=%z<_Du?}*h6ueIz6W?;ik*Su%a?zYp1p;fodXAN@qD*^;wFBft(g31 z+5d;f4m~nZP=F357YFA8o2!fJ0;G9hl;`xda}-;mP%9+@uTXRn%XNrBMFA9<&S*14 z=u9S~gV2fu=21{XkeI|(sTa!`%1_S=Tog|8~LPsCltsJYS8aK$-@y4+=N#0uJP7%4cK-X|*WVzI{HLWk)R zFiaB;RK;Gb9Se^iBRA5zZnluNExex`;E}ZSGEEbidzD)AE@We(dRBZFU9wt0N+f3j zn0qg;$lI%%rW;6>g5%i)`K{@uiz((9din1F;T-XCKP=Bljwmr*07d-9iWc8ZD<($? z7;KYPz0pA(11~B`U^;~hi|lOXyJRm)8PJQ9A%H6H7daI>3 zQo$yP2=0gc=-6%STu*S{$A!j5MEQn??s_8A;1{Oh< zV*TarC7|q7#0odfj$Nl|P}y^mpnv}U!DB8VJU@02h2|T#N#SZ-ejCC0pdgRJMG#pS zIu6<{#w|JU6d9Gsm5#PuDUN4%bu1IE7}&J1@@{GdQ^5XeJFQjO~?LIG1Q| z#xOW2QteBlUK=y;8^6RYCZ^5Pqf9Vh=~xskvcadOwezg+1+Az?1`MIBslraNp&e@- z?W<0F(X*@=&PfZ!qn$1hsW3l?_4jZlPP-;dZKZ@^=BRxu{Dl5*_tIU1;yd8}@sCQR zfBb{$f4bM!+{?q*?%(#+*l@)>{+E51%{9-5R=-1q=>;T-f5kBTLdBXQo^+|D)k89d zy3;hSV_+7@fG6X@qOhTtkL&HIiZ3m806{XnmM}gV!jf2c1qL|dY%HaYN{d&0iaMdN8w3009mWjk&L|SA z#j`q1M;GH=sm(=l>inuq^c)Iv!D%_o<4gqPw(3>x%j}eA7GR}A<~0)x%~@P?=8<7N z%5$4bf#=51>*<~vU^fbp+$DE~sWdVT>5g3+m*kZ+R}v?+ z)(ZJBX|dR35;fRlI!(a1ml-krX@k7Bb7u@%Lwc5#I@7qWQrIyk;sSGdr}4$`ZVdCj ze0Y&4qiY2_Khl_wsz$H@NR+a1=hLq23v1IEE`D=No~39*>BEINHAiwoMX%J@UG?+G zGmX57%NYBZ z%V|xV35iV--SMCyf)11bWXc4=^;GOvMASwMuihb|?+&%f5uiP9;&9v%g6$6LQtn`# z`?OgcyaPsu+_#wT=-)6r9J4-}6RG(hg%ca$B`TmNU**h5QqRt&-2@g_|JoV8>`wvw zGt3vayYJ3NLhER6mq>_G!`&BwBAJ}@}`5wwq&N?Wk%Sp%i5*nYoa+knZ`F>eKBP5N5U+l z6~`n*e~Br#*mY?c1^cx9ljal4em>&!={gQ*#}U>uj&RGJHww?LtM3EA1u$Y2hYwsf zsuM(|vKWVfq|%<8I3(w#1$S*(O1U)Ar>^793S@&X8Y{~p*=f&V<&~KHW~v7wk}LsNbVG@aSo6OC=9kwab6Wwdnbs) zQb9cYiqauVm;h?XgZ=N-_Ps#3)_qAt`Tdo2-8VS?AV0cWplOCQlsvKnH<7iaqx(X}v28&BG5Lb_*09EH zH2J!t<5H7&>)o~u7!#XykW|q={`O6BZ;<-J5}_K$@*-=m_q3Q*l1F@K`MSTb}{{~PUC4LA z2$^N>9^L&KlKo&Y7swCT4g70hoTd4OF5VKJ4K zCN!_F%nuxupqSDW@w7`%uOy`~wj(%NL8(kW45zlO z$idT>YR3o95E#p>jr?pSPZ`<9#pUzcYBzMstc9HutpSQ{llC9EYMlr7Ezql-1T`8QAITwi9aAgZT{#vK3eD-v3Y+?!xr+T)Puy7s z3NBR&_)b+XZ-kdR0uvm2Pi;$x>Ss$Nt(9cdZD*&R5SksBy^43Cy1s?jb{Drm0mf6C zfpo99bt!G!M^A{hC;)zp($D?iqqw7wT?1o9d>?s%Vkv-M-}LC($_Y%(sW(qIvebbX zokDS8c@0kgQf0&Wk>pp2Q5D}#>a=*no!Ua;R+5RWzajmgmKT>)iv%88yqTvMb!G%r zXDXTuT6x*I47I$Zx2fOR&m=Nj-uBsvmZHvt^lLe9UGjdZtW?%|H}-UMSKbD)_(-=< z&mu3$@f9^gS<;1VDQ3&V?s_$$PBjnvsOMX67XJ>4oG}@!V=r}p&jS9LMHZXQK)qbm z?{=vToog1SEMFp7Xhw93w>-1Ev9tIrT8VAtaI@KAM4$9PSpTmkJ4SG zElrHLC~RblBJ2qFREt)sXdO2n|Bi(OUM0k=Ymrmjdm@?ro|qn%;z%PMjOFSn`p(oD zhnxAqrb#;R))(8*b6iVpL5tTFk+@V=;1bS}ANS$u#UaXkAU+y)1;exW!`B>D<%wu^ zJj}0QWby2bUwd-Q(;N6zt3q*V-GBM`Q^8bp{imC(E_rpaiL+zu$U=fkE-q8r9ckeP z{`lk5PYT=%a~X9{dR-VHU5GC^`UOk`?x{8Lv>6AoZ|pC!k%RrZWaBjubTDiemNBAC zIY*H)l4yuxrv<@rvhLdK`Nj^g#cyo$IM}5>CbYr^bCy!vTx#-6hSdS%kp^}Rq!CG& z)+ByoTJaLSn43-!n41z?Bu6TG7Q?Z(rgRutw!_1soTN4qsd3@qEU=i^4ccQ^B(Nm9 z6vC}h-XR|lLL7&d8Xp8qnRk(xy?vD$UBHWKQ1Q?gra|k$D(R=>nByG~vv=@j8n75C zv=^(<71~-2fc8hbx1{?FYMlmEV%{7G(CuK~^h$>y*R4j9i3&zj_p+4M2qK~m6fJIW zJ^gN{K-VPryDhT_ZoX4M5&b)rJ*N~RV{nToI(qBGCVN;Fk?8C8?oPJKrnp4(${_pK z$k#l)LOH3dA^qk;E`bfKs^3qyksTb(p`}Ifz0T$A%afgb8SV#kJ#I7hVsZKg^LK*11va#uHSpx0rp=cu1WqM_iNLmjv27 z%M}`MSHRj$v8> zh#&f}1@|k=_N4_& zA4(L^W0_#7kQS+h4;y5NrFY-oi)bO238j0K3n^5~<%+Qg8JK@KMGsDv4b!C!#ICLb zFgVprQ~b5AS$MI%qCute#;+(94-@USs3S64RiqDPa3D^;!SzZIY1%vh!M&LkHhqp{xw~lIiVvuS*C z{FYl>kwaPKHn#4P(0Kef!&^&hU$3*0P2szMk}DYAIQ`OBlgZC6jX?3@q>PEjy?yVS z6P(79q-tPl9PKQTtwZP5SVEx7rK!8Ew%Rmg#zr{emU%WOD2D}2bnM!g9z~CMkOe0A z5pR#N?A$+1jCV`liKS8WF-0<8W~~_cJZRI^ODQ_{mCA!BsZ>Dhbcqo zkIB&?Z=*#es_FH{sWxAgtL|5*%tnXQz}gwIW<~9dw!k$dflkJo^VIJjAisCJ!>w(e z=DKFMifNxJ9K0!gtA^N9=zP1Qs?^(1NbhgOk3VRwg(#VG<&cf>1ftR(VNTc#MPu*1 zh=uV5fE;cpaEARX-lD_hP!glcl5QBLv4vw%nE*9YV)u)5CpHIM$q*oF`ll5b>1+W+ zD=R5k&3$dSraiaP-W&MhY-J{Bz#r`2`5oC`Fh%vBM!bvf|HFvq=w$6+`7g)eg#x+= z#wXAKYsCc{6#@g|QerLT2Q5nCf{OjZw-!2~k49~e(FU{h;cgT^Bt!AS{vl$)0AzFi zM&aM$g_)N;mOVVX>8|g051XFf=;qX@+bT(;eN?8N*Gy=-i1Xf|}{9tr1njFegpmhsgKbyiw& z-{^8+L{&rHOYrXu=vj*%E!ssjFWrL@z{R{5Q58T@#w44!2d7PB?|ln)yFAA|CAAvV z;d>f?048LuvvE}bPD>m+?w}j-QRuDJ>F=p1!_OWs=X|rcXxe9G4!w<_h$BciBI>b( z$@(+su#!pU-4kOjCys}{m^W*Ti_W`%&hZ#NT=zPyb7bY8JU4tXt zu9LAYU>THttq&E3vvv!8Fv$_?SYcehSd@8P$T5QV{3!FoDVE*>Zpr8QEhU^8i;T9@z*|SL#Bj`5Yf?Xy|4 zWxs87$ODE+fM2y4aJMGhQWGqyE#(tdSKe&PR5;gMbw!E8E-v9KfnFfVJdg4v9K{3y ztj(JrBgQfH9knu<`$KFM6>AlabL;!EQ*9n)MSSXe>g>PEbINyWJFDk=h!FsF=~6&& z0mlOSOJoIpf#j!foPr1^cRIu{EqS;`IHR500i_)pa9RPY6Y>o8$U?*c^+;o%pyiO0 zj}&6HW2U7>iTU!bIW%}DPLnJyR_REZf^GdLYbQ$r&JqPu1dMr#qa|~lb>kTWJ!FV< zs&CZ>$A3ZV8ePt1gp$vGjcVS9%i#9TU%hTG!#T!pVV@KM*d9#)jca5)Q{2XcI zNVr^#4(os&Cc`Q;z}=}C?PXxaaHd+DB%CNY9PgnVXhP+RSNlnfvy`aZZCcl>sfcbf zkh2t{e+JlHv1`k(aggSYixEfnZlj2Yfez(FM>@w95GWcQAeaPzW>y$;dl|M?3cLva zP*CgC4Ids8bV^`~S4`iT@pmRLmrmre?rm?HbSrz(6A~{hI@rgDAq$pEHQuQ;Sno&% zT}lrCR6wi0yNN~!BBGMQ^1-NV&2b51%0vLoF(I3ozz*IQwRt$eM$MZH9rg z8F`gulF^Z`LG&m^8Yo=nYDkoS2*Ob%ll!Xf&97b2TQyaqO(L z4JI7nB$%zHrI8X^a%~nLD$yaLY0m0l48hWzt)++iDg8Z8Vy0~lXZLUBlNZ=we4Ffo zCvV=@n1vp9Nt@U>49NLga~4o&*K<(*Ilr#IxZ5?9eJmwsTaYQIzb93Sic&pY_=T)% zifHYkJyO1dirSMcKEvR}Bvr@rD+8LFUD&(E!mUQ2Cp}4$GV}|J0W}NNoed^H+KQUX z3NI6J!g@8!E~d4!{r<*|(!$A`o28(v=Hfp#`s57;wrT?l(au&VNIkyLvv?j#72a*X z$_{NCvcfD#OY*=Iy#OWQlSr!Rij#?@Y`O7NnykH)iaF!H8ae!#ugzZf?o+k1iKooD znN+)dU9^fhqlOLuQ-R$BczOd{XNO zQx7vTo)YS{Z0n`)@odwVvJ44wnP55&=_dRZLlNQE)F*Q~h2NS$r>+u2>fCa|TdeRp z=8u6bF~Ok?bHhPmV_#Vx;a!)b8h1$uQNX((PgiI-CWp^vU6E$V#+Z~YCz703E_5Q@ z^q4_z!-jhvhi*_jk=}U#*&QFua{1i zPiaa7?HavIeQycC@8oW{rrGL>$xX`>j#OG{&Xg zM-Ea?ilKMJ6F&SXA_#GV9GbWz5%;(z2+0bLs|~P98XZ+)9943`nMlT&Xv0yk#wlJA z3te%E8eJa7g;sLVr~?!Q4N_OKH>)U2`XnV!mgvlso9AoDH7BUjRn55XOXN^E5leFq zu)XlV9KrK{Fx@vlvKms=-gb3QVE3^QJtb~g*BT=lj6!vd`y=g&A}f#pJwaUe`kx}c z$exFO{NamRt(LbCf_p@N!{dcUWI-5Ix462!ePJN9+&x?0P)8@M-2;Nf-CM$$Lm!tt z=$upHa`4kKG@*Hd57A~&GS;D|%?R<)Xl~Iy)A`6QMn7caAt~Y>+SQ3a!wbs1n40jr zbU`rrB8kc$7@j}emJ8Ki#0W@w1=&qg_@?|_^L9=DA8~;g4 zTU|UW%>Se$Qpo?6bh?_m{!1Nfuezv%@+-!V1FDRg77neuz<$0bA~L|lda_xec}!EuMal?C-fR9J6pLOpS=mS$2(vu?U zATk6M11XUjP8qErOOztI5-lMOdv!JBt|J6r3+0am+;19smZA+CF?HffgsO37m4~e# zOWRIjo^Sk;G;4FkJAWcgqeyVqO6+@x0s`K@?>!*^d8$vIc0eu7m^R5OXTX(b_rZOg zW#^`tIw+m6#Y92}8-&B^)3+D{H@8*VihRdTth;y(Vh&yRYJ)4z1ucu8ZhXr+!D|AT zXCmV%_Nz#aY*QAx1{gh{tu6M*62}{--nHynWkg0U(M{J>7kq@f3`-Yaeah86^xrG_ zYtJY7Fna4nTc)HkPPhzv&ddQXaYXmSVZUy!$9TM2#2xhdAPfg(rWSXhwFN?;mIkOa z7144`N~OEU@s>lk3!jW=+hGwNpoF46k=AdIOV>tb3XY3Q6~Y~XFetthx>u~KM%?ne z$bv!io?}a65c}RyNBui8zcccb*AZh;HAvIL%8n+dHZ6YoVexCbf?h?S^-^tSVzFZj1!QnnC@# zpiQCIymv5UZrl^+HRveuZi%X>_xQyLnKNZZyOfC9?|sY@hvI?e)J0pe`5Z?P2VIxEihsH zg827_8}z4YVErcr;v#(eM)6-84&dr)>iRDX)OA%=$N2O}WViRGX3(l(SOvF^EUMn3 zG0JE`$uRi25Q%|MI!+=lt++={qjozY(YG0O7!|{NA7EnsC?bi6YiZ=`1nAq{107_3 z^%>7O<`$hXL|w_PY*=13uO92#UTss&{_=vzgCypugX(cv+7Bn!PXJMzr4&ge7(h$s z>JhsC2*}e5otTdWgEr`A;WKd0LmMq#$qPO}PsmC-;*cIl$V#BC&_k3)t0$wS$oMDP zC8QA!dJI8Mu+mKbQI_Her1(U2mvg656F5OCiEbm>q%w-W(EkoTBjUfHL5mpCITf-ItFwSK$9t(XP}$*)xz{U%p*GeJQMqro0%3H;{Dx!9SMSG9=!$5?=wi^k*=q=*YpXCK zuAu>7uVQZX$$KmY1!&w7?P%VD399W4@CG&y>(+e>5WaHdP_T4!@Wi{Tqe6#oy+q); z+S%-~bbN?$GV}>AT->6sTe6!3EL>eMEXn4LB$doiZ1op@;@(fg<3w<-`@|%rTu=RJ zAFtyLR?*<_1n0Jem5(hBTURW^6IvA-^=_q_%OB-7c+Y|VDH3{3D(!d4GqSOXLxWwe z7mLZpsT#VS0?(23h*T-L3D6-sn2bbdcfUu; z=#6ZxML)=D=Xo??K_LFIBy2Ee`UKyjoFHgb@kX7|Q8gY^avJw!xq<77kyP!ZZ8qYJtD;PKTSDq#1GU?UvVmVqdp}IQ(zO9Nt0a<# zg)>N(MZ{-!$lguyhAtd3hPuVI9nwji*M&zcoIg`S53w}b+N#=+DX6rEoG6tv*sI>_ z_<@rRi#n#s7gDXtR9?}|$C_#<)n@ge3U#@U_fopw6+V<$tij*41wMagV%RN+;WDb1*1R+Hn zsV&?yO~>eeJEN$6pIck_MJ2O^sN7Tkra;$9NMuZ&5{)S4NIjEe8`sscx6k&QQTfpO z)%u}>#WeLGNGN`s^g?f=;UD8Y`MJTL!OAatg^{LB->D-?{*@tl$KHv61NC)$&}&R~ z83|sT8bM&D*uD^52?epZ@DOrREXm&OfFF{(`=?Mpk|+yIED@sQpp6m-|BbY zIzDtI=DNdwMZcD5sx)@2@`Wocv-5((XE8K2aWI#?CfS`$IML~h(Tm%}X}TH}olVIY zh<)W7W6ZAA;njR%`{cKxE3o-8jyc!-@G6ywQPg&#^YTP$KIYPyPBF+Hj+B1rqS?Bs z@C#4AG@lIY*x1yf6pOpkz57-fq{#sB=D3=~nCXZ2xOM9%|Aq+GD@M>$Y!^iKMF^H_ z_!Oe{r6yD!vrTCzN&bf`yl^G$5UOBt{EC6v8x9vkH2R z72Hf3WmCqzqn$z<)~mt_ml+jhUW0475O@7A59;F8ke zZq7%R5c#R;Fi0X+7VxE5NS;1k#oCuPRinCc$GLe1A%$X8#oB9uw{m~OI6*kZby z0YDiYe?pZGOUh5U&ntMgm$T)&i&&e?iL5hqmX@kq*bSW#n9`E8WGq!|Xbtl0@Dp2( zHP|Z;^s$HNgO$dH6Pt#KK;iVv5R{0MWpZqKky&GHM>v@s=nPSmG~vZQ5{i$i=AT9S z3%D6cO|;qx;S4GJDb1z>sfP_ofi(6;^(8J) zaZR``sRO#=MaE%`HDxfULciw-hTQDZ?Ss ziCLDI*2o1wY$Wqf+AGl4etD0U)`XeDw+O8*=O%l+?6F9x>9f>aqdb4y!N=Bl1$4@Sz!w5-#I7rT z`Rvm(1>~EfXwi=E0!6qpK0e(|zu>WBRvZTv-$>tJ+Ql_61VsZa%=3z$q?n5_6>Y5m z*N9K%3G#dBg7UCi_%ysc$uL9O3zcX4)BW`^{eijwQJ_(ufU?3G`pG zkIv0s3>|+7U{>a|gpPMlM|1M8P#g|uhX_lNCNCan4`WoR2t(NjE;hk>Hk*CIAAD@A zu6HDI9Xm>A)S*`ezEsr3CSzg&Z-;4xVFvj8AqdF^C*QrF)xEDtuacR890y~42yzEj z**J}7#OA>Yf|Qk!@^8Ol7<@w&Z#e{q83hMbMSDiEK@pFFJ&ynZ=(}&GRcGJ+R+T?| z16TIlDO^+h%M$Q|V@|0%+56{1Y~L^83+L~U{D82dx>WDW|Ik~rWyWzt|MTA&2ls!x zN-mE7Lg8&yRZWzyY+sacO$-&bE^|Ig+ zH;$4BFK5z)Z%MP?&&(tVI+CDFHbD}cpTJeeOy(d?}}@CfQD zY-w;%4ZbZ!KIm6tir^a<=BJ&6e-E2v*5EfI~F3IgklvavuY_5~~z;+|a7l6Fg zIDz6mX<1g0p<+LL`o(7T>|F$t@*mZlVR<}ZpKM?rE z#H{m2pf=yL1{{fqD1m@qAFC9s5hSSFyKBIub+Ns*G-T@(!2Oii{K8u8XGL56mzruP zD!7P8Tm?a40UYu3q~V6-!vqY8Qh}1O*A&dbAM+YZiPN#WCoJMRFzkK{Y{;DXgfE7a z6QpH0@*XYY+~$(b5QrvY$PhvgpJ8%r8?`CX4TEs_b{L}nkaXIS0L(9^9h^2>pPVNr zFMj<1yUewIK(`NTbE1CC0=cfbY-ge>2-yRB(XNU0D0rI=nRk`P$}x3zy}{2UVtI!V zmj|w_qBC0ZwA>qi4DaM=)`{L|vno;e!xXj;HVE!#VD7dI^^yZFxIWW zB5D8^j83A_G-`;~pR|7VogqE|Jn@0OuiQc@0Q=>ZsAuRMgh#xmJ9WTvatnWF=sXGj z3z}bXo`e?n??j(!TRD_Z6<%A}a14qN@X#Z81s!{+olb8z$-8b!<(K#_Y?j{OKL|U= z?plB|3dc@kTQ_!N+qP}nwr$%E7OP!d{m|9_Ftg{Gckh|K^yQd#M)~N* zUrlSTtoQa4bs#3%wsU^J%0K#-b8!m~y(_=VL*TjR1GMUx1wrU)!M8=*Qk~2iM#LUF z+oDCq5CQH^_g@1&EQk5a>8`cjy!T%5fRJXL)k{`aspar`p;r%sH@bNzBH0@%=%2~d zKb<2UYi#|KuKA}{v|SqC;Q!r22FJ5%b`1&w68!&MS0@uId-s34t^o>*is*bE1Q+Ur z_R*xIOo9=`pB3Y(uEWFhnS$Zs9I~IyHnf;s?l$ZDtE5JWmiy4VA~-kIoNpG!DIPms zowR-emv@vKhjWr91!7%>2wXqk6*9i z?o8A?9ifT)H;<*dv~t zPxzB-z|`Ho&?j+{{bF^8REes-3CyCZ?s6^Pu2gZ;utHo^YOD-4dUgKg!0$8Sy z34vxHfz&HP-|uY3s$-hv7A`}>@*u{_n+!FVR%`dl&U#Kq#J;NVRc=quJOTrkT>+sPtuOLe(!{PhQR{0_+Wsy(}^b(1lDXzpA3u$@Xv zO_=uTJ%XzBj8LBWqXE4R-~b;~-<2TYwc3oI^_K^N?`n`PL5w3yThB4;RK zVL0dv#;9s@hLph6Sj_ZY{9SB1q9U-EqYNKE4asp$@P{h0vnTIMG2E)t)9R|UT71op z#NcVM&qR5k$e0W`fGP_}_%TZ{PRNHOaB{=kB>C)z#G1mef*L=vodqh3d7mwEGn2p=tRT zvHvo9jP~n9jZLQ{hSAE}lFmLFf&-d#gpGAdtIF{=Gp6ld=AP<)Ssu;EfewvV8FDt% zxT%N`D<3$(FpH{$!mub9m5PBkzFvYXT6(2fGjwtvJ8X6=?IdfS+9EpKOBCUK7B(#( zUE-&E?yZap#u!gjCzF8&pyBzj!Ou@`&p%jCq2rJ>MmiFRSWnqh)7nghFBTTXs_n|F zRx0APD>ig?uxu{invg+$<{bZ>%7kRp`ngc4;&r;sb!2|G6q(!S%Gqg|*&T_sZZ55; zdqazg>JD{6O(J|Q4FuqLP7ll>@Y?Uff-B&@a!GUr8DM)(Mtgt1F_2Vpcko{(w2H5x ze|*>eHEVUw$g4o&c=jYw`rHM_$XNf%u_>LM9jZu)U7|FjeV`;kq^ZG~ACoq|jUV|U zVKQ1BG7H8yL5K*1hd+||jpfXyjTVayuF z0phSWzEVbN22ZJe(4VIn`HzstDt@oGU9lyM+xj=P)aKu4_8~d?z2&h65Vl+ zRigzA;mP+zwW~f@2ru`OYYNw(D#Qrv@1Ps{XgHcW+(Q)SJK9j0?%Gj)BLz4W2{Q*s zG}37F_U}7DZM*IB(H+n14e#9XTTB`iIV46MC{@W$cjXNTw~u=an$SE=-sw?vZzA%aE1}QOn~>F;JG$NM>7$Ct3Z$ zrZh`DBj=cs&x#Gi=txZD^973o9v7Eoh;!*S&m}-yNb9Vw&fG4`@wA)1=O&*upR21b zIc^m2>k%j&RqX++KgUd=gx_yFgHl{-xlf(>rNR}bX=*Xjs=7UY3%pyQmiY#|047)4 z6p4HI+XlHwGD~JFur88EfyEwP01AY>obd_~vLrR9TKI6` zG@}dR8Y5}Ck4)Yh5I8nG(ixqlyYX>q*gR|NNxa(TRc1vg`g(1xRkq#T9n3h$HCCx_ z$>ILmq$y}&|83|IJn?<$i$KDp-v&zBYW#`7*r1TC=qKYae(facodGnqnJRM{ASV26 z=hb*M{fSGgl=^c$ZT)`ob7tXl-^`*?O?cN_@S> zpw(ZHjn@UKaX)m2C6>n`&To@gU?QT#J8|h=BJjX{zpbkH&lbh(a01X0W{l|S{!*{+ zkS@olc5TE_=~BMAgKIX2d5nk$PK1f0MdYM;?{Bx>K#yx{TC4-9Y1TpApw<{u7Y$W~ z9YLX2-xf|YrO6~B28Wlf)B$${(?qkKyC;i@^nI>Rmu|X0W}om+oVR>`U%>o8Tt%4BgE!;C6NX> z{ny%|uOSI-id^PXk2tm!X!Y7>jsMbMje+nb@>475FGF(&LDh)bKtA2cz>te&`EAmV zL;b!TOMm77cl3s!-Z*~O*bq^Kf2vn35dpI40bX|${I_ox5vjp8QY9|EK{wI+OO4DQ zZF^Ru19uz)hPf~_m&9n)64o8MV_4nL4T$9^*_3MNweT7b&7Kv(cJTth2<#`O<;ryK zXAS=>G)X*(nqODetkAf8<{Q$GX7xMLz^t?TAWDJ4dw!{Ie`J9LrrY#v!ky)S>t7oO zE^y$&r|v4@O5;1>NAk)V5fQ>KlTIeyOwjOo4tmDi0rS5qt54iUR?Lt_1n9esEcO1F ze)*m)%G%jdPI{S(a^zN?uKV{YWbo%$xvcXruP?DJwz+-SV-~<>XHWGFwk&&)b;>E` z#7PMN%bY#{mo>fP<2T~bl6YP)b*MA7Ze(t8IzEzGN*5YVIO0xt`%0|hO;@A09&|;S zVKbQtwfI;WjS-9zd~FZYe-ZWUNjqsXp{yHPe#Pwz&RP0^c(DgOrE9_MaYDwOLa`@~!#@j|UeBbI%XI6cz+toBw?|WCf5ocdiDGc2IO0X4o1U7V|RtG!QhW5rj3F z3^K35$G4e;9vw5Jve*yK%TLpd^HbW(nz7AkUQ-p1Xwc?ZrO%{R>NimF@ek8cNbWtW zlQ%2>3TSS?;yN`XaTt@`97JhI;8@A)@$144Ac7vag4re14gR1*GX*#$KbgU=#ic0H zxZLru*EO+=9{tj%PMa)dusB5+@Fz%%H9skpW8UxAOVVqmKd}4^m>Mq>Q;9r(iKz`^* zNgx5{*&gQ~+}k=xRGmqs)w`bZ0LyN>XmRGvG&31i)!7iSco`YQ4zB{8- zW|%R*Vk?h_wfbPo#xO1fyWq_J(l>uj`vxpcQ2X@X0Zq7-b1dJO)-@67tzo?PlB>5- zfws+NtcNc+IC}0KKT;Ug_mtJ(q1hr!C>-LuugLO&KJJvr?i8ye?!!9I*n{|mX!q&bz@ zLD28r8G^O5HliE3+ymA9$F5%W{YU=8wwzAZrB_abb;ul`PpaEPMP%N`1US`fGe_uj zEFZR27J!ys#}$@o0+FDjja~*lQ>(5;1lwTWt+WBWx5?8z2w06_aFs*jCuU!-&)dCr z)q3aY?Jcyh3S{2S-H4xlG+rh$lXoDpeB#1<`5YFPWt5aOlE1>Jsqm=k@UZTJbGAON z7-r;VN}{ly;^fnW#bjpSpvT=e&*t;wS1^ky>2MfxGDz@X6&MC&O#-xg8Fj9rGI$(a z3bSh2W*)t=s!lSG1m=`5ipcKeZcz9K_!cte<|h*=tY@cBAkF&-s|vE%jk>4&v)ocw zs1Rx^(a`oewf%_Fvl9+lj?jKwpYT=TG(GXb)-gqBw|w=N+431`%oUbB49TH!Zz9@k z;|EY^PEor7_~jms&yCCx!%$hLcysdt$Skf?<88X<+)9SWmncD={&Q#Ot+~CeKw_1Q54z+J)7)aVKNY7=M>KR9CEyJQ{qfc zUGd61#HIRpez5J`>2EQZHcAdA5g;cKQcQV)W&3{x&P}#mX^ti4hGcHW&viav^!?Q< zMg9)M-AGp|=@z3)f+*ra=&;rgWIK8OdftA!@y%vh*oYu2x9sH+zs=pEkYzqD>I%PH zbuBKqE?>u6uWaaYi9lB|lWVH;x1&Pcb#V8vFLI}>ueDSc&z7Bgv1J_37s<=%7qWN) z-}?2wwb%yPvwEFQ4UN?GV6|>P{=xZ?h3+GN)L(n1mludSw7ntGZgDka>x*F=Zl4b4 zbm@C%G7>#rlW#rxM014+oF=5$ZArj2649;>g*mc3BS&|YoDZBPhgehNPAu{DiIMb6 zqdfC|?eR^HSWS|VGFthLP?dH5HD|UM^0Pgf#u8Fb5NjT_D>Ge%Oiyw~RRm~>p(j>- zrmZc)F>i6kt}XLXk$!Dl^Q9^QU6D^nEV_48AC>4pn18zA>hc&b~yiD6bBseNkg1&$X6Qlq1^Y5%CV<3R6L)+cV!D z!-3_RXNhFHRQ`^Ci=M4Z;nzH9mP~{h3PIB1S%fn?ANk25pefj&G-IK-DafBjSoDD^ou);ZMxH)O+41MK8HQNyd@QW0h}; ze#*@v(UFw5Udm&-d2u@%)|VKb+>K?{qlO*Wm)umLN2{;5LXJFTi!^AhxaG!(@ahU| z&I%oZU3G(v0kYJF#xTs4_TG{`D#KL{sam&KiPgt2)zxq8VggK@jbc(2AL-cTd=##Y zm?FWC6siS@NS8+?b+VrOU<<(TFQ)r*6CYj;S_Ya;8?Q5wL zV?NtT)DAAmT`&q-KZkpyMqKqU-YCOex>JnjScgQ913qeb99eQ~MCo7sY1|HAvrKs@ zB(VF_#SyNe#!VYjERIFu3Urs zD)LQpNuAH|rhQ+{O>6p$?(3@)kk5&9trCZ%KGk&X4oUD=Jcn=3)kl!eHiyP;Xw3Hw zB@rC;q*0i%!?DyVM~n|vb^A11tQ1%=iE zx+f)yrx=?b9Hpz`>MlQ3%1GY?)+b$;7P8_9#u_n;EYOibN+o#{dE&4ePd;Baz7Oli z-5%Bw=@pep!>Z%c64Mu{*h4n6MaC-@LC7a-an)g|5Hr9>g%9NuJVw64BIwSF&o?~3@Dekku*o7Hqw24b*3wAHbN=#1 zBDtYLd>t3E916U=P*J|9gt(@6wtHMIDLV3Bf*rD4c&ZVsZ|fXWR)@|%%G_Z|qHa*6 zlu72q-eBQ=$t-g?oL-#qlib|SbJmAc+0;w|Y;w0$=GyhnxG^~~>K6o#tnE4tYA)o83cd9@J7?Aeg`F>*nc7jpAsZ^b3vTNiUTfy@4Z%RvDb?hcRL zo&UrO^ULfjo-{}9>dQiw#fEI}ui4$6tv{_k%gr_Re9dKAj4k)ueON0@JE+8~%(i^V zrpWf4N%avK_hv`VvS~a_a{egrrg#jA219UOYz)cWj?4huBeykbhk@0@nGT^gll~q= zfh31_#N|5fia0wjy%Nsu%32A`b>eMh*MWs#>y z6w2RcM2>rAuqPHxG0QqFi6UG6mVa>NzD|;dZ%A0s8W}Br64}O##xVT)cgEuiOnsSo zj0FN+xdY!s0w$Coa(r`rfba?l4Dt2y<%IwN zS%m&S$yOIfbH{%Tqt$d&fa=KKf9Zn>9Y_o%N2dx+Udn_3Mg8nlo-Luh+MlwSV4T90EWx z2jNjPn8@~7`gRZPp_8;wUYN!v{NxE8S>`5$p_4)*BRt7>8)0A#oIgq;(HC+}Iork? zDL@TiHO(^>7gh#ob?UFWCa0H{a+MpFqYJ5}0E*K1ZmG$~md}OiYS;`%&r2d~_7&#z z`tEjHHS|o8mCLpa#iq&kq#_y{ECd>CTWre}Hdo^;p@+&WauT+zf^0z~xqsxg{DvJ_ zvzvP^_I;MGquUc@Wmbg}D3x z+*6!UO<89-j_G;Ntof4Jat$s7Q>?_8fTRJ3-VD1Mng8ZcIxhAG8U}z-n@-2AyNLd* zClCgMc1r8S@We2=U401o9ulS~u!OT(o%y}77ZJBvbROt=b0>ne5M%}Su*WoM>xkmGNkL%4`S(OuZ z_AW3l&7m4r#KBvmwHMy>qNH-QSf}#x_*Kim&ET=WVs%@(c?Y2ws~;9HF2;_K_c-!) zAbn&I^N!=kIgVbnXw}+H$hSCs!HaX;nn5|5S(N7ymaYI&aGOL~NwgZNf}9MLyeLlz zD&vo2x+C$G9%qtDIb0X-;bBMdhsV4aQ9x`V@Vc-KJ=pEG3+f>(f=`g@3sSnrekR}W z8y0DV0xM@I!eWXe#=OIkGFljOOexWkTP2EeS(Uv+3`UF=tSR3R>=1j=`W*#lQ86s< z5I?^)fcD2(6v=rh5`*Ti3NM(B&|=dI=Td);r9_@t;FEW-@8)v6ddXrrPT!m^pCL}b z5nXE#AOgb6dxJcE0%y4&`b9Q69x(MDgoe8DBBvwXMQ%{`v<0*tKfxLWhD-GYHs4_d z?g>qXKd4h9?SB*GoR-dbq+#x0=g$MEGK-Hg0;A2eogpnX%PGqL#K$C$5pR4KhBO2^ z{UZKlC_G^I4*gvOr~N@#vO)QELTJs8bM$J{>|}&gqk`&WJyJ>i1K+sX;rf_#h9p|v zgIo3k`5*DA6UG&gS+LiC1_uGjh5kR*hKuXJa}8<#)Sj^)Xagq*67rHx_KaVZ%vQE& z#Cyuh1~Doj1X78A?X4J6kBdxuruCu06tJE@vW4WE;4Y*Rm%qqT9%LOrpP zO7~KdB(~n*kzXY4U%cyTrmo$+^uNfirB}$AHNCcE({RuXPj9A^Gk4HQiEG=t#*vdV z?CGk#IkS>!*RdLLk?U@yN*u4(s1mEqRFQG2ffrTf()i6gY~oLUgsI13x2S{Jkzd2z z=j+|wxh~0}=Q8KGcrF|Cmo0YO{Ij)~6g;rK-~!-Xl@*>%UY;C4?MW_%7a(V$SnJp{ z)EKqEfoPJE(Ppw1xwj{zS}V`9HNW+oZVwxpj8Eu-*h{@y=}Hz|&XHep-pzMqLl58? zFJ9Z*LTu4+?Y2r1F=XL-8~r5IF^+oQK?~1$#ZS@#5we6+xxVMk*l??SsE+$<-RxQK}Mfe^Wq^i3(PuMGI{MpmzCKVMtU)J~1 zOo@5iAY4&F2su5j9Dy99S;)2tm*zCtEt8bb>18l<(yqH3-NhCPZQq z5D1F`E%@b6Ibd=6V;eY!Qh;;|xgP`SpYf_3$cSbDd#kqp0_Gd{>K*8S+#f(ya9HU3 z3p}?7skL07|19C8VbscF09 zD0!A$vX?N%+8~%$F?mBIg~26#(>j@1L2{@}lU?$Yr29?cCCl}bsly^whmdkTO6lAm zeq-J(iBCaSbYCTZiQt{Z=YZRhp-0=K`tP767BN@>K;6JC>+Cg~@Vr6S2?si|k9gc0 zn%OfxSKm8{d~cF5wimiLTj%MIKM2Z#bPqN;##5dESv+Z}Bl2Vb${pO8J|Wy!n(c%_ z@h8%MBTIW*KtvBD2nZ|u{|Q8Sy4bro{0mz0)N~Z^H2wiCbeWJ~q2v&Yx`9iX2Kt(XQX=8_2wC0P;4RWguQ8hF+yV5EoD>WLnwEH2MQcSiEwbCNqqr!k9 zM!ySzic_=M4Q#ZaVB-nalj+%M|A)M+=Ki0L3*12a&E`GgP4>SI0m9mYLla_*7{noZ zMxNf_UYV^!0^2(^0%PFW*O<+Vp$~K+Iy=V2B0s{sG(#OIA!MDWcs5x^MkqiR!OXF% zmRf40vP!BvmpkZoSwv=3J$shMiQh5AR(hzVR?YJETm_d)G^O43V&+D4r6|a3qEnsY z@Wkt-`7ZsWYC~w$Uxb7gp4x4{g)71)em#|ENGiv0yc!P$E#O z&+e^jbCnL=(1{Llu@o{}#o_ZA0sJaJYYs6MPa+pM3U!ESBAo|(vDyFeW`6d*@35x0x z85JplIUg!Q`j>;q$YM()&X$?8w1JnHj_A-pFBB$i)uoA`E&``#pBRUdBB6KHnzF9X~(ve7FhlfQCMPu&;P*xrTI?L1d1$70rxr zK3U0w9p&me&OQI^=KSL3JPOJWCA+SUA>7*}Fu7_l#ft661Jy(;+3jFn-hUDKQcxy?3BKXqS%E|q|O!yKC zOTzQ*IQ#5ZdFU^&+byjD)7vQG!P|zH75~V{;c0|Sgf^nbChdyNC%#qA4*ikyl)vMa zh}(c~GbA5Y)LV;{g8gpJMKa zJ-1bnA`fwAJK$y@O*RVeyb3Kr|zi~W~A*g zU*0nv=_kG+t!>T3Sh!#{GuRRfcapEI&B>!~|3l zM-k?ovL<_j^+lPbxnZJsPi`5uBAX?55uFnOG*~L8GXr2zq)qA>YRHK*EGYM0_K%_h7iHKLQf?X8; z5sy~{fkge06R12NlA7WKwff>bSj3A4iTJA9T_Ow`7=8O=rQdCuONyx|-y*qpWzNIu6(i~^pE4}T z`wGqVi!uUi1e*&liPmsHHw<`>^}&?|px_d-Vads6beg`$jOTO^4^oT?ddZ=gRWmae zet$7S)gpH_tKOH<{%EZ!a5mfr)5hU!|8v*-^$L+#ns5pQOLx^%*DmwU$q0v-0-fd%dI{Iova=#ol?Ir!q292+goeXZ+89U@`wK;mo>(s-}4j&glgo0?hllY z$^c?J)7sds`sh|V*ayiF0EmNc=m;IcLx1aVD{}qxkld}jYu^#!^m2du8}d3tg!hAN zl;C*#3&DSS7j%@MQSnBIP#g!}%rSOQ0h@Ptm$Tj{^X)4&B0+Q4;+E=#(B#(TpG5*} zehXk?x9B0|UattWkMOL#HbDkM^`@TjBVXF#C-jP7j7*;M2#ii2cx7H%;XB&D5%ie> zH`s4Cyst>CJ=WnnE-y&tuf+)UT87kUj9~)I^949PvjC3iTP)U|iGzL?&nd8gkanEU zEfBMtD^tuH&0T>#J@5gZTJgv)EzPBXtUW%~PYy<}fJ@L2MBgX#48>too-b@#o!&QEvqll zzj%0mos))6>j!k>K0bMU<<$lDH_!GWg63p~;kuJWno|zdq*n)3GF|#izmxnLys<-w+4jyyQ^)BmOx_t1&TmXcOWsT|5F7oQm)6b*Bk6^6S zKm({QpCdRr{CcZ!_$8Rwm(*10IT|F8Wn+5%9Xw%!X#@TWZ@h2;xNg{}eFwzkKFyXb zYHK$H*;c`|r0B5dhH5SXx5}XKHtqO_G}9ekD)@{TD=7e2Fm5I(z{A6S?{XK}g~iAP z7ysIB2{al&VC(?0JgKHnFlYiU9M{*CegY3ZOmfrPY%n4V=^5~%+%vpuv#-^^l|c}c zjr`QDg^kJjo;O>HS|Q?<<+TT2ubMD=kermmAP`p8ypTI zi!=;%o;4@tF9@Cqd>pW3ie*_xy9%1SZmOeR8r+V9(k?OnG`K{~x@^3O4=t{*d71-79r! z>TVwzUi>J*hDa}}KOyFjs;7#-(YnxY1$hpXshr`oVd5$)s4_>1^Ms&i07F2$zsRM8 zXw7LX0Zwq{g?gj5kS>lr!GFp9ZO9;>?9>#jVptxmlJz3SDK~gFeJyLw0!{&GVazW# zFan3kRF^nNr_Yk(DrWCF7&p~K~@r7!mfs5}o`SJqxpZffwo);e-IX|Jia|Lx7| z!En@bobm^FLo7VJ~)3l`+%_*T>=aTBrJ$?q4-nDvT8sVzMQGU+jph zc+c;DZO#Upp5ylQS-@dER-P-Zdo`f>Bg?!F+&Xyh?%C5+E2(jU+*pBJ{tMgXS=CC* zr0r_iMm1R9wtawz0n#4lN%;OnFAq$;=a&)NsmF)$RH{4MA*?rW>6J;VaaAMT`Y3Cy zBos=I-;eHGCFvgG)89Ga_&Te2zUJZ_em-iiTAG2piFK?cQJy>-Mv2iKGr94}d->v^ z3Qf6eTKnp$U8SCXUL|*!O7qAiLYO9xK}@7Y#?zuhZt>tyHNF?7`3D14c@3s5G5JRqvuo1<)%LJho9mv7LjZpQPLTbD=941;ACYE{33q=57)J zs%`nDgRkm(nBcFylWGzXka-!i=9H8QT^xD9n9x~IzTSw{_D)2Hy2$9LZ}zvVl+ z-;jj#TKn*Hc78?+VN#N^!mbn~QuCSEa`NtpX|YEoi#MdTHXSl$4|cH$&!M7Q@)z() z#gPd-*sd>kX&{A60f(Tc_>iTrt-l^CVt}E0&&gu= z?II`+1qr|~F2msNmf-I04#C|Acb7o|!3KACw-5*#TnBfDV8JcGLxKfcua(2@-ny!< zedzk?H!KhqYJFh&0datTb<>M-l}0RGw$_}-UzH-Dt$(Qpxs;nYl{4Whj}R;q2WW#PPk zbkI+wN1jVxrCD9dR4Hu8d_BTIlZ*sS3`%i6zx*Aj+Ix3uMT5IhT$U zM~iiYI;z=rq~SJScjv942Hun`!yakHZkP6aav^!LH?bi5r0o!}4R?xMttU-p?Ldz| zJ)Ucqc{W`7DFT8liKm2VM1de(4E;r=aPK%XkJazA9T|Y_K1M$lG+Mm!B*PHF0eWw^ zP~-lCGG?qH_pEW#Nlg$iTzrj}!vB+TG}{|NC7^FSl?&ce z+zM}vRiv?UUfoik0sG`7$NGy2BLl(=P5d>8$zBg8wwNeGLXah_TpgC#TyQaE>UKN) zLp^{m4DB2CkQ@gFmOV*#L9HS-zo&)Q0!Hc^D^uc5I)uWtIK(-TPGP(o-zpl;Vl;lBEk4YYrK}1z4}M`(zNrX% zyeK$A z5*dvCK1C)Aw@h)F0^q!dU9Vh=8M^6~r2btEdN%o9n3Atkf58AL6vD8N=i$f@Gw=ZV zN&f4*5g~3~(d{%{RwuGjwoct@--iMalxmKHG6yaC2^_CQv9Q43P~(j{QQj?c{P`)Rn~t@;cv}a70pM zqnY!UpSP$Z@@wvH$wYS$e(Muk``tPZ>51nv3}fQ<+VRU!IsAf8YNi2ts!W5l^jr zQwjo)Auy(3M+~NZ^N8q5>bBumI_Dg*@5y$_ zOtHL6hPpVVuko_yDnI;Ro_hDO(_#};@s!>C5T$TB6T(*bJ>2+ z-hAg#E%i!lDyF6mdW+(^#9ezXOpzC(P0TBk@&lZ1qg{`}c$L6Vo}ZIvl^BSjjvkX= zF@Yn1dgGVpJHzy!w|%!ix1D^@Mtnq`c^=p(3e6B?87Ts{8Q%28pqUG?MMSizXeq;i$Sbw% z;oki5v=jvu3?!==-i`&*cqk&;6Ve#c)_NqV05>HZy&D5r&y9dSU&EkcHg1EC&> z6ASes_uW)*Z_K4!}??0^_G=10nDdM;pG^+3`40}Q7g47#a3W?m@;6J&nAPQO! zSAni0Zv!K7FvFdxhs>q$rssFnRgaEyP?zthnF-L%I0HhLxU7bDcbHi)B8F{UyEYt- z`6=E(TEnuYFuez0C$!)BZXXPM^xRKQE#Ts1}df&-&nT98OgQC-lRtP7h# z)uUb+s=rze5=nS>ynG5qpn-ghj;fuLouTA3E{M_(WAooZaXRWzc}aH{x$mTzJyi%M z;YxsNYT6p$F^w;@to1?G$YW?l^&BcsHHmL7^UAoSZE7r)L^PO=e^C z0Z;b~mQ;2^rAu!(G;ps=#C!MG_ za+hw$VE-tfs#?O`Np@4a_thhDB5pNSlSF=9Vf$;s^M%0Yg1B5DG#hZ94Ty&z zW)=xd?V=d8x!9kVfg905&wNOi7-#*RS8#ziVGqi{ogejtKcLQFIQGGrOB%91<#23v ze67n|8p_`HF_#V+VV#4z8?0=@f5eJ{YgZFjqW8evV4y2j@L=v>?gRW4#s%&ld$qgL z8|1ss8`oYJ<%WB&AZgn$P}E$p&C$F5r;OkU<)u_BI(vZB>Eq_w3-xR zbnTalCuD(2YjHD*`46Fsk?e|k+pgugS2`yc&tYEtJ#6Fy{AH1sf6U`P)cpeV(07MW zD$rlj(r(ksb-a<#qw-{+hBYWE4C_*p3Wt9`#%COM3?Bk_kMe9W4-=c=84PDeY^KqZ zRh(FaR;#P<>cpH>;9EedRq=92hMcrw8F-y>Z&W&Evrj(h+jW@bIs5Cg@V*$caCb8? zeF(yf)k^#@k&zDbEj zkE&C$t88Lmq}>r(4v3BiQ$o-Rqi5^u@~eqr_a;}M*^@8prj^>jk)WWUR;3CjG3zh% z6U!S?f3EuImPZA`vMy%U2HxF zJl;>{|0>4-0s|$SNn0pK*0mNditcW}PqJMHKXTTZ&FCy^aa?mxZWer9o=@7dd+MY* z#&{`hz;#Icj&89?Mi@;AjjFPnmY(?CKP4U{31Ag)B}cJ9qXb5v##JQSm~##-V-)LM zi&c7`e%J=m3!IgHYIj;P?5AyN?2wV6^UF8^n3-808 zAL}4}y}D$#0dE3>53WdouQnn4JAVMTxFo&{XL7~9)%UGm79xFWU5mqdYO1gDoxC)& z0cU1*jcg;pPeFp~r{A1IQZIWDzx5-F1jh770>vyYIm6V50>=vk-a~D<0u!jbJEfTh zv~4-|?;e&?YPWpUqWSmND55~gLaxtLToIM-f28T}+Cb*a^ZI@sl&I?IlFxOlsI zWt!LO5E|K40SlL658OC(OrVSIzXrqEG<9EE-}G(BK9{= z5?;z?&4r1y-kOr)mdk@9eMdN;TwgrIad3q9aiI<+#)mDV!-|6yL2@T|`k$ zGJ6fa=BSwoB5_tzUPd~G7Q6VCaZXztWY!ZAYOU3AjdSI+!_N%G>96$Y+{&nO(?Cp_ zECHc@*&~!{tjf~${QDY?fn;xR0Nv8BM&)H^7gzE=x?lmK{#g;5(mq)`jUsp<{A0L6 zI8$}vOr?G;b!wgpP)8^+@C%TOGvA`doIq8bgVY&tXkHhGi{ETn5c;TJwEZrRW{(H4 z5^4>YHs3NEX~NGNJG0?TmEvL44tRGS2nPkGW zYMX{d%Z+n}74%CGIF8!4TF~jGGn~0sw+2YPt#J=n8X7L5^t@9jHSPqn#1GRhzgei?6sV<-EjG?K7Grqq7u?L+6BeJ{fJn{ z>w@8*Xp`;Nb<&!RKL_~F))d8%1AHtpL&Y{eZ$}*KnKK(lsf+l4h?rNfY~owMlj(@O z)Mk#duC_lz8<*$bAKc6^7WP)P)O93(zIlFZhUd8tXTQ$m$@@bkgD>3PmdydhHorK7 zT4i?iDfE4Ux6olpd5R={7?R;4moDq*yjwSRp;^-x!O`b0rTonK0()%F#t%xb)gDuL zT7ml-g(HN~OA1O{uGo zu&v_XRIWaQ)J9k8h9k#*clUUN=zfX*pafn$;2tg&OJ`Bzz@oahyC~o#_+X-EmNktT ztm8qQoG)4z;UzXFljYx#njGgmTeF3wm!HICy=-XKr`!#ZQFF&CRZssxj#1;aJV{z? zG9X;)oP$kYxw{e1aa2f6?fr2_NZh`WP5a>PiLoVc$04)HH2xQaLCE_eDHlwFmP?+~ z`f=wLw4}HmIUk=EH``!9DD0uLn@$XHaXoeq(B6C$cJfbeDoDT(5+!HFP%ZE>v%qK7 z^PL?#)q~GZu6r0gMO(T1{qk?Fb^a0iKU_;S>MyQEyZ!EOuC*D5`TK9KmHHRg!t=Pl zLJWyf-#Hm6wgjfpE#}OQ;Act}EZP4N_n6=?sX+hk%0S5MT{2zp##)-2Yk)w|_t9db zzAQqBiW0S|3_v}RB<4Y&*dq^`Zb_sT+cYwuRWTm{13DziNOb3?LfjM;WwKq`7`QT) z*o`E^&Y|reJYei}Q*qR!?f=Z?TNS$3-`YXLmW*g=(hO;zCaxq1w3)wtZfGB}eRSCe zAkmnBdPwo(4KfuKZQX>O&3*Nk zYrKoryIO=D30qx)Mcpm6?CljU82%V>^fB7`1j^0EUt{Uk8fockiyYvmvKF3sgI3cM zehZwpY!lJFzqYz=Gup!dzZfpYGMt)ew#jMlGFtw{wa)jCbc+9c0xW6@<(l$3s=m#- zcnMlEH0W}aFYngZc5a@?Vb9U$6}<4$Hn36GS7n6@&FHR(-nmkAsm}-q_WK5y9=p{# z*nM$Z5+u#t%O+pZHLA^h50{PdFfNyoU_RdVz;i<>Iwi2>%roW9HJQGtG02}lyeG(O z4(Lu0{q>D!PJYGr{P6>!f2eNHf>!PbA)mwfb|pb^?r%6a9*p^p!8T;g>TVRNMNF-) z5P|VURki{XjxoCLaq=*+=$Ii483{%daMBH%zpxZA?Y^#|^pkCmyou~;Dx| z5=gLv-WxW3*y|CU{)oboBzI1*%ZAkFq)d*$NH=2BIL6n+dVoSCKdz;)byi8`dk5k; zM`BhR2Tq11X*e}qj%FxH$AcPV$}sIR8hp?ssKFTa+9(SOoizGL@9W9NLGQnO0_daH z^vUw^e}d=h_p2w)s}Ez~3w4iDSWw~m1-e#) zxuJE3?z;G)0T5J_pjw8Oh)K-%qKJgR7Asl6>r$iwMQnIfsr zIm&ERgMBGg5%+Se-8;C_egzvS>&EA2qV--B)9W@OVGn zfP^0H_;@6Vo0Db?iwQOs9V@$TQvAq&U7yZ(WnvyqPJT&2bsTf>NvCq9g61>WQ*dDK zx!Q@f;jzU&!hEfiNkQ>U;ThZdQ0y!O&D4N~6C)n49@B3-=JQL`46|I)bZ=HEu5^8^cC=>F z>n}oCXe&^Qw&eLcx~h_uTr`(bne#~2`ba=ue)H5HG=&&gLz`}_XO&ChMcDy6SY+Xm zJ3$YK&jst!`({b}=u3)n{~eg1}B0YOIpf?ZD6C4a##2bIpXaZPa2 z%wMr9+p?!wk%WhBS0hN=>d)BK-e)5QSg7LPwD~)BMQU|rh@iWLKELuz=h(hx#4~qCU_sfy zE3EaleDk9?U1FdV#bX-afUzoaW{g&PHX81^xz*Pq#^%wAs?>M5X1mp@O$p+f$S0l$aM&vbhR4om3a(vh&&HQuVb{Js{+1q7jnup< zwu;Egm;F8Y5$`bFNRGA1C_!q>u7w~JpAZT(hE;YeugE|c5R$Caq@-u#EmD31MJ~8z}KWvjj|NCQ2HlvMxEe3d6-t;IpVfuf14iIMNK9b&XEN3|fqw zmLu*{u)Zr6h4zS@5)KYON9$SCUft?5iwcQkJ^;16_5@h*(K$L8KAu;89pP6SiGS$v zcy#)<_-)p(myiqRW%g5b!jl~NR@Kgq+(oVzSPR%I%D!-UC?+sbHwd5H5^j-17~$D0 zkhUObm}`5Rpx@y2D@M>ycOnXZLhft*Dn3bJ=M|s^Gz(55+CsMp6;+nkDxmwAg@YVl z9A5rGsOAYNZVFX7*Gu>QR~t5DE!jEbl! z1NUnv$dn}V8X;YIq&NWPkWO$vaW_dkC2Xe@AzgZ;pC9JEA_kv59$GF>%*YPHrVx4J z_9u`UjYUhxF(MLB?;Xu@RjjEMjE|dH#cPg0!IKI6tc{vDEb)jrVs#T20RP~`(Aiwt z*=MMrfZeaULwi_6gui++>ig$ar(q6AdM46PK<*sgeF*enHeHiaO!orHk_l=uBy0DkgAIcKbZ%Uan*0R3S{Y zS+}av1!}IfRB$5yqQK&`jD1elSHjMaYV9NBiS_}xsLy5kbM(OJW|Hh27w#Xt4cp~6 z9280kMTeg=*&dTi6p%!1h(Zo^T3sA9Ew4W?=8 z70LzT85=kTG&)$a?1qevO+vg|FXkdcvkMD>h|&75hylTL?Qv}IhhO~ZoE83#UGXHl zr9mE5CeZ`G8JrX-em|gyeud5LPhjOhqa?nZ<(IGSUZe^9$i1#kDjg2I&6;Zmpp-4)Ml zt&Ay{d)3vQKRcnC4L5Jdbs zIt#fc6}qh7!HFZe+rfrnUR6Tmud;T~MO?t7l*xcg&ar4UrK3Hqd7D7p)4`)Mu|UZV zoM7h71a{@8E6jP(htFQ(J#?aR!I=ept>u}Q#{I90%b_@}V^Dl9msv>9!(bYrtC{56~$ za6DCNEkf)&_3b(|(z5TO-&Y_HwpZ*~M4Y%c%>Qbv;(1Zj&fdaWs<^4q_lDWa;aNyG*xy8sgwh~SEXwx9ugDZL+v~z%#10rY!O8yzU zdbhqVy_(2&|1s*8diRG-$5;@c@Zj)JHCJfKs(F^bL|o>+joYJ0{)&}rLrCVnkGqa{ zaCv?s{A-Tio!*d0u5p^tw!8#bl zFgznCGWeBw1vUPb$1`}yhNevo(#HPM7FM7RgGHA82%z&M#t;2KM>d0NnmnMelk{&noLkb2<_aOkXr5Pb;6t@ z^(_r5>n~2KU)-qRsA8$gqOq)^Q1+voIb@w8n}#s5-m^ituDk`P>LLP$(A^X^5H#GG z$p~Aad%J94!?UoXp&+m#*{2`T0WJ4C2=!(8aGk)`U_fWwni*tz$>xE=SXDHrUv)mN z>>f)DK+q{7H%PQ?qD;O(AeU@K9}{aWei4dy@Ue}!G{8XOpy_w+C@?EhQ7 z{tx(4`73VpkOU)MGh7DbGSTcOO)nbjp3E|VJ9*Tj-cUb!T zaMq;b`0?XETQ16}^{44S=wuXs7}m9#68IK+-U&YS&WIgN?q<(W1|h&4f@a}N+i2m} zK$u~|#2Z6x-Ndt)zBg`^VJ|=oj)xw^AQBZ)*=2)W402q}EuW zW?;^jXMV|p`4)liKMd?`?&}?B;(CtxYs7&)LBzezgj*R_Ox1PRe}c0>?)Nb3%XGJTNEzFu&wS>p~5-z080e z|Iwai@EnP_1$pCv=~}W0e<+NQ?Y4xxaX~w~_C=BCiR}2E!@OTz(elFYS?lq|ws*9E zVpf;fVTr_n1KV16gN(#tsXLws)$6#r*mUhuphW(n4CkwsfQdlRn=Y^MvOw>ei9s*T z>IvrOSZt4gFfm@T;~QjQlVWq*Zd+0~K5jJLQ%NjV)o|k4rQ(8~`ranyH6hpOyog#y zo^Q43Arg+FmbA6E4l?MjIv;CM{OVW>Y6}`a(XSdTW1-_(;#gK29(gS_FKhGFNsNBR zK%~`Bcv!5s{Uh51{+QbASWV#-)x6=nX04gDLhKz?aTfo$3q z+GYX8hpIS+Qgf6-YW;u#>aQfx0%2mkE4b(pir+14$NY)W%UoTPc8O1}5tb2_eq$ky zsvApDr*z|`?`I+4$%+^)k*F&O|%ar93xA`U(CPx{$T$WuqBKhp1eiMz@WF zXv^V37iQ39#dkkWG$|RqGNt22f!RCUc*NWWGl6eB>KRM)5hDx$=f-PXx^1!Sgj!J3 z=k3-Vs_aheygu$7Ut{>w7`?VGehEE(%DcsdIFngFS|_a#DqYlv?nW!M;})p%Rb1jW zoDAX5n|R(dLEIK`L_PD`P-b_0ss0nIyfPJU)bn0Jl@lvB3Y{WBPlo=Z$+@JOE zw27K*=^7n1SNjgfKV2{pX#gFwwdUj#hEQ|Xj_3oY-G=$is_jR8wF)S2nh1c83bfq7 z{WDc{Rov;9qYd$^IKpyFt2N^-Oa% z(Fm^#3m)JUf`+XmSBFMhMl#TxyqwTnU&VLkT6=cxl&`lXWUDc>;mLH!W@lowpiu62 zVXPE9C72uwXN`W;sp*Xly3S@M88EPAutKrqxqDU5_KZ(xx2v{LpDGF=Xo=HCx#lr; zU8I}^I%05&|Gdms8kwr95!35#4F0UkJtPzCtJe3&t^6Kh%KQkvgBhu=@M2YKjobp$ zO67;g&(a}V7v`2`m^-tAWIwilNP>qb<38^c(PNoaJS;}>pSkMcLbb0<^?22476<8Q zQ+ys5=c?3h$4LQ5W1=~om5DM<-)h*UBIS#OT9QVmDVC&!^6Y4&x*r-8hWU^+@%w(=OWNt zTRgI-;~nX`_RB#}G@sPVOUNiMPvraSK9gacOQj`m5t4AJNp$iOW%W;VgwMYna112S zx(plN5$LZym6V~SCS{c!GfAbCxO3*@g>oqD^o$Rf{O4(nX*cN*t{6)SNNAi>YDqk^A2@aF$^ktWRLS|)26%qq$aSE;h@7xy{ zikSPNS|g1AAzul<1&aa3C*#S(3%k$Bmub~rq(z}Zp$D|aKm|!PwZw4)-Wo7ZYvLfb zeE6XqgP-R(JH=eiq+M0V1a93v_%gjNT-j<)q4f*TN_OdDsG5r51yQz z&qGM)f_Td@am7KP39WEsy_K;=PCI6y4cQ;OIfqQdI~^A+J5R%lb9uxZ$rQt;{<=BGr8S** z*A){YlFUDjs>w$(c^%HNiv9{;p*$FK9s6y_T-Dtu1B;33Uo-v!Ukv#gJX?Q-FXg|$ zSNdP!tNL&7g}KJi54Y|6=CrG+k`kt_kob1Rf$5LRJeN~Ta_@|K5oR93;=qsVJBMjw zbO@v1F36Yq;aj#dv3#F^c7fEjjR;}{H%6E}p}wD{jXA}qJk8t)`EM#D4nXDiG#@3J z;#zW%0sWo|r50H#Yw3MB41YpLcnjtrB`|G3d zYp!h}EdBEEggU2Hb%MChis9Vooo_lvD_>;X`Hj(@>~Asc4ow9Rkas|BltHlKA-3C+ zVC;mx8aKSHaLY@~hirmIGLCr0C!nt8=Ymi}vQ)r=t|r2EuA3i?O3U9XFQ0|KR9+g_ zti-b(V{+Zas+Kc^g7X-0@)db6cD~K&q*~NW{O+0RTmhqW>sdQ+d`C#_Dx;rj4s<;VY9(PQ+-->uDxQ!qDL}x+G=%>zT`I zzZAd|a#{%G+~Hf6$Th0pz7|tjWf6rKeIihb9)L2twG~2~bAbCPZY#Me^he4L6LF8| z#)B1pS5Bj_i$AxH|xh;hr z1`Cy0VgwBt@Z_`IdRkZ- zep<|RVq$+@1ue%)0d|<5pBXJy*dwRDItZlV?sv$^;M!r$iI|4WQkuXb@BF4xR%Q=c#h3*Xz;7fYR^Dkv$h$j0c$R1DXcz1H{%-mZ4c=|<*g ziG9`*qPW<8K|?a8W3pOO+go&l2Jk~n_THBaYUT`}8K{AoN6Z(BuM7QjMa9`gI*AZK zfLST>!9NEFIc}%yukiIdeoFB_;p^!y@TFpCSlYCb|3Oqa&vkdjqp<9AdAy)!8Xy0SZKX7Mv59~jB3!Gs;25zo5)iV zKP&5OK$|qjf!VbQGlylIU%Ggx#F}kSvRAaN&_M;a<&#aSmIdiHY)FF_`@eOBX1s1= zUFo_x)s8|Qf49X`9{#%WFC;}8yuQ*sfXS-k$Ri_1#fbV+28S+WP4n^)B(ylZQ_P34 zll*S2%Cf$j5|h5RdTFS=l=A)^Yt52@;sf)U(pF5FVH@vQweCo|uJgC-i%(9S7Ti~m zxo-*7?cViV?ezxo&83veJw+-R>nD?}eB_^KIt9P-Au;<(Qv5aY8Vbvtg3A0Q@={6( zO#e&d)gXF=z$nenZ7ZAbC&JDurV{mv!Z-{Z+}+*%;I4zaySuy0;4T+;cX#Iw9NZm> zAKZO#Y5UNoZPGUX>;JOz?UkMEtn4L33wL~2hhoshwpx#MF!BqVwqHPQcjfOUuRwxZ zRhQ$stMQuH7Fn2LGG5Y^&2AY|M5~}61}rMGQ{0OW+XIenK<52fRxA0b^|a{B1s<1O zRH9dk#HBo7W!NO}Y;IKM#20xD;N|c$y7QaWzEx&y9UJL}3AtYphNeMSkU=c&UK!p{ z4O`e-6a4i+?2Q~?pOrl%7-SRx-vO5E#S5ScDk z`D63p{6p_@M|0^d0l;hfq!JKPshJhXB`J?PTh}7g=>vIE0n+?{;4K0^<~_rp{A3mnF)H~8aHE_BGS*~Ls%rg z1^}q~S~*#jV&7oykhB+VH1tL+4RTCh!i=h4t(U#Q?L*Em$PaP*1#U)1PfJc?yHA@D z5+?~?aVf?Gq48Q9sy5X**r7+rEkQHS&kc}BLq^ZS>RY3KT5pRMZ~%cm@NN24fr;zP zOF@}7%BpXUb|T+f3uyH|r)^^&kt};PF&vQs1x|ZJ-=v^TFaw3kJWA~OhHjvcofdYj zklXDVFVXCo&aqa6gxW|^B+)F;LzvJbh|t5Kny_hN99`PiP!@-WRap8_;D_2=8ag3S zqI1Y-oWl3_ynGBcVU=S8Z+h2IS)-wE1Y8>)g^8fk|K?%N06!|5R;a#B&UdW?c0wns zMp@Txvy&f42H^)%J~dZ{Y+R!}Hp^_g31|1dvZU7DTrre%oWA}e(8C%vZetl10>S|B zKTq!Xx>%}N{^R6Mx~{Xn6xQhMZ<0~lbRI=QTF366`z#5>9g5m#%v`&`s=$l5lUH<*z{X*#kvO-$7YM-$RUO zet?x5121z@5>_R%X3YwrS{pkveQYx(2ocJ+NY)NxMV?zfT0BPX9nR_xg7!0@)#=EP zjYgqXA2y?s#UjoyK6}NFQ>=In2Tm;Y?)Ou7(sXR``h|~bb$(h}=V^ML8p%gzP@YSc*y*X3qmVLp zIk8pigRpHJ-p#6U$jFyWN|kDI$+6$0=#R46jHV{D?Yrnyw7rb@8KtnQ_;KmEmgGI1 z5=B1`mUMUw6=;Xz5{pCzQ1IqAK`yNYLjZCO4M2_-5BHb1iJfxSvam-YiY}MzDu)o$%93;+|EDY z(xXz-2^MNKGB~UC)SGgtHPZ>)z;S~w)Z$<6StD>Q-y=p|J##DRCUi6fI4Is5J%ozH zu5x2&m)H5ck{;(Ens9&G;MNsGw1NE%M*2nU;Jw#67e@?M>&vym=wO=QXO;xiADBe61M~@tyMWP>-5x$+1d^7^ zRiXBe?$vf<-Ho95jYmf7`+~;XQs!;)g!|o)I^zQ$M8WA>(;M`hFV&o{xaqIV=`Z1g zYk1N>!=tyDE}niG0@DL=sIN#KQ=85sh1M^sO`ZAjBpuHfc6}ds@9#@SK42$pTUnAZ znTtQb%5n&A^~sbMz0yirorC?XCN7a8`+k4-@AY4R)+{*oQoqHJ{lA z9%*_fgpwaP_MgPfZzMb8$hl9XEcu-O$O zmc2Lb-qk=<$?QAg9U>wi*2d<`jDXi_`%;EaO<{MsX1*I?aV>N5c)aR@ftMgHcAnrjYrXIR6R%QMJX8` zLVoc;Twva)>9e4tn5M9e;7+V|FjAK*<@^_d4Ujucr6NH0^6Pcv_cLQ zL`=svDE;KwX&RpMu4IR01k8JG2#t|C14i_xMf_ zS2PUe z*vmW**64luMEW_v6XoRzCXgAAw-4KJ6>7|H2sPN_ju7kp@#2-`HO+nd?yf$ z$;5d?t#3K$^g2}(POJVR&R$0?BA%+TGPh_fwv5fpzWj=(U5a6MdYVKsznAPN6nM>2 z%!u#1$Z>koL+Vl$(b1*=hq_aeQ(UD-)BIt2t~B@Av|FH9mK`J>_oeXrJ*4Da`{bQ> z>UPI9;p^x9yRySgBwO~c97VVq{1K)XYP8qy{mm(eM;J9gDV5B1LB#;!VA=8UA82HQ z!crIPsEZg*3{P2X^R6V{omYEijz~-w73(Q;VG~w2VB9TIo>W7Q< zv+pOMDZcyZr@Zrq9g!d?o87cc8gI!?yp(XG(*ukWqdS2BaSnBgTl5w6N` z=9)v_#b++Lh(C*C0U1!@pR$qs!Za4`)k5Mc(E(CAHs>mN@eOYioz0|dYJvnX!C6|o z1UWzXm%kbPt*FgPLfh1xc+1*)O}sx9V;IdzkYF_?bVjA|eX$Uh>9E(dgMv-oq?J>f zwhTwlB|FxYUyr4gJWd!T)^Z2)Mrv{in6vkbY%ZeLBST+5#XjDanJnif1Yfq&hJJbeWQ@(ryID0vfi@M^mbQQB;IGjJNRfBwHZ^by^q;dXI(@fo7 zcIjMrd7b(4N4+UM^{rAbT=O-?U}#PX8J$0l{_6B{tb2Vq|>@6R>T)%C??``nVdddWrhZJsTy+SDwQ2pdkBd0eA%(Fn7e0{H*HZpQwlloC zBc2><<`pMacl!MGt-4* z@A^@%;n{Vz^kGLcZt7^Kd&xY(*}9r_mOZS&?h2d5|a zH7Wi=&vhiK@HWWd^VTo%Ws<(*~@ z%E#lU*9PYpaO+37Sp<>vvsOk<^myw*EiadR3ij4ELcBpvfBQVJ&ySDj(vqCRLb5qM z<&P(n5t%#MO2*r_`CyCZCIYdhw?WRf&t&Q(ZW02*Q_%g>)07IFVVsiPSvg`(SH~kd z=BT`howuq1an=`}Aji(cq7MKvr^kct7^h0lg{)>pqXMd;9-60XTFWT)k zk)B)ZcO>^u#*zlN`|OB@9YwZn<*^3G*Glh^gkRBrtFWDrWGI*qJlpH} zWd-jm1M=n$Koz_E9SMyGJTSTPPuA{rQX&L8i1AQ_@%cT(U^XCs>i83dPw_BgX!8C3 zNk%|S5*D))jh*ri9rj%`|J*7*0({5AgXePiYj>0(;Uq!SEBcV0S)HW+8@d`)GD>i8 zA)m{qXki1T3Jyw&3i!vLEfM*mYrlr|va=_Knq?&_8~Ef+8g8W>Z5%4qq)#GOYMAUT zx1)Az8=M=Q9c-#h4ahocw3nCTRk2`j$<1M~#q1p&o$DCv%``C9m$+j15$dXJ8*B|M z3kjy{t8{e)fv zgR=q1N@p$_p`YzwT%DdJw6hAn9H?&)#uGcSBEfCsWD?jqBT7Pn6@Sinaj0x{eJXyw zhy@$325_MNCC_Wqu)n&!zPYctwrnE$nsO|?yctnKiHtAf;o-NWvP>mo=9I63)3j9E%`iisqA21)5Twt?VW_@ zaRP)aq-D~plJBBvda{~ z=nv~XVYL&UNbcHd)&@Iq*<;gm<`c;o-cznCUMlAJ{SRqbLf)7vt|Mufyph(W6>aX0 z)a3@M(-CB%K&cY%1=aRMr=pfj_u5-#M=o<-{6*oCgo*5lYT5NTd_Ec&IdhCi`#l)h2Ut)5m;wpsiEOQW_jLPZeu2y;AYm0@?&8c|^LO#eX% zVmU?7BcIqJB0%tlsrFwh#rHVUeghG2eY)tv7o4d0kg%46Hh{$-Qy;a+id|dceDIO3 zQ$PI9DwxlSB(#seT6BLKr%>H%tpRBuelUI_KI{XF%>#^<&5}DP1u2Q^lwA1D5I34a z4tIR8Bo-^VJlez1;+LwS1;-+)R60xZHw?aBB^F-wu5l2mrz@1i%VusA>8V+ErV{6F z6pPhOT*~t>7rQ!ci_a}oDOI+JZ*NKImW+U`s|Ie1R1wY5iCI0}!myx`O+Qc<7imab zF}FC@tVtGA*f5ttX>r&Lr%y8V%yz*CvmI`3Gs^S&&X-R26GIW^I|csKlan>?5b>? zEA5>c1Zs-A%7QFC`)IVz_7ud7PVleU_|x|=vbk5&j)Z- z_X+N?JwVZM-6lNynhsMD=ZA0*3(|m#I)k zq&sEWdL@2EKczvaenA`vc0Xg3pBcFmDtc*)Zy$!O&~9oEA)H9czoqB95*=+`NNr2e ztgXUqfzlitH7s-sjC6g-b8XhKDh7SRLb!Qj$^kCCrN|NBcJOG4^ywR;D8- zScWZ(Z#nLX@;^LKh$rcmERNf?$8I}B&tRiE9^eZF=D~1}lJ%wIAZo*WBqOZq-0zjf z>RR_Ian_!eWp~1xUg2hm?>$P!y;+-QI#(Rf3nfpyc9)BKkST1mE|5Mxxz(*&r8?H< zk5$VSCd>d{NWS5hy#|))e!|<-mFBMz|6qasIjzwOA3s?WemdWYC{zTxfjlqEnKi$_ z$iqM}oZGyvg!1fE!^P}Y@Y8JY+)jJWs@9n zz!R2SI!V$BaDP@$AXR+T-Kr4$7D&01dQSg_Zx9bINS^Vs`6_lOfC zNn+GF>c72o{5gvg`b2H{K%p^Dd;(-0Y#Pv2Ro8TtzGsjh_)AKi%De`ck%l^#Sg7v+_dvpSz#X_YjC9h?e2uRYw!&ouarlP3uBf;gK3N$w356sh`E zU(&^6{AHR@2V-&icY@#75&IHmmJ6d7OdaM?48S2uXVtv>Ny$s(NPn)AFb#c~o}=mT zWb+AraGoSV{j^~*X$3%G|$^I#On5jepm;5c;-UhO5tS{Gkzi*0@uj zwT;9X8Zz=0;=l%QB?fM+YkNl}G#?PdytF zV@RZnN9R+Tg2M)(-sGlOkF7S`vx1!8! z{lq7PQ>gGG-fC_W$PX(awvo0!T1H=^?50q|&7&A)*?At#D1)i-aKU&jleM`)|%+KR|g_D4(t6N<4l{g&;6Fsf01OZ89+ zdOnsOc0^Vq1+%GbEaM`=GrTANV()CtDu9juNUW<0gVU+(Uc)w}Mvl+^Em?JWWI~zJ z@W_dCu|F|dIU3(vEeSj$AaLgr$md7DGes3dgz$Y3g!8YO4hw7~MT>apfN=S76Uy^0 z5Ei@|K}zxNO85!W773QK6MAPKKPhN>wXXa0zX>b}o;l$J!?(YPP`%6Wy!#FYJAi`4 zpOqb-XA!=-kb{5T7_Z&ne)}pz{=x?T*$)1b{Jn$coq90X8e~lK{>1Z+8um3G@fCd| zvT>u0@D+>v#RzU#zga~H-ir7W@-G1!)Ig+9rNFpP)WI(~uQ;$XzQ6;|d+cs7W-B&P zp=z)nICrzkXqgce0*B#E468b^=PA_8tNJf;XG?k$4B_RiI-{VVT1DeKLYyB<{C4sr+{SIMLK2kA5{# zplATq_~sd{Lb{OtX%Wqo#cL`;h2{7Aqp&44+=w7crxO)pn2ZXyx>rm7j%=QU+W~Z! zk+KBA%octyOZB2m_G10VyA)M0`?xWpwHSWuU`8SGnJIDZH$oF+4{-s9(srbolCMt* zMg>?RayGfpFS{ENqPO{7Xg^2o4+)@I)hDV70#s*$g@PKq+*x4K#pw>L5seQA92h3l z?USq&bC(EiHd{vorVgh3B6KN`joR{6pvScPg~2gi?g>TW6@@MVJ<_B-?}~=Xyk}r6 z%N^C`46RarhRvcLza_q_ zn%c24U#JHOSaS?->=M3`0LNu+kQATi880E5N5y_XZU%af{tqg90Y~+7;W4e%>qv(~ za*D&bl)j*EZC!A!OB!Z&(7$~ZijKpseha7hH9=pMvwXp`u^v8rC-qL3U19moutX1X zF(ZGP=rzscNf>{)Y)qm(idx=0WT+X1i{or=Nz%%;nxeRi%Nv2PP97L6Mh3}A=9 zs8*z5;sr#SzB68QY(5J9fFnI8&7n!3L$OTn>R9^I`VW<%Q0ZbgkR*Sa}&bKm@d`$81l(+H@2f5szoSJ zB~o8?cYfsEV@)2&1u@6&=s2E%2ghJcRoZK(cj6&SGRGM27m94`Qv~@K2ibkwMgOo* zvbi_rVbNOCfGyS?gqKQYAEBBFZFu??7RgnpE*s1}7*Yprr`Y@fAv~oI%jZ#D6hDHD zdQvf!j92}nKWt$uE%m*=WXK!7teafk2URuXjfc85G<7UUY5aUPHEFvT#se!T5%C=z z6Fi%V(qMwq8`E_|kPp$2Lgc(FcSAE1{^vgZjj{p2c^}aScQ)+F75N>0wg`9_iF#}A zf_429eKVFpI6)}@?j?~1<3?)f*79N3m<@YJoV7pk^jTzTq$D$x5~yhdR8$ziry#bD z5zM7#XwvZj+fsylAJQ^lXa{q+5^F{2H>q6=5!|w^L$<1x$|%Fp)9ZSIx46Ot@1-4g~ea?^7TiILf_Rg)l}v81QaLXjoQ z(4a*QeVU*J%QKkN1Tp~lu53Al&n|RXv6Ut5 zRyC3kX%YFr^vAgP!pDgZpARI4*v5C}a z7-2IU`UcM_-1^4s`J0hlxEu8)UEU;mCou*AApg2&GKKm?L~@h|AbG-|=j`m>D7 zN{l=$@k%8nc%Z*%@nKOdDS`B2`xrtUY79~)5Hm8D!YG^vDGHo)CNGzn&-r3|>!oV? zUcJWh&zIvUFUiQP+Q_S+0NKrUQwqZA$PJLFM({5_&{G41hBc<*zuXIawWpBrj2#YT-}~2L54%kP zxp2xJ#cX-`OphdA|G1*2>E^QTC{mQ43DV&&SLFE%!3_lP7R~maifPc=gijcW`#G1q z2{ZM*yl(tJ|iN$Gj`r+$`13AVSY)+?fk^N6@fE1bHP&M_MjbhRTACW z>rLjeoN3tuYGWLG92pGf{+3YL(({1m*AV&nHahfyx%Ww5iWsIqPNq%uOOAps!Qae| z=!r_9y;DS-tG;D6df!N5^IYb4eW6;rBs0O*vb|H?!jn4T;=DObQLTfo0ik^G=5_nP|+vWZ5ifSy!BJy+QF$6;e(gLmM>qCn0af-0&g7uGwzev6s;8iHU`UG;YEiN3(NSf0o4xP57 zKm5f+YtYsMUGMmoB&>xnCIXzxEv3w{HDw-K*}TusJ#b&;dnkJo&^*~0M&*-$GMFkc zw>_by8w~N@T0A<0`U`Hvv6~qtPZZH>4{_mAe&Nz?3}bb`!&L|?im*^+6E1d`cuss+ ztD=)|rs5p$ydsqAVR9lfuXdC^GoDZDDrj18xN}BhcKBW35pO-H-wPOPEi{&)*?(x6 z7#DZ3JMrVS=b1uUX!48W_qE;!yw(@_w5xh>*o}7O*Vvgz`)di&N!8cTnMj*o|5LBS zX2Ntn=!@}zPOCw$uhlPd**Q8C7f~xuGD`iy3Nozl>>mp`SFsJlhAS zWq2}^^;33uhY_gV8-p}VsPX6#ldRFwz} zk5bPBBCi3XeU#i!ym*uNn z6*aaDkp*X+xwn=vH?h+0yF`@mBq2!pm%cX?`XpR;JHwA$Z1JHPZj{j;oY5XgaxMZE z4Bm6MgkhLzTPjt8XxakP#%Q#=*S8-!` zaaIy+zt3YWoQ&bH&zP-d&S)XJ*_1{Ra?@b>!G6)f&ycVW>Thq17>^xP7uWkRhOKl; zDx~>#hz!+raef)h)kZ;^_@4VV(vC!vm7Pmdl|E<37E5}ZB@}x2zjv&pxjC4vmk=3C zv~=*>_JEvcgj&)cb5oUAyYX=`>QixcyX|pyn`WzSHyoS{GwhrUENtx)vg{jik1?Sx zWsnA*X#I8&+N5C(_`kT}!Ftf0S7Zjx5WGZTgvh()p)M_u8u*vY(*EaRVZERCn0GXp z^4a~;^p~FUw$9?scc`-3+aUpmjzGB=+$ptf*n&IZ@_AwF8jO2Q+8HfOm!j;jvNNn& zjm0LT>A__?lJ*)}Gts=C$5kyi0c~ikDzP^dZFsEO%EL9wYQ4IKA>NhWU3>IQ0~eGy zQ-0e@H+yA^q#Rr*eA;WA<6+GSH+oj-^w#}G+uYXkfw%%fcwhZoa|RH-8`Z_;7{`2{ zdih4&YV6BpbAaaHECeBN1OORUd8=~*o&ca3xL5-l$^x;m=3)@MX@)YkFns{Z@aT>_ zcER`CE^OnFy+v%};=S)`0pl^VCC_S&RM_9k>H4{tZq4Mn_a<+we3rKou%))+_MDsC zrwhyD@|jyP-xP956*&EyHqQRa*Euy;!XRNdGx5Z>bCQj5Vq=1dZQC}#*eAAa+qN^Y zbz)~??QYfX#ctK^-TMQ&FS_e_x}`_9V?gOF@gwGO72c@+=_Xw~@n-&?U-wT^vBs$y zyN=IAoP(uE5$SrTn}EA)7QQXICEbC-5r;7K31QL-4mjdk7sSBKWrxdw)|YNhQEmC< zV7Z2pj-J)uZ3qeU%xrK-P*UFsWN3qYgBZw2KgW^J%8 zl63`_0!x2Wf!S=8v|(Gn525I#Wk}5r>JUnZ}65J~X)5=**J(96F{$ z?h!Qvh+p$%m{LD0%k=4MAK-v!l=$G}y|PN^>jbGLMVI@IScv0=+qMokQrVt;lAkFr z0w?+4Sp+hTetT1^n#M@9%GSofH*ez4b8vW^lVWO>Sm8Hnd7v)vMbrZ%b;8c1?@Mge z7oG=u6MlwCoc}SstG(p$)zoX{wCp?`5M zh`N&XnDBoUgcbBk7KDw2TaZ!VZW5*4oI(Fe##bbvwaylE z-Ck<1hFZ)~+g=YLgEujkM}a&H&mHPdCr={yUQ#rHsWQ_U6D)kzXNjUN*g8En(p5J0 zk7XKbw??J}My8D#+@Tt6_9|6bRfO1d)RWdY)@4K1kzn?rg4SH>lzifdWND-77Hy{a zOd8nweeVrYMQ=kmX{xRun(d#n16z5cp(eOO4seNGjN?1aw!nnYT~Xc~J}CQj$63@a zwl%$Mi!0SirVZ!2?je?q#^=v^{x?X?kP?>$V7)J?-IsExLFP&~1|uH3)){Ir^??%h z=&-F*x_I`^P|G%o?-Kb~isEx@z&*qLr1erfP99Eaq|{iA-V1@Y!uS=~(Et z#HN&&!8Jw`uMq36XBeNvI};R>vSTIHZ3F>!sHi1Bje=0abo>A(SBQ#5S%pHoP~alN zT%KJBa0ww_tQ&5*3`aE63qGq_59WNSRw%3kiK9YYIQCT)u7cMf(TfviNjO@;p;M?E zg-NY9Vq+2ZmiB?HOV1b4UiC>)td7LJBJAd`S2kj$T&(u9*dh3{`+drX(E{0zb}nsS zVVAOARDDH%K#hVwLye+8MNjdkoR7Az=7q98R@maoaN-%kKKFzDzUu?Y{`HyQaPN|P zGUbDyRK=@4K=&gzq0+BFMqMIF6FtduA%9Ui)v3gVuF@p1L9OI(oKm$;l``sANq7@- z>7|===5#3I+!K1->Mu3)N;xU_$s`krs=7G^X5&We>NyoNDW&DkV5J8W&kim6)N)g& z_I1+9MIgK$#pF_RgA%`lTKPB4>d?ad4_EQu9G^!axW0VZ{R$>zg;Kpq&`iOOpv`;7xYk)B>Tt3j;kN)y|io|qdN79 zPIQByxMkK}^C;B)Mp@Ja_B2RQc;!+BU6LkAxGTW-AhQ?aQH~ejsOlZ`D0}b@rM}B1 zjsNL$htK$J-Fwi1;)}$nzzg;0H`lNO_?M0Yv6s+;);oJpD_9%!bm$F2IeY^Z-u3FR z>~rSXL5akb=bOE2SLFA#k=!GFxbu979$Z5xB_sk%J-hYHi9ei=+Li8fJR@j4BRsc% z-oj@^rDeUtQ$m0NQI-^sqkyRyPVl|?jIVFwm|GeVa{vbtlvmxQ4P z-cCay4OgqJcc@mjKx4&Q{iba$LsgP4wu(Y%u6CQZIvTPtn9KK!`d3I(UyRn!f?`lxoE}-`Pd7szMv+_>PK1}hI0g|$w*zz? z+D%hd@STefntJ$!^g{PSO!ad^w4a!XKGqd2nL0wdxXDUKdZ%26K890w96_*;?pTb7 zU4kd)q~A{573bD7b_;x~?ihoJ9hOt3M#o^xM!oVF(ZUvB!+#@&*D;lV;Th!O4tI)k zr_0$B))~?{8ngA>i4(JAiH-s*xvzLOALBX-1>z==Oqt5Am!b?+)fhVR?ELWd;JDue z@EK}tOqi!tvEn=gF$nOBwAyKoL2(V+@_)0fjClN`nLktGu`%#+FK?$^*kW7xBWwd- z4By(C&A6m_9I*w>>6{ZkGy1L$?Udd=QoD<#(owzkVP&OdNsYah)MWW5MSUAuL@jWj zy97ZHP{hHhwp8WdAoN#U3mYcbR2 zD4;S2y3)IoSEh391g>$Yd%xhXH4Kz`O?*Fb3qFDFYQGojySG?rZ>n0vtlo(eMJaZ| zg`2d3SkwmZDvQ48;rDohzZnb_ViTM{q*ndD;o8_BF!Uekh`z}PU&A$pYEVizgN< z7b&yI&RbNt$jw>eXP3>poKDSIQcW*dw749d92TQz`>0eX<4rGF5+|Q?VLSw32yLzoB=M>TJ8HeMtJD zmH2y^p~*cb1(P3^Uy9B4$f6>&voXoCb_vqmk=>>njnrFRG=`cgG7|LqlkqBEQ=n7vasGkMhaoc9=+WVc zmU>%!{^GgXSa43k0zAZ_VSFYn#AV;;HFQi*PKe75>50Fe)NS z{FLO^)}^K=(Ix)wREcOUGg01y3pxCTn_~KB-1g^}=hT;j*XsW>IB+PQQW z;EQQuv-8l!GW4ic52s_O|d*s{&CNU-_Rw6VfJ2)nhA@n)_I(+n9d4-xH}M+ zd?@2hy0gJHGEANzVTueOOE` zv#Nsw!iUd1A6d=99eY{^)T%519<3`m)+>oi8(Q3Cwvl2zx|+wMY#j#-khyZ=&t*Ya z@qo}w(Jcw2sOYeVA?6*tEq-)?gX6M*p_d_k78>7A^mZ?EVtLJBwokQkaH=2v*K=($++9^MEaxnxnMFw9k)ahu(l=q^DUCp4J!(qn`A3o^8bgw~E>(kI2!} zUt1`5+>d0#$9%inuwk{#wj^0k<@V9dG6-=KO_+FT!x^)qKc|Kt9`#)xF>_q@T!b2^vflF!s+RQf3cQ za;SqktweJZQ@2aysFoRmXPOciGD1#mbm6h0fJRHva!9#7AX}XXXS~iv zPca0gFb_+!j8HZFm)~{7H1s^?;iZJeQ)I?$Lp-ePS>B7xtP7)k1J_4T^!EMzgbvmA zObgk(`OfDvSM5Z^XeRQT5g18_f!TjE7~%daI%Thg#2i?8Eq0_QGnRgP#W+Z8(={~68yxw|t$uObmR38V zH%8a{QO_gm@@?1g!c4K>_-~V%erw;<Z!w#LtI)=j8f`5{bmYawifbI4y#GMi)wJjQiF76QCAgE~Z`e|SQB@C* zsjSSJT1yJGJQSfRE=<@gD?t1dS)P}~XhS#4Pjo^n@v+GlaeXY`HMakiG%AOri!X8z zE2u-v>D1kVvNHiz{Hz8)U|o)8shWnV479r$D6K&tq<3SanK%PGDNa(ezT z*lN4_N~1G*QdkZw*I(* z#>Gy4bn%N!Vr2`4Lq}?Ih0oF)6$z{St;7kHn(in`m|kgWUzlETYC)J@dCEylUiA-~ zSmh&}ffl;nFUIvTFrv!07~1$>QE_6@3PO`yRVl{U*^%5T)A_1VE9J!Y^O_#18Moh> z6@D};!89uhxXxj+T5{MHIh~dKILilM7SgWE(4C@NqU3q~0Vh%!b%e$`2Jl1|$GJDU(3PH7mSTOP z{O3$le??>Z_8kHu?f)ug8p5LXc6O%5E|&Io|5na)7NRUS%ELc2ZEWH+b=(@>3Q6+c6}(j~lq`tY`-S13bh{Z+w^Y<0*6nU~l@4?^ zKf0>j(eH&EGhzX$MVGbhL}T;CO_u$Ty*lM87?Y%_G@=KYMOUW9y%t5%VEz740Mf^5 z2@D84zz0ZMbb>Dv)ZC^a_pF9*ed^mfsL-5C736iG9-#7xym`ZNG+C>v%5uCsxF?rII?pVR=$()n`^#yGHX?Qw*gn@- zs!O8j`_yY`ETlROn?f^~JoyYh>fgd2uF{jKKsj!&tDyov;qZ922%l<9A6Ieg&z zZ7nTXwLvBuoh=+gqEj=@y5mkrpv&pLQ*DZ}j8xG}FGw8&2n``89WGJ`yQp z*do(+6c^CIiz%%%LOcWlg>KA{nwCv^;egyq3g}jj51d zpb1>~KYLUJE{fS0ZGkgTN6h*-gl4IIqJJchLZFEE>H|NuQ1lL)M4OSh(}$Dm*pC5H zyR;o#@DE1IAnChY=Bm)Tk9&*exoxbKMdvpxe%|uZQga}%F&+NnMJXO5Y5XSA^~^s9 z+gh7_AO-1DVz5JoX)y|2!-4RHM=cR2)-zuY+L~0m;ea7UIllHJ!Z6kJ_w@(ZV!g+~ zc96&U>m1M3Yk(<>C(I4;4&3T=nEBki*O2AcR7kPPjizHi2IF`=!hYq0mPAnIdS7&` zb1fFkY98Yx$e_GQKq+B$h%04v2!$jOUX(<^=7*@a3bBIB=0tQzVi|6^S>l(9Zvhrk zz%P)6KiOsx{?!`y8ai;y5lBu)3tCO+mzswIUO9K_LmQOj= zou2MZO4+=C&|uOi6Tn}nO+i9%dGkVX!D4;zvI|0@l3{WZ0m46rv0TN)B<9d^?ht>_ z!UdB`i7UD|5RBSxVi7$(E#hV4;gLF5bTl@cyxsQIJZyHT9{U{gmNF9ad_Ma@43M-bF6$7DJ*(%L!haXwcgwC;06^hh0wZ`MS* zT0J5+Ph>N`BfFOyb<=W`)pyEn9_+t9F>Xf1F#Z{#!uTpadz0C`7NO;+JpD?!x#yD2-fQy)g=Bp#IGbTe$VVlS(Q!SG&` z#$O8bUfMjcit%OS3!ql5*JoHX5&DYPZ@YozE2hkG+k?nqxvfGlc2K~IIkTNj_t+jH zfmfRz05|7H3aJ{lb!5!dauLF-s6ad8sLoW5RYwOiB8fXqhT>GL8HllA*33}5AT2Jc z+yX0j`4v=g=)-@)8M&b`;Z!h0K~-2s4eqUz2AH8uMLM{$wb55lj-YM!OHvZ1>$IBa z#gUNvjVNN2Rd>@9mQzyVF#XWMAFKYM!ZgMZBQCOp@a(Dy4%y29$Ik_Z%-kP0;`#I#?9qvkyT-hkLeMnD)-S= zf=#jd@c|l>R^^DP;*e-+(z!0aXQu6n#qEFT{i+rOs-){D_5YAE=#Lyu{Lb!0gu!HS z&~32~z!;8}hAD_heX&U1gI}r|Zu-r@C0%_|hKLiIN)P`rweiB`b;&@bX9#hY%0)M* zOx~X%6pWJOm0^BRn~n>jhr6@ZN!}~ptElkwiOcl_v8O5EFHnPpDDHQjUeG2D}8zf1P|BZArJ*F-F`w^@*|9HgZY zLMP*6yGQUI8}c>WT2-G&yFTFlOqYK>&Y&_UX9v^M$_$&TQ8rkNonpvM)}4saP!PB@ zucl8(5)Nb3p%i;>_!&xr{Rx_6c+b-ktXLMjkw*YjyfH0(z)RrnV1LFGQh_wNKw{V# zj;52s&HWoK!$o4)*arDx-xZ@M*Kqx@@l0CBOl0GOvZ&hWof1tIzXMon=%vU}NM129 z7e40>>mATaT+r=|i#UE`%P`N%|4 zH%&xMCfnpAWckPCeBm?)hXizVbhHtS%1t|R_NE9Fdy__gR`^>A21LCV-qRlfOR+Tg z=#>VMb91+k7QZ-0)V7!I4~@>s#>tRP35j^;<}FXHmuZkzKF7qlO3Hgm;dmK3Oju85 z-ktPRJ@mq4F>kkRPVs2-sP5mna>_M46m|1x*#wLBt&B3Esh|rG(j`)Y7p;Fsx%{*= zzg_@0&+noiJqS^vYv}dIr^K!0oEiN!#>6wO5WkR9$b(y@QV*IdX(%o#9k|y~1_}X~0;RbPsEcu?i8;M>;$MN< zOgqWB^e0L7%w!{yoGI#AGCPrQN6=P57%DCOQWfD)kn;wo3l(bW6f)9ZA<;TM=mV3p zTw;WVmoq4;s#vP$Wz!tWpDPsnh0m07{R7y!KkZpl*jE=G%1w2HMM2q+^G)SbZ6KZ* zdn(wJy1&Xttde7r&Eyc3A?1_Do8|*xx;u5_jJxl(h_V~heMYHy=y^K3-X}!QzD<(RszJj$C&jB zgF11%ukQfEALVYP?>f@{JoGi@22`y~%hpn>ZF1976WfpzP5gW7 zNbxl8qGo27p$x!eZC;lae(Bz!889j%EcrKca=gJgNOLl13g%368~W4WeB{hoIpMPM4zV`g#!kdYje_vpa3TwGLql9rvw(OV zx^zd*4`|J#1JxU3&AB3%ew^TGmwQ0^E^sUyeZ&3eJ;E_C;rxH2 zec{~dXW;C(Z0+RvQOi`LQUZp$?O$|&HJxVSloeL>W6cK#F9rfmr4Ce&)yw9#{I`N) zCL>>M>7A0daTs@9y(sw<^YU&^QW`Z+A2))RMLZ9h2QOl|M_Ro3ziM8a1iT?TlFJs( ze_k}c%%p52_kK3{Ymmv;(*|sJRJ6kmhqN%W|CK8CN^rIMCN-`SWmOA=UeAx=ZR^c| ziAymrN`);7`niP6_waaNVJ$KB4lwxTp*=z(Uw*J))h@94jFox^neEyB*!9hbMJWrt z@Zo{=8>X%ZJ;v?G{99?^iSTq;u&Gf^1VlLt<57B9_=f}(VMrLExRR36fMV9D@pP4> z_Zw`VYO#A(gh8xXXm_>kKdS0_7bDAg#Mg-Wd~uMcSLiKxXGG5M{fj(X{rZ#8%ft)- zbXrIntTvA$5XgLNy7H4g0uuF!2Wp9copLCNq-6>?)^8qZ+3ihx~6xvt-PFyun6f9e;ExEGAH-b&w0dtZgycYFJzr}h+4iB}L*j!(ns58`!I zsQN=t_#$QJTf^3rINHRrtK?bXOB|p2A>Ja5?bTCql_Aja6K(x12rVIkZDN3QLYT^! zDJ;~05=r!%@r?*Rs5~i5+JaIfdKe#n8Yin>W7tDS^uUoqwr`pZ?fk@NQ&!9)t;861 zx*tPj92a>X)%YGkE4cT!5n;X+n{wJUskG;H<@1r^Bu*^WVxpg{uLa=xOB`RQ@>E7k zl-q?LsgPhb(|#Xgvp`Yzn>tXWT48za0uii-|AckOAGshWxqL?yXVYiF=}w*`s(~4H zH%Om37D<3n`hq5r0G+@d`Yg%7Je09uO1aLeD$3y_2JV5`oUeGi6#80{o0J3hXF~6El(jvdnX07jv1A2-W2He+IDvao zLMbN;{*l-0hp{JKZO$|ImsLChhh@av%JFM~CFjtcyY?3ax7_(8=R9IY|L+(sBEONv z%~^rR^dqO4KCoXY2WMJ#AAP zd?ia@<3v!%Q;CQFwjLp}9`b9kFLm*nB?_M8Tv$?OfcFUbBx+DBghc4m7(@I;r~D>mzo zfaV{T>j#W8saz$d*XV^4XMw@gBw2lBM&C)U&j9h?vG{|@Cw`c}qFd@+5PhFPSKQxA z0}ojK06oJ-6)X!ThS1qH_;aYum}z63u?K2MmV>5_1Ls%7XV18oCwoaX{65iUv@pXj z>6f$z+hC-Pnau>7g?%0MDh>HgEm?SglZ;p%c!Sw}r_C&(M33_il27Y4n@O8859=2U zO3B$|SqH5zHjc>WO8xS0>kfk#B}cfNk5swUH0+t&(^CR{o1^LJiH$9%JR15j?2#Q@ z7d4jb5A?|6c@#Ehg$@gjln5}Hb@{z@6rx-#8f`2(l>3Bx{kVH#@h2fl@j<8LSU@rS ziD4mn)YI^A#46PEHXRe=X546Yqi~LK1+Lh_UXU}Rx>6st#`=b}Va@^(04hM$zc6dg6#Y0Au7GHJ z%wBW#s3zZ~;Bi&_kNU%Q%t`fG5W&3a(yaYq@KnjtRHfi>W##;3rq(vN`4lIE z!!7tzYs*coRaY#|X2wgrAuRpIspY$xeRWM?o6?HN+>S8 zau#IiSeQh#h&v0mr4b=aM8p{Ounj1RSxLq$F)3ebN?c{CU&;}_1|8fcH#KPg6JUpP z-~4*N8-7eX?Zd#V#ZENIQ(@T_Z(x1&H+L_B#k(tG6<@%H(5cRqihU``gsEDJld`+@lZW>z8IGYxw`Vpq&N%*!PM;?&d@C?F=0xo&=-FVx7u zEfg0rlP4LMY`2k)ym>TyQQ@c65d5kNluZjadSffOrW>UM2Jo3C2bflt?L!(H7_LvU zIA%Gqta4#S*v5{P8U3+W)nn^{Kg&vbG|UpAB--YSEwY=M1H zb0tKLC5_5dMGVKMjL`BBOX^n`HP8siHzEl#1dupl-L0{O?BgdzoHI*o4*7Wkk0P|| zH8w$$Lp(YRSAANJ)XNc_4y~(yP45%iV4xU=twxH2`s5=eZkkp>$3w`3=mfU~Z7B8; zZ@2lY(St?^0;X$Bnvc9GAMvKK;g^&{#wOv}hiKk3nir)41;2vqkUNM(GpJ_O!sMfF z?T4B6cQ~>})>a-c%77oV79zgbpx>fI)I+pImr+~Dc$A*_61P8Bqp1gw(@UKUu@pXN z2S7LJw|`dFQqV`y4SCJ`1v>xmsFF`{*KeIK{;HpG+sbxQrx-qdTsvr|o20QQWqpWN z$>Y}6?R|Y=_fY*J%r3>Jm0wD?WE$So+u)Fkq1>@wc0R%be);rxiFP5<=!F5c4dA*W zi1!&n`!-IfxBG=|iJgXFr=Uq1UIYiA_nAu~f`>{|A6>neR1diO1ZN){sF6# zIyz;1-8+9U2IL>TBYbEh7xNXcI1ft>M$f+Hu6PC8-b<+T{(Lx?#B>5HC_iv@ZaK7! zZnOG`cN*3fnl4uB6=$&Y z896l&{mk{nb*`7g?E>*nxzIKr>V1P9pkxPVhox6hQWf9=aK%MWY$lF*qbj7=l<-56 z!bMsvS(QxOi^g+KsJ)HzWW+iyqUgCHg21HFad@~Cjm(P3!u5oqtlU2u!5UDeXxI}7 z^>Qf&-C2RM4TzawHk){0z3R+}n6xV~X-Rv49LfVl}kFD~kaS~FzD6xTnV-9vqO zpF%Ti7VPB1puVf!j_#kRzMFd|MVPu07q^n2t0ynlo`MdZK1^;^lJ_Ji9^?I+?6%kk z*bATXx|r-vfJgf(&!;_oCi%goXH!J^Fi3^Ab%E^#ZaO)3L8Lt!dosI8^Y?Bn%;aFwQM&@dOz%k6rF}_G}FMXHUym&$LL-85N`v zxQ0~zE{nig&owLS{H<7&`P}>lXWh%c=2?fH+6Y@NZ};IL^OC6RYcOf`)^em&co)lj zNcLE-+D6WpJJEc{KP|MOJ$(84mFy8!xMU?Kzy5QHBq;I2k(VcO9mc^k`4L?C1^Hh$ zFD+F`c~K!Cw#XnLNdM=i%+S%q@n6sk&p)A=rQ@l`gz?EZRCGMjs&Ar!CM;$ZF zam;u^--z^BnZ|eN$1~G~R8XPB<_lb{`y=e!M-x*o1X4qP+sMdY|IN#}Y ztBrilz2D9RBtm_UYus|4?S8U(>hbAvdwfxbPymfq&q2=?iBkK7^*17dSh+@axna5y zU!hjVxh8hGf-n$!CU-qyn3%c7cfHlVmqK~W|KPqsm)67HeT)8@{NZ`?Ls`&Z&OSta zFHGj+Z$x@QE7dnJU6vuOyQ7GH1G}Y&atIFm8}I4KO@1@GIEa4Z#=Q*#8#l;}*Q{^W zbX}tt+BZE|0&`_M%+Cy!K4Xj53wuvDuqB^q$Rz##z~?lHudx1HT%Unmf4ui}_jiB9 z&jh($Wx98)&ymHQ^jBErFOxHUnUBnV|7XnH`U_{XUV}44Wqnqz$qV(LWEyDmLiG6Q z?3(k@*k;h*epk&+oiU!FKrzmaqBiI6;W9*0(P2v_EAEB z;tGD!gt{}?g~CtsSAuCX43^mAFB=J*HOc7%S@iILlnw?%Zq$XAAmm^|ZYl?~X7M{Q zjrq2mmFbvRRd2|I1q^~|(4_hpe`Zi5^$-ETIIzb(IEtr8K{bf*$FEDLW_s8^#tU#Y z6p$Upd>x@dhidj?G`4!fMn*iz2BlTO-Cdhg`2`BiQn?$LD=u+Qkz4HjGsMFi+h}g7 zsVRC#b}FSEl|BNkiN$2C%E;qVtrw2JS(hq_9-6P#Y1N5D%#gSN^w4b7MSC((jgy+H z%H~DbkZ>u`+kbI(!5Mn(FjRN&()@j0PIrPhEM4*ZS zEh!1r3HF;uJsaiWy?iMOjd73>+qqEF(*lp^=fSg%Oha3sY6S(TR!)q?ZPGG)*89mu zL@(~#ep&8DJ2M-S4Pu|6?elgRh7#b~TQtNC#38l~A)`44=aF5SI{XL2JaE^7`YLj0P3Gh=5bgO}qz_UOYF% z6{<&mcnXjom_{};1_jQ92|#1Q2Ec{TK`$fPT8q?JC`ZUi^aNL0bch0d&amScLy5pWqSr=FFkNWFGvV2>OsaASqjIvgg9XS8BZhZ?mzu=K&UYE3;*Y^ab zccw1=rgsu{Q9(I9w}M;D2N3*kjDi~>J-6S`NJc}*1cMWzUvLuyW>S#%P0$h=;;0)$ zfz%Sd@CDeQ%@@Rwo5&XiVk{7@AhmIQq+hP46gR=spk*jP%nG9XqEoeu5xsD~EPB-d z%f>Tf);+_}P=~X=$v(cjaz(rJAf`_mh3hP zo2}crfg|eTWkXT;$f;)1OlKEIPbx3aPZ~-|u6<3I!OUz6nh1Jwj@U>$yJmemep({n zWUVZk)WNYXmz1|t;!S`jikVpyh;7`k-5^6Fz4|VOC#P97rHBwouf0f0`zDdgCBCc0 zcUgMR5zwXBB8cDrXC;Z+6ye2V5#8u6UOlh(Ky-T2OsZKuUDdac#fYTLHq*119|sZlURH)Z2A`~pn)Mi^Puw+~b+ zM(ONXt#_!3MTb)2^vX4z>}vWmCJK;j<>qD`2{-)!$3>blYj9rKOz~Bk;TfR=yIl{d zQ_Siq(({}p`gE8*mHUb`C%YG=$C~a0!B6NU%<L(uAg$WZiR}sAlv%As zbIIt?kXn)c08(097~OS#u~p%_?!R3exl}P#t72ACtGLr=+iJ~u zNsM~;w0QYN>{5k zJE``FNc>Xb+)FwS%fwbaq&jEwmZPR*pSWmq^TFzEVzUkulrc48kkRkmX>UG6n#YPY z&^4PNigy=#ZdR5Rnj)%-s+(`42pihCt{ya5-^D|=AxQ29mm!D-fRHMs=IX^i$GK-Ed;~G|(Q_Mc{Y>Po@Kcy5jVv#NY)d&@jL#A(>41}^to?>J0 zUgi>h{WhL@j?om@bfgr&@k>%Ts`!b+6s2uAv~hDLZZbLy6_bfOqxdk&xCE*mrxRor zqUxi67dHrm7!ym zPJID({0LjZZ<&pQN2!nHq&7~SD5N#?xFQkN-AI3CAt!huWPf_94J!qKM`L=fyhr4S z4c$d|$zNj~`Ih;2@lqNDqu=jOUnEqOd-1{pR;uqS`F_u)R-QhyrHWF!eG_K-oWmji zG7Ro#hr@q4R2g|Fsy2OF(EuUw?o=H*@b;;UJ)Hk_=YBHH4t6-6`*CAb{Qn7NoCt$S1m1U5g#{qGWcodyMY$@5kck*EZPc%!4=jrHdl z1TQIl*Yq)*)*MfWo(DVpGbd@_51$9t$jGQ4MEj_+q#b#t4UL~4f=S_1=omfZgydWF zq`$z9Mjo=L9h&PLR$8dF;5~v`p_Y9_^^{u~yV@ic^HsAfmCUYMFgISgQwI-e9jsKqHC4Kp%ETQ?AGU;T@JcBV z)s)*7E(I`)VN8Vh!FPkpBYD5U?74g4`imxe?y0=M5=SWQp?)ABlMkXz2U4?;; z!OQLA;baT|nxI**YK(-_&Ji);Z-L*BEXC=;%W{G=1%#KxTB@?? zeiF)JVGz|NY#Cof(8elWLGb-S2fv6{Sxhs{Ee}^G%WP>*A(OnIJYKWTj?!jDypxZ8 zFi0~UE2<)@Oc!h!}h4MO5j;yRpjm>nTp@0yfzgm2?%;r^} zexIM`A6xF0LMQUIM_|7OqZ^vh+Fy7AtpMged{f=`sPWz4%z8$b3{M=y9tsxu7FYv>@F*kDXSU2(h z;rp26GzXgr2^PsaKm0w%^U3*joQ+P)Yt=IcrHI-A`*13x0_|1ci8zxflV06Ajr!;m zdbz3-q*u};$YMO?X2|WV+{G7*ZVxFF#YyzX2PUC2e)e9*64&m}zIWuu`RDVQw?Oz8 zPdBBHB={RMx(cN|m|L7|5bX!!X5OtC!e{*?mOcFuX`^d?aotM(s%O z^y0`26RH(s>^dN!+ky60;9&#Sm>DXy376uigLdF1fcJU;@8w4i?(^bw2scK-fT=IC z)xJ#A9dG)fO%J9Jg&oP^@e3`}aKND{e~cU=*$Tc(!wd^?#^QGCAPbBZzHQ_DT%@8H zJ14=)A^s4RzFp)V?~uoqaR){{=cQEp{&z=?2h-{eI{3Zf^EPJVs4KZMRAc-Nc>5T8 zD_}U!ddAx5=H(OOA3+8V*i>EB9U6qCC#Bm(uc1jSo-fl@hZ$L6VQV5wwM#?L)f@SW zDoCi0Yl)gtWx7Zhk6txecwEWqg^|q1;ZBRmZhzJyjFJEuhu2CPgvAixK%bU3VG=6Z zxqIp2MRWriQbm#_w(qU*bB;pT))nzCzBUlEg*&birYB7_+#I&v7t_c1x=H-af~?K^ zkTtQQW}SkgWy|GQy@#{eMi_mhq<`+A*LRPrvt;TvYTSPS4S_ro1jH6=AM}6 z0g_vPTa@=o8Gd2PKT*@}MRF4o3L!{F+`V80yda&1sR3MRe;RnDw#3g%lMs($Q26Cj zFq>i;4c;8kztDa9VFXAk>`T4S`yzdXI_+6eyu$CY;oi28A_Z8E4;K(n?J*;&feeNi zd}o#8ZwRmtVZwPolo{Vd$GOFF@;#xmA-OpYT{}(~Qs)@eS_El0C84L`95Dbju{|p}fem5si2f;XX zIqlDxJQ=F2k0TLcmY~qU@7`df-$cMwsZzctQKXCoif$mM98u%(X33lcjZ)iQnO(&= z*dW-g*KSX)ICK}wv}nvbI@oSrJy~?GI96{z&eQ4I)wTvNxc>Q7Fin9zfbL@WyyZG8 z@SN*x4WE6(9l31OL+is0HP# z09=LohzRV4B*bxU5Bvi%mIp7Ek7a+De~Ui(o$w`m&xuzh`aR4C7zG0ujEcBzXxN<` z4LI0TN^EK=V`~2z`ihl6T$=q@UdJ7&qa~!k2M`B<=P*WgZoqM zvFco&7Qe*U|NK*`Vl3>fOj!x`k^Wl>I5F1W_KlkSf`7DYyd%&#l%dWabQ-z)f_wi0 z&-XaMQ+uijJQaWHw*MfWMR*kDR6LNNZf2f1BZ2H;*h@gq(t`YuS<{00&;i;to%VCz zc0mMCPOtCGA9;Gd5qR1={O(H?W@NY*A8hpcPPmH)OX)^XP%TT#+5Xb@!!wGdK>6~q z$yHm&6UO%$QB$j|`ACyEY>TO4X ze}-`0`u_IEyX||)z^6~kO8d&;ee3Ouq-Km1G#rAZ%Av^01d+@cT(1C2DOddHBd*9J zN0T}Vfy<3E|9B25L%t;ii|X%d`~07SKjFh4v>8|mJ;lj~d^m_P?KG_Pwzk(f)tbXj zPqpuJz(HUGHh>*tA@%`nt-VP_odmOlRQZ3b z;3C2lmrTqD)4qE6Jxofs?5^<_7>Rr*PVhMQ8`v)-j&FxH1H`+}u5%p_8)E_bSh8~y zuSGzqZlfD&cS{>QzSe$874C?G=j0|aW}jXh6*sH3z*cAZCbB3mJ$vE76r9DOPoE`c z$@pXzE`@{Zn}j=#Csu{=q6DcoGE!vfv5L`~D8vNG5Qq>!z~{yC?@vRsW`9qbqZ@Ra z>D{uihco})-PuvSXQ(F_Td|;9VF#{vEaE*dZUWDi7S7k4t-ce69+C0A=|>K^!QjMB zT3qB&E{t@IndCTqc9UKuRU5Nq#o%p>^HYbTR_Gz0KTIpM65hajNz=LC$PH(D6-5J% zH@CU1((^repE#a4uCbL)+{PgMNURYM36Qy+qxpz#+Fq*!w_DDEHZVKpv*Fq?wnHSHZk>^KONf@#k;2tBG>5Sh(wb-y$*nrloxRfDa#j=)*w> zyPPeRip`}MrQk;n^8~PrM|FjQ*FN(W>ip@!8 zj7yGRd^V3NrY|N6^w+Q4r;D}i&|R~G)TeJE5PuDn?^XdSfIE)D{K(z!3AS4qC0Fz{ z95TFx#_3bTS&Wo!BK))=?nk8hC){; zkF<*LBLlt@sZZ?FR(*I?W~Ss7*~LbkE*a{QjuBH?@)(~Hy-E~ls$wu$RE!X+ zOSi;U#DrLk;Y_ zRRrwjz~0}kSkK)kBEI}yebqABQf@CQx+V*dN=bMZGaw=ju)G2^vx_$-DLZ&t{Z^-P z-DEu)kamdSQt;XLb_eOA$!YGVCL2n5$|=6)LOj(wBtaX)Bs9A- zuv)INF<(IppUH#`Kr1M-vJ8K?751Gw!{z_QS&A~5_ANm;gbGj=hgwf^RdLEr{%#p)fG1tq0C!S zgy*nPA@(#f5PgDlVs3kJGHF8PZg$Mhb?9#h+;;b&ZVK@6=IEjA6^f>C0{Om9#D^)2DJ?#&Def0TDH~X>_?Ic*=p0-8tycmcyr%5BqWa>8mKsqMLg3&a+M+AeE1xYCbJahx{A*lN`HNU zAoa(=<^O$+I2znLkl1MI9}UvAsAzS5lM*NrW}qUj6WH9BM_F0OlH>+f?_Lq!m;TCD z9BuCgFlt2u+Elp~iTNZX!5b%>3wDNc+Kbt49GXgB<4zlsbg1tASHAMp)Ns@f34ySVF4h%+v`cu$0d3_11fF zz2)|NoHw_2R%gYSEO#5o-YuTqU&=q>A&Z*P+2%XwOXH;pj4~$H@ckLPF=MYt*?)C> z({g85<0@66D(OKh#Dt%3Ps5N``(B=11*oOaay(8WVq4G5%YdcEk-prf7nsIB%&%35 z14Wtr2q3sVz;WU^G2`-iL3%KJ{TO=B3<$u#vGP~KCo%5hin}ozpC$68rgbopN8(4%+5T|c=AdDO)>KkucS6_M zw}@M^%`XbUk@>xjwZ0j^#D3tmey?b7qiQfK^gHAv0U^^E#iT(z90Tt(fiYkN7aO79 zoDhdF1(ubwHG|WoSKv>kZo)cxF~xT7l!SImbObv@p_mj-JH$UGo64&c zgzSh%;s2zU5)9`_@sgN}D)H*u_|67HGAuh0;>N^0A+UE;(@^V*&4)B_g^QtoS;NJt zKOpaD+2}gw^8LqXzMB%D=Y~>7;XOaAOC#MeAJOWvQ7AEObb0gVLlw$f<_u2fhfhkZ zUjke?B;FtLXP<>B@pq2^uhB0NGB|sIwM$; z+&!)@q@IwYeib`YxKQsrQjus8OPg18q|>U<-6+GiZnynOd|dWi1=g#CwD7Kx3vQe0 zv;4SJ?pWN*J^qJ5RA+hPXiz{)fn-^fCeN+SA6W)d1|!oRx@z~(9tGh>&>+10law62Hix`Y~j4rNYYxIVHo|f4tsDr$gHS- z4?>)>4);Utf&(VvG3c0XV?reCPJ2QE#wKUN9EK)q!VGP55I1LeY>yS8-n7Q{qHJxN zU2{#ioV|bc;SYU<=2rug6YE1rehlj-1JkBoDHTmLZ5odK=03QHuRIKndBC!CV0LDK z6X>!oHT)13`zMl~W(Qg;p_q3zMXTdzl%Cg8OTfBGAK0af)wK3L?n##Cgxjn=dM}jO znm=yVD^`vId97#36*BiE8**e}@ibe3u8#7`gLSm|N^b#5w=wutJTrdz>$7}2Dz!~i zT50FRWo}@`Y(P+MKon(4BfpIj#+kO)T5Pm?FveL+hkVKr1lm;ceU@Yk^_&H$$J+A_ z)qW-OW^HK_?`KfWQrAL@YpE8fOD!(y36z6?DM^e}5-Qmci>@v5-k2`gm{cc;U=T8O zu6yQ26n^fbFUGYe<^~3HF1aPiwXfKPH+GKAFHSO2;zrL^maxD2K+CTH14u^RS9s%} znKPj)-mD1i6SiJEwkt{7lXNSupSVfZHo8RK9wS6MY6q zlTfPQe~Y6lD(}ep)LfoxuFCfx`*m6BvM5&-W~fQ@5Zx7QsNwIUa8;sa8@hA!(?gO- zxm2*&{vw4=%ukVLNhPheuf}CLb5aeZ68y1(PQ721>9LefgSm?Bv8zhiY6)F0zYC~Y zmA;`_dEACnHQ6SivDvi@U&5nV?4@&U^V(m56^l>%jM1JdMh`FIF3l!_WI6bwH!P|Q#&&o z@ZD~U0X@qhv8@ZurswC=GL&a6F? zraMEMeV&D*!#$Z_#z`8$c1Eo4?;Bo~fb`Y8Kh=LLK`rUv6@6dj6N50zQfK9x45HN2 z5BR53?@Cd8q2puQc4}xaFnomn*L=D;S^us1EYo;*C0NG#b46Exq5jGp{q!3$+<-E9 zJK!>0m^f6ri4fC?LQ0o9l!C#|n|vyXQYv||qf8jQMcC39+VU(lE8IgChW9gye~Tj& z*g~{%9R$h+`}2td7`YdDw7XX$ksUyESO%?J zyoX{C4b%k76-|q2{(~qiVv#JG%u+m6d^(z&oXP^t)kJ-;!uG7C8Dm9d3a>zVWBv4p zwT;V!ZP|`9eO!s7_W%M5W}LZTnp`O|CsLTb9+g^_3P~k%%DVidlq82Zd!?D+XzBXV zu=Uncjsqo6c9ZIJ5)6l%HmK*S#BkNvylH*72rE9wHAdbe%!Yh1D~4ohvlB}dr&*oz zS7dXWKvmI|xTx5>7bh1dYx;z?TMB9n&ZYXOhxOPmDZNe#3s;{r?%ZFk6*n*YisvC& z?-Sh=W6he5cZDgF!x);;B4g}hSuR_RX{Y1d%b97D92wrNO9aacE#ZO5Nj@Wa^|R^( zZXPq$%W})ImL`sq)vS>Vxq1%_^{V#M*0A|Z-6LJ$%9RU|tG3Cw1UzRH)%P*2s(_#S zv6pM0mXzAgu%^@DDGO?9`|SyD_j-?+91o6~M$2v2YvuJ?%!s=<-AdK1DP0Px#gz*3 zylCTmg7r?X#*5Z?^J!&fhQ3jZ(>pBOqRB(EKb`Cz7?& zo3K06u>Z98rU@9n0||b;j`$4an8j`B{xV>2CgvE1u37$esUQ@ny1j8H#5+jF6(f|j zHercEsLE*TB11n0EqA);@59DQ_A{DYcUujaTR!5W^lpxcSh4hL%3plFyfMvlgO_-Q zaV^rY=9F~%I~V4>r2XA~L?p@6zTm+x!4FsvHp!0cM+J%#x&L&;dlbp@K6PZk-VnsF z(wlRv*IYz^^z^`i4|#aQVIOydpY{Ph=<|APn9uKp_P{{!g9F4~ebLa}Ih(KXdezGu zFrJn8hhlu#!h243gxEQR0+Ew#KKf*Y`9&p{N$gvGf5`AG`Be;`^sf@B(F0rA?L}dR zCo5~#E8Y!pNb$2qpgW{QsCcN^TkV;zs{m`Dtnf}pu17o6H zVPvNRT>qey7fSt}Up+emc>05(ADzXu)bf6znhtaY0SHo`eUNu3ZisEnMThMC{1xbb z#0b}_=eB1UE5m4JLFrls1qM%9zR|JwTKt5;EX^w1L+6!d_RkLi;oF`Ib7(2eRlI$>4)5 z;rI)X+YuY58Vt; zYnz7qcK0Se5tOzRun*+059oio<%GRtQy&uK9``UEICVt!9~$^p!<&$K!TfGjo+aWh z-X7poz@iw=i*KSpo0;itepE`A5iH0#sT~K*JOJ{P5|tvAGL=FTXn~mKbZbmxbj4z! zq{V9GXUQ7vjz$s>U!J)3JREbcE!CXiA0{y*JP78dY`>EWQtj<=Gm9)#Oav)F+2FHyX>>*LT17l79*aPcaPEL zPtBi95I$k5!|gja>XSYCEjw%!vPAv#4o27OhDzclEaEk~jpF@l{*mHAq?d1X=Guxz zs_PfTAXy?QmT7f;qs(3pG061oTi7gy3dDLmQJWDtjxWtz*?Pk&9$jmn5=f9wIS$82 zTlE5!QmYmOz#L|UHTJc`8 zMqRR|bBG{1Dix}P%Gzgor}WTMHM=FcwgpVp8IA1}sByDNC6zF=h{P>Gdvzw}tQ5W{ z!pi0kVE93Sp5_^A?3Id$ih!1^{=Z*A1{Rtmd9tSrSQvD~I@#uS-CA-RvjmjRN!1oWFa zU6G53tUpetd0cNg??1;@oxpV0+?0V1FrLos!Ti^04Z4H)`$=b1r#O;Ig4*-89QjdP zlJVq}8!8lUw7gh;KQt`sL`AegipTn0NwL(|Kzt&lCs@VPE4zAXpQ}AAlg6B3HF`6? z)Oq8^sPg!Y|V&Byw>be3>DndIdA;ThK= z9tAtQCJgV0UB3@M$AvyV7IIC?h5X19U_&2kwNYKPHrm}@T}3?VmSqC++J+myyJ+6k zV#|0BYOKq!;=R@}o~rn)jR6^)$J4A1ZM82e{7uWK;Ne>Ym-{s_i$pe`O6Q zh02}#E9=p}vZnbztpDAE=>886B19CzuQCNa8uea#X}aaWB|Y?3@I~qLM1r6xaBOn3 zgo>obk^#x9;v7Mhe>EXyjpR;!xXy67{`u$oCyX${4=i|Md$JgpZ)xDfZ2YG_UQZf6 zi?e7>Kk(~crEK{6_8fLkKPkHR{2EbRX!U0rHgneH^zN^WtB}afp%%%ZTkj{%+`Zc! z{ETVNO&TIEzvFNCGjJ+fjO%>1DN5O=Qo^$wCG-Mgc391Szl%Xjpco7^EZ>8hjNV5j zrVD^*OXPci7G6d-VYI27uGH}-vQD(69s}NVBUy}Le36&Z(-Npec;T$qv5z32^eWA{ zvddW<jd_+I+T|KLQy#KqpxKSZNOyaMJ=!N*- zLVLA;uRxoQ=qi{7<@(TPbE-8sxoZm`#gJtpCuI`)L%e8_i!X~%N)g$NvjRGh(;32Cm3K^tXyd_N!OdwgJ5cX*; z`5d9&?F3tuzmZ~4zq%rCLkCjOdz|l`MxxZ;)lTIK$xnBtU8X8$4m9zWFG zH58X!-QDxcfs0&RPCE@i;Aw82mS%bfgk;X$(9MraU_I?ycLkgw(15*au(-K$JZxQcD~fbUK(nMrUul zPvZK&Ufz&|3A%}+J5KiniPiV^Oz`w9>@o7A4Sl>V9xkV&J(^!td$?Ti>F1-&Sf}SY zajQDnbx?N1WHr zL0Ea%9ayNcQoQp|NJR~+xEQ&H__Tv>!qjxy`tqr8#}t;s0@{#DAc))g2qlY)az&MdJ?^@jySE5;)ffXzVKSUpy)~N*PV_i z{)_|$VWjRsGYNHjGghCH6-pN&d7YzJ19d}+a1ZmP`_%G|A;dY04VE`OlB|@z}a74yNsX=a)DI$H?>G&Wl z3dbKzC>3NAq0g|{$vwOI#XozKdw+UUzYEr7ZLQqU9>-rrXG@pQ+OsF=_Nwp}Q_p(S zw(0b0b>0!Q*ZY0%kfZy^tP#_Nl7FUwkJnQ(o|t=IwB7VPBE}55_RE4B|5jx7&tYZG zVrM))6MjIjxcy%!yQbhu)FhltHnwfs*2K1Ncw*benOG;bHL-2mc5-7)Z0zpCTD7l# z{cqjXpQ^g^rUjYIni;r~HhS0T)67+GVEs)XM zqLOr|Wc#7OY@hmP^?L-0#H8GvS9nh%EH;MH&4N+GHhnoF|0+-+WY5e02Z zbL0XB#AQ`)$4EU6jkJW5Sg0CY1Tpdw1Q*cGTHHm^Zn1nv)DVCPW( z8GNkl%>KR=lGSw`@Fg%lOX?b$J7Tj@#JCki^OJaxelm9*iAFKQIxSnNZg6s7t=nIy z)DIbCK2YsSJ;Mt;V5{#(eE)_@LIFfk-4P)fgxCj1IfFn$LxUMice7TPuBe^QVRt#o zVn2R6n%sOj4~YY(xGun+F;Wd*5c&hk16gP*wx9H~bk@y2!}NjIVIQ^^Lqv~${lO6RCO&uYMFGG5$vWwl0u#>DErW@7`-082is z$AtDyZId{IyNIrPR+DK}$>EQt;zO?}UER)dR)holGhOe-lFakDV7ob{r2f?Qlqs`D z`Ffs_T_x_xl&Va3nHoE1v_$Ob4wb84^ew63HC(1-$P%vbPYaF~c&1E9YmhcerTDj;=Rys|SN z<+(B$OUF;0NzZ*NriUB#yu4%__}pZqWu;MxU1~Hu7r4SS%>Yied!8|i$v zQD{PmYnQD0>VVPFypt22MDT2qH?6?RXo>p?7&uno?`Z0{ybN>IY}H0O!*JE(qlF}e z;WlWpYzDooxDcK|ZCPP*zkjCX^uNXD3 z2{sC(fMBm`t<9B zYj~Y0$KH?HHhcQgVaYXDyKH4R@bo$bZ|8$;*bWTFMu>zq%#z=ho!D*ricgX zuJnTNiRQ*laj7OK)^Mx>C}@5KO9am|#oF@64a1BH&B7P>hZ{VQkCuB1pBh|*YXvgmgkb?`AaUNdm0N5z*vF$2-kw%F735zSjs&t z?n?$Xve$yY zxrON__b~o= zYQA}(u#8<|QtacK!Gm1zBPP^RO@7&qk@^Rg$(cu*dXJRq2YA$3+-QX`K;r{fZpLi_1OMGU||6mYSc4q&9K`eYn@lzXdGFFwHu#i*bakPvCCQAD@VX6w10Zm1c z(+FBCxo+sT#_KAksQ!*X3`0c%#{nMZJKZhp4v%kff5H~m>)x=a4WX-DdrZpByV^@Y z*tPb3!ySB~MX9FiZ&kXO^KrGXsGGmg?Pi>Uue)hHm5wZmxmU_w32C?8B zpD!wca1m~A1?^uJr~TuLv1aw^n48qCbF~}C^sl>)^dw1fuH~2X!3`?}=&~OSn!p(4 z(z8ovAr-2GL?CE`W(Z!=nX=pX6b*mjQ`{JKSh(Fvxm~l^j21$9V}} zJ9ilVRm0BnxPGVq6Ih(W|JN$JxB~1P|8bLdjHZkWx)#dk@Nbd{VcJlG=9zvVv+vE| z4QZ6OP_niVDXa3q0z`<9X>+5|lEYAjhUyc8qq3Avyi z5ZueQrHDbf@!HwSR*m7)c}<7K{c%svJ6s+*aab*4sn}{HdvF%!fnNN9od{a+Jb2a7EJ5q=4a_ZD|1O;b3E=Ge7j(w1v}a@vf@v6>rM5l2+#34M4JL# z(XwM%=UV24ROu% zFCBmNP(w3o;l|B8qH65f3GbG3d*aUn%X1Cb?QLJp)L9lw?N>)u?&=LIx6LA|Md6Cm zh1kAPHc86Cl_Pf!S|QrKb`?EK5{IXsu^F=*UCQybyczP<@><$8h3J>l@qGHR#96c1 z^UXkMjcX?2Iql>oJ~J!Ru|})Su-A%l?Demhlo}mZ z1omlNx0-!5(cMP#6u^_X1XjL!x24T%AgStV5|=aIc}gZzac&DTJTctkZc*@)lbi^G z9UL2uTAs095S6qh3SkSTypd{Xz7d=UM%pNC?Vy1{yp_mRzov3vVO}^cUqzAM|SRE~=3FH7XH(Rx~+W#_Z(1ChcM5gsi3hP&CYGe^wWWM2 z+?BUB%mZJay`^P8yOgOsXF<5ttj;dTt>8mD7KOizzZB2MU#5#bO+haxbbNxDKR3N2 zr%;iR(^wx`!uKt{J(Kp^RP689zfA_8K4MA~SwCW{)7!Muwn*xxnrcSqOkc)8KWNh~0io3>;(*54hsU1z&ZI@;~?<~bR<o?BJq{3}{sy3u&$u|>h>?1tMyTgUa zq`rYjLOe}!%<8!Mq}o%vpV*hdUmYX}?Bw=uNcCb%oiIIY?7V}&S6YF0Yq$D?e;zrY z*vEDSfAKC&sSg5c!Cs1^LSY&S*{q=BJjlWeEx%)f1QZt)*`&FV+QH9*GgE*>r(mVX@3Va`bUYTY(D8YTa*op`5KKn!36<{> z%fGY50{$Q<4M5X!3e)I`QklF#d_ifshTido-dcbD?Bl|{Sy3NnTc^B56YjNXhg-Cy zAa#>2p0UZ%Z^!j*7}IAKIMl~mUJk99aMpdFYD2NRaja^RNqi6-vS&Is1PsvI`hKHa zZVVrtg(twCq+$#Ev4nizv1X^m0?3==%)|yi!29AfdL)rQQ_dhwdxAZJ2!4q-5~51W z%_Gd+Ll7DP>n744@Y1W5~H3WXGO$yY2`ivV*t1=VXxiz{zY$dUdaM z)BCt8KCW;%^k9DfVC#)t$+}fnv@`Ix?mkinqvjz=@F^eKg7lq_TfKE&%ZHp-V}jcH zXM?P(>s#!f^O>SQ!4A#;fSi96D*9@8S~&i(!SJm#3GuS;;hc67w&E;!AzZMAk{2R~ zC~Sz>{P0<Ra06x3YUplagx>H4yjzT$i{zAuV zcjtz}9|$Bt*ap7QKF-?r01Q^<6qG09Kfn?rP8e*CL?TyslC;=3d(yPXwEdRqjt?iK zave@;+k<9SNZH=JeP+6zZ8ET_gl{gUjey>1cluBgPRL>Xpgq7A3&iZ;(X-H=Eow8n z=&5fSoS%oVTVY*Rohs2xvecrFtgej}7c+smh4_$;<8*To)~sh77bW#QJ@(33s{iR6 z+m~yVss6)C>;5SJdY3h%Lr>o9B)p5DsJU;KO@6>UEw;0`{snH$Y#p(WWgJoMf}q*D zpYFVgic}1r?c0MO4#@rURhT~~al`&aJL~8aWBG^(xH`UlYzYE8O4C91Z0vt>tXSo(D{QB{n8fWQ1;b z#LB$$L08yQ6A0qo*F7}2Pkr<3+odu0zLyVkmun-0#&O9wN$Yit8NmeFIixpNEjk$9 zCM&i??3?+_QvH%2?Z2pBuK+*gzTKzP%9N+-Zj-pE{!8bnh7 zy!HAD$6s->#}Uv?#AX#FGLi9)cdFGyvMq&~m(_`J3{tNtg4#}K(^@QIH4`*`l}xXR zo0gr7Kg3;dxUEVm3Ln7i=RO6apPm4%d!Tg+(}Z}5ew-=tIo7P4API;83mhJ&oFLkW zknKMRA^iy3J4Oe_&--*g`E&=J#NkByL$Ba&&bc7ydqbP~`QkAV4YK6sry8fs;&$#t zu}CyT@5bizf7tEVNeBDJYBsdW$rPPBsC&jAh5S&XA=M(|#Usj=r+~-@tz6G0B=-jy z=7lE52jtx%IyOm!q zM~J0WQp<1zQtuv4EcV0M-)aC~@JhVUT;5TyZm6Yi5Sl%aAU`pfJ&8EG;X_id!C!U) z&y|3fzGb`QU&PY&J3ohbj~{W!T#4`e6iW$&!ciXu->JWhi$qNpe_HQ3{NofLustd- z{gb>f`345Y{6D6^ztI?eD!P9T%RUud4Am+g*17B?d@bo(WxiL~p*maT*DfYhdR?2P znTGM0HQ-YvekYayeiGh@oQeem3d;&~SVPhZO=hw0`0lj%e>pk9<^?H0^KQC05+low z?gPN-AuG{xBHaae*}d<#BPFYv$+vNM5t1!K^G~Qw)Loa<)7#+w09fNsb~z1Y!)p_? zaphPi=c#IuGLUl3_yh;k5lX4ilW(N%$z#?@j=pS}XZD=vhsuGI_SBHu8KSf4E(wut z#6tWzEh~z(_&tcNn*bP%@f5b_P_htZVP1yh7OdsJ6#zNy3Gy$eM5Ly;5CB4DxHiYrMkXJW!qeOH=89Mi$`ROYU*s))Afb^ff?4RHan0oAx)7` zM-vTFhpV2zSQg%lR*sfM`M3UBL`sFQP(|(iB4COrzcNjJqgrT?B5gM9Y`!gF-Ve0V zth?<*%C+&ZH@`c-JE`pFPM2RDPn$l|FWHALKb44H!2=~4heOz%vZ2qNy5f7VokKFm zVnn;C4yZ^CQ?Ylhcg-&z^PpQsH-%x^mSQ#>JD@#w6-mEN`t+Ympgm0DIzLk4yF|Mg zUA`z(uTXCZN#B5*^amZHpE@ZQ*v`4qZ95^**Lm>J2fTC#d6j$=2R@=iXwItP0o$$0&v!fPc(3k6ePu4SGetD^vks}4}Mzi2jgJoZ^nc#WCp0vRF0#4jh7G;B& zpoK(O!C3ZOH<75-M(p*pqrO1as^&_%>@eB}9!yRNVwD}EAY+Vv1<+W(aHRzw zbK>RsO$|*Qx3dt=!Y>IT{^gbA9U3O78m_qFV=p?k(d= zrQu8<_$nglW}w>Murvi9hj<#ErCoMebtRK2Dad7GAY}RF%5E;{B_j{|H+t$T=Y39U ze}~og9#}<#8S0y9FYxp5J#_|y6@pkPbiX~*5K6#Fr)PGh34Us9#8d_buYTR9%oxZG z{Xjc0gEH)6S(wHkJ(|VDDFjf`>A(XfKT&zUg&I>tr9GTw4n9;re627oI}wu7KJd}$ ztT;Wi`iVG#xw^F8UEWYp=jW%Z#hve))qBz6J2wI=vF2ks5&gRzt9z$CE~B8#HL*k2 zAvHT+N%Tszg_j5@t;&Z4)$U@0RUnD&8+jb`t@oj=B9`KN5Nj5_shCy+5B0B{rf5KS zB7;GT+qrU*Qsr2H@v{C@GGn$rVzR;?R%k)3m_v}@uy9Jpy^d^X`hrg`r=lx7G1a*WIDQdozl@d3$2-5(82^<$ESx zPq4APYp>!(S?YP9m2V$b3c+` z)5rgiy3ZCvf>C?ZR&IM z2WlIc2F`mElD8Nfi2;%Xf-rP)$wFQZtpOM&$9aL6BelQ}4}#gqciEU=_2NBI-yrax zDx6D}>T+&)jCnus7z>7?TYNtk95JhxEn$;w8k1ysh`HGfpk6uQRN4|#A|59=`O?og zt@G4y^zgFjLNFUu3l|2rV+K)ZjKZxJ_GV=>eidOCmf7Ym;2wzt|d>W%7{OcrHZG{`O%3OIQlFa(2hF7lbkr3n2*yy)W4zd(w@ZbJ$Tp zHDet&Bz`+2i$5@J!zvcowxj@fttO*w`Xjnq0VU(#&0@_@*%`Ok(0FRH({?)cwy%|4 zHP~pSQY8~qnkA3DZWvNIp{TsX-A~6J`EoBe@S;X^(ItOg?fa>Wg|0mm*zoI$!nIQD zYOmwiCZ8}d>4{kp*8!-0m+7xmG90Q7kJir_pvc{Q*pLc+rn?~!o6cSoZMbi`ch`>x z_tyFCcyn+%G_~XhdDN5Ht`KE>sTZkd6;z)d2F!to>Bitm9al5nN8YM1&S=XS&(obG z)c(K+>;&<4E4ZOeQ8DW#2bq2npHw|aW%z=C3ysiV!RQhKwy!g0f@vgdBg+;xu9jTh z9}&B%4*Rlh5N8KBrgqYfjC}>Dv%V(Lfi<1$MBm(scFRh%%$<(6j+00$m|NElX*AF! zrg>Dyw1KLK;J9-tjp*uRi*5~3b)@vs4{@78M8d~pYDQvr>8Qp? ze%652jBsWy8iNzptse|yPrL^9o@aR+bgc2W6Nua%&Zaf=FAf|HbJsqzF@=P;gv_vi zqlK(uyo@=I``u5(*fzW;&e$)Q=tjk(1cH#BVgUlZv2j~Q4tI?xCX0TfYaql=m1Rl^ zHNd|Kab^s5bIjB^BtN;hx3Tjh7nN&B^S*^@ows;66d|hy6UHK%tbPNE2fz4m=_u8s zGZc;bR_ZkU-Az02bY6_*SPEMh7C%jkCvyb9&dRnEmruCE3F$7^%$}0q9XSnE00vGo zd6)CkFn>cTKe)XrOH#!#_vYrsLtYMG;*GYjHaW9Le!S-*VDkHuVCX7i%BsS3|G*67 znz5TlP`Fujr)bNm`&K@`Tk6%3m~CIMlSOjhbYrC1%C$}tj1l-*EzPljJ+SJI>^-SN zV|o=)%W)WdHALtaIM294SdG9l34zCrE3eWY%pAd{-wyL+#g zTCG>#g5|$F7TF7-!IN-$!#O`M^ZK@6>Htf0JoUiUqtN_j7q>_t8i9bE-?%-EuefV? z9DS)PiX?Z7kwW0iR)~EP%NQl+coEgzEo8Xko?c&E+I+1ys$sXFUr1BY4DB{TQv!F+ zwrbV?+6ncG+jDBS6yG<$Z-(WW?9o`Kc6|ni_G#lK1(P&&XSxt>BPD*r!DB3X#No;7 z#|>K{Y$2-}jXXf4O#11yv17OK@<$bkIzxeZ>^}R0P>%x!HQ!a})l+f~N2E^2-oxAT z!P|L;nsDy|}?A2UXdkOZLgm;~7c1OTuRf~zx0_Vjhm%9@G?>`|HcsPz+ zNYvScQfu!t>*X?WCC+iA@K@(DYhx^oFVdAms+#VZp^IvFdIQV?%s}^c0-&=y>3vI zDSfzV%Lu{g?@7X#yulY` zUT-6!V|_}yDNY^xM@;SU#}w*c&tJhiN@10Wr04HFK^HVf%r1nIMlR{+By{ZBYvVF# zt%-Hc+$LtoCWpGw$$rtvKDhL6xb(P9^TKOa`mH*8J@OYR zOc0js_IDfbbVz_X0K@i03-MsWW975HY44{f%`4faE39Ik+*)xefKPvlsS8T(w8FB$ z#)(fqj;TFJ-z#wsiFr{)-edoc*vZm@-i0*PLM>e^g$*=Dw{WdRV=|Pr;}0W8eda=c z?!tfWf_;9cuzYO4d`z@#L45AQe150DY$1H^BHZsvB9+VR4_xAX)dNN``eFUXv@}$l z@4Dy$!^jUj#6|woDK%FdByS$6*;L0dia%rv7|a$joYWDBr0%n+Dfd+gXpLrYtLt25 zRjnIe_;(cLyy{wR12}Aj!qv_Q`{;y6?thY&3TOiLG=yrd==5=wV)h&9a;e^p${Sgy z#d^9LW!wv+c^eqB=mZO0BPEV-r|2K|!C3?3MyooI0ZWXhlTScXp|~9rQ=u7hlQpL% z`LipPtZsZt|2R%&bQ>VCgiY7VuOx6BbcJ)A(7z?mU1Wsx z(-rP~K&M52C1zoXL1YU8{2TmK0v*nsGJ9!{@XA~a6 z$e!vXEikjB=7=#0&Zyjx;hkz}EA>bScLnR;^HJY&w@&!ObI)(AD*W2j^v2#Pd2$r~ zfE6x6zM=2~8qTY{hjyH-oT9&{$AT1sWHILC%?bmZ=g1CAlEhtGPExTUpof zi7=`xEU9wJ{ZLnC{C(}P+<+5D#h(c->vuXdHkMTg4Iy{nev~=Rcz|d4xaXzCSV2 z+BeEjm}NH7I^h(J4W7mFgs$#_XiawO->abPK4}m{U!`aghud(_WZc}fF1ndy4X^LE zMAdqvyDMABl^j%sS>jW-zB<^URK+AXV3eYLvyEC=4zg@nlCIr=w0^8KYOyH7G13JX zPnjD}*#o8kfGI1$lo?eal=x|F#st|JDmBaSlO%P0f-d0hjz_f!hAF^pcgfL4edsLKhq;naS|wfy|GE|t*{1js1WhZn0{X(?cY7rPu)YMM9TeV<`(e#3RAWDIxH%bls|NT=E6i?Uo*e8AbF^6N z`%$xtcQlBEIc$O2itG<|&K4lbmVw_CcB&PVssGmVk6uPKBtPj-NH8!=1TZl1|KVl) z&B~yVvUC0Gv%0sKgZ-aAy8gxf+Dfsp#n8YQ`Es#HwX!HR)3uVbqs64RH)IHgELOgZ zs&CRI>cEnd;OFOWRBLW9bBDu-4@` zB_;L04LY7y?2t%VoiT0r^Xcri`)CHo$R#1^(cYqrO4iyO0xo{_W@qr(~O72ydaP3{Ngz0&o5j zX^Ese@vDWSir zZJ+=*TY2GuIM5y?6x*BrlPv0_ZCCgX>EQcYbVy=U|YPq-Kw5B3^wBQQhuloou-Wip9>HF)zV0T&81CCE-K+dJPz ziLPu)`6NE9u7I5GB&KF(Zvue|&gmLU1NvzrU_8=lmL|py%T;DBAOZ#66tr$*9|xFk zm*+&?Ji%!|J+ah0*2cK3!BbQ7E;YMZ9LgwOh?R1uG{;=POEZaF^DyQ@9>3fHP@s`6 zv;kEzO7Hj&+NsrDXmALr(B7?Y`Ay{qNa$V-z(u74mE@>~r4&}kMyPDNq`1Q_0N^jc zrDZ9%1uFYCqQpsA@&$t=VZv@oS42H$a4=C7aS6bJC_rA@Y%L+`FEOF(o` znXCBMaMWxco$`r>tOBh}h2vJw-t6UMnn=|Q{YxRAo}0wP?lD9wJkrY=Ig&~d)G@)5 z%*0jlh4CJ@o72AAH*cFcJEyevHKV7PtzE{YS~Ry*F}j*QrL}oIi~JD@=<1{{IIe|h ziy!f8q)BxHWu{WfLpg)8j~E%N3n#`iM({pZ(5rVm;|9Gh7ZL;}%zHdOxWDSO9D}+d zmDX&Y69~l^hwcJ3k_)EiPOwwgp*Y%YR}x|zW`;7OE-_@^cz0xy%-X7@P=7k0t+a%n zZwx;0I0?$=?T}WNhTCMc=1^6u4L&e9`Q^6ekXIi^oI?*ji0!}5A*L~j&6<@bGUhU9 z*)x?a9J}Sa7)-24S5H(`+>RF~baK#*7c*Q4CB?tO_I*Yh1t`|`kgOV_Uev%oN(6r( z_H~Qb_K>gcpkENfJjVUujXL;)z3=mf(U)Y{vxn~l)9+gDkg03L+<`p=9%j40BM@5n z=OL12;RiU7kL;vDe4SgiBl$=5?AmVQ#YK6lv`O7#XGtDnU_GSzP^ni6=!7sYe*7M+tF6K%St%qhfumGGUoWGdRiK1bzIlhNb^3`aQiW98iq@XfGgc z$7&UIs`RWmU-5J6sPCVk01ad4ND3AV%oyYUf&wL5)Bg+wmzq9~NlTbt*_m4(?mZvh zNNaPq4^(*Voo7py90(yL& z4%SR+z_bIO^vWbFBJuQoiQ;SiWC*4c)vhW4w<-DsMY}9J$27!;N!Y3~en|uF{Gu!@$?iIyA>*wN(X>F-hcNWSVsYBPmqjUW@A_BzT); zXSl48F!GOPIwAv~_|3L2RWFnsqaxvKHLiIvT})k}-RW92hV-l&0jZ1jYEJxD%GX|) z@J^+{%rwtzeW0@#DvN3I=ZxQB1qs;8xg^{BH9+F7QJ^w732xl6r0$>0O7Aum1knXLPZ-iYqO`_{{P&>LX0_$>Isa?xs{1tj~59EvUtOwPS_k;u9e& z>fcg-{KT6gd1Cg}baneC_rtqw-$V{$2RQo%+RN;}(Q=Ltsl{B3a4;=q#f!_9g@3kG zAA6cn{uGcS*BHTZghgYFnM}0X>jIi3w?>MvgOIlRxjKS3PJi|2FD2fD zJ8E^t161BA&((YEf;D@{f|YwP=(gS{JIl^8(Kj-8O}IO$`$Y74LvF-*>FcKSMhW{! zUm0ZV2nR8}R0m>s%l3GU=5Ikpb9EnTU1PX9BUajQGT$G|i`E`yoj*8@qIFj8G5aeI zY&3-3On`#^7~rqtQ=V=&k!H;sMSj0#uP$Z9(NF&laalfdl@O&g<Sr=C;<`~6z@ofbWN}<~oRoj~w{CN>L7b@i~fl-}3L!`~c`9oj- z=aa`frdNhG(;gb9q@S-o4i?oMp5iAr8m3+C&@b5s`fgH7x1(z~ER2gU7k-FI{z>(M zKqLOL-Z=u3Fb9HH7H^nu?9-4izqs3}_aF9NFI~>h&yp{6)dbTQBtw>D=51{(MitE+ z0t>hF-D1)yHeNQ{WBSTeW~p!F2Q9j_+Y&pkq74~$%Z(>IunJ*xJhh|R^=ixQYFa8x ziTD8cC+5lX%a5!&CDN3g@ymFOA!vnYiq%!xE+rQ5Kbfn<(bj0V5XAVrQg6&YTZ&dl z@*H%ABzxIaHW(X-kI@l@!pa`Q@JK0BKL$H@I+@_kX8v)xCT_EL=>0>D0!v42aSa&l zwp*>2X=qOY%5oZ*=*u14 z9X>8}?QLUC`m?mkBR7paGn#&s71H7LGR;#j7iW zEX^g(P3BbbS^Twzulq$dxu~?eo6|`$CDikFd=6=i$z5EYwNuCSCYYwOhSK=h?Y=VZ*B)iL6Xxam-3{0Ag*6a=88OXF{=!z;IBdEU z1h>t}qF3UL7f%&e>Bl}+6^kyr!&$rEENkH#*Enw{Zze^YU+JPrChgO~DRSYmU5T*| zKGPJc3CP%2eFhhOlhr75k#!>Gz-U+)Qi^Y9)vpGch*UvFbbW1@s_fKm7<2I^6e<&n zi}l-?!0>1{2WyMiCkuyv1nJW&wa!_#e`%Q|YeApq=9dsSwP+7lT44FXw-sy$Z6T)P7@yvw z;>9zNFDcLx&Hc%OI9(JRNs~L^&g&}O_f~n*#vS1W8>C%u_j~u9{14AL04S>n`KA{K z^v2A2XJ$9>kA1&BhWcTI`jLmeQ6M}I0Iq)lu15$r<2j)DCe9*byTZM@!lS!^(R~4t zeZK&qZ@LK24}fa|!cA$yO&f$~%+NPUgl9Xz6%ODe8E~x*xLyEUdl7ElfS^I+yYEDP zfqlF0PeEv#inmsMhE17$)psod!iLU`#jc3~lb^k03Iv4F3jD6Lzi6NM9|8;K;$=%Bn1w<6M*N{$?)b{He86LJ>RQx(8;V;J)i4nxfp4 zfd+*}yBzdPPgS8B{9%huj-E!aNjzmP7Yw?>H}cg`C@ml2+7?C;vl|&Ov*5?9>d~Y{>dn!eOOi}9_vaVxCIR3pacY1`c;Ectd&k}V;?#0p)9L&z*KT(fRvPAaNUEQTW z1S_oL`$zSZe$y;QGoCcicYsbr1i}8ZQ3KmbG;IF?2Id_W21fM%H){XcrN#Y)Dj|w1 z1gqb&t5?_360Nlk-cmatJ|Kyc4dtTvL$&EasM7$bQasIYlZbf1xD>;7KUAcb+@cdU ztT!5YZE||5?PS|cg`wr!^D?P z5^S(B%CBg<2JWq6m#UdsXt{8BUY|^j^E)4=IP-zbnm1=5NgU^viG)|#wF@#p;J5QI zI^}WHOUnj9u;prAy%?FHFHQ!pLrkG9M;D>iE=oLOznJS)y|z!-P~-DKx(d%i^E9evuEU}<$tLdG z)7@C8l-TkgK#zY2UmxSCTgNc(CgygW6_Ms?z(aL*PQFCzXKIfLOL1llx8MIRDE5rs zLf@*omJK1Wb# zHrZqSXYs&voUrAf!oU;|{_nn~f9+i<)j>AMJ|gW#zC*=4uvGsBOac)=z+d6h-& zw(rws@(!_59yh;LpM2INQa-R_`h5ZD?%T}<j2x=0ExTJK9yCUOivZ1<$VGR4d`Hy1A^DJ~{U zFmRm;V)7`aY$Cxm`{`sB%!!>l?yjUycX@}fn3dZd=oH6#Sss@a_VctGp;kLiLTqm+ z(|sA$+{DlL>=cA4$-!~*fhxbj~e4~`i2fu zT~lb+_^3uWY;7IHSu&ZYdmLiDo!jJ((mV+u>9U0(E>CG8RSy|7sSCrcn!IsT_*g}X ze1?RTV+;r>mH02))vGg%SvmAMU$17rh~_rW^d4#sz3;wDdlmUPOncfNxEj@$5BBpN zwK8Tb9RcClLaNG}GwxmJ>2^N~GuQbGqz=^o&@rINmn+v_ORq%T$+E}u0eddlyrJi# zDCrt$#U9uFzS@@>E9!HMMNXd&wzDV5E6TLyeEzRzuHFt>uI^%z>BT~nR|Phl>rz5H z>-N-2YK{8*Z(fk?Q_j}G^eCEmo2D33SL z&$7gt;20UV@}zb@I5{gy&u7dw<{~K`RXF#E09)t|dFhA=H3G_^;JOW}A-}}{H(OlV zOop7f?hV>$u!-|6YEp+dm1%AJ+)R8suXsYO$qxPL$P-G-z8HMZ&#5qUHbRiutygFDF8ND&SP=aS z&$j95+^3pHcAKbF&Ya# z9b6j{@RAS`Z_*Po;oKGye;_Bzq#h=&!O%|+!L2vYU|ju*p+Y@#O$Nunf$7>{vR^hk zt3sDiQvF+GJm&M-a9vNUsd<5yhr`Xdhey?Pjec{PmwaQk+z3ST1L|+T{!$g?lDKQs zb!$P z*{q=YJpT(p=nv1QY;zmG`VO0f)`muZ6{~uL23%(r!kLKQk%Q7H)S$e zeF~1TmXn|-ig^XB1zV=2#h@dNWPXqM@|POQ2h`_BKT2D9-bn~*r)lbSg`bznc($$c zq}tHpI?t1?E9vSU2AqLt^@%f1{&=&it*#qJ5-k*GkN6#d<7$@OaALg^x%QH zQEm~|H4Y!>m*jbwAPKK%N0%?Ogp^iU#S}b4kY1E8jPDB^+47M5JR=;#gz!o8Ae&!` zpE_bw2K`v9j?Nva@_92;g>KU_x~aS$wk= z(70{BqYNnV3?6PXV6kE9`^2eqACPd|bt*q8L|0NzZqy$TMjDd&{)gh+Hwuf=&LZ`r3`;&-IlYv)A#zC)59b2e!X3~M|^vKu{Z4$F;0STsdl zPOjpy9-%unvk%S@lqxG$S%8p-v-ZlES)7^bMePDCV*h0ed)LfXy9Gy^$wc z$PwY69RP&CnlR%v+qkFo$qhu6e_J-+f=}j^!x8v(oQnQE*Q|nze*&EGKo|X;T&gM} zz8Jb}y|OGn%-&k-Ilso9vYaWW;AsZ1_>yQ0o?r0^zP15A2n^R5rfXkUaoJFkNru-h z`(vZB1OiY|@rUYG9otFMLOz+X;V~_h9q8bP78fMZT4pOuGdSNnrnY?6XJ@)Gv0&F& zsb9v6Xz1p6V6WdfepvGl?F27s|FEuHHUNV_W{Od=9N^LjJwn6M!WR2s?GcyoJB|Zy z^aHD*I|JWvF7?eu_h|AGZ2Idcu4a6iW_@r4=>TQ_Q5d4Njauh1f`gKv-P&jVNj)=T z=BWBx6!|gB!EvV8QG0Z%HP0$Vz7J!(2*rh3m0wMBUyX1z8aZZ!0d`!v8Y_Kz=XP#6 z$$jATtF`Yyf#h0|EN{nnGk8%Rq4t;rk?z6~-$jdS`l zyb&?X|9~-nGB2)2w;8qx-hi`ER$|9Z5~CcrMQ6fE38xNV?(X&r39%T*9$RIm=nNRn zMUHk#Zjr-@{{HNo9~McM-`l2webHG`9{Mn7gBz35TT)9YM9Wl=sPHA#NKwlMZ~|O< zcOFbPDNB4XW;h_rbrFvHsZG6hF|`Eyau%AYGdv0L2A#9qnDUnu+zMi|18SGuA5jiaUM zVouq{GuMx|CID4${UyfAZj1kK43#kSagEp3*qJBmZZ9ty_nc;WIo8Oz@vepZNwhjf!xSpgGb_=loD{&dXbdmcp@tL$uPu#0%|bc26PSBZ@ao{8EPWZ z+(OWG?p{XlRL0SDrfIc^;=#|{wUGHvQ@(Iw{{b%h>(pfTNsiZyPyUJEjod2r%0QlvpWKKEJLPzI3Gbw=! zRFZr^ok&Z}ZB&O12%uF83w%*nBlUB^5y znWwcIZxA)~MSWoJFf!za^)}OLmW{GqTTw-5Spf|n-q-t7*DXcOf`ad{ro`VnN@kaY zs(W#!tinQup{CJM`~G@5vdp=~<-$&^tdXjWA|i!TZvNjcc5b)sI>n*SS~S(qeAy9+Es z3}dOS*w2^K3@GDfDa$C}!3JvgMn~l6OlWeIj6L)sNNlkEK+`UCRk2Zug@7YhJok{F zLfOGJBy1+XuF>vzZ2?fTQlhD=-9^Ct)ms74JQ7LR)|IV5! zFf`-9x+i>azu%afep?^-;sxuFE!btRU!Pwc(z@!k2Qz}`Vr}-5`=`Cn-7F5cHn+OJ zh31hlg?1Wom(8L2z~0o|i20J-qX0K>p|=B)AAGn^fv`bSC|>=J2NmlRx(d$v?9hvI zi*Wv-TNBDd#r-+Zn4id}N4yfW53^0bP=DrDFGS*tFhk`YvAQfMeudK6Ffu|?QkmV+ z7NY0r&ss2U$^1gq5*`xtM?rt(oLn+b&dO4>z6l3TH!4J#cfzxLie2_LJ17RHFDWwO z1b`o^0ZQ=h-t9eDq2?Pp;Z;h3Cp2Z`sN;AMIv4B1b9JswP@O?J=h3~SM8`ayL^?E% zL8#dXen5xi!QH`URswOA?&`iKU46{t>>Om_t|71n$SN9CSsRGL`YD$3JY6`Q=kh4l z7AxaCF+4$sH;rlU(GYXNt<8?XB9atxw>z%621J^}M4oT*mw@V`Hu_tj0FAF!{e$gH z{`?FrW+&h2k3aOOIOBED_%46-`;fPDG3>V~z4?b3wf9a@N1mERx zYfT(^qvIw8d`xA1Wj`f+$4SCt-xG?1(F=xyDSz04McFH80jJOtoAAEL*Qj^pT-Prw zt$a10`G8(;%YQkq_-a$x+S9+9jK@kwd1R(m)+7Ju{*OoZ2_wgL<9Bfb{TR=ToXJC9 zBT$Gvm`cZsse`!2S&_N}Q@V?VE?~OeF#b6o@}kM;`Sbw>hU>o|0ezhRiOLkGrvI1t z@Erjk9}}fovI9xaL35qPRkm|ZYM^?IMkgCymI)&no(Afn>#QU5A}P$1mGQD$74=*8 zV6B;JZgJ3uH~r=^=O)|j`$qhXF-%H5jyO^qo#Vb1E(*8irk2YW(dw>iPW>q=gfb55 za~!MVtgjnfS8Yi1Q)m%FM)?Zq^Tb^)K5aVwlg4sxCa6Zu4vyZZu_R!cLooo~fZoNT zK?eMWyHt1!BePZ03}#i=ygu4?g=ZF)J$o3xRP#3VG)_D$U=Mbpe$xuj_fsidv{E@D zgkr4$=)y_<9DbP*kd0aD#3vqc^13`opvp`79WlJH31199@QgnVY%9lZ-%-Xm-0$-2 zVR*CT`(&j5JQFpNP;kF{h3a&<)lBQghxsK&~;fzD7? zw4ckSwD4EL8n#20#1&m7$+$z*u>wQ2o(c<$(xIvcELM^IA==dW1-UZ{5l46Hmr`uS zij^vMIKjrZ-{K}Z6um%H?a_#{=@HHeG7mNGGbf}ubX;pB@lrzxI@FKRvCp{CT!UlA zyU63(2|shocdHXPBeYig2qw%;N@>(Of` z>4EfXN}3k62f4U%k=%Ev&f)v6GnJ1$##LAe(Tj%RWDiJ}(V}wpz!N&V{7VN&{?bZA z5h%A-=&SZ3t}>`4sHF&F`@_sVQmmJtWNP70fM`LdB}q&JvTCGzX$!v_7D)%mAVid4&)~MA%OfVFAS;3dt-b zMW_T{im2y*w|N6x62HpUYCfoO+k}CK^JFe)Myp*Z4>HRnm+qlKa;!3rXW#* zuM3C=(ORIrt$TVayFs^|xzfGbj%rqHxk|rjq)1H(bcCpe^j~SuH03E%x6g40jMqm9 zIj{RKV0z!DNNW$K>_a1?knj&iP3XTer5!-y1YEv-Bp4wC10HB^?a3a!Et+o5)U#<& zvcDFlA&@qEYftSMGYaZ3euHc*(J(ivn2hEHU;|E&XWKWAlr-HC4T&p?=q%RTE1$L+ zgzDTyYy5Zbg|DVjfAusRsl}R#s!Ely+HdRys=D-OILz13NN+!~EEGRjwJ}Z2BYvG% zMgdDrCVsQYp_;;^75F3E>k0e&Ob<*Hr$cChY=c?}(V5D3#MQ*-PvtTZ@N_*C7uYOs zl^lV#AK#vIw)Goob|LxC#1srjf{LVI$5(+5ec&VwHeLIKqzI$PPF5Y@MyCmr!*?3d9 z&wBR0|A!pC`p*i!fW1IJQi6dg82gX#WKCytQ+HFay@i^En}@x-x`q4SB;1vY=#Q(p z@_QyXb88KxpHvr&DaJ|>Mk&XR`w3Zwt}u+UAS{6iQ#KekD>@Quho;6S}WU z!jz~J`VZ$>Z9Kcz)%Z{|-qV@BdLVG54+b5<^%z#ST9nL(?E||$*csg`-b} zVC+o9!xoOltAy}ZlQDz%9NH5%wxk0o7fAApJtrbOFm}&`3GslJa7L5@5r;Qpw2vB{ z#!Y3g4|m#v0davhW4dn)IJs*=Lz{V2=yj<6a;YJlJ!LfnoZOqh7S5iCk|!Pfjg0+O z{O3-eIHKXcJc9nPO@EFrS^m^XBfP)XxYd!rCviUWVIzug)nOxpaMf|6q<>4sjP1*} zw3+jlZ+SCm&S&zPK13r-CmDE-ukNpaZb9`_ZOFYYnI2v3{ixMMmF6ojo!X_y?e(2l zSRkHbw#rA?*r;Hf;C@Kb-=&_xc)#%IzSQ4^h_*8)l#v&j6k4V6YKu{wRI7SqC)A|Z zJxyiIx>GRz=ed;8h?k@JT=vVQrKZtMVGL$m1{%xtJ@d(9Z{e+N)_3~i59y1!W@PTNLa#3g3{I}H zYyR!JslShse%zl8Kstv$J)JC6LpFDl5N^-7HMg&m5FXAnS!|HV$yJY}4U-(d2xz>r zr*noVvwF$C`ulHwIvaitW4LjbZQnC29PcnlaZ56V9_j`NfJ3W!QA;Jkt$-*o9}ZtbHvKqmk#`e z7ZWtq$K(G>jv+MV^HckMSzP|`M)3am9s>y2pCIQOQ}%zh!Vrpbe?*zad`8U=s2cC_ zJtc2rM(lBUyaE2~OAqor>N)%c{5hpZrg9VnErDe@Q_~ba#d3VbM4}rE-u+{>RwAED zLe&0l?^y77a11ODA{lxo&>Hx{d)uh<$C(fyb){T`G(c7Dr3ep^0$oi=&aO00T2_7C zH^sd)S9(lk-7f`QPFm}PTWLNjbQe zD}iO=oiC16Gg&QXEY>XTWmZxht{B&0wO}~dtxUc1??{-Tan{0lwZ}$G=A+v;K|xe+ z`)T9Pog13Wm(kb2p=*zC=Ye9JH*VFq_nrz)2bv3=^e!=e0#0hCs%g^W;L=ssFjUu8 zB5S9z5U~NbvMT_{*XeA-ITN?DCf@bm9JtvXRNx1TvVwPl`|P&)u56LS@9Ug zL~-p&e&X5#RiWhFL)M)Yb15z=jWx8e$LMs7H1Unnv<+3WTMJ5T0}108rx;Akm*m|p zPNq;-kmNEgDhz_*0%#|N&{Lu&h^fy{4kMfm`c%6bT4v@qiE&5G92Cq=U!ThDrD#& zG1$d|SP$kD|436~raD(m2tpG(j6?)DzZhry@wK9oURSuLQ){G`-mRM65AQ^iRnJIW zI7rmc<#*sO1U!-}HNm2yB5%;hGJf&i0GE8f#n34^ev70B*KYq+sz9@eL7>ZfBt4ZO zN`t#XrXXef8-lWBj`&2?_(cS2*1A2FJ-^|YLDd!k?qd#(%vcqRcww;1k>+0ikMXv> zEczUPZJdD?vC&{IHU1T)*^=K=ms8&YFc}PayUkTgg!drpKeBGa zBu$|>e96hYa*PnW0m2v!i##&KWJe(p10G0cS&Jis9<%aIGW@39<6E7xL$@TUXl14l zNr!iF)@|-7K!(4oqzq*W5LWF#PaDT^^O2ta3kDutrH#Tjjqr2|FJqrSKPrqo6m?c) zZj7jom%{CaQ*TrCjO>O5ChX$qZVc>Py=2Y6BZ5>)m9wn5vktCLYVLbUZOs)Hq)7Cc z@Cv<}I5nU14MPZ5in4B#?$3R#asT+oKdd{WoKnk>*`U|p`0E86VNNDIj(2z{arv&S zs1NH34;wV0BpqpK7k{@-f(kKOf!`Ttf#_j#Ra#(2DY+AuT zT9n~P%Z@P5er%lxYO4>apPF#p;VZZ17KvhH)1 zEiK@lTRd6{K!xBhtq^%7aPcc(j+JYrruX*|&Oy{{2-O^YG-apmWmqOhEH#i33d~FT z3c@48B&FfhzYQs)r>BJ5soaONl}wgdgOw6=P42F5F~qTPD;P8_$&m**sMiWUGJqKf zk-=lGIX(iceOH19+^yxpbvlfF&rdScr;ZDt+7e0wO)WJJ>YBvV^W&1GY?4sTMr>j< zM~$HKLzm@q?eL2qlqd-|gZs1AZJj@|^sd9I%|1$Y)fAhv}5Gtv6kS+)>4p#S)6lH6h9OpE8$pFV|gK zFXHm{J(kTYXCg-_MiBjZpL&^&GKt|c&~K1$faqRIVlsQ;80)-WmtxT!*}PMIc|Lph z*(1j=RY0hXW-@Jj29~mJycFcB%qkD$W4oQ=JuW3UZwU6Bh@zrVBqhq9j+Abfo^k}a zrr3-vr;+lZ(35cpz#hNfT@BUCxP8r>h&)4fC1NL~*UA!d+zi`%G2q3w@g#;rd3cnl zhkLXxS+_V(W~1epN-i5A)ns!t_gC`eRJ&qVpJKF{xn6k_b1?KM6~;sv7jS)@=&bjm-Vh!sR^$3Y@2%8!m3mvLgF?e7xwF@+KWQ#43yNHG- z?(s`1lU~>x4#yT2FmYoDxklP(ClBWe2Ih<{@o$JSMRr9JMc031ceBO2lZhj`8)RCN z!L5~`OX{B6i#H9{y1N5bXI7D`S0yxas?!HRtnmr{kU%VJm0RO1<|M&NTB_(1N=+*V z!d^odZ^8fd?VzN_Uk``p)uMx)X8Ylfl0xN` z<7%3^WegM9TAKM9iWOf*Va*5safSS1@1f3}ze zhJaaL5*8(+!gZw!^2=)?TNFICUGo*+%GY-ZaN#!A{Q8XE9qnN_H}(LuYR)dh_?1&x?IT^%DT(xc3tV%nCmt~a|;bUKfj>P#jQF-v`7jmTU}S28Ep zh%Mq+Q+IuW?Z`A1a;CU3$wuTDi?}(_M(ij{e~(PI5uMM`!AK{vO}G&wWn{KFIrr@ZN}KH2?0$0EST+6#*8Lp z#+gDUZF5c+L))0rS%*1uQWrzpoYPsY#hlf}Bs3>=mVT&D>srM$GG=v_mNVvcF)gQ0 z>#X_k#4a`;%++v#2Iy19O z7orohHVG$Yw)*obGTAoQ!6K3q*nC8E6tu-g2h4~y80$vc?88_#aw200v1}!$7#kMh znyQit9_Gq)og4kXu@zjaZ#GS+vU>k$5+l+`64}tzljvh@&E&@2V}GqaNi;4;)LDF+ z)$PoJM^eT0hHla1I$)OZ&yUHZRe5dn+8hlzI&G1$`yJKUvM(2ky@wf88EOy=FAJB} z*M%+hY{k>v`bq;@__oP zcxy9hUUelOiozB1%*6c??w~gHkU-zLYGr0tR6lodeYj@1nUfn$SYYndE1CKL?u#z- z3rl!lYZaM8**CJg8nYMkQA~b4M@Ki2N0(HURp@huo|*RDxpLDuO>J!tbCRRGjuv3u zV=}N+*0KjHcf+b>XlaGHgYGG+uCFN#kJ7t+YrTDJ8{&PqN}AX#c4*>magQeMezW+#uF!VjYSUH*#YswXz%ZDuck@!qgu2inl#OLA*P5ejvmth0V zm*Oi;xrPh+T707^*DBX(%Js?(n)p_HrzvZdb(;8I{Gcf}DmQ83N6Dj!UzD2>h+j2j zy|O_Qzl%RK%jG|9nA z`R(&QP1&Su)+AMOVepC@=2`GxEa=sw5mK%ujgiJ`(nM*JCJmO3x0lQFE5`CLdUT>$ z2;0vMhQzzNBJabxmcs4DnI#p(&3kk84tf)E<5@cE+hm9i>io7{&}!le$PM`=>Ngj**`qwTF|Oq{H_>pNYVR4mPjv9q|8`lLvciliy3 z0>j#=?9!y^(#fh)#}~UbX_j<~CXJU0BUTvQ=|IjgJ1LqJmgZ^F)6!l|S}HB%pu%37 zKEP|z9_cAfx=mW7NoPnuXi}|owk9p%V5ziIQ=U}zXwtb7JlIoWx2n`@%F_xQ(>~=H zRav4b&nnMp(lY6LYhRsUF_V?b^Q!WKro5=U#6mA~A@J0%D6eYDYs%}K^%_-Ksww|g z-rxjps>(9X^)0@5n^UjWly^{~v{sj<$&q+HkBQAFMEOqn zUQ>Qhe$e=0{J?LKCm!F0uDDNO}_|WGaehl)CfFp=Nx=(W?aR$kb6ixQB zSSv?JbEI-5T4QK;v~i?qaw|EciH$t#xldrw?3O^k_<5Y5jtSD`meg94v>R1ZUOb|H zesTYS#r+279CLimF$0Px=1(c^-|v`XBK=;slPL>os+StC5Tqn{ey=*(!iZY_v>9V= zqWvd+u_o6#U9;>Hbx2UH{9MeJaZ;`n779Q3?(Y6-OIP4<~~=M>f{g7NsYRiwvTJGwQQG2BFFLDOr>>%#gANO`sj79iFD+cqj1XSVRlHDN4p za>Mh>t88y~B(fRSdoJw8bQQ^^P^~Upw7A0J%|~Q5b1@V1KqQ(4Ryo0W<@|1y{=&)> z$b~I$i`Z?DAIs`5t&|;Z&0%TRroD>oy&8DNs_MG(dCT)SbK^C*t_eiPRnND-aL3yO zx<1yZZi$v>c`?a&s~s%NZWMjzD(3ANV>h5MysR#okoOpD5p6OPit1Y?wfb0~zoW=2 zPs^@Kqaq0xv)Wu^8`~6h&&7CTp39m1YDiJD8$Q9lYm=tnDmUM#M3EKMQO!~07=ARt z+ue;(qfo&zeXqMQE+0)fH|kEz_%;!1ihmtK$?VAv$IZJHX6hvCBNBaU8~5wrhZ5a4 zUoG(0Mf{YRC^a@w!AXqzN|0(yG+{6wee(wjeS0`vrBe zKKp9o%@r`SrfTxd5sdanN@r~~B~yRwlJI%hv}TlPnn|N;j+^V6+f2GoHlBvHP2{^K zjhl)xjQ1}h+nPr5u7-P_T2))WXi+skBpZe6`kEMrotD{j?`xfzsPt939H+n~mi!$589yHsgtr>NmrM^tV@9Lr2= zFTimrkEDWBTpLf?rZ(55HQImU+Uqb*&EIG<<%m;i0Q3VR30P^AinC~fg zjRb{}SE~}d%8*=}@J%rb7Gnl6L@zimszRQ@0Ce&=hDRCOBYe4}tSqJjM7%k_G+7>< zendT=ZCb*`EhwoiG~Vl+R}&8NBWmF0InjiKySE8mZ*R`Nr(O*wy5M|9oz$pq^uesU zgq_TUd93S9s}C_#46%uEFPk5(F<%0Ti?_G0@szd^cQkT{ZSiG3w{4X<%9>7(9b#L{ zMIPmbGV`q|jc6nd>7$A6$EQ?}!F_IexO5lWl+lt-UgA`t?K&8Z9OuEz1u2idb=8q4 z+upkB=n~X;Mqs$6{PNmG6(!4!{?|K^J3LJOYI$v;@xUxlS+dZ4=4wu~OIp_XY!7(j zwV0XU)m)Tsu4E506-prGu5Fwq9_BA9tbc>xE-5Vy*Va~ZQ?#FzNM?kYfW2;&{@(e7 zdHLaaO1F{-*I(ZX>^!hRT^ zGVzo#74v#nU{Pvz1Nvz0&{#Zs}1h&odnv0SVmAx_u-Ugiv3 zpJ};XiR-g0*Q;=Sw(XkuX_WpaCg+MZ`tdw*zJ9zwT&N!}5*O=fFM%8%FEx*siOcol z73T3u^LUlGT0dSRuGNp%iR<;_4Pvc+T&L$R@slk5c$1!ATXC~Z@3vyS<$43IZ?Rn8 zitF1f*SF*Pju`nnW909$$$NM^Nw44C;vW5YuYPRHJ4`sHi3f0uq<;|C4?*9^^(NW} ziOu3)IDZ&1Gs!{xXUE;MwvosZTS?+T&gzw&5mL61lHEX#tOjyU&r-IMx>^5IxGj47 zxe!*9;(3_do-O33#nhVWD4pu5BQ2$Fv>f^9e;p^BdWj8YiIdF|J2z3HQJQQktv#s- zS6ND1jndAccC>~%(fO8=B!1j!mh>Y@gtBR6ue}t=-b>z)k|h7Qfm)*oS1^A&xpN$8 zjt25fPjl?d>a~l!TS(hVzO3x6%8ATPeuuC2^3#fv= zHBRH8ZI-l^()nIHzRcLHbLU!2qY%O?DM(j?(>2iiTIxzSP+wY0$I&`Eo^GV!bQ9&# z%`}?U(|FndTDQ=2x|L3$+o+6gr*gW3s_0ItrMqYuZKN~l9`T4?dnuS=BmSt^VRE--GIp>&2DtwG;9Fy}+`C0(((k9CQ{PB5B>0w2js2PHuz`plKeW zB-%u&w3*t_7CM%;(JbNIQnLc zdlClH(NN99hX(3|L$Yy|+yDdGLMg^oigA@>TqPM-sEfvjN2m*yirc7b*1xD5H?QF4 z72LdfBSp@R+{V53Y$VtCUVE}ZL81VfjLRT@aIfza!q^KTkUZ=jLiq*?Sf71O&kkKUt&^gb=3573o9q!siLokbth zx%3HLNT1SW^cl?ObC}H+FpaP1Uiw-moJua&0cxX)$9+Cu;14QL#S{BUu_3=n>@-c{ zY3Q%uI3QC3;xLHI3Fe@|ZefwJirNc@h}e<9@|8VxnZ z3oI^#Q?Fxy90w>HRg`7-MAXk_@4LiqoN?va@+TCy5as@;2XS(YXoagM#U2yFY}4*i zBM@}M&+N5llitR-tD>(aAw?3k(vODPewGsHq>2nm5*>8al1Usw5=j+LK|d09?F7H5 zV3xYfEVZwJvFA7(v-Xjr*Csw;kZ@OCK8)XZ=+|s?yKKI(DO$YldPO&Ki5?UXnNXn@ zrHbB^A^K1^(T}pku_i6~041qn-vLq(`fd6=6ZHuF}<<$P}8M9-;C0a zX=drCp!C@&y%?pJG^_L%no)ZHW|lq=r7u9~9UTJ3U9N5g>c?FcY3d&p!Wv)f< zyuMkz^VMc*F{qhZ+ypJwLyHa2;#O#Jd$Y874THmxEOl@*E%k0_a4$5t50?5svn=&> z@o%&A1?IS$u9rUk$w>Xv8|e7#J@*%8^YF>VhfrOva+-d$7XL34zXioNz#g{i#iwxb zsU)L#k+A$XqUA3#%kK~=-_i!qA;+de8my2lF+)FE8{u*2uoF7$LL)qhmB&+!dbB-^ z9&a|&7KSv_7M_I~&qIwDpvFtEg;$zo3vY?HO)b8J4!jhZVWA-kvz*&#C{Bm1!)&mD zhOb3GPTxi+ti}Ak_dZgUjikui=tPbjQMeJaMU@4Zpfaa{atnKB@7a{2Wba8+j0#M` zq=(l%)AXZJfj*ePm{%udc_8j z^B>AYomBD8XjQy>h%05nMikfhUEvKJLamx^gZEIFG3{=Lbi6z|?FhB+Z`M9buW*i% zm8MuIq$zvJm!@zY4U`v;Bj3Q`01k(NV=k4V)KZ$S9}OHim}ijq4LJS)jz588KX4oX zjziQ}5;RPbDOXZxoaCShl8dHD9x9f6R4N5@G!sdUp!whsCT)%=mJgVWFlog^>%jI? zl5_-SA4d9*NH&?xvoMo~$203=GV9(XGk2QOKqH68@ftNe1D(*yYc|#egny;_(ZWk= zMXHoaUa2+tq%=yF(kWAF4_+O?t220Yq0v%T8Y}gniBeCRC1rzIAD!2j2rpr!B@(d` z7E-<=k@^VcYxJ!yNXLs#Z?tA7Z6e!jTsqDs`Z=urs6ZYa54oTPkdFuCA%Hv-wI2@1 zCjxRFAddv(lK^=%AQu4gI6y80BbW|aKDZVmEsfgo!m=#ALm1~m9$%2y~Ge}8Q zTG7~RZYGUS#$R(2JR7g%+9prfP7`ySX-<7p#JMw7x!~$}dXo%#D(I;Oy&9^87PYig zKN|FMQD>4)2ECb}Hw)D|74(WhZ!YMS(FkcC6-x8bl^4)-X(62=Re)SIl}U@KTB@U3 zX^Bp;OT_EJ9kfwG`$;_lp0D9LkBT8pjz>|{0z*0-D9!|ml|ZoyC{_c-8lX5IhIAne z=^_}?#W1AHU`SWMkgf)fYmcfS{Raa~BPlh8lsor`q#Rjk4l5}KlX5iBl-xK{Q*%3I z?|C4{2~y4@ky-~*H-Xg6sKN%2x)r4E0I9n`>TZy_2c+%=sRuynA&~kPNNur`Qmmwu zM5L6Kkos19cNm-Uj`|7aAsaqg=T=jh1`RSUHO(%Goqa?n}k;F|m`^-|Umu-x5z=e`|@E z{f;U1QQy@Tcnt)v!Qgc~cntxsVc>Nlc;$juK6s4;uTkJt0A6Fks}Q^<#`5~p z&g;*_y#8znufLG!sPLK-&#R;byrzQJbnrSEyk>&eDd1HMUM1jF3SMR46$Y;b;B^{! zRf1P_EU&-qy#7wi>+hEEIw1ZzI=tq_^D1otuX^xW3SP^=YXx|n0bXZ;*V*884tSjl zUTeVX0`R&Bye?g56~QW6NZ9^X@R_zYUS;;RDM)vI*D8+Q^_`o#idEf&eVw3 znYP(a+7Y1gpB|b}-$EQeRr=rvQ13LM-rOYARk2X3Bcm>I-a-qoP6FNX95v0cn@(Fx z>1oa#v~WfmNLO%@=~zWoLToVKuS#%VG48kFwU?S)%}Xy=noD1Lxpv02*&?IO+-Nhm z(PnSZo2clU^sat1+H4+glF7T!W>2Ec_Mpw4Mw{(Jn>~j%djW0s658w)wApKDvp3OZ zZ=t>3rqkqisYZUEE|Nc@tK?7UUinLEkiVkG2DnlQLDy{EQz-Uj?mo7|8*Z)9N&j(TF{3Mpgj(vJr0pi5tOXR zl&LtWui~O%iidI)jm9W`DpHbZCKlv#l-5+Lw50_~JE~PW&{Cz-|3x2iNY4McBX6ME zCLMWQJiPkmJ94Evvdko}(i8A{0bXyw>j!xK0q;1#8$hF#fizY*o+c_oXqGaZij@;% z9r@#SNB($XNB(#V96A5}^3gHEC8iNBi7~>Z@f?>m-w2hHP*edpjseGU;8+NblfbbE z9H)ZgbQs|b7~!cf!eSU9RtHKLMmQfvcp8kbBGw4qb|Z8rHbQqxjFA80{pidlX2!#t z)dC}|MV9q|w*>H(0p1G0I}`BE0=%;UZ#9hY92ntwFv1I9gcrjIFO4 zxg|#Ekh~_Zk){!zeWXR?NE6sFqt_-_M0Vs6Yx!DAN^|U@<=G9if)|wf(z1@vLROBr zeR_hm<#OVe)K<_+T4CQ3RIWi`*8%1A5iX5sIl@DEV< zhba8xW);p~f-pPOZRSjJ_mMi(8nZ*4*<^>B!yRgs*`ZdU$DGaGXbi`$UQ1m#b~R$p zF}B{%9i;A{H8WDt$dNa540XSQp?qvEw`}AmMe^Hxl5V%V6)|t z8e8s2?R06PcDgLmPHOMyQ?QM6H&nly?$?h-J59#Yh8*M2PK9Wv323KDXs05y(=@cx z$!MpUXs1)qPN$-sW}}^osoF6Y?NdhQIl^?AV*y?1SV-47D$z!Z&_*?}ZF4ZLZ4Nfs zHjO(K8KGvijg%&}HQQzoCK&w2@45B~SpzwNKT|*=m}quY%Q`+v!@%<4AqF z=E8K%wG+Aw#9VX=VKzZ$(3#NdOgdXX8sH0gFmNmb_!R(u2KgK-Dcx}vb#|<#fsXTO znBxLE$#Ee~a$H4I92e6x$7M9vaXBq;TtN#R*V7`$4Yb6umXG$uM0XPoaP$Q<}|nU;U@$grA{Wa5hk>AjsR_}2`#V5 zML|biY2C0cviq{uPLP*hH^i?P*2SSb9mYraw@N=+mRszO9M1yfb3pk5P`(6|uL9-k zK=}rZal8eSdz(&iyhFu~_bKf70H*gbRXRSUWsWcC498b7s|TsG9c$;rSUX3tcHK{| zBdi{}NL`N(*c+o@Z;A(dV?5ZKTLAVufc*hre+1Z{0rppb{R3eC0@%L+_8)*f2(X8! z*eOxiDboU{lPaAqTITf98BSj;*lu>P-4cWC))KJYr5+~O1t!=#j{vsP1RFNNGRo16 za+SFounN>has)=Nwj8m#f!60ZjFD>_ZNTmB2J%~Cyn(HW;?Un3hyG?-4~5s$ZTivj zw=2#RQk^04I#bE#Y(vS;wv_42puWxybeyvjjdXUV@y@O^-Pw&woZYF+nMI47y=aLu zo0dEK)A`N;bdhr~UGB`Gbt`>k@2(Xm^ zTLrL-0Ja8T>j8Etz%B>a(*gDjfISmnR{`wV0DCULo(HfO0_?@HVEfp?_DKx3PfNh| zmHHhWup6Ub?~Vt%F&^waEdYBZz+Mfo*8uEw0DA+#-UzTa1MCKXy%k_@1K8UE_AY?k z2(b48?EL`y5WsGZ1$&Gg>@kVK9@7%A{iS1%4%mC6VDF0udv840`&$5Z8^AsSu#W=l zV*vXE!0ravJplVO!0rRsX8`tDfPDdAUj*1!0QNP2eFI?MiUoU|9qe(5!5-HVumhxl zM+fW!QLqojgMA<#>_aU8`vJgy1h5|i?56Nj}v@ z$*Ko@eAHJB&@eTL#;7SYO>IS|s39s=+fZ0dqXlX^s#M$4GPM((p>~M{n_~x?lNfAH zOTZ41h8`WT%cEc)jt9Fu9_*GDfb9vey#O{FVEX`UKkzvgUp{U~>R=2*3^p z*b@LY7hv-N_9TEUhy^>$4t7{#u)|sccDQuH(E+DlJ*vSAp z1z@Lv&kTT_1+b?AY%##j0oW3NEd$svz%BsT(*U*-U}ImdkxsOOJuxxZ6I%jygp_-9 zz;2I%eIy?2_IR+5wg7BBz%B*YWdOSZV9x-bvjFyNfISCb*8uE!0DC^bUIefg1MFo0 zdj-H=4Y1e7g3Yso%}We6uO(pfrIAMmY*iHOj(D(D@n9co0oWS>_GW-x53siY>}}w4 zC%|q5*n0r>K7hR+U>^Y3O#r(YV7CBl1He84usdSGj5^!f%Ry(j)L5|N>|nt2Jf1+EQOv zI~wL{Ph(siX_~7Oo#N_D#jb7?c6A5dp1|9SR=WDoYFEElyc6trCnUx@!G!S0I(`)muqo&vD50k#-mO8~YM zVCMns0)RaYU@HK&5@4$Ub}_)#0Bk+LE(O>X0DDF(*r|4~Qxk)o+7htSB4C?*|KPdi zy?@|ZjoO}z+ODA#*ZIwR`C+JG*P)FCb)WvlJb$6|! zUap&HglhwhcHN4`y`4&2cTkyYBbB@Ep(U>S>2%kF<|9oE0bKy)0A;As49io^nR*+} zNbpqCa>v{n4q6{+&P<4SmUPPhCE^zoBYvqxh_?dqHXz;(#E$~;4j_IEh<5_=KKAhz5|gm`vB#KqDa%U}9)7wQ%1 zJ1>t1VTah1y_;TH2P*nw-|b*s*qcfB-kBZqsTnrNv z`kH#W{;Su^O%gwal_s>YX;BjSTX*ViegexA(c;R+KSuWO9oNq&)=59-;xYMcF-JZhk4z$4CnJV2~X_>nRo#E~o>)Yqs zef#{xzI}d6eER~aJlZU>{s{_CR(kd>x}kyI+#J&^$Dm5b+N4jD7Mjvs&9B(GAl<2f z-inpY0gItAvK5v;jpve8$Tra1v7));bm!YdE2XN0O25-U@5V}xhSFnf($&(UgayAB zD_V$xC)z|8OEn2a-;WiY0?}zU(ORj_6zyiBax=EE8_Sqodw3rOrI2H!L5GU8!Nd6`fQ-m+w%y0jseLLQXX@mTl2d$Ukp@3 zs&orEH&QUok>->`Y6E?_@z59S9KOm*M+RSGv67>*<49At(|;^~r?Qy@6fUGm^o`9K ztbvZ_!4aHKsqPD?gZo12=Dv)2yDz7K?kng-_m!0AzKTY>uckuxjWo%94Hdbsr`hfs zsLZ{V=DTm!ok4eU976W0G1lP!<@mQk6~F1P-C!)z#;ellp%@ls`-{%xBp>cvV6xE1 zXVBnxzjPeVG>6GU4LQNX)oGAB)$P7!J@wB{bIBnmbl*<@ZJ=)ldP80VQJXZCZ+U?z z)gAJ#2@i5_JoF;Ju>@3{z0S(3v+^=4Eltx|X*#QHjEIY)tn}Bz+;^kTK0pEYgOuie zh`P8pQBU_~%64y|W8Dpu@7_k^-P>up`%yT~9W>Yd82CI+Rqm&0vHJH??kDM7 z_Z~Xmy-(+s$=tHZZE{l@!6{6xBgnNXj3al3#eSWQ_KO+Ncd;h;GMe{Q>-YEgSE@|x zgCXq4of|?9M@$(mw{SHi!_6aZvpMEsh*IAX7F$`z$|}5Ga&o-xfwLQ88mJNUz$&E z2A|#xLun<})%Iq13-~{RseTOnp8)-*biDgB8tVQMrusEaaeqUny8i?8-%_>vJF0Pi zPfOiD0R10yw);mq$NdXk=KhtgasNiwyZ_Rgp%1CSQL41^5XK9S(H3q6!Akr)OO;j~ zzA-8icj@o-F8yO~6Q16se>S_c!|c+(C+gC_nqB%gy-UB}(k|_h$mNmA=TRut
    6 zCw239skcX?fgT^7=cz7^bHalVQ_cX!4n7;WN;W<26wmip$~0W+aGYB&R%ET`?4>iW-m7~wS@-B z#K#{ZC?)#JLtcuOMHcMJEh#EDAy#n~l&Rjk$h&{5xcOK>rYbn=#e&qBH0N1?_?s%I zF#H&BU3cf9!Yy*N84(@}0B1FHA(tErW>JFu6~24-3}&o4gzZ1Wr|X9sv9{BKS1=QV z0o#9&+PRsR8!^q>$aXz&VsEpRV4{2K^?SZqhwVs!XUU2S1BGZ&l0HI?;?$hcuR-as z`dZEegRcT#`z@XXseIXflp9B4k{Ib6qa2oZ*2KrYSO2A02SwhjPR z-*|X3u51`OhLfA<T$gZ@ z2(&?a<~AhJA+6 zIETw1YyNUYD{Be@hu&K)s+G~qvvCa9MG0S~K>rfhkS@dL6CAYioAQs*?NsUH^^(Ne8{S$PNqQ(w2T%22QTQb_$lJgyfiZyZg zVL`D)hB4k=4?5P>jpT?<&Fpbx2dHiwneqa2$t+Jzy2vE37uL@Yud;JS)LOV3+^mEOh zs)&k>O6+>B!0BL0K#6IwGiJ#veIU3hkA0Q9Jluo+`XWchugd~u;KRgDnF=mVx7P_JP;x&9z*! zl#>+A*Q+ahI$O5St*8$g0ne8A#TchLmQZXm;NN0B#J7g>&bKB#NzA-*i?*OXM_F;8 zy#27Ul2Y(XaVNZ|$xtcloQ`r?+WW|(gS(9GgOCQvvn2rQR-)M=f5}Dd7{&V7FLJu8 zR)hc4CYGgGs#x02UrDPNQlhxExi08)yg1g=lN2UQlM`pg8{r-wjrHOe#g@{6yTv~w zQgY^?{ga9PP{ldrYKCu%+jIJu>9HCD61H2kPwYe>nIWX}= z#C7GTGRp0bQ#tTm9mFgOo(f;h#HZCZ`n>)y3V5^N-`n5u%LlIxhqqs0x0C>cK*qmloe^o3L2gwuXu@}YHgE)( zhMZ3jEZLDj-cXwZWiAu--!2rLCh;+(oFs{N5EW_KO?xQa^5_czrb+qseTpBm*x;no zhIZ4pO1RR+L=fR3VS5ro0{PnzR}S!1@U+yqnFpM`gFfK|ZU2RDA2hvt*TCHxeS%Sh zCh_12zUnCoClHN@BoPhFUP1>Wh^=fcrR5}Cn?OwxOLHPq=Xj8>1aNlIX^|;ryk?-F zx7N~>$do3vknnDMVmmi|tc*vvDZx;d(M-D%0{1fYN)WqXNL=p5Xo|(O3q6eD7XOt$ z-9<3uH3E32aL{vYk~_oicoe$j^H7$S1DT@c;-3Z&ex8WE`def2`oX= zek_^Hge_^`EEh1MIq@VBt%4NUPythPcf{$kFL7&;rom#}6^wvvVYko0itrfQQlA#B z?4KjYWS_Ng+C6PPcK9Tk`TN*War9SfC_u)y5et$~x3HH@M?o9fjjw{gUAXUZ5=8KUO*x7WSIk1p zS4Gfml6YFcj+4lWmj|RTTWURO73a>tHmNf$d2IWoq&i=F$;&m)ofA@OC`n?SK25Y_ z=Gx^h2(K|z@UYQ^F&vXE!b;WPHyFk(O z;!Q@WLC3fC4eWHlw>8b*+6_Qp31Wk-AiHz7Z^?f;(eQ4647LL-6_Q6-bK`jgzn`Q= zZ3sjJ#N_UNN49#>_XP)z6^LH3U~MsbD*(w*o$+Orrrig`bBewnGh0_47xyhSx)$6} z>{xM3OCR$JefEKvTRFgNj{z)GtD*T&Ik%TzS zA35x%x=W9jaIZpc2#%-xOG=y85cJ2?T@}v~wKk9YQpXMt2EyXTR^bSs7~?a-Edo2&kKR~Xeom2v~C47d89<|B1n(HBmC+f{1I1+3stD<)coSjk_2iP+T@tx{NUKHh*M%nNy6U>Lxw+ZhA1>~an17{9l6K>{T{f3Ybz@~A zY*b~sYj{TIW6dAEr+tm7DsHZe$<~~jR``F+-Jwp&bZ_mm7~{Z?$Q3;vRf^F3=qwvK z;wdk8U`A^SSJ@6cU7O@m4tImo;BLu>1%8OwC8&tQSLV|X=BrKzmggPeOq@Fvq9lhn zd%XK?pmgD|*+~m#V`1`8vNK*I!vIw;!`%4h+j~1$5r7IgeV8VJSXUmjN#ES(H)q>Nhf=@9&9^K;Cv-K@AoN|ztm+8Y0 zafVG)2%J9c6t{q9cR;`-zDC;to< zEd(pn4`nB=it|gt$?H|RIECnDdro#LKg{ZajMiu`9<7-cb>*zOy$_D`WxISw%X1x2 zu&*I1bbc0-dTW_YKRt*IPlVHJE+KNQ_kZ|bDOT=r-T1`j-Oww=fh?bNplVcx#nIeUrIZKAyC1H#%Y&vf-d9&k45R+ zbR)|g#511XB*R0&mByuXt9Vl%!$ZTB;-$2Q_>~hFQ8{fhP5?)qDzz)9ReH70L0sbb zO))%#U724>8wVqL>RDwxq5sQ}HcAXg!mUulLT8Rl?%WGrvYr#geIKF;u< z?IM#*o%N02`O5=?>`bRrOhzKDb893NqVD8}JfCY$@ErgBB^&LUKfK`k%f9>?9j$SJ z7s{6G?$mCjyZ((ER8FoI%*E}S+eoiBhmRrC!sI{8^!80@ zM5%YX(y87l0^!suQK^3do1WQ5sfu&oDLPo=6`B^yi3?5Ke7)X7n7_>K7LFvp`D6+J zt;0v)1z*{)HyaHLzDB=ql!@6f9&eV7Sym(^FV`fFpN@|>54t-1zzs49&ZyH4m`rs7 zF1q7A6UbkyN(vLIGrkg%t>>!HJ#&};4zS+db3yydmrpw&QtV22N-H&>rxnsITy|Qe zvQh!;wwu4>Yo6M?RGw3K)T}UVO@fMXDf9aSPwKsvsg81{mMg5d9p5W(@pu8Ue(WAd~AR%h|?u-lK7 zZ@^HT1XgDOab^L~GOko=QBOf~HRWz}m65ANy%M1b5y3LrZPL(d%sA3(5^YaU-BNaC zSMPCaT%1I4NtKihUqt!got-zQ9pv88r{P(Z*RvLC*Wt{1Kka2~z}$&^Df+A`r18_$ z{}`Us6bZPdj1@lM;>f={;DaY=NMUBlzu9r{Ii2m)0}oh)-+4z(TGk7J@ z+JB8Ycv_oOd=1#AeQk9misQcv$OAtCr;cBY5fZPbO|!2gqPuIV6OXtVHeag^qc&AR zTx86=+uJ~K>ugSv#3IFjw~z4{#ED~x{c~Js1;Fe(O03+TaRZ0&6`{Y~e;1Dv*~8z8 z_5UP`Hr<0ase-8Hu!eTkmyz})KFHked4dW9LhC)Uf@WE3Wv}RJWe36HYyp&96fjpz zCPH+9azpWAl{X}A7@p<&y>g3zNC0yA0*OFEGD`HRGI25xdQ&lTplb!XYu=Lhe8d_? z5#kU#r|q=VRzLMM(w6{IF=pgv%UxlswP32{nQW=0=MfSprq)J9D29r88{Uu1#QG^B z4r5!|*N^&_1#C0#u617@bG(Os|NBC`GHOiTq$Us+gEl4u4PuzTd5nQ-WEhsja*l?RhMhsM|?e%t3Y9? zOk|%gm6wVt;dZI}jHE6pT+iUc6(8=0Q9m+iPrB!CFAU;|_?1^qD+RBv)}{}RrVn1^ zR;nK$&Ts8(Sl~~wu5^`rv_tr_4DUg<^XR&7`7}`G+2}43L2|zni@Mtbz0c2^v1dZ# z9USsp#k!jVHSX>nP%kddA^K&eJe>)2Nr_D9lRBk#GooL%&4cwkYd-Q(`Zm;;t8C@^ zW2Yn%W~hG2%l?8wtnnyL@2$rh78c61Z^zy$FJXAF;or-;3mlf*fBeMtB9C>6YZ z39vm)7}!M8SjvR66$7$zS4y6BZVaItRt0VO{wGJ5uxkDkpnbydx7r*aHkUT^3)|F z8U8Z+^4?X$Zc?T)$f$!EQRox&##?A1$_T4udbw}zN}&$hk4m{PH|Q7zML5d8FXx+Y zUA%zcf^N!RkC7FXT%6dHKv-AGIgoDfU(t8cp(>iq4IJSu>CWKNy+#jNG+fD{5M2QpAlb{?jK(hLb?6`ZUg3=;usRGv{wc(qO2Uxn91d!2rs{ z2j;e@rggy-G6U1mX@c>FehSJ57xr+wlkZ9{{1LxkriX5VSqF+dv)Yywl~Y>$dF6A{ zoPFfi-pn70!)=8;&BkZ)TdkZGx;*#ShlD# ze?6>Jk}wp+N04QPS^V5{2Hpn?+qU0rsKyR|w;%}TX7yt&9;zA(Qca?}BP>lvHh&-( zzZ%|O+0-K|Hr>zN`DDiS_F%oS=&xKUQ>eH?UplQkk0mwQPEm%gu@GN3$u?$-3Vw51 zWYde$`?Lj?y3*zF<8_-))%=rxITT>5N)kYq@8T@HHBUWRoEx%}zRH|N-&-B5&u1Vt zC5;;g<@K3sP(D8CjbLo4hCN{y)HvBYpuc?kQ%ir!q}|eeznP>j=Yj5xXg4v;CT!a= zQRko}R{Dm}Bozz}2Zug+!=n>|H8uWu0db^f;W`X4Wg_(j??Nd7`X3PM9dV*2m4 zJRK8fQ%e))e^*kcrW$H4%MymIp_nd8{s_!CTTBY!Y2kb?e}_KF(}EQn6^r4X7x-5D zw|=44Z>@Jc?N+sqtV@+f{B~ikOPMz{kbUg{HOAx5=lEYm00*SCI&z(Repe?sv$+ob zFGRhBIU^A?M8BA()niNyWYM?^G9xs&nY}f+PBwF5$TNuRN%6s{pBSb3{O~i=>!?i< zO|*0mA2|#vTMiF32?!d!hk2F3ho6_{=4EDJ^X)@$DWh4^4$O%dDLPYf6*kQq!_jiK zPrut4ztGg~HKx*s@im`#c5mE~hxzr=dFJL9H{@vV<1bq?_)jO7JXD!`yZ1HiHf^6_+c~-(L!p6~502r~L?R(9CJKFAS}0VTiIzMl zR3WwcpUAZ!dc!>U78=s$*x5&&DqD8l)zxw7 zzOvq6v%eUeCB|E*IySDl`j2aOZvKL3i7h!fwwc{a@dTw)wl0l|euy8KNb#Z)~+t zeV%$jUeL!!c;z2~MU$aMA@~Eyj^Ds`mS(f^07)9ZT{@|(<)u2C;0mG94z6@PtD;&gkAc;6oS*e# z%kE#PU-G@Q$mR)#U4|6Q(zEfdm4cV6HMxHiy=2GX#BwFjw3CS4HWBy?-|G76qsK{d*>Tbb?httQha9kx!;X8KXKxNk2!dy8SulK{kyy?sMILf z&D~d+fYL9tglh5$KnpSM%ETy@m8wUqtBDXgM1~6&_r&3OlYS>FYN0Z*_F=N%C~%zz z3HoqKm)@f{Q-f}BQ9fXt%6q0qQptqxQ_&WXzZo7UNaC1^)9F|hrcdNZ`b{FgsUh+% zesJeU*$$U_(nY+auUZGE3KGE;N+x!McYNfR34GqX4wUG&#Ln{qn& z`a9JKLYQ2HeMx|+%z4PmMK2=^w3f%n>liXOTfdh7^tYY;1)C-!*jny+@o$F_*_=Jg zF0Bi8RRJ=mT0A#=(yDhh7}2isn5#@#-mimf7_Ad;WX~v1)KrmhBzlqAj^vtpu*4K3 z87V^e<$3Wf85MAg#(yV^G~hnIp!~b+zFm7eg7a@kNO{OeNDTkCT>e!g>!+cwN~VtY z5@$f7TYUAcy5I_@GF8c28}?VeyMhA!50NXg#-p6xEH|3)Um*e7%Sn8G2wX(GwGdi4 zi2TaL;?KRi`JdbIu?gd~03;^rQt`epp7QsZotP&Z-9b#0KYxp)l*-|Y#8Hpe9eH?- z66(wo78?a@dqVt%8r#3>Ro{eIwTt-JwpLfMWoxoG>;XMU`LIdZvsLE#G22((ZaKcQ zB{ZBbQ*!+}bN?e+)1DkF@}S{7o( zcw7DZd&zO{dg-2paHQeCNll(p zCm?FAf7jO%^>J7GXHk0~m__U3ry_Hx2w;rLpEW&+4hOBDGio4C-P3;C=w#dYcsrN0 z**Q5Zc|ud^Nj*2C0adC<^rC%Kv_tznCbzW_ZRsD-g+lguMp zOSUW8{s*z$Yc86ZRjXZ?mAS!V)Q=mCK2FIc{*YI5#t*{JY(Wp~X1aAnJ>W9~h>md=OXi0o$)Z)rY3_0|{ie}@i(wLdTa4HA;^Kfq)A zztH^`iLsmdsLHZ9p=df3#FWzQ`Pc6P4UB5Xq>7ZkRS;6BvB(h8TM^sJ68I3Jl9Ge6 z<)5o6-r`03ivuyQmqa?4498Z4E&jAmtnttHAkEa9(*%}mrLp|0yu`RvSjTPq3&n5K!fIx85G#l*`OsgQ6`)&2n4lI4e z)Jho9#OUrt=X*@Qz#VN3+{#R$uKHW`>Lk-lwdBL{kV@*Mm}u5b409JIqWYj&+J@iw zt09rSVwb2j$E2d_gC|N`If?`x6Lv?3y_#WX5BMdQ9M!ItO_nj?1>N)&%fij7!p*pw zZHrs@bJigjua|H+`Jq^Ro%!W>M+b$@RIw3gB^EAQXmK0S4RNA{5>p)zC3+3UBnGv( zqs~F1b2-vpc(>d?NN>4?sR>NN76Hja_d z1u8X&z9Rp7)|&$qI1~TKdgLEjv;5zzRorZC|1IdmQG1v;Vc4reb{j87sAOP>G)s`o zmk-&}n{zsO24&xvS+w6ZSP~c3iz*sYbY?9`K#7RnejpY>!VML0hkdMYCw5`KoDf_a zyMH{rr9uK}VOx4O#C=p08WGCjf^I|3o;oi|O7R`$4jt|-=qZdZ(oQcWk|39X*-Fg` z>=p}0xsjot{P2~>O^TpjJ0`w1_2@mbpSH;6zK?=@%8;Xt80?SVA!EU6pURufr*luD z$NaR73+;^-`}EyL*c7#zpd-no@D$~ODQ8h5Hsn}Swy~?%>`w16oH@m7cPVb4#epW( zYuKx5yIpM>AWNIXO)CAEW(HbH{`1|k`0&HNnkypqujLYN4Nff^Vg6L8NC`QLzF3Vy;CMkc4@2!=kdLB)Pgrxze2x}GBpSR<8s@=Ji|?e1 zD<>Rv(XIlwmi+Qjl;LxY%pLLL#ZQ8~id9C_tx=ih*KdszPsf?Oe}s>|-7$L}JBd%_ z%a>BcpPGv*%&Le8ewNr$c-*mX875PErzDmx5-*Fv`_umj)N=#C!fcSi~T9hy0{I z$gQL~bCrMTxI314-+gMZJAXs?!|GAF1c-nTK*xeklD6)uBO@OyJ6fP?ez1TUAR{T8pzMWDH! z-Mtas7bAhXl}ve)aGI%8UVYbJVVomqSWAgpf*UsP)=nQ1vz_=T7YFr(TxeotP|Ynv zzp+5i>P+3k;?c0q(}2WS?KNAGt&RKgzq@&znUe%xY@;tHX?8x0U=5C2h69?FWgtQg z@X_pVk1PqC&zViXA`9>4(bBHWVI_9a)Mq=Iv%w#o7skGkc$wWa$kYB(>z2JW{xnc% zv-)ww>K;~p%4STgS~LJ|#Ha=C&8EjLRmvWd2CSXH@~nALMYCkihIz+u;g!T{xmxsC zvtT!qMbx9op-D?gPC_lgZ95u}aC7hz(Mo{}ai#9wvKsO@jp_^Fq9R1+&UZ&xZzoT0 zddqwBZ>+|J<+X{1)O>hDhW$kKDy0H&J86*zdez{R6iJi5tyqkuuK z`XhDs)Sma6MfD0f-#$*&=mhym`C`l!oDnqK76i4tApLu*u>45g*Puf}+TcM#qW^#R z{A-~UXQBCO$&er>Ryu{j4GMh2DdOWz(ENNPlrzYc<{~A#cy6v6-BugY zTCTT}1#yV-;i&nWncHqF;$C*Kn$JIw;F@nRXFwAoQks|XvUh`$ZQoIh`dgvM>Ad|O zI{ic&EV|vTe>2`7ORsU+M?GBuu|M}FQ+YW@Gq(P!M?|KtZVUoNZT^gWJmYeETvlDS z>zG}sNj+H{^=qbH8=_thfs$K_jVn08ZxXP=6; z%&zAb=AyAOic~ug>*`0*r-PNw+Uck{RTg6Qu4IYue|!uoPf>)|mZvRohNt zxnF0$PeO@XQCi&etD{Tv*4k>gK>7JbaLp*6K9S9PkiF`v_!nAX%`bqb=MUoBwS|B+ z<>SAEt}Hf^-Q&<7})~Lsv}#}pBR8}xws1cJcr3<>&l!$OX;urR`XAe z@^IDnruAjWEeBZ>>KC=;$l`E^vV4>dovGVkRF2~NO1>FaBLSwQ-Jv+p=@mT6l;^b3 zhjg(OdT431F?f1#xDLpAL`)7pk{2}b+%`*12`|Uj5=yd<>;A5 zEI3mixA*9KrX#!LPUiS+r4-f{2~1LYi~yO@oorQoloflfwc{=^mj<5QCdy+6Sgdv* ze%?Oso{)pMJF#+F$_znW61P)eGL_LahyKBJle ziuTp*xjjNx1?7!}pj-VuJ_T~q>CV>O^=tEmAtmr+Vi7g^?Wv~nc!w_6M|D1s&6L$> zaU|6&Y-ZeEj{NBGnunL!D$8_p4#cyQ^mzBUC(JjQf}g*vk_#-GBn0znLrnKLiicVK zm+hBN)Jd{d__U#OFB_s+u49D{)fY1MJj}04JEJ}UDtU0KIF;^3fl`uVF=4h%jjRit z(Tis_Fw=dW##otn!EqSV*jCqTx8Sb zVJw)hTnS>iN3E&TX$Gr>sdOUOgn0?ZltQ@HdOGPfVoEUPZG`4>^r49iF`a%f3;|-{ z4DwXoGqzcja>CuMrQg*?Xz~EUN0qVd0yvgW`v5ARKZ7u)?w@WanEoGsy&Y}nYM z9;9~ZchRSNmE=p4EhHqWIhRb#i7nMCWjbP& z4{|~>QlC>gIJ7C(^5;2Dj*-fmuM!=q;=G8t3`faEyl`TYP^*X49YrZ_4xyFo~HQb64xv*3JsnE#ra^;$>_1(}czrkCfCJ0G?i^oilvV=21D z-{Ovyr2olca?S}pF+01QHl!~LS<_C0dqN*L z-kWEbk*tP3gs&a>pFe-D)#!OXy@GCgbOb$I!_A#+AHdO8qr#o;tCgPv(p$2dykHE> zk9>Cf8;&E_=OcbI9?$)>v7s;e2g^I2j(ZoP-7|ZK>WerWxd16Y7DkF#p=qv!2R)Ia zR9{_1Ry!3AdE$r*tN|;Z3>vpe~o2I78yL8{+E@T`%uBTNvg6 zZ?(59yoy(}OgCC^-v1-Vv5F{v{O9d6XDgy>OKfRsLhX+sUkz0I` z!Le60KAK+iUZmIDQl$MMnnSp@#nfZKoyf;|pTzL%7$BOHOuxq-a^<7)A)P0?=~#m= z_7FTem7sE2SD>PrH^mL1fvsv?d$~UN@Z?{rG8;}>WM8AB+S;{#aTgGCM|)3i$v z!9iH|NEwBP-Mhw{zJ~anxkBDRAm;RNlwXeTeNL$oalydvpykC-rRxVyXHV;CmHZ-8 zmEGGw%s76<#RU_liWrx_i2a!Y&Vzdbv6Aj@&Slg#gA+;n<<&0&?ByTaEhlc5OJl

    1R4!02(q_yBP z-Qr5K^7JeFE;C4UhHxoOL9#rs`i-Q6<31OU!3L&h*Z-p)FX*k@@*?Lc7*FBS{q6o3 zb#jR=k9?upC?zj5W9GfQMu1G5905<6B46S7+g1@G_GEs;LPifS_M z-gXu{DG>udEfI;i>w%y3hoTt)5-KuR(M+^A87pRFo}94(Fn1UjU1mla0y8Gl7CAm; z!&$mff7DVx9lmNoEJM29RZY;bx!(OmgopcqS^qRnsKSQH&cY9A4dVc@#ur~TBUSa) zgqHvXRa#(EPkV-YU!@M6-ALD#{buClP9=4$HO9EFHg&qR^Z z@T>5IZ2a00bb90&Cxm<+WchS-2R%6?JS4N@F*t{7|ftj$y!j->;jUG*Gtjh zBI8R8I8hwDUKhF{e&3lGKl)QmA>UWVD0bkNp0v7>dTNyWOCRRzeZRAtERqbzl|>7% zxZN-MWmvJuE=5^GKf!RNBLa4)$D6QN{afmh#y4!E_DTd<1lcOl7l_%PcyprkItWcI z0}jSkMbePVe_l*#>)5p zhRu@DV3(@;yG_8x0K!#c;O5-1&Z14I{D6f3#ivCw-W-sA?Wc#1aZP=!=Dc<2!vGA^ zs%@xZNRiH5e|AKyPQuOnMqx1)3PO1E0MIxGxM(XuJ*Q3HX(gdKCr{rQMWi!_iMgY? zldkbB$5V^dBkowUB6>gf^Ot~i}$$0v{!hVp9HYdpq&2m5Af><`B8{WOQ_2$I-iDa*&m}Jue7#e0vfdHFQ@L$!b5( z>oW>oj(LhvijlE)nCeFAa8=^P--ksu@T+I_g=?`VURO6#!8zwhLv4Tg_ClKEdDy1H zTMXgO+4)OaqtN>dR!D-I{n>-m=>09{R#A4dustzvdpy)P?X#!sdn{E!^_nmC@pHmN zT+mdbrFM6)m*vW*Lw2?316%j#gb3oh}W0Sgen?Vk{6b#+qz!Aon z?sUOmw#+n07sK4rIF;qi`_s032Hn8Fc1GgICgLl8dGAZmhwq|uLDmO@FR4HJX_Vn? zTK+FJtw%k>*w+c1d-d|(kDworr&WftTOuDDIQLIVhIfDbhyZ?k;J9%we)kgjo&ULm z*a>^;MU(y(BN>!|KivuaUDFHdW%Hnp+nD}VyX#L%Tc6?WI;O}1zgfb+CK@Z1sQi5?N&a(%A*Ue|;9yvWOc3)KO=EzapzX5vCWrb`FB-OK}F z=zAECn82!xxHsD6mhc>5@YG=Q@p5p_ODE*DW>yc zOu|RbGMSY+h2EyNJ|*SRDx}*qj;wTDM?kV!bPr90vB!6^$)k5~mM(Od4B!$bc9kW> z%jAOYS{-z-JBjn#=rDA=e608`Jt&VS{HEvEpY@p07Dw@bcPIK5F+(*3K4z2O2vcn? zTc6NEGTypP_a_lVZP>s@!H{tjqj*A*1YEa7N~zR`Suu~G&qnrd6HH2ET_PRl@al~? z(eb){UaL5#X5Z6kVf$=d&=``%j3U?ZG$xI&a|yt+_PJ(hBnJ(6VIC(hw$m8~;k5(n z_8*-@F2R29$2zGh1m^9hZ3kw9$L-4%CjNn0vmU-O`4M42BrI@Xx66DK&*eg@yx(8k zq$iGXP(Y#1M0#?|GOt)m1$_&rLh(CM<;9#$k4S=QY;T;SBX%lmeg6Z78S@s9eeFoo(EN$Tz(5>K+)&@zR}!1{yr6$0#N_@tq;R)?Cd^oS zW46teI=P(77q#|?Ebm!w2CwB^*?t>Uo*xK{w-{Wrny*lAW%W9jWVzy$#TUrI@p1m? zYe0hi#5wlB!;IJ`Y5;|Di;$TU7He@j8Y- zz1IL^V_f$mnpkWK<;U*Xj`i;&qu(z_x{{vifwV*96Zwg1ogS0<>g?G9sR5=D;Y{6< zQaLL_QTUm^9GMys(B07m)oeutC{pMw6;N-UHp5K*Ai080=|*KZ_{dK}4a)Kb{P72r z=>C^*u`hwie$uRh5G>(7^R!?y)D8D6`mRlI!Em^$>(>~GfUeh*Z*d3XK)*N8^l{oDLfw)rNflM;1_ntuB+%BN28HU9LzT31^SkbI z>J*(5b>ari5x75%X{AJ+l4x}n8COr(?G&ydk!rmQ=t1^F54z(HJ`k=MpI zYWfJsy1)h;@S{<04a4_@W4ep9$H$z=$(Tu|8_s}(SsCv;N+opEN zpCc@Atia5-0+_ksper)p9U*(p8|x|sfz#S!f5c{m5hAT-7qPDzzbD6E#nHffdx#uX z6be(xCPl=)A9OeU0ZyVktLMuO+>cb>gqsFQ7xS@@xO^soaO^8Gt%(wWm3>Ckc;}Q| z62cO}Ic5dyH5B~l+^I>^i8y zR;sjAMY{BY)ej6hn1dTC=}&I0bMFwtrPX!ciMBl zhR*37ZkpS{!%kM3G`!Bxy^uRHp*Lmi#;^q6HATc0)CKoO^|t+69;sU`4Xl)0QuPq( zMbdog_g0zklwC%87_DzcmSjLM_*e?X9}r7)Fmpb#Fs!Dd+@f6`C?FIh6IfOj6mz4A zGzKd62>i?~xEpq4KIM6JPEpC=knbM6i4w7a#@I8?iP#7?a&~c-wy;n=T$gYRW%58YkWsktLqVoF&7H> zG@MHoMniKID@ZGfNEA?i- z^+T$v(`4ajKSmYnv+F9Y+Wc<-MEfxY9q(VBC15#AMq+4JQN7=k?5-EIoeO;H`wbEH zB?8M~YQbVE!LQYqf^2zJW-Bdmg%YQj8N1I%-3E5Og49lFoDBboGW_nJx2H z1#c!^QPEaQnY6He>Ukg}-M6p?>bb!uW!sttJp{HN{xs1sCb<86?MtME`98J1TVDw9 z|54w;0eCR-T@^e-({z2PsW1ET@2A=4bos2^Fd~W#@VEP9hHR9&s;gXTqZ{%<^Y`mM zWxN3nO3dIDs8++)y6cVPm~J??@w)ae3=cx1J}_yAfeHBN3sACO6ZGwUUnUM-)Z1Lz zKH6Q)9=G*!2pih!`kg&DJxuKSXju>=jENA zZqNMao{f0H-`A!moss?OLT=hw04hko9x2MQqJnlewg|VdrSn;-f@@f@vZGJ7ZO)Mm zMi_i8??atTncP@W!YNFV%>a_3wa!T20HcFSd-O`C*+`ht3r2;`Fx@uU@a)ld1)Ex^ zlL^Qpq4gu}fL1_SAJZP2FFRv+(MXEZ+6tHvO>9+;-dQC8JHBtGpa(NP|C&KY@LdJ5M8|jui zS*EAKs9sx+mt0l(F!5ArKjFSabWnQAegM1VIq_rZX##Qy`5@u6;a0pxBXbd(ioT_4 zT<5}ezEU^C?bL(n5BKbG!MXjKTyvX>TuTJCIu42Q z-x+J=ZRtp-f~BpeE(rH^WC?)eU-u^h9D8DZ%d)*%)6FJuk?$ibl#5vH7p&y@IT+>mIT_`< zI7v%;GA~O%GQTZ=%a@+iQ_Z-^soL<>R&eAj%5mk)%W>w+bzAV2Y1_WaH1)d~G%ejD z`^#39iq247gXaKwO3;O<$-Xprg4iGuT8n(ZL)onBq>Q)J9PkLYG4IRlA# zzDm@apg^BrBifklpE2@H)NN?=WmL1D?nhbM$k)$Jq6147)YH?_^3V2%FU)dt%+>=l zY5tbkuqAzInEc5!GvedBs}VFr zk<+!r&dh&DI@dPL${+n=VMy`rzeYLz3^)ETIP=HVaAhRWkRzBABustiCDssn{s^Y^ zo8$WO=Hp@F^i29-b{{7`Tl-RUAHVD5na$@J*o_GO0~2oh?rOJKlyoHW>biG5g-OHt zaH~ao^*ao*Hw0@su>~d?0`@?LW$!>M!R))C2_y33Y_nJrC7YDYj0&ri^o$C-lab2NK&t69eF0Zf4$C!x8H6LBz=7JCq+Oim(>zn1~kpn3xsrHxfGllK2W6AiCa^ z1**VQDZ1WL>1SWugi8o{Fanfcg9a%D%pm$RuVJv02@A%~l+m|=(0)J&eXuheHw-4) zCDJJx5fT-t0Ir;f7i;>@YYP^_xuAZz5Y*sRI71j$G)CMhiS4!ld^mrYJ9Ka)Y?5nP z3v{xGeher-5eBgk7Og<5VI!djB@0I7M(v1Q*gWc_F|~ zT%3I+nuWzme28Tw%xcmIwvaGbKSB$p3!N>v2aY^A4jmyF5)Lz1EaDL-r-v%$l2{uIU!4&|Sv3dm^ z55keWvXPOzvKEToTZWLqu$TmnSqvd03`SrlOhz!0#i0|D<)OohgOejEk3|r%#-m#f zkpT73gK?cDzp?H{0tOLQaPp zDXzwf5n66B6aWB8=?=jGP0%@`0q8B!>1gD*kz(CbQUWI5$l)XAqTPVe#>Mm|)%rfE zg3+eM_(xvAL>_9E#DNzCa_emO=wep|Gm0cv401tUYWDdoR|N7OJcj1Q#7AmC7$*f& zif~sxa_?+*0PS}6_?R$AI~wUQdwL8F^cz5Xm^~;(dvq3^>52VavXg z2iou)v9l#MdID&Vbc7{fWnZy3{=9<( zZXUkJCoE;#;(DjK5|Z2U{ARxeKY{@+yEvGc2_8`axm+A9%-D~xfq1<5xT_-_DG7wx ze*&xycjP2&Wb*@7Cp(f7;&?q-T>|dNfhf+G7W;5VM8H^=OY?nI(2r=}kr!5SYMv){ zm!EfFBw>Ao6J6=@)o%9NsuKm&m*C(RzpP$qDq?qkxy(J9c2L zE0N_s)e$_gbO5c$~E8D1i3~F9KHu7P-h#mf%Ej5 z1oe66!qb83GK6`VS^9(S$S|vUdX0lp?=Ud!czex*V(-{633z%e+SEM3m&no(jr!(^!-ql$VY+@xqQd zzw9Wel;W||w<#V8CT{x)b3w;~7?4+$-rMK(U6 zag)^IMUaNGl_bS2aQ~))#uY1Sa|(04&~Z@@!l;?Q2I9>Btt|Ydu>H08lqT=VqGSK~;@Up}VCw}L~|UjYE<06##$zmQ_A zEZ71}c+pWHgu%jv+wx;OZzZ=!0V+O8B8;3N@MFX6OieM&ys-(WHTm}=8sx(eug#k`zMG`2WqN$d#l!*^lRWm230ht;yHf~%qGA2(~621LaijP25We`(+d7(s>KEJpat)b!Y$06$75dO z4*au@l(ks%@z7t2}gvPWuU5j zL{~RzTFTnd!{&*=8rI*l{^?5xxI1&bNp{sEw))46`ETZh)<%ka;k@{_EEPH9nWH!0 z^2MRzzxP@k=$$wJmtK$krPs9ouh;*L>RkIP)!7e&iId4?za}aopMor1f*0>2OGd^L zV+LP>u7qvO%Jvw+$L7JYBK4yRsIPWfh&o$Vv1pI=utLgEX!cLA^T*2_P5@OUpPGPf za8P1cW7rW=T{~{Bf6C^)>`>OjEB~kTS}e2IpPszGkAu7or$Y7M(%9|pLFb|N&mJtC zFbVfTCqluSFLn=|-G3tTGo#5gW{Eo|!CUoXxGiTf3;$@9mONJ@MPS)S>F$ftL6Whz z9Lmoupa(4fVL%eQw<gnwbaO{_^iAF;?7tt3oi5S~L})NDYlQzv=4q*lxVgDlo4C7~OaC3~RJV1-R0sHR zty(ZM%wnrZ6*LEkN(Ium%(>VuAhwncbCoDnZgc62lE|}2<0j)unyUdV336`O_Mk`K zQW|KG*(a_OQ2m~^SWaCPTC<8n`b*!k1+Tm}T{q8Gdp}?HPy+O&vaCef0)h8%5%9-Y zvzCR#kh>QV0cFrgnScRyh+T*<=x9JlQP6vJm~v9J1Gp&!2E+(7!2(NxQHMUm;lhHe zgym4K`!|l!nN^$%s}WFXA$+Zw>Kkn}>97GEA2jr@iu53?&54kljH1sFxFR8%q-7&zbo(^1_y6Cbd(AfHUa}se|8GAAZ zcD9LPjadKn2T`Qp)TgZUktl1@*{NLZQ+3YOv^g{13&b!25&WpDH-Cn6;gLmY z(p-jbrtI7=tx$4Lo!q|!#ogc|^zVpL8*)9#-x`xPruoj+!akK@;X{5g6>r&Egqs@7 z%<>g{)Fni|DmFJ1VF}7h78kxd)j8hrWqVzJg#R(}+C&?ck!!GtHuME*18AUV#l*NPfDpoitTMkyhdzgq z@1;7YV%co z`;#`~gO6x))5+nZmYt{hJU+20Y*?8|a3LRK9T-IgTMCE%Y$=7Z{5%3QKJl7Z^IVg? zK-=*up7-{LM`5t1CL*&;45}^oZk%`89-rs0&78K5JLJpkVbSL2`s92g_N~{QBmAd` z^&kvo>}||#oP1z3G{^cjnQq9+Pp}&jHG-hPL9IZCYEe|w$b^2CKt+d+$f7t?lKJrq zy4TX=$0BgZl?m>YTb5D#i1y69IY2*d)OyGjQzm)NZb?WVMDtYvViAYTdz7qSM{$=d zALZ$8B3&Ai=Qx_ib1@eB8aNVLfEbclwg`T~u;dL7umK1Dm0RHi%5rp0x-?ce3U9w| z!b0L+T+s1DwntFfvCM|UbMd!YnoVxu;R&9+M_$>QR%{HE!H2ukrE*b-DrR@v(@va-@Cq%MoO**MNjYx6kW7=42Fj)x7e*>tGRy3=`ED(b+kuvTKyg=jhhmd?Xq^>XM`fur%zCjkg6Sk+Wr5|{X5zJZ!hVv(N zUctV>LcWvnKfA)U^kpF{?|Ba z^aq}Ggrm~>Ef_Vvmt99Wu9v(=o}dn9=8vZ?L@=G3>Od+2r~YseX(5{NaEcC9$tb-m zHl@fe_jH&rw4`ifNTwlof@DV^QZyOqcsfP+ephjzbMZbG<9JBae!bev*hO({wO(2A zF*>0i;S+%458=e3L^;`8V`(9>aY=WA1*HtO(Y+*03x>^6SmY%^(?j$oO6$_UTt!#q z$T%C5rm#c{PV9VDg3Vcq`&pX4;bp31PX`O0MB~bi=#GSin=lS$3?+D#9>hwGCd#F^ zRyM+~O=Rw2Li4u?r3Ec$v2Nm9da zr6b|H8Rfjm6r+N;GmkaVgL}OKXx4+re0WicW|$}6FdtcwgDU4J<2dZ@nL}B;c~&uy zpFAWA347Xrs5ItX{wx%l6^nDLm_#7{vuo7D7rvK2)Ht~O+sxEt`V)~hwhc21#p&>8 zil@x16BngZ5~^|e7i|^F;oPAB`%ay%i&Ji;s#B*Fkh8P<%xTvf1?ITsQ-UtqKFcp{ zsgOF+)ng+tGWw*1NFHXiT7_cQbdnk)ox{BkctO*7+KF=fOB9c{TmL1ykS$9+r4WgEeoNI(37PX}o>W`N zQ>xSCi^|U`0(oPNkJHy>rw>l7;#_&=7^-EH^7p_J`4N+`JT!Ge9i>`E?!d(piIrrErv;A+pA#|-C$R4JGoyW^WG7W)7 z%7@&pEmGW&BAEuQ#xxE954WNiMXuYe>8%(qMG;q7kp(Qc!|h`3s+2!=#0?`GC0gw| zOqmzXj~XE9W6eF&78W&aFN+TC={a~we`acYre!|J{mEt;a*;rT7~Qv5(g%}^_oi1P>$NKtkLxHL!3omZ4AId znt(zG!{JNMVp%``xDhp;y<>au1NzDnIyc-LeJL>CcdS2MVwjf4Tu?3ERDX!- zY})-c@^Wdcr8WgDau56UX{6CMD-wkT2#Z>fO8f_Y0@W1@J?mf+D!ZfhfdRB#OKaP9 zvFDj)aha@oqTBSSdTP18k6UNDX1ECv(*-syBdqf*lMdtU zC06U7)9Qs!34UOL=I`~jt*<23%x5<)%0F6;$=`1bCaDehCkEoTzcLH4qOQlgH5mlr z2k{19?IYsF>QF1)SDS_R9mRpu`{36@jE>iOb~#(7`K`1TvO zJ>o$8=F*iL(suDxbxUjK9&f;nOZIZ*rI%47*U#v~LlwhRTN5OFDPmK3f!G$WAoJI6 zllRukL-3-XNY2^DjlIz{3XPh-f_M}fe182Tf5y8!cxCw&D0#yu5V?@-gJL+^#yax= z?F-Ai>)jo#-5tc+{gb`2)fX+M6-GldxSA>Ig3QKk@uuSwVtq1Zc1DFzm?AFRT<~T) zVzIi_yGZg3dB6U$fU9d%C|I88t-EOh{hF_ODlJ^P{DCiM*`8PLcU3|ig?pTk*rI?B z%Gq6a{PN{gudBD-(YC#(j~;t`HFBHopOE5qoEzqP6ynf%f@2c)U{qh?x`Rk99sdX& zO&4h!-QFSF#yWM1+wq|O6P;knk&jFKS@>Dct{Zv>=4lx3q}y~;MDJ+t zDaduDyD#-aNb(akVjI=F>^*|!*O>GxM%hH%s_A#q%$QOuH9U1Zm=g`ImX&+*!TGCIzMtJDG>IgAqT&YtYW zsX3%ffzC`LK_aTTVDq@kAE6_;d1%~3QxMha?u9N(**vh;%uJBpg6F- z4W-=c6=8!&e141ExCqahCzt;#2jyrBHtEJr=wk5UYH+-qxv#1iP*0=4b5jIm?~9F= zf(GbK8yH$rnfmpYg*k%U_%bw@J{V=j=qEP6n8n!yNpfMDu~)s~>`oZTJQ2ArZ8FsZ z1>9khwsNe$9QM^n{Vi!FS^N6$tRzhC#jQhfKS=ToYL;3G!wF}-u=dkQ<0zmQweY;# zY(YadXLC-Hy~#fqr+ET1sTV$t_5%uE!aip`MZJ$DuMJQIdkUawC|6`Osg)F&fdtF< zn=^l=|;=qDdyU&54tVZQHhOTXStc^jf?7sk-W~Z&i2i zRj0i%oaEO6`;{QyzX^FkTdMAj?L|Y?D{d%S;@C5`gI=b(;bS%zuJiCBWq}lX3q$sNrkmq3 z%=1X1B=QQ|&OzzljSp~v>ltT*!K#6XL%adMEl`zjaz`5I_L&Od(xipZ5AYLuXO|3A ztH+wjAg9efw=_q2@{47RAU!oJdf1aMRtP$;A3kga$P=Z|;t3b1~SncgDpovT9$lg(qu4muK2Y>MQ3PzDj1+;_Gs5?oUbo7mYK!WlJ&aSm#+@X)~d=xc;rHQ&LR4w_MqO7Pu!i?MV#?L%;(OfhD>${&>I) zqxIU%;ZvShzJUo4#GLiVFCcoboA#F2QkLFCi2!>ZgH)V|cQD}eIdJLjZ6H=A+REjd zuFv^R%nbKy2uL(KM$x5gJIA-eSdw;;rKJ!))l$&QOZ$?1t6C0MX|cgAt2KiT?Oc~9 zuJi)zX^ZnASiK9UNV!~7We{WB>d_WOSc_pl4I(#LVKpfBDTL)X(4S6gG@uN))n$9! z6uAuGtB9ao;hT^+!t;~#*R{Dpy>vHX;b6bQ(1Cs~z~jrfhZJa<%r|QloQkj#3rJ)F zDlw(xA7$~%r(P7HCH{@BX&(276h~6qrf{SbHUF@7sKEM@iJws2bzklq%6}Yj0218V3RQ>q`cx^Sk@LE zj3vCqO=d#eg!HJu<`A{zQCEB~br2yd$2C3G1l@4SCn=(CNnrO?ho6=CvGfc@ya!Bi zQGlPb8LaHZ*Ps-M!>2-lprI5i)5L0uQ1KmCL9Xu~!|TuNHHu$qp$Gmxa-Y2n{WLi#8;t<%e~1fikG;-C?U zQ|H&f!>6&Twi(r1=m9^d5y65mAmh=+T4}3@l?H`5_f}BY;l|mZ6nTWXy)^bt1br*(({=~^1RhDQ|A(dxp?wNIDBhD3Yd>{8OxfGT@Q>>QV*-5% z;`{Y!a)F~g3UZOq=7P@%lrgi{u&Z*@y>q&vCM+Lj*}Wu)X(3AMK81L%H}r@b-! z9c94wR4jxXqqTF(bEPxM3M7(G5`Bm$vcENCFGPm$sKp<7sn4P(QKQ^01NijX9p5ua zvZw1dBFSQCUk?I}oD zF(1#88}`wH5yw$NtDvoWlA>;bNw8p4A87im7UDOO`vb~*D@-OMI|rtXOSNqASc_Ep z>oZKEy;CG>mPu6m($Q?BR3BdmE6A+d=IFww`9#;cqCR;%wwxDoC*Y9}GexP>Ld#}$ZPO_hxC_<=RukZe7NFspmLHsw7Y@ilymjDRd$ zVUwG!FN;>Bp)YrXtd;{?#wH)Jlfk1=2(4onLZG5!-~;Z9=loFX)L~gjRA9_ z+_S=(!a%xH-^J%p1eNVmeNA(u(jG~e7#VG zNbfUofi`M|5qg`(J}fN8D5-;&Wgct;yhMO%C;!m$;OVg{XlKXVWI-=&gK089*%`ak zFW%OP?@BF)v)<$J!5T;Pb^35jx{4u3>F}$C%e4nVIXwfdg^=zKyH{jW@>LzGCkxg_ zE3KM5LG;^?(cK-zN+(Wf6P;Y)0Sdf~VkQ*}2I51QV$$mdi6?oONjJLLTsybjuw(ab zikOLMl1&tt_m6Q7>#(5+RlX?|c{?*+#9Sa{b=}2lgp>5&Ud}i8o_^Vm{%zZa;@?%H zgr)_6(%;RvK>zuP&(h8X=wxSP!z5;73AA$&H*zsjb9HdAcXIjTwG`ij{gNOQ6cia0 zksB1F8+EM2Cd^=i7f4sOP6bE8Xd4H|=M`nM!i_fou^7(xO%kYM|tITfTYan27q_c3;3iK&bxRmgRt7-R+%BHH~asfq&^#A&39_2Ti>?x2Pwb ztKj<|HW+#+#PrFkq;L@;anc62>}d!_y{$j@#3#CDsRlwm{XR=(6RI25sE_&2dG03M zSJ=j@wv>cGZSs$MdZ>`$wOwlVjniU(6`9y}p-a9yWo@5RF-WAAooW-hPi2f|hMDz; zE@?hWKiHwo;W>x}BiR+UR`Z5c>6N2Urm4=%H&F5wvtmtmoeaX>E=CzH0gKato7F z=f;pYgq(vcTF{Z`_cp3>o4Rd6n?#0zG~xT zi2Szc{o*_BmDcu_p$n3u{IqR2)+cAvw(O`vmWbqJq|_IXMQP4xfV!AAI~&HFfQ}lYz4sh7hxKFJLo3QQ zxbqr+MmaO$H&`RTIo8fk5J^x@Iyae+{)`$q4)JZ4wiho&W!3Dd-b(OSEN2Z14fqO7 zoV0oRxUPTjXkC(#k}PY?p46K_7gS_Yl|-e$t{Ph&!0&yN0-$q#BHwgysn6E_Lg0NP zgw7(K=>no{PUt>H32IToupKqVa&n;eCbP?GH{jfVUFp5$8`ir!tv+cVfD?*8(E?MD zI_MfJ*01buc;10?8A05Ukpz1r?4{+uTzcMjU|_q&IO8e!9`zN1&m;JVdK~POKyUkW z@$nchC_=AaM6t2uH~AeDwU3#RTSQNg>csyLSn+Rn3}(NZdH!xt{JX#^8CwBO{y?XH z#FCpEl%^XLrzBM6_WNw!zIxMmrn)4Q?;kky2S9cF9!`=_FYkH%`)gM?5ZAe8^s>_04uI5`>p$zY$vuWGBp7~NZNcs=0tL=7RUd?!Yp zUmkaDerW1gI7mN8_9^d=ethrh~nA-Z%1-eb* zJ)N5?q7o1f1q7RG5&bc5;mx#ks@vij2U3cXO8aauTso97e^CuF80T-^F;BmMPaz@& zb-#8vG_kr^lnYzHx!2&Q!#D;BDnPEH{8c!nWMwDXnp8AD zI4IizEBrPpi@#`y7ML(of_2aKiY=j(YhwG9D>P$gmEzeLhGU&}aA-*S= zL+nD=E$6e=nmgvs-S2Cj%ve z2Goql4I1y|2^#Nd7sWDk3@uSP3du{}{w~VcOA(|O3=AsoE)%Wn)=-Dh3pfiufLc#X z){UF*iM{1KM7c#;Pr4;qq}HB0DnKjyhY{LWEH|CRoY1t%|?#HzE&kUyOt%X z+KCd~G$v9R;3J7U*oV6N^$+RrTu(~W2?_$j2mW8vLDbCB2KblWiS~2MI08h4E2D#q z_4p}0oQ$fswbJd6mKzdQ7?$7jNNT8-?sQV-FKyh7zeR<7_cM109bFGKiWIsEsTLzM(tC zC+PV#)e}qS;PrIWAT%)ZUMWu`St0k`DY^_QKT)_wi5c&`%6?5rXD z93{l_VW`mhkoRTfsp;n%Z+5;ohEE!ZP2ga%ozfi{GUv~b4UX~x0C!{JzevmFS+Bzu z9(w3f7-%UKePYY*KXlHnZ;sb!4Zi;z_aW9Ev&Ydfddj&ZRzZ-;0w*bOMp$FdC)g?+ z-4~GEFXSgKh4xLAO5Q(VFBKwL+0>Avu|Q++?HjjYyo3Htl;o6rMJ!c;{187wFsAdP zvtZxl)eG4z5uJjiW%d9Ck*mg3PxY^yO0vu1y{S>;BZOr9!+Bk{tq$aq^VxY^9IWH7 zet7yl2YC7@^QBnRm6B(q8p+eSh(X~8#`-;ba3+}6khRfKaJLW>vV{*?Ky+P+CpG?` zznQwp6K=ezjhuc9@5HXYL;rgP=nuFQx%>`@jF2E86#qp5HulDU5`g-e;+il@RuG05 z9HMe>14GBs3FMRSUKqK$EJj#kX$gc9zPSt*0si7y$^G2xH1e^OhJZDiL#DFC=&<== zW)@G~V@_9>FZzt!tHlg{#HP;uWZqLGrHisHr=BFd+Yh(lw)LClEhjg;kluxi$l5g_ zJ;!q3b_kY_VPb+2&2^io<;rz`Q#T5Fd;CzJLtXWd#Vz;jfEt5nrjgcDL=as6=&m+w ziuH`CDQ>;-wzu4I-hB)2Mi{$=YX!s=v(9A`IXG3Ch%TMm!|eL^wZrf>of0;S6t6f# z_8jFmS`Rhq`N`YqB&S?E8WpXZgkI;U<`Mr>de16I92(_FRyU(A7!D=W<$yez;{gNhM$$zy3ocR}TfE!DHlErLrz zzTk%)Sv;b7+mQ<@EvZp4DGLVCBaz6}6Vz#0a70_XkZCwN!?Z}8k?}PvxbJ$TTo&Ry zoru7Fg+Ww%3q9w?@;t&mb|lETfAtKXQ}C9=cXT=aO7LZSOnTZg=ogFU2lC&S9|nC2 zNW#AZm)h^7%le;XD`sS4V`OXtRC6(M0onrXT>hltxCuot7K|W!Ok9Z65e5Md%MT6zz#g9{D4 zr-7N|DNBRW#tom10nKh0`;c;mH&r`v9)p=0^^`M7Rs}(#Key)lLxd{JRl4c9nI@?Q z%{mbrU4hsebn`Ndha_t5gu%{`3Eho>rK!UrRq$ZrvzV zZ(3N@%>oatSrKR>K0gfu;|uP9y{p?r*-{Z<)j0Gk)^pkS8qU8;xrkM=K?4|G8%d;0 zCJ!v4W2q*_6z{hvfXHzBsdUxIE6F{e7+R+k)W4Q2wSKt5BmLunWSUf4`s#PFn1cGR z7!ms`Ml{ZxW|dJk=Sb`CMXw4qD;9OHXFa-pXu?$VGUx5qvt3k)aR<#6$z%}lE=t{n zAa9HDT=KxO!)`P8QEpxOw!K{-y}!Jjae?sr%fdCPR%d;Wp?MZJY#k8qVdJTSPnj_R z160KSB${O_bCzOSqaxh#x`mk46_R%&Z8q_up+-;b)5}-Tw}Lx#yF2Q8*}}19#a2^W zf3s1ymH^Awv5V=}jy?S$_cQS+ir_ZNs0KvdDhVV3`JmRD;K^&pEuuSK^Cm)j-tI&& zJw@aMjn6Sn2GSZWRb7MkQ6=k_X&JkuJc;%>0fFHdoB~|&tW7EeR=r+m-6FSXQTHO- zIvc@TWXpFh`p1np{~z3adD$r`Yz(O?3~nV0BA-0Aenf2dqIbWs1K=0E*#xZ33&e;k zc~~88Gpu_42HGD&a9b9wIi3*Vw6b*(RlpOBZYL;6Upf}io;w|D<*srpD4mYq26@~{ z48EX7c%jFYr}CVwDF!?KQFNKYwu?F=hqp*d{<3tt^**yZPm`#*0+yT}6TWDKpFdxt z{M_&fYpz2L-u-~Rb+VmF8j|L;7|U*15{&<1np9nO${%*Gmd&h59N&H{VqFvLt%uVb z^<%ddoN}DgI=Lj*3PS8P-r^%y^IL4@Mt9Ato?yp5gCV|o`B@T;S3E<&oXS!zww}jP z=#&Ffc3dSN;gadvy6C990xTKFO6(q*HhclEc$%x--mQ(*3AWKNu2yFE;J5hdtjQZj z?2GDlxt&1f7h|RS*Cnf~VoDjmZWv!l5`Q7XGgu6a_|U>@27fn%I7jKBSlHBl>~{Rr z=&!8Ib0On{u{^0m;Q|m?AQ)?;^aG?RZ?W{{{jp=!Wwlk^3#mtV`dLIr~d&d9tAk%98-T1XWgi@V`J;t_G2bMYhbY_Wyj!A=Tz!EA_SHne^Dd$0Qz znU8V)j#KFnARzqzv)5(poL!9UOn}Nx_6|TNm#=^NNlnexepVU7myv<4x_3DPDKo=P z-v7jbk_~SdOeEP52W3n;lvw)YRCRVET{Zc+%0(`7#^P~>7|7ogKWrd~wNrLF1lcnEGD3CsV67`ksVv@^iyz9# zO6GQ;WGPu<2}VU`j&*|kmuYr#S1auK&(Bd$2n{Y3RXN8zx<^tx6V432iBs#M9zDCs zO=Av6Q0rDj6DW)2WR+fGDW=kvEazOD5_2JmQtulJFxtU)WTLQeFT$5at@8Uf?O0JL>;eq((AgfCU0$S_^aCF zdwd}(kWU&dgxwf00KO&EA9wxmdA5&1{H|go+`;sZ2=?Lqnq5h-+?^GA&#C+~blTAMcdnLYVWe z!i&a&hnVxBGUz;pHZ%qeX6uygH7UR}#naLB?ep^)(GXFWMS6HJt}i|^GP2l_{8~N~ z6Vk+SbsRqC2u>AD3$p;Sk|q`7S#(e?7}mL|1b-kNP;o|#Sl4W=If?)~SLZQg^`e-8 z-+8cxV3p*&M%SWQY~qf?X>B`Y)#CQ)(6utkx85XR*Ye_NNZ&BR1(V&CDQ$v-PY;+G z%QJMEZq%hoKJ%>TiN#~ra;?jYzzpE;(kkz$!a>j_wo@Yav}w_wiAYl>d1WFM)KsB*Zdb+aPwfJlcjOG>qSQbPdkn4!ygEJEX!*p;U^StceHusY^gTFt&6Gu!{LN>G>B|(}sQqLxuWY%ddbC{y8#eeW@Laa;_k$ycC zzVCIrJiseg|4D^Oa|!OJ%L1Cq7qXzpTzHhC*VN0sg6{rA9Q3cUp+;~|J z1*+|TC$aY+_F!o8eB&6)eW8Gr&R-^h-$Q@EO3Q7b@&veW{Dyo`N)=+9RG#TKObkjn zq^}R*cLWt;iCR7UBX_hpVTB&!Ik9+qPR|&lu*UvqDPTZq<$38`1n5y|c4f(fF9ktf zF4Fj_$YPRYvwhVwp^wZ~nSLMUv66wwkO+0GMa%f~weI&*v!Rzf#gP244yfqHq8JoL zxO+k4LVvI175+nx-&cS*P#_?D|Fe>{)s%imRHNU2i`kq0Nyu61`f6xK7`}`8%aB^a z?{E-w4G{DrqwFN$jtrFXgA!Cl5oSG6Jv{?h4rLLHuLAlQj~pBv22c6vlWle+hZ21T zndUilM|(U+8yh)You42MgaB-abr%!RCUN<2Z6_0mrZj+=5*nK1Mxc!3r8EqyUL5n} zb!8w*Ut%D0Uwt5K@J~`!0&o12knmUPER}3C&LkI+oo%1;!zWiYYt1vsqRxEh*t*~! z8ENT@7RQK45iPByN!Fg;?#1fST2V!IcsdN(O_^!D1Id8P`%>PpN;_*=MWYSx6Hz0! zwpNW}7@Xr~^}=b)TdJ`&M_XFWSmnk7Cjip!y&G>+VF^KU_C5W=*W3jio7Ds9`X}1n z8?cU+vLE*KkFu?RX<3fjP|cTjHY8-y7X1t1h$Z%XG_4G?g%a|-jxj~eC@bfnzGYls z-O4d1bc#*|j!qpg9)ZNTr9XU=UvpF{uU>=(P`TndECRZMK7f(mkaDiF4JYIB^C20q zxb)KonXFjtP@4=Fd&OFi#so1u)D;O{;30t}z>77nnQ4!ovAQiaQU$^kA`RD^vR^(m z4Hkmiqm}Aln|kRKN`^36T*-#y%W7dZ`()uSRY~+rev~s^*-Y2#jg8XJV*oVnhT_B= z7r*E?Xc|mIbkIN%{2^O}6`V%L?ZD*hS2U=|RinByH=q4ms2A5TArB zNGT({D{Py&&$!~}&ouV{+z&An<1gFX->>aOiP!i6$qtbGGSK_WHpgt4HP=$1SHH|W zj%l8;9d4Osrn-9RUtX!rQM6dhn-I`zlcSfRL+zC~ybxg>_3Fgd*a_Pkz1v?5gT`%X!kCqvOuWR3*+-<<uFF{`eWWS0Ng#+1~I=~$Dc1pGw4QNkSk{P zMJ^@3&0C)~y`H*! zecVB0wuNcx-wy7mvNo@Nw|0415peZ!webYfZSXt=@@@s$e5RoM}BVj-tdm z4#LPHii))5eu%{K zNLHJIt5$SM%QKv<)-^@>r0%Yycu>E+P4#HbMefakzyYLdB$5N>D8s)3KuDShkj-C6 zPZz#x(uAJ+%PJ-!9YhS={^lLvNB3rYp>vN7`gl);)@0+(gjzvPq(WEbU62=(0%Z9z z6VXhe5f2}5tp!@iCy>?{26oP;(9`^b>pq@AarB@zK83E9_7Kh~Xyiyjznq%ZAc*|* zp7|GL_a|G@B_2~&P53kCeav!xxIjEcThWipO(rK zt{i`d_2V(G5h*@FYQ^xfa;-se1*R}woi}9ANb$~1uwE0)q`pR)qT8u<^&d2)#! z2Q`ak(8I*Xej|;z*rZ-C%A8t{fAXs@!btpP8zbjQJ4{x*yY{^*E(V-B8Za!}` zv8s1pT*0<#?GRVkX9n!T5)PTvD}y7t3d?Z9UzCLki}qCo6I&x9iCaLO3e>D788=j9 zyEMLP9zt7?wd_YGzkNLAL`tgWuQ2x7Q+NedBX-DTZdSa*9!P+0o{md7IJJs4`}-e5+@6ilymFncWwQ0FaC|tN2oP%y0rm zY=>XZQvKzPcpAGuU__x+3bX|j$186#KC-W;VVVkOWI#E8guBEIM`P$sG26!T82n7f z9fJ)$!f`7a7N&EmiN1J_!g)7%Z)D~b-)KnLbOr$ zVl;DXq@S{lbXJvARn-(HhEmBaGMO+Ea94mu#P)hHj3I#NHXu+mV^SoF%(II-K`HPC z-*#5bwi^@7Xf|6WaOhb!^P4=ix$1f@1kg%inJ+GQVP4>Lzg9q>v0uS24e7sN7#<9} zM6b#dl7kgV7T-KCk;c}Y)~eMZP~G?N-zZF3K{4WW28|B5gcyisHLS=oX9q-Dc0RHs znPGd6v7cW?L*g7vnyPg5EO2@h>|~SQK!$i_!r#rrYSdqFb8W&-UN~seW0<$9l?TNW zCKi)~*rXnFF2v7;41*yKiSLh=&|3Yh-Jv<<&@!G#1W9>xH;0~?I=NxWrFyzNvb%VS zWIQST4L;*C*wz?Tm%9 z6dY*V96Y9q_xvXQX0@z0EZR7}d&4d|7a~DQyd(-dytU2Goq-j`E%ZcZx^C8Mx!>#E&F@ zUU-t8Y<=SISmeC+P6+=*P9UQnHGt^xoBqHx9-$;FyPu zf-kw)!UZ3+Z!f--(>`_$tB;?ctt40QU&(Jf#}UEYVJu$Pvv|(!^;;OnyG~p?H3m*Z zoM-M+Hs-U|gbPHS#o`GlG+_=$t2CUX*}`Lf6~VNwJKcTYb{)53fc7!ZvTPG1a!kFs zhH*d+p0hHxO*}^ER4jFOMKI?g#ckB*7)RIscCFD3oLV-bCk@WnYH6NDee%QJ2rhME{x+7QALuY?(%NjY7s% z6r^)T(NwfX`=FdHM?J-m_g=0Yvv>)+D?6C@JyM5L*O#l%636O38M3*2>XTUx{A-(( zSwZrV$qBH_wF%v+9;lpL9zwWSk|9WI%<8I}9j2*Au(9GzdF=Z>JdU5nh%Q^v^ge=5 z-ZaziG7$MCfl499urT+Mcl=frJ%M#b|8#75ij$eQDfmdO`n0Zx;73>f8|Jo0jHY4h z6H)a= zJ7JDp?qy46Wc_wp@YK$Ygb+A&s0)rMP_e?Tv1}z@1Suaqg$vU)+^gyClm}|wG#uyR z5$#LvlC#eca2r-t6a>Rmbh|4Px$isJTZdbmBF_T{-}a+$ZCayOZuv7OhR45bC@(lX zyGf_jC1D96JgI5-HEVI$S{x5$m*&x)kq&M@?kBKvrXb>HJSJq*W{L)ptd3Cj&H&^c!CLt* z#dZfGqdYMhB}nb#fr7zSNwj@#5FenVg^X6g3Zw!$w+`#n$%| zdv5H&?`@^qmxha?OJ#FdMV9IeYk34?>(-DsVRbD6Q zZPbk4zuHc!jARN%FzWPaX6g8MY#hLLEE9j#j0&{VmmCai+FN6p+}J#@TbJpBb4nIl zfjyKTBgraBuYM0kO?{SK!NsPufqgAkx$y@+i;UzlrR^wwDc{gM_I^R%7G?A)W$YZS zt{&8GWW@@BNSn^!Q~L?gE!LlNPz~PL!>g^-RWMssPz`z##o`HbqEOu;hD_E$!TAko zR@da7^Svo+Pl${28`12M^E)5+C%o|;Hfcw~URUT|7dPiO*x5GjPiV*Yl)*!(SfYbx zroCsT5IWxbB_9hboK|Ru%9UgAGIZ{d zmpO27Ro!Q*Yfnk%OguQtA*Hc&6dur{Xt>q7L&bj6`Bo8@>{Kv(XNHqwH}%o6B!xb=SG za~WcnZV!&#_6t5lHy_wX5YJdaJ_r|wp^z<7yes*p5JA3Rm-@1Zu0i4#n?_k7mk03& zbc#!}2lx=1_hSP#zKh!V})0?GhS><<4SRrP@voSFOXMb3%mOehJ~Om@SGhMTGk+#f(RFQFjay{=sIW3pn7j zq!7sWBiN6%_Vea|E<4+Ipjy-p4&G#s-PxPfJNQ5LQh*jPg2iAUAUPjEKv@5C1t6s7 z=wzj8=4kr+QXnenj~&`z6Eh-Y=s}1>m_tAPS1(#r-?P^;(-1n}UtS`Dk1);GhlR zubZTFONW)Bh6~M6nhaBw!4g0ftBqGV=+i|Zu0oGt&JAlBU|yZ}SdLNEn8q~HvlJsd zRD`pfw*_Ea-X41Oio!jZhkCfdX8o?3EeYhO^&nt*v%l4t&F3M1mD=(DVA8XEn{OzS z`Yo|Evzk|yk$NZ6HNnPJihdqM>7uIV#O5nE3W0Rs{iPB@r2!mJ*Tb~>G7H=vBfZwm zA%=6cfMoxB`*o{QeVILfW4*jG6zQf&zP(=(2_V*0`jDzP1lU-e#%jr!8AC{u#2qr_zSExh`2b- zpzNYUbWy9p<0$r`q+fJR`|wI8@1UFE?sGNPL-6VJy8|e%kl(}LMG1P*qIiN#aNH0X zSg%mEw{##R9(X@gzJvW^SNBL5RW0q8^Z@c-=_oRP*G7zFLhNBghPVgoLl(%*3&iR} z)q&0>gM_TNqO~=&9JY7GgGAbthYq1;{gKeXF@E}d?FqW1H_T|1%7hN@5Db~a@d%{! zVpKs>aY7zBHZW?Z#l1uhEProzb%+bc#d5Okxgtm@i{4dfqNy~>QzlCUU(oKm^9Ek3 zxE-KcwUL%R_iQ{F>z0z*gAw;qt^v>-iFZp_su=!JIT)_#%mYvm5PAp@5Q_h-oUE;$ z-CtR_iYwN$0?528!A&BKPv$;B-fMg3?&jLuv-34g;u z@&q9aN_EOuSQEmiDbvd4G%>zAefT5)tgZJ8oCjtTSRnod7(Gn;?g7>iffN0ysvWy!jS_k(iCi(yq(LDp>$6276_q6gKrLpG9=b zP#hYHalBr%J?4tXOIZn<+aUYCL` z8?EahWGJfe2;P<{p=Z{z?%@;i1z)rKeRBpPTnqiDh{d3k%M=eu6#KbXW2KCyIj=ha z&P6v|(wE-x_xwS1I)h$Y2|AdMdo9b={Y*>oah3FSKS);@F76&V?KjZbe+3*6K$Eg!VWbVOI#V%qR5X)WRS8 zo(E%NKkt5P2!c%LZut6xa(_6*ku!{qkW0a()RvfWF>gmE{a|)|^bprgofBRu|F}wX z>nH_Zd!QKTpwh!QC5sQz31*|pWpTm z8d%@~`G;wKtgo_gW*=%}LBGxWa_V2_7n(&4lh8_2j>3?q%c-D_n13E7Ph?XoD)B~N z0y&hehxw8xESkHedbApAx_PN%o)psbFOM7nYsYZ$xcg@cJ*vu#~r7 z*5YV9l1neU)~$pUiUj+3a#~ zPqq z!%LD9VFZUzPgJ+oi^eL<3#vCkwmnB6f@)z{Nb!`x(G!8CXzQT;%USxzOhrHCh94B! z97!KeAR1^?x{bucx(dhJF713=lV)-< zt^18@em+k!E_PFjbpNb#Z(rZFko}`5gGA+HEQ`XRLvojUeMHx~59>3tVeKTfErdbp zxKC1TG9>xA%9d8yYZHGbBv|X7(dBLk5Wa@Bo_@+z<~tlT?L}=U&PHz%&N+(4Ux=z4EZl?j8B?K-&!R8Rc9RTt7;ceaD&b zhiNk+RCu3e&bbFZlfYy8B)jAkd*(5sPn3FDxv6u6Mb0j(4O&>=(Hr9J7d)~BE|%6h zH4m55du}e{7TMGUrU1(`FE_ZxB^&gmE7M(q#8pkbGbU8BQ(95Mh*58M*}`F%2m(=a z)Cy5=jbbhyen->#l5#cc`%7y0wHW?KBm9xv@Oz@TjPnPe^KW!<#NTnn#ovFUgwK7O z+n&jY-<(4|=-Z7{`ZHa8+_NgfTSY>l#@kq1++1E;KbjAS@Ecd0?vGsYr#Er+l40^l zc-W!k>LYyvLtR5%Fn!|>$iJST@lx<*zoWeKwD}(d{E|9B{%cVFt1{9?j(WfG-~VTQ zuz#n|#$3G6-x2pSJ*(<|rxGIXZz^g1qe>$~A2+9l28OzZx*+<-;E8@c!G5E||85w{ zIr@V)JOl^`I`n^4>96MtnWCMgq?xthpHxapT2aMSMjzCes9~ zQ^V*BG&Cg@{LBK1plk=N$W^9SC4P7%d*SWnMCj~M(`q`3>TZi z*u7)%k(3V7B9U%iL^2-ZBT@E8nMKknhX4i@qX3f*YSM02BPm99vP8&0ca$I+`(6QFdG3za+J6ZaKs}p^&-|$2Ot~iS3LZ-LL7ll$fkA!v@{nk0upR%R|t1D80|{B)8()4J=JI zNV2H2ZFF8NoiYkhQG5zFh8A1pyS@FHK0$zG%#6c*yDi}EGK)G@u~Lz=vht&fTG*kN zSoEr9{~S6s=6Ge_i)AbIr%F$;vZaf~N9SX~iRB8dbhN2OvMkRKI5je&|MB;v_rd>_H^LcC#vR`Z|h6Q@V?jH0Tc zfL4#BntELaw~4G!yn`Fqtlje|C&=_FGPyGm+1dzybxW$$UM_tx*mU%vJL7Y+O9V#9K(8(!N-=Sl29RY+9pok*PP_^YBE>-fu} zyG0_=d?R3<5>MFZp3#V&egvLj-kw2Z<8?&Bao1wcP{$Nk72OY$v7P*OiIw6k(t-sE zIUBL&(t^Ddf}P}ArZ_m9*iZOL&mXJ_f?Z`k=BzO6tfRghnJCqb8@{$w;6oO=9Zr84)n#$+5HYrya%~B z)*LB32X<^E1bfY84R4>a)I`(eVdti;6aAf@d=y~kr;QTxxmu#)HAQ3O6^4(=V_mWY zjQNQ*2g$+M){J&Q1ATOS!q@R!6SQCH%*Pu`k~VUnJh5n8kz6kLvTLXUk||F<*rHbfBtN`*-UDa zi>aSn1-XDfvWVpmWKGe0A#pvad}lQ2O!@82XvN8V>dFCssLdSYL2Jt7A6-3M*FFb) zJB0k5UQib}lXN`Q7jr!PS>4Vo~v1g3A11mva8H%aNbi3Cpc;9!U3a zaYz?c0t9*tvc)GmWiI#_HNfgbhR*U=uzv&t4eOqz4j2eX9OQp3eia?dA3#gd_R(k#XMBjw|XiFLG(QFXV$Xbnx@m4A3sFizW(urx|b6m zP5?0jX!W~Qhsg|1hmZ{)?>8`CFISW94#-M6j;c)rKa7|#Qq0y>!q8B(rJ9JSP(^lK z8BYQZx^6U8(nJ{A&iAbvzl%J^hD|!^zFF9nyCkrF28ac_>B4QLz)f#%6xxrmjS(j9 zCny-=gjiCf&*1pTL%EFv?cZcbUb;R(Ml5M>2m8qTt&}Y+ci z0BtEHA~^C+Gc-CAj{394fWM2eCNGUpD=glUsEP%+(3@cUBF9LeP*;q?WO}UzomgS2 zNcuL9rM0$QxXwtI-C4K(wA9qLY6b>@c~J{Z^|C{m53L!%s*l-GaM2t% zTU^#vT3YsLpxAILxwK4hqIfrlF~AZq^l>%o(@(&VR#TBm6B5##16%{b03r`-td^@G zk;lc7K$dU$P591%qN_1uRxcblm0up|gI8E5*5jP(eIxLvHB~w^MwK%7OoRb^oEp`e3y6|pVV;2YR=GjG znS#2JpU$HC%w1(;Q8}({;^W=!15%tzDcBgVd6 zQjhDGYgwjWL9?Exi)BUiJps@Xqyhb``k^eA+VH z7WVUm7spHt*$dPr^&=>q7Ke^sC4`rAdc|)7D1rW3i5PL;#3ZOIN*XLf&|Y482ZSyQEg-;(YAe@wO&hH&KPYnhlCnHfQuSiqqfnX7&q z!&mv;fmm4zC7$*RTe$yW*zWJ&Ec_=0f)unEz(1k$Dt?#55ccv>zRlrT>a!3gG5w4~ zf^o^kjh}AS&?;pT7C=KHaBZkuz4N{|Nm;qESdL`gMZ zwZ485aqG@g#kvuo*jkej@cc=VIg(vdCo2&DOR0mkM1DDvvN)DISAEK z+$aINE%EPbH9>n%8r0byD&fioL-^}3Zsl6XdbxdahZ3(z{9E|PtXfuek93VZKe<&B z6gm_mtXbmn{u!GE{}P+%NxxyU{_n9VkcW+(3Lx^0^TQTnW~u`DT}6w5D|>+a3z5dZ z7RkT=)56YwP0g(2q$PU=kiAw4%LhzfyV9}RQ5a^P#hV!^jO~xMJ)W zKFJi_0sLKrf zSu5#@O^mk1E_0ceF<&KX>l_zmP|Yf6teDeQ4UB}zW1O_uG4Cm;uK^*Y>(1{|*Jy`Z zX6Iv3z-}NA-{@XN4Mo>wPwL_b9@#MPa(m&_GP^biT;X20_1k)z`MKOeTz68sd<_n# z4fgv%Wy72>uWXktIC~0BtnE&9AAZ-ld)YsQ$owU({94ri#hy}T4vt3FM)tplf%UHd z<@{T)q8Irv@zNHmyI3>VhAQ$w7$N&#dc7FTVw~}Jpg}2)lr^>!H`g|g(^k<}Cm{`h zaVT?dCR1pgd1Ox`+KZUWsz0&v3nOyuIhb0EzUAju45i#bhCU__PTW~h?r2ziU zM{?$n)FNevq_pFc&&LVyvuXoT*s;u3( z{s10FCAK+M9z#mt*M+dh?LKoS?d3{9sF_ahThE9w%h=GKdN92EP|B9~%58 zE=(ntV8`t=3fhr8B0>y6A}+Sp#YwODa3MC^zW2b-!qMmu(pn1zV`%1<#c_u1>TEY4x&fSxUvkUB@~v!Fu5n^JhFp6vN+l*>MlMv{dUDj7>0 zCt>{rpR#>dn}lH&o<2wMgA1bPp1y*a{kHRDvl&82;Ms)1`SJYw=9?nRr_8*nbQ$2))kJ({HE!nutrvj;T{FBHXQhPygci7Euuz*mG*yYjNJ|m`@iG9R{Vk%SlT+(Z}+8E zp#OZz+ZdSrr8_1l{`+>fRqUihA0zTWXPHy$!u(pqrm{22J5-y>y#jimep2{75J6Hx zdVy8TlTOwjim)pLwFtuyDLr-1sC=un5Md^K|GiITq7 zXyCilq}y@X%=N{jSw`tY02`cHX1r5V54jsv5L`?)cH0noydF9Y-FbS7=5i5jiFm0Q>B11Ib44Ke*)%T)ColIqh{ri}w!Q!aBQbBk zZ=&cMW~Q$r(n{ywtXTfbirZ%2Hf51OKnh6z*^0mYwy`(*vn7AqqlUlbvVXE-xjLNZ zmp!Lfi^pICi?#rCjBrDxr@!)7~T>-6aTglIDweA8X|#Jlns3chKofhUcFr?hsze5_n>5Bs3rFUV5cHn_ziw_HK-Mq?51IMRqpVnQ>uhHupqf|!g}isdUxFFG`!h>_0HS$L4Qf!#1`w@S@tE6?t@7Q zK^-0vkh0+6SmK`oM4f0b6NIrj<0h12_eevKJ5erRU{6EC6}q|>R=cQ*8K-@-WR0KO z=F$t2F7%{`|4LqSzEr$0voN?zKHZ%M0bBDaK*O8}8-E^6yk}c;>+@Q&x?y2BvGhjf zOnl8$%3R&LAX64Rek5Kr>j24R&VV*Ab`+BOzI9AE=XGikIc9D3T+kP^yutYC96jE) zijt$!Dl@IrqaI%7bl7{-vV$rhz!<#o3^91Q$BNGDEKnUUDUl%T#Dk=|ZolUpRpQxQ zL&GiXE``yuJ7)m=LQvk|UGKnnIWq%9jk=5sN1g%GaI!ph`!3*9<%YA> z&jGWD!y}Z5hPbpkf+#k7YT&#K1+gXdn1@vrrL{{mhVt7Hdi|meOWtB~?O@7-1w+dy zxqkDF7%AbHjB zoB1@n#j}x}Un24kq!I!vqH%Bh1^q$vHlv86MTClJ@Lwuu)v*-8AxsuTWZ=JFX?9X@IoSDJsYWSQ|^8k)ou}eVvi0 z+~vw?KT?t!co&i}XIUVvJ;?Zmz3TtBMlU8@-OYnM0^wh|eJ4ALZFvnF)qa_^72+plY3zLr{ zi>Q^SJcE-Z-~!J?R`a)IR)uXJJYkhfmB`yL(yv#oR!bGw#ue>Q?-?bOG(zhnv^B`y zXjO_u3djNbpUY+xGzzy_nne4t9zOAD$k>}U&QX2@RG}kubeSi1&+3m-B>48d~+#wBrjJzq8>hX(mhPR`FTQ)BWcDY63b9{>3xY{ zFBNj)Wo&}FpsvzxqnkS3(DCKz$-PHwtvO+W1}PUY^x%9!nw8h zPR_%GqcxePnTlrRWq8K<{LK73twP=#zP#0A#iOTuEhqNV`pI>{P9&UmdlOS|N6)}+ zT6_WR2zr2m>r$cy;XR-DnhRMe(n0C{W5Ywm-DBCp%%acOAUR`qd`(RnNr)fbqT0`; zj3MmQhPHCgM+Ov<>?0dc@;i7f>U81VnW~~7ht!0j?JHM#+z4rV6sife)PxPm{FI0b z$KJ>Sv#@Ncb3VmzpBCXSu%QhwHT$_#IvFbpI_2SBHRo{2QEkUVgOB|lpZNF-qqnu` zu%r5N*}u}cON%n&Sc@YCEtVs(TbXLNR=b@gZDm?{d0MHpCNr{kQljq5!oWJ4gmc}4 zvH;N_bX3GFXyYZE$Zw*BxcE|g`9_`J>`!7jxt%|q# z8le>w->_x2>vKF0ms}HobuJiX_@U-txVv0X+xJ#y9n=(`e)Ks7Qm3M+o6Lnv+>DU) zH7;=>OG*OH^p!i37qx%%xn6i2%z0tN8l6u<~ zaIuE8_ah^t%`ZQF7R))7O0U78LTr+hl}d_h&f6cD_^~L>B1xkLQwDdL*hlSC#i*im zMoA&I=v+{rU)R`NHKv4&xgTjE`XiFrnVa%%Xph5`cwC}+SNQ{ zfJ8Ew^;(2)mTxRm-+q8gPZ0Eq1hPrZ7nI+>lhP3TzIw(_jii7x#emy?6AI|@B9~ZJyYvu{Z(Icu+(p|xuA)Y0CL;LiAearpLc~gtWn|(b2 zJER&+rn&S&ihr{18V^Qw6P{9_Xe(AUj3?uYlGo@Z&8$mKZa|j5w$c}uh6(pOQ+Big z@gzzFo}oMmbELwMPSLS3Dt0lUsQM;eqL)4S^Ve{;kORocs4bE5r`^G97T?_ zj^&G8-@RcE^>#)040)@7;_`&%ud}u$P8G(|T~A{Sy{mWnL&gT{sX+{t^p3N+S6 ze(`p$1fxULEXFJLmgp75{kP(XQAKOYd;VaHo#UQb5~Z1(X#S&Z zKEMy|3UYwxe#swfM@$VYoz|~bXvmFnf{8A=MJdeBR=5YFtT0+!-$LVm&~p{&nF( zjA*pD!cwIzd~^9bPv%y-6?y{P*u8W`{Nz&IdgT3q7*%%s_N6;KRhB2!WNji=>QCYH z#GMCU@`7m5&#Ds&TqnXJULBz+X=fPpXqC%CtN#4-$W|uabv_0LEf_uu(2^4`sqMom zvdbJc2DE9@+J+?#9M`@=GW)MYZ*wyj1mC&bPYf5M^335KxKAeabI?&4u;LYi0a#E) z%gcO{IaR5!O{PpEW}r%?13Vg`)K~h%bW9CNV1tN|jVA1e_+u}`o=Y=a`tz-O@VUa7 z#-H*^%=b^3;p%$3ShB;41&l;IFk(K@$Vt$s?@-eg&R@iBOld$4k|iWlK7{(m*du^f zqcBEN8oY5|FeTq#!ly2(ZzXZ%NNnjjU}o2-;%W3E0x>E$T&~uc$;)>+KY>ORZ}sRT zq)?j&e@?%4J+Eb51^Xy?Kxig`+8@msvc z(!EMABRihWw?Jhxu%4B=y}jgju^fWRBkNoS_kLu^j^{b7wl`oyHvJ_iz&1` zg;UtJgIe#7$X&e|o(16`mv{6|I80lw--LUS(>IyT5!5+ZUEZAUdSI$36q}X-4q&)= zYUh@enO!1KUnOxz#$swd^lK{MXzoXjo^ZvOSB}E6i9V5~_)h`i*JtclHzJ5X`PCoO z)pt#u78=WDF7oG8`h2~9E+wDs;$IvaRBi8dJ zjO$^7)GZb36pUqV!q|)1={JvQ(d_=#BL@zFd*V;`JCt4ogoO;-c{k*%;z*kiUf3}+ zg02|^1By4$Sp|a^Xk0<6hcIp8Me66+=DD>Z-Z6PEbe1etPL=+XGWN3j!0=?YZljYA zZ%HYMkL9p@MVlR8#mD?uQligXLeN+FhxgR$836pSe3SEf3g({c=JX96vE2(Aa9>6l zg31>nbidDyC=uspBIm<|hYKx3Qes%WY_Y~VWfF~kId;NCDD4NM-b#(8sH6ce=zb?m zys+3#M@ov5T*pjAyy%C$u?n84g)cZ~Ozaqydm<1#;)FPQUJ~c;;(H=~Iugy;Jjj`a zYf97Zv$`?xjMVN~yHVs3;O`Z@afqB{xPX5}ot&<`Ky8mqIZ|GD#G%VuL;$RjFfONo z=aoAH(kMqjXGGA%<`XoP-!}#9M|`B!`(O0i3j}2n8H}vIMtvY=EXsX_Df@ot3Rd1` zu%5;XGKO}JOb8;|y%QU3Jr;Tg-U;=O*Jj#ByYdxqARw?fARuJ_u`2&tL7u4&ld3q6 z@pev@mJ&D!L?+@0=nYLBh6c~8`2zq_EUnYbu$auk1T!-@6F{Ujyh$E24?;3#VbRuB zi;81%xuP;jYk{e&fof7sj^DZ9lcH=9!$Bj7lv&_A2 zd=+2g;Q+7R$6sG(k^9|{@Bot!^4Bnb9b}P1Jbc5Ahj5sOZ@Td?j_~k^gh$<|#vTce zxiJIZV!_9Gc!Jqay73gg%?sag;=4RQ&1>It;`>beK*A5*@MDh?&+z;s9-ejL$4)%Q zpFd%5e=6Z;5}udvbAbsNHLWR$HEKGerIM>dZ31GYz}VJQGLu!3*)>Wcr#hZ`Vq)*u ziEj)FRP{yHh1;Wn-rm5vXt=$5MWmAuAseL+0%P*4ZGp(@E@lYH}uqMEq3euhD z^aj=j*G1ZyX%leenW63oGwcGgp{i$fFsutX3hFz;Jpo;;vY%Kml9!cT6@CbXnVN5OQ5Ed747aJ58Fbmfk+QQ zoY@^iYHKR4l7)DGq(DsCqGpvgC98yzT9%TlU7*G(N#_bQL|aosJJQ;~U^dz`Z{EUa zPg;p3)My})i1so!6YW)LN4Bc*DCIi5N!hA2CY0nrV_!C{B?nr_QgC%B+{P(xcj5&B zN2E8<+AdJJL?dg<1Z=+gH3Ig$E91jjQti%d=~vScr9VL&yD!A+8 zY9^M}hO()&4w1D?PyZ%0mSrWnf5el5$N)nQj=HS zV)0%}X4Q03Nf_=^H77}iyl%0W(AAM<+0YzFrN z_p!O;kQUpVP#4YDK`Y9GR_QVnS61DgZ3*Smk;`g{Mhby)I3hg)ouknd9F;0h(aE^J zEt&3IA|bGNR3?IDx7e9Y<@F29_N^bCAI_s*2rL?n>5+DM7d_k3T2}4T`z*JD4oywO zGXf_XRi>p3i#@sQP%cYnNL2{AM#8TICKC}KiJei34JED6UsHAHc8><_W<^H{F05kF z3iy4aJv~%Hl9uUi?F>)@l&Kz9Q5k6&U5k^*zL>&YW-2$ME^33ce@d?!%hC0+RZY;@ zn#?QR$`&Q;u z=))4a=hlxrG!lLzNOdE!Rs>qioePDJFmWhf5^BD7t6RDJ0<*6#=o#Z#=r3&32(}H3uzhu z1#jokJmz;YpGfk%OnN!Ew`JUfn`PX9-7@}%cO<+k<2}4jYjk~M;gaRsw*mj$S68bhW2rdlURt+0(lKXIT`j+w;z}ZwRF~H6P&0MQm&rni3f6jyKt*k>ENp^a zK~qcXESRI>XZNNoDJH&_pBQ9;l*z&_96ZpgN7T_3QQJtWC0s9KEzY5q@Zq;NZAj^6 znGFsITq7mESTe-5Ho~X6vc;jj66=}Aq z^eY*)J)P!`P!*%YNv-$%gh_4RXnS2~WOW7O}kq9OATRuXXxCdIANn|jc z+Q#W6;hD$1O1MRD)`mD9{RK`m_iqzz_tmctayEkc92j*}$Bw~8y(O$B2lQO~ILG-b z=*m8KF9*okA1CCx6uKiB!wvJpTSfrp(;sMuXi}_ zF)uc{dN>I>b_{hg9Q%GtuotcbMoEM0c9# z5Ya15^jSoQO>`I0-6pz+{9R@7XBy77_%jW?7JtAu6#pjW%SE5*+M;nf_ez?*SV!|w z`E!Y0PwU0_XVW*`b~K(x96#{{&2Ile2*2$?RNSZk+>O#W4*Zj{1$M%^C~J({V8T@x zIGg{32VpP81qs(ixDMhf=qKs(bT5UDtFY}a$XDtfbR)(;kLf$EBh=#})>sf5F<|({ z2vHWnQ4c~Zl@kX_&S`iQ4*J(D zc^nmY!0nZeT)Gbvd77!Z6_4Z6L#W)f!0B;545_)&w!r0ad7OJuGQcFr0lmU1Hz+FYd!M|1ew=S{e?)-7I;fVT@Vpl^*d{9?-XwU2dj?gWeT3Tm%W9 zBu#O98xDE~37n6#k*gXb%MSkou$OMgUW<`Tc_VVEk-N#r zJ;ceDH6oW9Ibbo8!&U?2)l*2a_mu#iGy&|`Mw!Y3!bCY}KB0Po>khaYhA~zgpmAKY z-S4$m&l$$};S0W1cKE%H z8n3;Km6r(e3R!uTth|Ovc)h%p3vi)f@=&QXRPUb+RL3HVY47E!Y2&GLek5KsSQ-=Rl9~UX;}?_P9BD5!?K$FRtLl+xP=EE zG1a6FROc5P>Wa0}a1c{UYDLU|L(~?Km(ctvIvZt>Q%jMv3F*_3l|)~HOKH5UU{x`& za~f>Jm{vM)tsAp!%oW4%7ERQ_NuTq`#C!^`3FF0Sm@H05wKxN_!~&cu7MYx`;GYAA z;TX+aAdOTS)0gtFjE4nweRTMFqJwG7GS4Si+IrsfGBUlKOrMDfB7i9(h#8_4vqc-` ziVjQE0=uYteE5+Oot86pCH3Np5AVg|YzyM5!cjgpVx0wX^(YVkU8`i8J8j!>C?&5H;b$ zn6Zuu|HLjo9ll!ssZ_Z$saoo2KB;(?^$sJhf>T_LiQ*b6m20U=ud^7r0XG^(nu*6o zrs&G;2Qka6z36HccK~q%72u6j`!~_?-fcPF^lR17c#?6@q=u@KhcUbKl-`a?v8TkD z-3D});f&MYP)+7fDaGCiN!(R}y~V(4gyas{Y+GRW*sJ$qd_$FQ81*~tbT7Zra2S5d zVM7(gHYb1B=TfTxT6mns+jT$g_yAB#0|W{H000O8twI_<{nY-Ln=aAiS6R4!v|VRLisy$5&{N767{ z-P5x(J3Gn(D;5TK43skevnF# zjh+fn!VpxrrYJ~H5t^bJkfylYm}pd@)010M3ZOq zv;m{|_nH!8K$a4#DRBmjA$+_6;|NYLU_9lW49HPp-IyS;L<8~&$RnV$0h0)rL_ik< zrVubi=}L)439{lfpoD)<>~_I$2fC7sxspOjcS?E~icjfjurj5Wru5d7KAO_k zfZ0kvP3cc9Qz;o>C}~Q%reqK>kdhN98DxN08H@@4O;d)T+>}fMYL%fRj$u?`I3*(} z8A-_~Lpf2&qGYrOVw5quGM4gj9_1uuJSEwbrcrw=o^HS;$_z?oQc^+5EJ|imatbAL zbY4j;&Q-zs#|c|W$vjG`G-bX4s}&bjs-~wJ>c&st0sA1LsvaQ&axp zhE2*@RCXpYvjR03YoV&nCDp`a5G9$E45MTOC8H?GqGSvu4S0>@o2pzuPZv@$o05xkWfkQY>&hjR zU#csYQGPikr%-YQwYpMc&rp69VXh|ayM~f$3A~Py>j}Jpbn8Z{_gB)p)r4E4DSxB< zCaQHaCAUy=E7e*{YIqx!t|Q6aP6c;RawnDEMM)bacT;i?72Hd7@1x{?N*+KQ|9}b} zq$&^5(|QA{m4^v@guqAXX#*u232djQO_Xe=WQ!Ydk5R$nlsrMnR!X+fP&idNlla?C zxE+-2q+}O${ty-HrYcWT@)S+*9$nc>z|%BiD6wwJvjjdzWzQ4t1&{I~Eut5dmneCe zaIet1dDWx5ro2u`uCBa6`J1}(mae=_k403sh*)|@Q{FY$P~|=9{5^VlpPt?)I%qmR z^e7)$eSA!qzw62;n)0c^#*yjz%wXe{&voSsvMOH^@RhE7tt;Q?%D1}m4_*0ASEMca zL05j%m7jFwpStohRsIDjDE~5)UzLAr%5NmI->Kdol_dOIS^i5bkjwWE|PVTqKodj=%EWAmGs16h+ewrO+X)A^rgI?F35t4 zR9y_9JWUtry2#K48BlS8E(Ym>j3?0@qKiyj4AsRjT@2U72wjZS#VB2zsEaIJjMl{% zU5wSmI2^t>NfYBWkLK$JsVGvzb zIVroWvM{eadqQ@3He!((qJ~u}OR`JLBp)1c1`eR5wK=D@r5S;inr3^D4D>0*$l&x* zgF}x)kZuZV^WY@G{hqD-XT9!BZgCwIC)GqVaOsHz9 zDyu!i&!AIPUG2j9CI0%BQvcG{+9p3eVjop4EluUv5LxOuyP%<|s=CfUXmQQ_>Ou6} z(BvOfEOAt4v|YcbY6;a(m|d{A>a?msbyf8X2bHxn)z&Y>8c_j?b}e^HO+#)OjvSc~ zEe*9b4EXFE#8)q>YAW-$-{y^)LAQ{Tn&xY4K+wXsjXRt z^=q5Uo2u%YYvmXca;KG+<`tD!PAkhRbxbOXyi-_FSw&HCQAHtxt{tH(hYViGAStY< zWLi!^er~8?kE4`Y?Yor}mzCw`6jW3emruev5j?33x*xd)k)T?r*Kr*-*BHb*3hbV# zL`O{w=ZCOvtbaI{RAS)L$tlgto|cX7@Wa-3H>-D0Dwv%`||Qo?y71!@huo3kp~PQoSOLJN(r zxS#-463q}5B|Ft1*Oo_$6PaTpyE})HGcmtF+SMKmI)|`mgi9+V=O^bm`^+yaaSXGk zlk*&@MuhI`luC}JZ-gHxEo*ssZgI&}g0n2j<(0)HB+}Ay+%xPAqQ50TS(H~aAyklR z(GIn-@dK)vp8KM4jiznn+T~R?l zYsj)qa1)3s%{zHoK{gtr?DE`6wDF*v3i1MAdSz}yq#((GKE8P}NF`r4LpXp>V1Oh?dBKot=}PUv@ZYYGvdttM)gx;Fg73MOy0Nl`ISzr$Oie z)cdQcs%$wX^%%Pq%5-%85u4`*n^Pg$7}~BzBd4=-!syo4xA>dttLkjR5mct6&UTWa z{i=3;Ym0w^zqz`pwy~w5Y4o3<7KPhn^{ItbjZ$)WDAz=;#=q7CIzd`X18(ND7Zy6D zR6Kt%5;*QooXkpcIKQS%IlHN;YB__F|2g@|`2%Jj-h(DkSv(8k&1 zNhT2)XEPqE%OE8+OpxKl$fKZzA=UYK=N?adn!wE~BlSEHCv})%cr6YYO)62{dZ*S2O6<@ic_m z&?x6?{AZlQs>a5;ivA!tFk5T0BLrM{LADFTXWAK`Vg25*6x4s@}=R z)5+nZILyp3m~=dpa*m5sOo+)E%W!8M7x4~9j{a~2x$Nem*19@Um_JW6VEOfsa*X=3 z^JFVA>YTBtDs+-{*Zci7&E@i#7u&q3p|!4NQq^hxfI37+>caZY;1{pL&kwHh}lpQ!_ zYhtn{rXZ2(CO;mbBlj&lk%sR@hizRvcT{_UkLMAn@m(A0U)Vzb%n!qz^6m9d48yTY! z%aHT=t#}@G*HB)LI>n$#%KnYNU0=Ht}Sn zs?Za38a7>aKeG@Qr#H33?j)Dpj!-s>3iUD7b@n0EC~IhKs`gK;r6Xy4*le6Y1WZ1h zk1$y~yTfFgDA~%knQS{f?O?Z>Y$rYKV!KVYm%yjlGbVeHa4)fK4Ei3I-%WjtHrcb( z>^V&Ma8XQ2i7BRvQj?eSnWiY?(@gd}y94L==z4@JJ<<@F>`C^NCdy5I9ly)urMwK! zj;5F|W%;Bdp=y^=-H~CgR0uLHT zuV`HalE|Jg#atp^Ddw4?iX_wf=uPcQ#k8Z>vM-wK%IU{dIdFk_4Bi7*lgE&SystdQ zSmY%cNnzTt$z{(t_6!yj=Nz+Aj;z%G=#|Rz3-jb{9D@PJS+jiBF()Nhw}2}5J9_27 z?WQT_3v>!ok1_P%ouw&i1TLR0k;^Bi6>XLuZI6pQi7cNf7KnwEEHXtcze^K~O>wHI zGsO~t<}~gwM<%c$?Hi>D@=)HRW78mwHq|gigJ_I+nPPigCjTp6ZSpnzZ<<(YiY9^9 zIX2R%HTeXN3bKn&CId3ftg*hD`AeEBEtkCM1l))#Nn(|_S2p@nvobTX zhGt|9%g7p@ku@SCYvh2@K7W19Xj7aeR%qg6Q=H9TGQ~OKTvMFKr<&q?vC{;iwaa_!dZ)+7!E} z#(-drDqnR&U7fY(`f3TA;a}EBaQ#9bZ9rl-t&tv9gVQVrJU|-HmkkT+(QU3V#gpPG zOh~e4^1qn;CVsOi_K;-vil<;6))gi@F~2&;Bv-a}SU+_;e5Cq_RIADa9U(vpvGEc{Y_naMBbxLiKQCCFD{ z0l%1%d#Li?#V4ltlosP>;&V!HC4E8Qm*Oi^d`-A-h}~}~`G@$< z=was9pH@{@TZ8jc<6lNz$Tg<;p3KM(XlKNa_{2VADAS+BKk;O1il1qz{38BkieJTa zQ~X=}hNoRq{7%!;t+u|p0lm-W7F_H!ZN93&Vc8Ua@N1ZS(|!Ui#C__npESeQaC*JJDZ?kt7M&S=3z{01_|V2koo)7=zR2I?w~Fy-=^Kl7 z4-bl_IHZE9GL_@B1_n!&eDcPlQ^2%X`-$a?IxLRELq(oc1&M@tM%WE*H>xmIRdrFo zz|uN$p%IOXDpYg!9A6e<*lave&5?zoUS0-ibPV>%SDY>6EwAxsV0)@KBIOv)h?ui&*Sc;c2&I$_~2!l+Rapxs8{AQ z)nwI$GT|dMk#DLgYWE|!P11vC^854ZtQ|t_feNVlDCw#8GWl!#b(6n|>Z8myFZmyB0OVXSHRZ^zvcFs4;_rHOKkFVImYeCfrv?RBKrt`At3<_fk}x zVLxOS=Gl+()n+7IJfkSD)HkuTxX>p<6(o|1%X~8?<(207g01A*@)eg(!1_5Afo>S= z|8Mt;n@FnNM|n27^%geN)Q*@a^T{``z8U%DlYD_FiV)+u#YII#0$DF9%`Yx>(i$6H ze_9bbpFX=wY%05&FfF@az~RGZ;{Uke7ZvALnot~V$xy>wbZUfQ7lnmqE0 zjwp}pf`a1|M|RN!pU>)atgpWndei^U=m-(8N&{4^JX~m*zN1TR^#5g2J6_fL&qz=C z-!45G`TtC2$G!4eq|@?0Ha=GKqe{W^f1(urXEx~A(tz{-E7AyPsl5im_QcE%xcK$I z%0>8eM6?P{htMQF*bid{UkiRfc@B3OX1^(Z1r6ydu)AiP-#4DARFiQwN@1K#0Do`kLT~g7O^g%PX2Nnz2v+ z-|YJSgWKKzFK5~0gZYr7UUvs$dYlJo`87c88CED^^2Dav%IwyKm6;-NI zu!Q2B@X!_Z3d~8Xq{-h{)#R^n(25Thmin7p>ssXN;e-y}ZZq(OIL)oAYHluSXqnj1 zT3-`9s#EBFz6_l_JkIjC-eAcWkwwQBd3pQ_8ZLg-*FlXr-A9PWB{RjCC@ee?UYi-O+~U zs%mWX*CYLb9Vp4+p%3;e6Kt5=QTR)!SZ`?vd|u#l@>0`Odz!zA7F*T)s%C#)QxnZw zydCbcw9cWsWydY~jsjRZyt|?xmIbwSb@}x&^tK!+(Tkz57?0qhw?`2QqB(k;?BS~3 zap+5kN?{eLhO(r#p5DSwo=hPgMvX(Ala3m8O3^3QGD_@d?q*q09}`>a?8O#;_*%20 zDykRxmsD9{A!W5o8td$!oc>3Q&kpNoGDT}yhKy_@gTY5ur49`!j-^u*ZspB5!NsjD zB~?w>y}U`af=Mhj>YSS20a-F9{$>8^R*I5wSGbHC*yui07 zYDQm&$vm|tJpBDY;X za?!OTV?PZyFKeXE01*;&4%t?h3?ilo3>ry61I?GKVZnlC+PtDry{b>8u-j0ZKvfIl zZa%fP(Vi%c(9?1Bgb4aa?s+t=6$~Qvy1FN6DPiU5*P&x$*`wNdtXLcf=rKs|hU<&5i)GqP?ayIs)WL zQH#m>#afH1nnOzy*Mb~n-=juHhr*X6p(goKTWP65#-gj{H#gMb>L|8nLzThU#}!6D z{jlKZqwRi2RI@(E>?uE>4|e2N-{Xt~cQxAL>3v+np$V{}>!$n%;<_lb!s0w?VR+z` zQQJIfi1n`0(stC@&b7_C!IzZsMPy}Tb;~kbgrx7;^)pplDKPk95qRle;;)&A zaBEY9zu`?ivJRWI&DkvtOKPjFC~R+SbN&+4!&)R;w>%KrXq8czq-C5e*r15CfTcH^ zP3%K4lm!w;~k{CFZT#nvZi`I&<&3yLZWvu9!(Ru+gc z3{19LLRMG`sUhu%5>-a#H6b|lL07t&%xOp8^xz7!IXZ06VPlPvwVaZ&MiN%Z)zUB- zCtjMM;|RU(DOGks6`h5oqe2z{mvPV#P?U^+X=_zobN<5m2694Z6D3z0=XX*q*@sx$ zKXIJ1j^U&nb}}O+z}cGU$62tVY)#wmnA+-ZlIz6LJa~4qtbx9eu5I97Emlo;mVZf!{}DqH}6^Saxut$*$S! zz?GVBErclalANo(OE4BSlA(l9U}!KrHR4ngem3av*rLfO)Vlg3_|((s+|xlwdWZl` zR!-}J1vJauI*1*&%IGtJj!VcHYMtL~Pj_IEhyDgYOVDR9YUYO=h;By?CJrom>Ec=@ z!E(?{`JB_xK%Zb)y9|!cd&D?n+c%SR!o%W&Q|OU~KR_`77dqB)dW_AMuQ-6NCE`K^ z=*+&52JdNUnB-p;&~{bM2D&l}$#dy`#7IrH>ua$r9;x>eDXLkhQ zI}yIi0kqMeF)$0fFD5kK?nR0!s{LI!w5g(fFDJ8g9F}(zwHRq-(%P$ z^R8@j1b{jPx($8-o~3S0l#pTEsYBj~K@r5psXi0l$Ut+Yb00 zgx__*?;-rY1O5Qv4;}DF2!HH=|Bmn{4){}qKa+Ck%07?aH|M6)~=_BgXYj z1ifz~#`TYgaeWstuJ0qp^+UwCevBB`PZ8t#rvv^O;a?o^zYzY_0skA}-yHDo2>;=L z_aVIB0Utp4paVVxT{(ncjt68+La>6caKI|UE(fe3tUF*g!iEF(AZ$9|D1@UOa16q+ z4mb|scn6$-a3=?xh;Zld^~}3C%DW=$b->*aPIAD>2&XvU?g;mAz&?a~I^bRi_jbU2 z5bo=M`yt%l0jDB7zyYTrobG@#5FQu-pAfzd`Jga;?M81J@Y%~VF%PsGitsR8$DwvJ zK+s1Y!1zeStO5lX=Ht^g0ZS8Tw$kF>{%Ip9Y05?rgizBufomh^X?!EN)6lRPY3_~S zp(m5dqo`)|!(=e{C`?B{6sFA}U@W*{0>nZQBti*vgEF+=<z@k-oDVUu z5<0;J;DrmJ2dv^*SRzmYWwMXab|05xAN2Pn^3u{XWETnl!Qo$tLmvy#IQ&E$em5L` z4;+3!9DX_ue=rVzI1WDxhkp_de*#<+!Q>d5$tw^iFrS!~o;*-;+37#X6-DsR3e(=#5Aw)s_oD@ zErZH%uGJ9R6Cn=MyZ)qZ-HkQxL7lo6row$N9Uh1n#yD#jt~sF5FvO+*+hJt1Ll**Z zK-)G#*R-?^&~+<#sk-&pZ6hQp<5CD%ha=tqNh#?mneC8Vwo+kjhrUj$*Z@3^!8yo7 zpq}!ptdf!?yrLbt-v{&$y91m&`b%5DO6914{eZcK`GuIf@%MTBHSzZet1f#C^Av1C z)}j*gQ!$?>|B4tu4ZDB$Qd0e}(uTa6CrJhvjQJ_#hRO-cbP& z*gmT^Lf;?;1>3KUe-hS699NqMB}}FLcR*^eerh`mXyaGg1k){7rW6Q6xrZllR<$dL)zG@c8yG|F|@3W?Xuxv z2oFd25gQ(X@JNK$+3=`}G}5nLo8UymUS?ynDlFV+#4WRNW3c5|gcsTHIJ?eCh%2{o z<853v;>O#!92=J#2=?m_%S{|jA3Fo)%H{OuOy72_xdZZHCltdj zm<79WVLu5C@D!Yh`MIzMx54M(MtBi!g_qboc$F=I*H|OG!On*_+4b-iTL*8WbMY?Q z1n=ST;eGZde1OjEN9;@Z7@f|)vtQv;F5olX89wLz;R|$RzCwP#=9A$YJ{!K}bKyI_ z1it5I!w>u__>o@=|Kw}oXZ{HMf=2XLz6<`%pMu}{tMCVZ0}k*{;2{5;G5#Cld><2v z$y6nVX-YEFl^)Dc1~ZQ`ltn2MShR97i&bW_IAt-5SC+6&$_kdKT*W#o*Rrn49n7n= zvu?^3maII>Qk1t@cjX(_L)piC%0bpk#IW8Xh4m4GSYI)o^%J=)RZM3CLN;5`(Oh8B>n+ue}Edc=}h2x_TG6f?w$09YNw^|fztGyFncxV={sQddVD?w zH)zb}tOj>_#%7pHxXRVwMKzjNlr|8nRpL)ORMDQWUMknY* zV6aP&oy%l5=yXSik(|N{Y?5PblAXwe>_z8->_t3#rn9!cLC!=p%l1JZ8~jKLK~vV>2yk1E~dpBTl);{KpR z=pqc;icl#pv+JeU^;GI~eMHqK5h~}?Y%ZJa#g~#^QMfA&8C*ik3Z2i4-EClGiHzM| zvHf8jh=6z?HzpAe6^X$Cbf(7absWH(IJ=Ebfsdyt;1ycze)~z+?1xxa5EmONR&DZI;B*3A!EPkD1y?xC zK)PFCIfoHiqP7|u61BKW&#lNES(V9FgEPps=w4mg7Ja*{vKA(Y5iaUDPJ7+%t|Nj+ zBZSTz@_!}=Ix65`?+i}${W^38)c-GEj zAF=OIT?L(oN6i1hr3`9*CCU8U^|(t9duLi6_B*JQ*J2KG?;3!}Gikyn^n>JA44T9BJ?q zPe=D+AnfOZ;1EZbfe&Q~d<0A3BUvw=#fI_GEQ^m}V|gyi=M&gWp2z0!li6Zk#Fp`5 zb}lbLLp_yU%S+i`c^O;FXS3URIlGh3VC(rzv{e;s3!lTb@oM%4_p^_9Jv+pgau;vH zk+#UybuO3(pewE}4LPEkIxI&&ouEcXNF0yvGN`hBQ)j@O|99n_DxWlK#!8xcOvhhd_+YZ3CvaaQ_ zl*SH8C)W>t76JH5E z`6@`|m%%x-UK!LHmJk1?s9$yoXziq^Z31RF@FHA&ff+hR`(LCIHoX@N6UE?O)!03J`|8ZDdfyc=;g=n4SMFj3*f2%0k1D*^t z6gRaU`UwSeb8OmLEE05^k-iCTp^J)Jt&0hH=xm3z!2<`J03LjN8|Cp1c=)Ff%Rh&1 z{7dM?zlC)E9Sr6_z;OOgl*=zLiT^73j{@ZY#A>`ooA8dz*+F*VM-K=+Z^RV5``op?;gt|fMk4kb#t23<$u^BcvPJL~V znIhIg7dd_Ce@MN)xg9pPg)bqwPO*j9E``{3@bS>Z-Gz<-@Pp`f0k{=7oipF{5uQ?0JR82{{iv5 zE1smZu!XRgpK3dOze!IB;C$(%6v*3;Z74}{It(RqCzPy4fy?I|P*RwI!fek-m%fXv zmnR(;I0t>2tU!}ZtMSBcH`%lSHt&S>t0CEm*#YY%sV$Ne{uZV09=IJD(Qx^!Kz0Vf za+#k2XUTj8ZVM~ImzYuyn$if#N(=N;PJ?u184Oa+fGXu|SgM?d&c;eOL%9f6C>MvE zwn1p(_rc^`jqcv)4_4SxxB$%odENPG>F9&dWh&;6ZG^`tkCJ8q#e;4o^Pq`LSmFr-zay^VvZh-O1ji_0x zk)?XxV6Arbc3kZ^G0Ij_Y1~9^mUbw8Ex6ha{UDz+)}veYLEJ}}zmLEFvg#k}mk+b^JM4TX{_b9Bk4JQ;a-(&qI^NBM5rV&!dTVFr%$ak}1(66k$JWvmao_LRj>bW|*k zP?}mnu62}c$qLat4WL@rhS#$0G-dm(ktMDpmdN|bj*8?hq%7DLULY?YWx@9F0(lE5 z3wDGT$m>X1urs`1lyhJw${M@EYXt8oW#R7dLU~y!3!V%w2;N%C!l%er--EUl)qM?~ z;^~w^TVd1|*drjkW$yTe8k?LoUXV3jbk<;n;Wv^mwZn94!?7wts;@_6a)<2JyAhF1}G77vIXQ zA{9~~AsH>&Ue>jHN?)(HTUY$oGr8-27^v~aKfser|9bWe+f$eFCfm8JwD;6b_Q9Vl z_{(_uE6Sivj^id5joT4zN%1mw-0Fyfps84*a>+>|;6X3OKA$vqa6VypXlk{)-HL>9 zUxW#$o3CVP49~sVUSuNO=M{-6IZv-<>21*0tKm^%S2)`1-rWWsJo>tK75AUWNxw9i+oTu9$abyxYe!@t#*SRYIo?X_JEJSTqkwzRcMfqSDE_26ioq7W3>R>R{ArPkygJg9C3|3E+ z12KW`hdAVPZn)?L{mm)cHQ$3Y=$`n#j4X0h-@IU?hS^&q-03qC-J9X2yEb4u2psMBGPS^+1jvmsAC1*WKTph%q$)6^QMQvI+{ zT>y*KT3D&p!S~s%-ogf}YuRXZ9V@|nx_TFzqu#^jsSmJ4>O-tqeVAQ< z`K9Uxc8$7;U9UdDZdJFkJJoIMZuKdtuqQ(7LGpCZ5UhKWH)=nmia(%x-~G^EWAhJy zq47!V59sv=xCwwt1bQGqCk3Z=pNVIB>*8ZK>KDD+emx^gq|Zp%3_q@hr%A8y_osOm zj8vtrYl&K{x#DViGqDCV(FTIvP3YR%0AM8Qv3d~lAY=w16C2C702UaPXsm{l(qm)W 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πSq4aqCrA%x|X?%^TG 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 z zKp^-{`ckv$=|1bpC4h0uXXYoPtk#(0MwhElz2&9CU%!7^RMhVGL&MZ-XoB3qABr#L ze-=H4Jh^)i$EH@KcS5VL630?3WbGX9Hq`^an`L%SD8-t_?duH6=`^a}4{0Co`pjB~l>UySApgo}E={&c*gzlc`u?$++cah;KKZcr6^lL`TpjF~sE z#up$VGZTpU2(1 zMX*g|5t~lSveK63S!>n`*2eFG!KYx4mNXLN2NW)-@*4=1RC4G)^6VVp@5%RfsKad> zYLQT%4u=3^@c}{U3S_wk3WK_1F|>wM79HS>N4bW1I*W+Cvk^N+q7{guSQSp!piFZ92;u+dJ(8& zes7z3Qf(+mEppOW=c@dI$lV?W^5>+aN#?r^QCjB$%NV-kJSxtCx!Z0YZT3o&qI9n! z;%bw+%5+-HFxw>R2DIuJN@8~meZnYjqWy|}$iMkdZ_GSBTBPCM`g&b&0j>e3-gBL) zmR~PtreL$9xdwT$wv+oKt^9gpQ^@xqQb_1t;Dhl_-wr&ogAxdpNiZgn=9SwqU=SXY z%jZtoZ!%W#kdjDnh{-_%q|J1)?>hbMP2^zwCEDXjhunU*bIso!8p-F~5&Lpu(ZvM1 zkLB-znlDx^rSeeqq^O)4D*_I1L~oaw31wWaV&{m!HhKzl5X2 z;HOsdIRCR%Ar;023Q8{oCLr2taq(c)f+1tELQ5>8o-GaFa51jn%ZOenb5UM2!g*=2 zC^gIl*}c`?=kC9B-LUHwH107BOhy`#f%B4R{Y@­vqDIXWtDYF2?M=zBbw0Sc-T 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

    b1_ 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 zℑ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 z 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≪eK{x$w%wh^{{cv*6*!b(H6By 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 z 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

    XPC6;niN+gByTh7uA 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 r5{r;6RV>4Ki4d`+PRv`QaG?s0hI* DEPLOY_TOOL_HOME must be defined + exit/B +) + +IF "%JBOSS_HOME%"=="" ( + echo > JBOSS_HOME must be defined + exit/B +) + +echo copy sql update files +copy %DEPLOY_TOOL_HOME%\DBupdate\. %DEPLOY_TOOL_HOME%\sql +echo - Run database update +java -jar %DEPLOY_TOOL_HOME%\bin\install-reports.jar +if %ERRORLEVEL% EQU 1 ( + echo - Error detected, check install.log file +) else ( + echo - Database update run successfully +) + +echo clearing sql folder contents +del %DEPLOY_TOOL_HOME%\sql\* /Q + +echo ========================== +echo END OF DATABASE UPDATE +echo ========================== + +pause + +exit/B \ No newline at end of file diff --git a/distribution/install/reports/update_database.bat:Zone.Identifier b/distribution/install/reports/update_database.bat:Zone.Identifier new file mode 100644 index 0000000..a45e1ac --- /dev/null +++ b/distribution/install/reports/update_database.bat:Zone.Identifier @@ -0,0 +1,2 @@ +[ZoneTransfer] +ZoneId=3 diff --git a/distribution/install/teamcenter/data/bin/clause_propriete_update b/distribution/install/teamcenter/data/bin/clause_propriete_update new file mode 100644 index 0000000000000000000000000000000000000000..0e9387a512338b6437c7b36944ac2bc2d295d970 GIT binary patch literal 2090194 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,zlsb%`#2}`sh8NU##c(?D;d#dt@FX= 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

    LNW>@^uZDym5u^iyLZR77%4j~P; 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

    122WMSP07&)6p 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 literal 0 HcmV?d00001 diff --git a/distribution/install/teamcenter/data/queries/Report_All_Sequences.xml b/distribution/install/teamcenter/data/queries/Report_All_Sequences.xml new file mode 100644 index 0000000..4b54ccb --- /dev/null +++ b/distribution/install/teamcenter/data/queries/Report_All_Sequences.xml @@ -0,0 +1,11 @@ + + + + +All Sequences of an ItemRevision + + + + diff --git a/distribution/install/teamcenter/data/queries/Report_Alternate.xml b/distribution/install/teamcenter/data/queries/Report_Alternate.xml new file mode 100644 index 0000000..38d3551 --- /dev/null +++ b/distribution/install/teamcenter/data/queries/Report_Alternate.xml @@ -0,0 +1,12 @@ + + + + +Toutes les revisions article de type Alternative + + + + + diff --git a/distribution/install/teamcenter/data/queries/Report_ChangeNotice_R07.xml b/distribution/install/teamcenter/data/queries/Report_ChangeNotice_R07.xml new file mode 100644 index 0000000..14e2cab --- /dev/null +++ b/distribution/install/teamcenter/data/queries/Report_ChangeNotice_R07.xml @@ -0,0 +1,11 @@ + + + + +Récupère toutes les change notice associé à une part ou un générique + + + + diff --git a/distribution/install/teamcenter/data/queries/Report_ChangeRequest.xml b/distribution/install/teamcenter/data/queries/Report_ChangeRequest.xml new file mode 100644 index 0000000..734e066 --- /dev/null +++ b/distribution/install/teamcenter/data/queries/Report_ChangeRequest.xml @@ -0,0 +1,11 @@ + + + + +Obtain a Change Request RevisionObtain a Change Request Revision + + + + diff --git a/distribution/install/teamcenter/data/queries/Report_ChangeRequest_R07.xml b/distribution/install/teamcenter/data/queries/Report_ChangeRequest_R07.xml new file mode 100644 index 0000000..1b57097 --- /dev/null +++ b/distribution/install/teamcenter/data/queries/Report_ChangeRequest_R07.xml @@ -0,0 +1,11 @@ + + + + +Récupère toutes les change request associé à une part ou un générique + + + + diff --git a/distribution/install/teamcenter/data/queries/Report_ChangeRequest_With_Seq.xml b/distribution/install/teamcenter/data/queries/Report_ChangeRequest_With_Seq.xml new file mode 100644 index 0000000..ec42338 --- /dev/null +++ b/distribution/install/teamcenter/data/queries/Report_ChangeRequest_With_Seq.xml @@ -0,0 +1,11 @@ + + + + +Obtain a Change Request Revision + + + + diff --git a/distribution/install/teamcenter/data/queries/Report_ChangeRevision.xml b/distribution/install/teamcenter/data/queries/Report_ChangeRevision.xml new file mode 100644 index 0000000..5bf5ad6 --- /dev/null +++ b/distribution/install/teamcenter/data/queries/Report_ChangeRevision.xml @@ -0,0 +1,11 @@ + + + + +Obtain a Change Request Revision + + + + diff --git a/distribution/install/teamcenter/data/queries/Report_Change_from_Part.xml b/distribution/install/teamcenter/data/queries/Report_Change_from_Part.xml new file mode 100644 index 0000000..5498b3b --- /dev/null +++ b/distribution/install/teamcenter/data/queries/Report_Change_from_Part.xml @@ -0,0 +1,11 @@ + + + + +Toutes les revisions article de type CR + + + + diff --git a/distribution/install/teamcenter/data/queries/Report_DET.xml b/distribution/install/teamcenter/data/queries/Report_DET.xml new file mode 100644 index 0000000..4eee89a --- /dev/null +++ b/distribution/install/teamcenter/data/queries/Report_DET.xml @@ -0,0 +1,12 @@ + + + + +Toutes les revisions article de type DET + + + + + diff --git a/distribution/install/teamcenter/data/queries/Report_FPP_With_Seq.xml b/distribution/install/teamcenter/data/queries/Report_FPP_With_Seq.xml new file mode 100644 index 0000000..478b00f --- /dev/null +++ b/distribution/install/teamcenter/data/queries/Report_FPP_With_Seq.xml @@ -0,0 +1,11 @@ + + + + +Obtain a FPP Revision with all the sequences.Obtain a FPP Revision with all the sequences. + + + + diff --git a/distribution/install/teamcenter/data/queries/Report_Generic.xml b/distribution/install/teamcenter/data/queries/Report_Generic.xml new file mode 100644 index 0000000..4e727e1 --- /dev/null +++ b/distribution/install/teamcenter/data/queries/Report_Generic.xml @@ -0,0 +1,11 @@ + + + + +Toutes les revisions article de type Generic + + + + diff --git a/distribution/install/teamcenter/data/queries/Report_Generic_Assemb.xml b/distribution/install/teamcenter/data/queries/Report_Generic_Assemb.xml new file mode 100644 index 0000000..fbf8c49 --- /dev/null +++ b/distribution/install/teamcenter/data/queries/Report_Generic_Assemb.xml @@ -0,0 +1,11 @@ + + + + +Toutes les revisions d'article de type Generic specifique montage + + + + diff --git a/distribution/install/teamcenter/data/queries/Report_Item.xml b/distribution/install/teamcenter/data/queries/Report_Item.xml new file mode 100644 index 0000000..3ba1ce3 --- /dev/null +++ b/distribution/install/teamcenter/data/queries/Report_Item.xml @@ -0,0 +1,11 @@ + + + + +Rechercher le(s) articles + + + + diff --git a/distribution/install/teamcenter/data/queries/Report_ItemRevision.xml b/distribution/install/teamcenter/data/queries/Report_ItemRevision.xml new file mode 100644 index 0000000..30fe7b5 --- /dev/null +++ b/distribution/install/teamcenter/data/queries/Report_ItemRevision.xml @@ -0,0 +1,11 @@ + + + + +Rechercher le(s) révisions d'articles + + + + diff --git a/distribution/install/teamcenter/data/queries/Report_Product.xml b/distribution/install/teamcenter/data/queries/Report_Product.xml new file mode 100644 index 0000000..79bb4a7 --- /dev/null +++ b/distribution/install/teamcenter/data/queries/Report_Product.xml @@ -0,0 +1,11 @@ + + + + +Toutes les revisions article de type Produit + + + + diff --git a/distribution/install/teamcenter/data/queries/Report_ProductType.xml b/distribution/install/teamcenter/data/queries/Report_ProductType.xml new file mode 100644 index 0000000..4777f6d --- /dev/null +++ b/distribution/install/teamcenter/data/queries/Report_ProductType.xml @@ -0,0 +1,11 @@ + + + + +Tous les formulaires Type ProduitTous les formulaires Type Produit + + + + diff --git a/distribution/install/teamcenter/data/queries/Report_Relationship.xml b/distribution/install/teamcenter/data/queries/Report_Relationship.xml new file mode 100644 index 0000000..1e05aea --- /dev/null +++ b/distribution/install/teamcenter/data/queries/Report_Relationship.xml @@ -0,0 +1,9 @@ + + + + + + + diff --git a/distribution/install/teamcenter/data/queries/Report_Unit.xml b/distribution/install/teamcenter/data/queries/Report_Unit.xml new file mode 100644 index 0000000..42599e5 --- /dev/null +++ b/distribution/install/teamcenter/data/queries/Report_Unit.xml @@ -0,0 +1,11 @@ + + + + +Toutes les revisions article de type Unit + + + + diff --git a/distribution/install/teamcenter/data/queries/Report_Unit_from_CR.xml b/distribution/install/teamcenter/data/queries/Report_Unit_from_CR.xml new file mode 100644 index 0000000..1321c8d --- /dev/null +++ b/distribution/install/teamcenter/data/queries/Report_Unit_from_CR.xml @@ -0,0 +1,11 @@ + + + + +Toutes les revisions article de type UnitToutes les revisions article de type Unit + + + + \ No newline at end of file diff --git a/distribution/install/teamcenter/data/queries/Report_Unit_with_WKF.xml b/distribution/install/teamcenter/data/queries/Report_Unit_with_WKF.xml new file mode 100644 index 0000000..3c3c3e9 --- /dev/null +++ b/distribution/install/teamcenter/data/queries/Report_Unit_with_WKF.xml @@ -0,0 +1,11 @@ + + + + +Toutes les revisions article de type UnitToutes les revisions article de type Unit + + + + diff --git a/distribution/install/teamcenter/data/queries/Report_WKF_ValidationUnit_on_Unit.xml b/distribution/install/teamcenter/data/queries/Report_WKF_ValidationUnit_on_Unit.xml new file mode 100644 index 0000000..f223603 --- /dev/null +++ b/distribution/install/teamcenter/data/queries/Report_WKF_ValidationUnit_on_Unit.xml @@ -0,0 +1,11 @@ + + + + +Toutes les revisions article de type UnitToutes les revisions article de type Unit + + + + diff --git a/distribution/install/teamcenter/data/queries/Report_WKF_on_Change.xml b/distribution/install/teamcenter/data/queries/Report_WKF_on_Change.xml new file mode 100644 index 0000000..7e0ac3b --- /dev/null +++ b/distribution/install/teamcenter/data/queries/Report_WKF_on_Change.xml @@ -0,0 +1,11 @@ + + + + +Tous les Workflows associé à un Change ou correspondant à un certain nom.Tous les Workflows associé à un Change ou correspondant à un certain nom. + + + + diff --git a/distribution/install/teamcenter/data/queries/Report_WKF_on_ItemRevision.xml b/distribution/install/teamcenter/data/queries/Report_WKF_on_ItemRevision.xml new file mode 100644 index 0000000..4ebdcfd --- /dev/null +++ b/distribution/install/teamcenter/data/queries/Report_WKF_on_ItemRevision.xml @@ -0,0 +1,11 @@ + + + + +Tous les Workflows associé à un ItemRevision ou correspondant à un certain nom. + + + + diff --git a/distribution/install/teamcenter/data/queries/__pv_snecma_search_report_by_source.xml b/distribution/install/teamcenter/data/queries/__pv_snecma_search_report_by_source.xml new file mode 100644 index 0000000..86d4cd0 --- /dev/null +++ b/distribution/install/teamcenter/data/queries/__pv_snecma_search_report_by_source.xml @@ -0,0 +1,11 @@ + + + + +Query + + + + diff --git a/distribution/install/teamcenter/data/report_prefs.xml b/distribution/install/teamcenter/data/report_prefs.xml new file mode 100644 index 0000000..0b0cc2d --- /dev/null +++ b/distribution/install/teamcenter/data/report_prefs.xml @@ -0,0 +1,20 @@ + + + + + + Specifies the configuration for eQube by allowing the system administrator to change the Application server Protocol, Host, Port, eQube installation location and eQube servlet name. +By default, the following rules are provided: Protocol:http, Host:localhost, Port:80, Context:eQube, ServletName:eQubeServlet, ServiceDashboard:action=Dashboard. +Valid values for Protocol are http or https. + + Protocol:http + Host:localhost + Port:8080 + Context:kurt-web + ServletName:dispatcherServlet + User:username + Password:encrypted_password + + + + \ No newline at end of file diff --git a/distribution/install/teamcenter/data/reports/REPORT_R01/REPORT_R01.xml b/distribution/install/teamcenter/data/reports/REPORT_R01/REPORT_R01.xml new file mode 100644 index 0000000..3fcccb2 --- /dev/null +++ b/distribution/install/teamcenter/data/reports/REPORT_R01/REPORT_R01.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/distribution/install/teamcenter/data/reports/REPORT_R03/REPORT_R03.xml b/distribution/install/teamcenter/data/reports/REPORT_R03/REPORT_R03.xml new file mode 100644 index 0000000..7974d92 --- /dev/null +++ b/distribution/install/teamcenter/data/reports/REPORT_R03/REPORT_R03.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/distribution/install/teamcenter/data/reports/REPORT_R07/REPORT_R07.xml b/distribution/install/teamcenter/data/reports/REPORT_R07/REPORT_R07.xml new file mode 100644 index 0000000..fe34b33 --- /dev/null +++ b/distribution/install/teamcenter/data/reports/REPORT_R07/REPORT_R07.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/distribution/install/teamcenter/data/reports/REPORT_R10/REPORT_R10.xml b/distribution/install/teamcenter/data/reports/REPORT_R10/REPORT_R10.xml new file mode 100644 index 0000000..82e8921 --- /dev/null +++ b/distribution/install/teamcenter/data/reports/REPORT_R10/REPORT_R10.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/distribution/install/teamcenter/data/reports/REPORT_R11/REPORT_R11.xml b/distribution/install/teamcenter/data/reports/REPORT_R11/REPORT_R11.xml new file mode 100644 index 0000000..9b1510d --- /dev/null +++ b/distribution/install/teamcenter/data/reports/REPORT_R11/REPORT_R11.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/distribution/install/teamcenter/data/reports/REPORT_R13/REPORT_R13.xml b/distribution/install/teamcenter/data/reports/REPORT_R13/REPORT_R13.xml new file mode 100644 index 0000000..2c883ec --- /dev/null +++ b/distribution/install/teamcenter/data/reports/REPORT_R13/REPORT_R13.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/distribution/install/teamcenter/data/reports/REPORT_R15/REPORT_R15.xml b/distribution/install/teamcenter/data/reports/REPORT_R15/REPORT_R15.xml new file mode 100644 index 0000000..4ee3e39 --- /dev/null +++ b/distribution/install/teamcenter/data/reports/REPORT_R15/REPORT_R15.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/distribution/install/teamcenter/data/reports/REPORT_R16/REPORT_R16.xml b/distribution/install/teamcenter/data/reports/REPORT_R16/REPORT_R16.xml new file mode 100644 index 0000000..ba03d48 --- /dev/null +++ b/distribution/install/teamcenter/data/reports/REPORT_R16/REPORT_R16.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/distribution/install/teamcenter/data/reports/REPORT_R17/REPORT_R17.xml b/distribution/install/teamcenter/data/reports/REPORT_R17/REPORT_R17.xml new file mode 100644 index 0000000..8a273b5 --- /dev/null +++ b/distribution/install/teamcenter/data/reports/REPORT_R17/REPORT_R17.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/distribution/install/teamcenter/data/reports/REPORT_R19_Document/REPORT_R19_Document.xml b/distribution/install/teamcenter/data/reports/REPORT_R19_Document/REPORT_R19_Document.xml new file mode 100644 index 0000000..5d6680b --- /dev/null +++ b/distribution/install/teamcenter/data/reports/REPORT_R19_Document/REPORT_R19_Document.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/distribution/install/teamcenter/data/reports/REPORT_R19_Document_Design/REPORT_R19_Document_Design.xml b/distribution/install/teamcenter/data/reports/REPORT_R19_Document_Design/REPORT_R19_Document_Design.xml new file mode 100644 index 0000000..34b8760 --- /dev/null +++ b/distribution/install/teamcenter/data/reports/REPORT_R19_Document_Design/REPORT_R19_Document_Design.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/distribution/install/teamcenter/data/reports/REPORT_R19_Document_Revision/REPORT_R19_Document_Revision.xml b/distribution/install/teamcenter/data/reports/REPORT_R19_Document_Revision/REPORT_R19_Document_Revision.xml new file mode 100644 index 0000000..e11a955 --- /dev/null +++ b/distribution/install/teamcenter/data/reports/REPORT_R19_Document_Revision/REPORT_R19_Document_Revision.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/distribution/install/teamcenter/data/reports/REPORT_R20/REPORT_R20.xml b/distribution/install/teamcenter/data/reports/REPORT_R20/REPORT_R20.xml new file mode 100644 index 0000000..246a09c --- /dev/null +++ b/distribution/install/teamcenter/data/reports/REPORT_R20/REPORT_R20.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/distribution/install/teamcenter/data/reports/REPORT_R21/REPORT_R21.xml b/distribution/install/teamcenter/data/reports/REPORT_R21/REPORT_R21.xml new file mode 100644 index 0000000..e6314fa --- /dev/null +++ b/distribution/install/teamcenter/data/reports/REPORT_R21/REPORT_R21.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/distribution/install/teamcenter/data/reports/REPORT_R22/REPORT_R22.xml b/distribution/install/teamcenter/data/reports/REPORT_R22/REPORT_R22.xml new file mode 100644 index 0000000..fd70201 --- /dev/null +++ b/distribution/install/teamcenter/data/reports/REPORT_R22/REPORT_R22.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/distribution/install/teamcenter/data/reports/REPORT_R23/REPORT_R23.xml b/distribution/install/teamcenter/data/reports/REPORT_R23/REPORT_R23.xml new file mode 100644 index 0000000..878bd92 --- /dev/null +++ b/distribution/install/teamcenter/data/reports/REPORT_R23/REPORT_R23.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/distribution/install/teamcenter/data/reports/REPORT_R24/REPORT_R24.xml b/distribution/install/teamcenter/data/reports/REPORT_R24/REPORT_R24.xml new file mode 100644 index 0000000..2601a14 --- /dev/null +++ b/distribution/install/teamcenter/data/reports/REPORT_R24/REPORT_R24.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/distribution/install/teamcenter/data/reports/REPORT_R25/REPORT_R25.xml b/distribution/install/teamcenter/data/reports/REPORT_R25/REPORT_R25.xml new file mode 100644 index 0000000..353943b --- /dev/null +++ b/distribution/install/teamcenter/data/reports/REPORT_R25/REPORT_R25.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/distribution/install/teamcenter/data/reports/REPORT_R26_Item/REPORT_R26_Item.xml b/distribution/install/teamcenter/data/reports/REPORT_R26_Item/REPORT_R26_Item.xml new file mode 100644 index 0000000..022a4f0 --- /dev/null +++ b/distribution/install/teamcenter/data/reports/REPORT_R26_Item/REPORT_R26_Item.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/distribution/install/teamcenter/data/reports/REPORT_R26_Item_Revision/REPORT_R26_Item_Revision.xml b/distribution/install/teamcenter/data/reports/REPORT_R26_Item_Revision/REPORT_R26_Item_Revision.xml new file mode 100644 index 0000000..37c8444 --- /dev/null +++ b/distribution/install/teamcenter/data/reports/REPORT_R26_Item_Revision/REPORT_R26_Item_Revision.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/distribution/install/teamcenter/data/revision_rule/revisionrule.xml b/distribution/install/teamcenter/data/revision_rule/revisionrule.xml new file mode 100644 index 0000000..ff798da --- /dev/null +++ b/distribution/install/teamcenter/data/revision_rule/revisionrule.xml @@ -0,0 +1,139 @@ + + +

    + + DMA Configuration Rapport PU + + Product + Generic + Generic Assemb + RF Generic + RF Part + RF Part Assemb + RF Admin + RF Admin A + RF Admin AG + RF Admin AP + + + + Part Aero + Part No Aero + Part Mat + Standard + DET + Alternate + Part Assemb + + + + + + + + + + + + DMA Configuration Descriptif R25 + + + RF Generic + RF Admin + RF Admin AG + Descriptif + Generic + + + + Part Aero + + + + + + Part Aero + + + + + + + DMA Configuration Interface R01 + + Product + Generic + Generic Assemb + RF Generic + RF Part + RF Part Assemb + RF Admin + RF Admin A + RF Admin AG + RF Admin AP + Super Model + + + + RF Part + RF Admin + RF Admin AP + + + + + + Part Aero + Part No Aero + Part Mat + Standard + DET + Alternate + Part Assemb + + + + + + + + + + + + DMA Configuration Interface PU R23 + + + Product + Generic + Generic Assemb + RF Generic + RF Part + RF Part Assemb + RF Admin + RF Admin A + RF Admin AG + RF Admin AP + Super Model + + + + + Part Aero + Part No Aero + Part Mat + Standard + DET + Alternate + Part Assemb + + + + + + + + + + + diff --git a/distribution/install/teamcenter/report_install.pl b/distribution/install/teamcenter/report_install.pl new file mode 100644 index 0000000..e4fde5b --- /dev/null +++ b/distribution/install/teamcenter/report_install.pl @@ -0,0 +1,273 @@ +my $env=0; + +if ($ENV{TC_ROOT} eq "") { + print "Initialiser TC_ROOT avant de lancer le script\n"; + $env = 1; +} + +if ($ENV{TC_DATA} eq "") { + print "Initialiser TC_DATA avant de lancer le script\n"; + $env = 1; +} + +if ($env == 1) { + exit 1; +} + +my $myversion="${project.version}"; +my $to_soa = $ENV{TC_DATA}."/soa/"; +my $to_bin = $ENV{TC_ROOT}."/bin/"; +my $args=0; +my $usr=""; +my $pwd=""; +my $grp=""; + +$numArgs = $#ARGV + 1; + +foreach $argnum (0 .. $#ARGV) { + $arg = $ARGV[$argnum]; + if ($arg =~ m/^-u=/) { + $args = $args + 1; + $usr = $arg; + $usr =~ s/^-u=//; + } + if ($arg =~ m/^-p=/) { + $args = $args + 1; + $pwd = $arg; + $pwd =~ s/^-p=//; + } + if ($arg =~ m/^-g=/) { + $args = $args + 1; + $grp = $arg; + $grp =~ s/^-g=//; + } +} + +if ($args != 3 || $usr eq "" || $pwd eq "" || $grp eq "") { + print "Utilisation 'perl report_install.pl -u= -p= -g='\n"; + print " -u : login utilisateur dba\n"; + print " -p : mot de passe\n"; + print " -g : groupe dba\n"; + exit 1; +} + +my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); +my $datedujour = $mday."/".($mon+1)."/".(1900+$year)."-".$hour.":".$min.":".$sec; +my $suffixe = (1900+$year).($mon+1).$mday.$hour.$min.$sec; + +system "echo '------- INSTALLATION REPORT v" .$myversion. " -------'"; + +system "echo ' Import des reports'"; + +my $repertoireReports = "./data/reports"; +opendir fh_rep, $repertoireReports or die "impossible d'ouvrir le r�pertoire ".$repertoireReports."\n"; + +my $reportId = ""; +system "echo 'Import de la definition des rapports'"; +while( ($filename = readdir(fh_rep))){ + next if ($filename eq "." or $filename eq ".."); + $reportId = $filename; + system "echo ' + Import de ".$reportId."'"; + system "import_export_reports -import -u=".$usr." -p=".$pwd." -g=".$grp." -v -overwrite -stageDir=./data/reports -reportId=\"".$reportId."\""; +} +closedir fh_rep or die "Impossible de fermer le r�pertoire ".$repertoireReports."\n"; + +system "echo 'Import des queries'"; + +my $repertoireQueries = "./data/queries"; +opendir fh_rep, $repertoireQueries or die "impossible d'ouvrir le r�pertoire ".$repertoireQueries."\n"; + my @fic_rep_list = grep { !/^\.\.?$/ } readdir fh_rep; +closedir fh_rep or die "Impossible de fermer le r�pertoire ".$repertoireQueries."\n"; + +concat_query_files($repertoireQueries); +system "echo ' Import des requetes en une fois'"; +$target=$repertoireQueries."/all_queries.xml"; +if (-e $target){ + system "plmxml_import -u=".$usr." -p=".$pwd." -g=".$grp." -import_mode=overwrite -xml_file=".$target; +} +else { + print "File ".$target." cannot be found\n"; +} + +system "echo ' Import des policies'"; +copy_policy_files("./data/policies"); + +system "echo ' Import du binaire d encryptage"; +system "cp ./data/bin/encrypt ".$to_bin; +system "chmod 755 ".$to_bin."encrypt"; + + +system "echo 'Import de la pr�f�rence report'"; +system "preferences_manager -u=".$usr." -p=".$pwd." -g=".$grp." -mode=import -scope=SITE -file=./data/report_prefs.xml -action=OVERRIDE"; + +system "preferences_manager -u=" .$usr. " -p=" .$pwd. " -g=" .$grp. " -mode=import -preference=\"PV SNECMA Reports deployment date\" -scope=SITE -values=" .$datedujour. " -action=OVERRIDE"; +system "preferences_manager -u=" .$usr. " -p=" .$pwd. " -g=" .$grp. " -mode=import -preference=\"PV SNECMA Reports version\" -scope=SITE -values=" .$myversion. " -action=OVERRIDE"; + +system "echo ' Import des Regles de Revision'"; + +system "plmxml_import -u=" .$usr. " -p=" .$pwd. " -g=" .$grp. " -xml_file=./data/revision_rule/revisionrule.xml -import_mode=overwrite"; + +system "echo '----- FIN INSTALLATION REPORT v" .$myversion. " -------'"; + +sub promptUser { + #-------------------------------------------------------------------# + # two possible input arguments - $promptString, and $defaultValue # + # make the input arguments local variables. # + #-------------------------------------------------------------------# + + local($promptString,$defaultValue) = @_; + + #-------------------------------------------------------------------# + # if there is a default value, use the first print statement; if # + # no default is provided, print the second string. # + #-------------------------------------------------------------------# + + if ($defaultValue) { + print $promptString, "[", $defaultValue, "]: "; + } else { + print $promptString, ": "; + } + + $| = 1; # force a flush after our print + $_ = ; # get the input from STDIN (presumably the keyboard) + + + #------------------------------------------------------------------# + # remove the newline character from the end of the input the user # + # gave us. # + #------------------------------------------------------------------# + + chomp; + + #-----------------------------------------------------------------# + # if we had a $default value, and the user gave us input, then # + # return the input; if we had a default, and they gave us no # + # no input, return the $defaultValue. # + # # + # if we did not have a default value, then just return whatever # + # the user gave us. if they just hit the key, # + # the calling routine will have to deal with that. # + #-----------------------------------------------------------------# + + if ("$defaultValue") { + return $_ ? $_ : $defaultValue; # return $_ if it has a value + } else { + return $_; + } +} + +sub copy_policy_files{ + # + # Copie toutes les policies dans tous les sous-dossiers vers le dossier SOA, *a plat* + # system "cp -Rf ./data/policies/reports/SOME_FOLDER/SOME_FILE.xml " . $to_soa; + + my $source_dir = $_[0]; + + print "Import de la policy: dossier = ".$source_dir."\n"; + + # entete du fichier genere + opendir fh_rep, $source_dir or die "impossible d'ouvrir le r�pertoire ".$source_dir."\n"; + my @fic_rep_list = grep { !/^\.\.?$/ } readdir fh_rep; + closedir fh_rep or die "Impossible de fermer le r�pertoire ".$source_dir."\n"; + + # Browse all the folder"s content + foreach my $elem ( @fic_rep_list) { + # Skipping files begginning whith . or .svn + my $absoluteElem = $source_dir . '/'.$elem; + if ($elem!~/^\./ and $elem!~/.svn/) { + # If the file is a directory + if (-d $absoluteElem) { + # Here is where we recurse. + # This makes a new call to process_files() + # using a new directory we just found. + copy_policy_files ($absoluteElem); + } else { + # If it isn't a directory, lets just do some + # processing on it. + print " Import de la policy: ".$elem."\n"; + system "cp -Rf ".$absoluteElem." ".$to_soa."/policies"; + } + }else{ + print " Element ".$absoluteElem." ignor�\n"; + } + } +} + +sub concat_query_files{ + # + # all-queries.pl + # + # concat�ne toutes les queries en 1 seul fichier + + my $source_dir = $_[0]; + #printf("$ARGV[0]"); + #print("--------------------------"); + + # entete du fichier genere + opendir fh_rep, $source_dir or die "impossible d'ouvrir le r�pertoire ".$source_dir."\n"; + my @fic_rep_list = grep { !/^\.\.?$/ } readdir fh_rep; + closedir fh_rep or die "Impossible de fermer le r�pertoire ".$source_dir."\n"; + + open (OUTPUTFILE, "> ".$source_dir."/all_queries.xml") || die "Can't write in ".$outputFile." : $!"; + print OUTPUTFILE "\n"; + print OUTPUTFILE "\n"; + + for $j (0..((scalar @fic_rep_list) -1) ) + { + if ( $fic_rep_list[$j] eq "delete_queries.xml" || $fic_rep_list[$j] eq "all_queries.xml" || $fic_rep_list[$j] eq ".svn") + { + print "skipping query no ".($j+1)."/".scalar @fic_rep_list." : ".$fic_rep_list[$j]."\n"; + } + if ($fic_rep_list[$j]!~/^\./ and $fic_rep_list[$j]!~/delete_queries.xml/ and $fic_rep_list[$j]!~/all_queries.xml/ and $fic_rep_list[$j]!~/.svn/) + { + print "Concat query no ".($j+1)."/".scalar @fic_rep_list." : ".$fic_rep_list[$j]."\n"; + open(F, $source_dir."/".$fic_rep_list[$j]);# || die "Probl�me � l\'ouverture : $!"; + $i = 0; + while($line = ) + { + # doit contenir : plmxml_bus:SavedQueryDef + # doit contenir : plmxml_bus:QueryClause + # remplacer : / ) + { + print OUTPUTFILE $line; #On �crit la ligne dans le fichier r�sultat + } + if ($line =~ m/\<\/Description\>/ ) + { + print OUTPUTFILE $line; #On �crit la ligne dans le fichier r�sultat + } + if ($line =~ m/plmxml_bus:QueryClause/ ) + { + $k=$j+1000; + $line =~ s/\"id."+/\"id$k\"/; + print OUTPUTFILE $line; #On �crit la ligne dans le fichier r�sultat + } + # if ($line =~ m/plmxml_bus:Text/ ) + # { + # $l=$i+2000; + # $line =~ s/\"id."+/\"id$l\"/; + # $line =~ s/\<\/plmxml_bus:PLMXMLBusinessTypes\>//; + # print OUTPUTFILE $line; #On �crit la ligne dans le fichier r�sultat + # } + $i ++; + } + $j ++; + #print "\nNombre de lignes : $fic_rep_list[$j] $i\n"; + close F ;#|| die "Probl�me � la fermeture : $!"; + } + } + + print OUTPUTFILE "\n"; + + close OUTPUTFILE; +} diff --git a/distribution/pom.xml b/distribution/pom.xml new file mode 100644 index 0000000..68aaa11 --- /dev/null +++ b/distribution/pom.xml @@ -0,0 +1,58 @@ + + + 4.0.0 + + distribution + project distribution + pom + Full report package including tool and utilities + + + ${project.parent.name}-${project.parent.version} + + + + com.capgemini.reports + kurt + 1.32.9 + + + + + + org.apache.maven.plugins + maven-assembly-plugin + + + package-report + package + + single + + + false + snecma-reports-${project.parent.version} + + assembly.xml + + + + + + + + + + + release + + + + com.maestrodev + collabnet-maven-plugin + + + + + + diff --git a/jasper/pom.xml b/jasper/pom.xml new file mode 100644 index 0000000..aa18bc1 --- /dev/null +++ b/jasper/pom.xml @@ -0,0 +1,56 @@ + + + 4.0.0 + jasper + jar + jasper + + + com.capgemini.reports + kurt + 1.32.9 + + + + + + org.testng + testng + test + + + org.assertj + assertj-core + test + + + + + org.slf4j + slf4j-api + + + + org.jboss.spec.javax.annotation + jboss-annotations-api_1.1_spec + + + + javax.enterprise + cdi-api + + + + + + + + + + net.sf.jasperreports + jasperreports + 5.6.1 + + + + diff --git a/jasper/src/main/java/com/capgemini/reports/jasper/compilers/JasperCompiler.java b/jasper/src/main/java/com/capgemini/reports/jasper/compilers/JasperCompiler.java new file mode 100644 index 0000000..66ee659 --- /dev/null +++ b/jasper/src/main/java/com/capgemini/reports/jasper/compilers/JasperCompiler.java @@ -0,0 +1,69 @@ +package com.capgemini.reports.jasper.compilers; + +import com.capgemini.reports.jasper.fillers.MultiFiller; +import net.sf.jasperreports.engine.JRException; +import net.sf.jasperreports.engine.JasperCompileManager; +import net.sf.jasperreports.engine.JasperReport; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; + +/** + * This class is able to compile some template files (.jrxml) into a {@link JasperReport} object. + */ +public final class JasperCompiler { + private static final Logger LOGGER = LoggerFactory.getLogger(MultiFiller.class); + + private static final String JASPER_COMPILATION = "JASPER compilation"; + private static final String JASPER_REPORT_COMPILING_TIME_XXX_MS = "JASPER report Compiling time : {} ms"; + private static final String EXCEPTION_CAUGHT = "Jasper Report Exception caught while compiling report"; + + private JasperCompiler() { + + } + + /** + * Builds a report printer with the provided {@link InputStream} template. + * + * @param templateStream the template file to use for this report as an {@link InputStream} + * @return the compiled {@link JasperReport} object + * @throws JRException if Jasper could not compile the report + */ + public static JasperReport compile(final InputStream templateStream) throws JRException { + LOGGER.debug(JASPER_COMPILATION); + long start = System.currentTimeMillis(); + + try { + JasperReport compiledReport = JasperCompileManager.compileReport(templateStream); + LOGGER.debug(JASPER_REPORT_COMPILING_TIME_XXX_MS, System.currentTimeMillis() - start); + return compiledReport; + } catch (JRException e) { + LOGGER.error(EXCEPTION_CAUGHT, e); + throw e; + } + } + + /** + * Builds a report printer with the provided {@link String} template. + * + * @param generatedTemplate the template file to use for this report in a {@link String} + * @return the compiled {@link JasperReport} object + * @throws JRException if Jasper could not compile the report + */ + public static JasperReport compile(final String generatedTemplate) throws JRException { + LOGGER.debug(JASPER_COMPILATION); + long start = System.currentTimeMillis(); + + try { + InputStream templateStream = new ByteArrayInputStream(generatedTemplate.getBytes()); + JasperReport compiledReport = JasperCompileManager.compileReport(templateStream); + LOGGER.debug(JASPER_REPORT_COMPILING_TIME_XXX_MS, System.currentTimeMillis() - start); + return compiledReport; + } catch (JRException e) { + LOGGER.error(EXCEPTION_CAUGHT, e); + throw e; + } + } +} diff --git a/jasper/src/main/java/com/capgemini/reports/jasper/fillers/JasperFiller.java b/jasper/src/main/java/com/capgemini/reports/jasper/fillers/JasperFiller.java new file mode 100644 index 0000000..19312f5 --- /dev/null +++ b/jasper/src/main/java/com/capgemini/reports/jasper/fillers/JasperFiller.java @@ -0,0 +1,20 @@ +package com.capgemini.reports.jasper.fillers; + +import net.sf.jasperreports.engine.JRException; +import net.sf.jasperreports.engine.JasperPrint; +import net.sf.jasperreports.engine.JasperReport; + +/** + * This class is able to populate a {@link JasperReport} template with some data and parameters . + */ +public interface JasperFiller { + + /** + * Returns the a {@link JasperPrint} filled report. + * + * @return the populated {@link JasperPrint} report + * @throws JRException + */ + JasperPrint generate() throws JRException; + +} diff --git a/jasper/src/main/java/com/capgemini/reports/jasper/fillers/MonoFiller.java b/jasper/src/main/java/com/capgemini/reports/jasper/fillers/MonoFiller.java new file mode 100644 index 0000000..4f244a5 --- /dev/null +++ b/jasper/src/main/java/com/capgemini/reports/jasper/fillers/MonoFiller.java @@ -0,0 +1,46 @@ +package com.capgemini.reports.jasper.fillers; + +import net.sf.jasperreports.engine.JRException; +import net.sf.jasperreports.engine.JasperFillManager; +import net.sf.jasperreports.engine.JasperPrint; +import net.sf.jasperreports.engine.JasperReport; +import net.sf.jasperreports.engine.data.JRMapCollectionDataSource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.swing.Box.Filler; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +/** + * This class builds a simple report. + */ +public class MonoFiller implements JasperFiller { + private static final Logger LOGGER = LoggerFactory.getLogger(MonoFiller.class); + private final JasperReport compiledTemplate; + private final Collection> data; + private final Map parameters; + + /** + * Builds a basic Report {@link Filler}. + * + * @param compiledTemplate the {@link JasperReport} used as template + * @param parameters some report-wide parameters, stored as a {@link Map} with their name as a String key + * @param data a {@link List} of {@link Map Maps} representing a series of objects to be added to the report one after the other + */ + public MonoFiller(final JasperReport compiledTemplate, final Collection> data, final Map parameters) { + this.compiledTemplate = compiledTemplate; + this.data = data; + this.parameters = parameters; + } + + @Override + public final JasperPrint generate() throws JRException { + LOGGER.debug("JASPER filling"); + long start = System.currentTimeMillis(); + JasperPrint print = JasperFillManager.fillReport(compiledTemplate, parameters, new JRMapCollectionDataSource(data)); + LOGGER.debug("JASPER report Filling time : {} ms, {} pages expected", System.currentTimeMillis() - start, print.getPages().size()); + return print; + } +} diff --git a/jasper/src/main/java/com/capgemini/reports/jasper/fillers/MultiFiller.java b/jasper/src/main/java/com/capgemini/reports/jasper/fillers/MultiFiller.java new file mode 100644 index 0000000..8f217b4 --- /dev/null +++ b/jasper/src/main/java/com/capgemini/reports/jasper/fillers/MultiFiller.java @@ -0,0 +1,81 @@ +package com.capgemini.reports.jasper.fillers; + +import net.sf.jasperreports.engine.JRException; +import net.sf.jasperreports.engine.JasperFillManager; +import net.sf.jasperreports.engine.JasperPrint; +import net.sf.jasperreports.engine.JasperReport; +import net.sf.jasperreports.engine.data.JRMapCollectionDataSource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.swing.Box.Filler; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * This class is able to build a report containing one or several sub-reports (tables etc). + */ +public class MultiFiller implements JasperFiller { + private static final Logger LOGGER = LoggerFactory.getLogger(MultiFiller.class); + + private static final String DATA_KEY = "DATA"; + private static final String TEMPLATE_KEY = "TEMPLATE"; + private final JasperReport compiledTemplate; + private final Collection> data; + private final Map parameters; + + /** + * Builds a report {@link Filler} which is able to incorporate sub-reports (for tables etc). + * + * @param compiledTemplate the {@link JasperReport} used as template for the main report + * @param data a {@link List} of {@link Map Maps} representing a series of objects to be added to the report one after the other + * @param parameters some report-wide parameters, stored as a {@link Map} with their name as a String key + */ + public MultiFiller(final JasperReport compiledTemplate, final Collection> data, final Map parameters) { + this.compiledTemplate = compiledTemplate; + this.data = data; + this.parameters = parameters; + } + + /** + * Adds a sub-report to this report. + * + * @param key the {@link String} key in this 'father' template's parameters which leads to all the sub-report data + * @param template the {@link JasperReport} template to use for the sub-report + * @param subReportData the data to use in the sub-report + * @param subReportParameters the sub-report's parameters (parameters are subreport-wide constants) + */ + public void addSubReport(final String key, final JasperReport template, final Collection> subReportData, + final Map subReportParameters) { + Map reportMap = new HashMap<>(); + reportMap.put(TEMPLATE_KEY, template); + reportMap.put(DATA_KEY, subReportData); + reportMap.putAll(subReportParameters); + parameters.put(key, reportMap); + } + + /** + * Adds a sub-report (which is also a composite sub-report) to this report. + * + * @param key the {@link String} key in this 'father' template's parameters which leads to all the sub-report data + * @param subReport the {@link MultiFiller} to use for the sub-report + */ + public void addSubReport(final String key, final MultiFiller subReport) { + Map reportMap = new HashMap<>(); + reportMap.put(TEMPLATE_KEY, subReport.compiledTemplate); + reportMap.put(DATA_KEY, subReport.data); + reportMap.putAll(subReport.parameters); + parameters.put(key, reportMap); + } + + @Override + public final JasperPrint generate() throws JRException { + LOGGER.info("JASPER filling (multi-report)"); + long start = System.currentTimeMillis(); + JasperPrint print = JasperFillManager.fillReport(compiledTemplate, parameters, new JRMapCollectionDataSource(data)); + LOGGER.info("JASPER report Filling time : {} ms, {} pages expected", System.currentTimeMillis() - start, print.getPages().size()); + return print; + } +} diff --git a/jasper/src/main/java/com/capgemini/reports/jasper/printers/JasperCSVPrinter.java b/jasper/src/main/java/com/capgemini/reports/jasper/printers/JasperCSVPrinter.java new file mode 100644 index 0000000..7cb320a --- /dev/null +++ b/jasper/src/main/java/com/capgemini/reports/jasper/printers/JasperCSVPrinter.java @@ -0,0 +1,44 @@ +package com.capgemini.reports.jasper.printers; + +import net.sf.jasperreports.engine.JRException; +import net.sf.jasperreports.engine.JasperPrint; +import net.sf.jasperreports.engine.export.JRCsvExporter; +import net.sf.jasperreports.export.SimpleExporterInput; +import net.sf.jasperreports.export.SimpleWriterExporterOutput; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; + +/** + * Prints a JASPER report to .CSV. + */ +public class JasperCSVPrinter implements JasperPrinter { + private static final Logger LOGGER = LoggerFactory.getLogger(JasperCSVPrinter.class); + + private final String outputFilePath; + private final String outputFileName; + + /** + * Builds a CSV report printer with the provided parameters. + * + * @param outputFilePath the path to the folder where the final output report should be saved + * @param outputFileName the final output report filename + */ + public JasperCSVPrinter(final String outputFilePath, final String outputFileName) { + this.outputFilePath = outputFilePath; + this.outputFileName = outputFileName; + } + + @Override + public File print(final JasperPrint print) throws JRException { + long start = System.currentTimeMillis(); + JRCsvExporter exporter = new JRCsvExporter(); + exporter.setExporterInput(new SimpleExporterInput(print)); + File destFile = new File(this.outputFilePath, this.outputFileName + ".csv"); + exporter.setExporterOutput(new SimpleWriterExporterOutput(destFile)); + exporter.exportReport(); + LOGGER.info("CSV creation time : {} ms", System.currentTimeMillis() - start); + return destFile; + } +} diff --git a/jasper/src/main/java/com/capgemini/reports/jasper/printers/JasperPDFPrinter.java b/jasper/src/main/java/com/capgemini/reports/jasper/printers/JasperPDFPrinter.java new file mode 100644 index 0000000..ccf4552 --- /dev/null +++ b/jasper/src/main/java/com/capgemini/reports/jasper/printers/JasperPDFPrinter.java @@ -0,0 +1,39 @@ +package com.capgemini.reports.jasper.printers; + +import net.sf.jasperreports.engine.JRException; +import net.sf.jasperreports.engine.JasperExportManager; +import net.sf.jasperreports.engine.JasperPrint; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; + +/** + * Prints a JASPER report to .PDF. + */ +public class JasperPDFPrinter implements JasperPrinter { + private static final Logger LOGGER = LoggerFactory.getLogger(JasperPDFPrinter.class); + + private final String outputFilePath; + private final String outputFileName; + + /** + * Builds a PDF report printer with the provided parameters. + * + * @param outputFilePath the path to the folder where the final output report should be saved + * @param outputFileName the final output report filename + */ + public JasperPDFPrinter(final String outputFilePath, final String outputFileName) { + this.outputFilePath = outputFilePath; + this.outputFileName = outputFileName; + } + + @Override + public File print(final JasperPrint print) throws JRException { + long start = System.currentTimeMillis(); + String theFileName = outputFilePath + '/' + outputFileName + ".pdf"; + JasperExportManager.exportReportToPdfFile(print, theFileName); + LOGGER.info("PDF creation time {}: {} ms", theFileName, System.currentTimeMillis() - start); + return new File(theFileName); + } +} diff --git a/jasper/src/main/java/com/capgemini/reports/jasper/printers/JasperPrinter.java b/jasper/src/main/java/com/capgemini/reports/jasper/printers/JasperPrinter.java new file mode 100644 index 0000000..00fb786 --- /dev/null +++ b/jasper/src/main/java/com/capgemini/reports/jasper/printers/JasperPrinter.java @@ -0,0 +1,21 @@ +package com.capgemini.reports.jasper.printers; + +import net.sf.jasperreports.engine.JRException; +import net.sf.jasperreports.engine.JasperPrint; + +import java.io.File; + +/** + * Interface pour un gestionnaire d'impression JASPER. + */ +public interface JasperPrinter { + + /** + * Imprime le rapport sous le format desire. + * + * @param print the + * @return the generated {@link File} + */ + File print(final JasperPrint print) throws JRException; + +} diff --git a/jasper/src/main/java/com/capgemini/reports/jasper/printers/JasperXLSXPrinter.java b/jasper/src/main/java/com/capgemini/reports/jasper/printers/JasperXLSXPrinter.java new file mode 100644 index 0000000..dd46afa --- /dev/null +++ b/jasper/src/main/java/com/capgemini/reports/jasper/printers/JasperXLSXPrinter.java @@ -0,0 +1,55 @@ +package com.capgemini.reports.jasper.printers; + +import net.sf.jasperreports.engine.JRException; +import net.sf.jasperreports.engine.JasperPrint; +import net.sf.jasperreports.engine.export.ooxml.JRXlsxExporter; +import net.sf.jasperreports.export.SimpleExporterInput; +import net.sf.jasperreports.export.SimpleOutputStreamExporterOutput; +import net.sf.jasperreports.export.SimpleXlsxReportConfiguration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; + +/** + * Prints a JASPER report to .XLSX. + */ +public class JasperXLSXPrinter implements JasperPrinter { + private static final Logger LOGGER = LoggerFactory.getLogger(JasperXLSXPrinter.class); + + private final String outputFilePath; + private final String outputFileName; + + /** + * Builds a XLSX report printer with the provided parameters. + * + * @param outputFilePath the path to the folder where the final output report should be saved + * @param outputFileName the final output report filename + */ + public JasperXLSXPrinter(final String outputFilePath, final String outputFileName) { + this.outputFilePath = outputFilePath; + this.outputFileName = outputFileName; + } + + @Override + public File print(final JasperPrint print) throws JRException { + long start = System.currentTimeMillis(); + + + JRXlsxExporter exporter = new JRXlsxExporter(); + exporter.setExporterInput(new SimpleExporterInput(print)); + File destFile = new File(this.outputFilePath, this.outputFileName + ".xlsx"); + exporter.setExporterOutput(new SimpleOutputStreamExporterOutput(destFile)); + + SimpleXlsxReportConfiguration configuration = new SimpleXlsxReportConfiguration(); + configuration.setRemoveEmptySpaceBetweenRows(true); + configuration.setRemoveEmptySpaceBetweenColumns(true); + + exporter.setConfiguration(configuration); + exporter.exportReport(); + + LOGGER.info("XLSX creation time : {} ms", System.currentTimeMillis() - start); + return destFile; + } + +} diff --git a/jasper/src/test/java/com/capgemini/reports/jasper/compilers/JasperCompilerTest.java b/jasper/src/test/java/com/capgemini/reports/jasper/compilers/JasperCompilerTest.java new file mode 100644 index 0000000..0f1a99e --- /dev/null +++ b/jasper/src/test/java/com/capgemini/reports/jasper/compilers/JasperCompilerTest.java @@ -0,0 +1,19 @@ +package com.capgemini.reports.jasper.compilers; + +import net.sf.jasperreports.engine.JRException; +import org.testng.annotations.Test; + +import java.io.InputStream; + +import static org.assertj.core.api.Assertions.assertThat; + + +public class JasperCompilerTest { + private static final String JASPER_TEMPLATE = "/Jasper/template/report_r01.jrxml"; + + @Test + public void compileTest() throws JRException { + InputStream templateStream = getClass().getResourceAsStream(JASPER_TEMPLATE); + assertThat(JasperCompiler.compile(templateStream)).isNotNull(); + } +} diff --git a/jasper/src/test/java/com/capgemini/reports/jasper/fillers/MonoFillerTest.java b/jasper/src/test/java/com/capgemini/reports/jasper/fillers/MonoFillerTest.java new file mode 100644 index 0000000..12a514e --- /dev/null +++ b/jasper/src/test/java/com/capgemini/reports/jasper/fillers/MonoFillerTest.java @@ -0,0 +1,45 @@ +package com.capgemini.reports.jasper.fillers; + +import com.capgemini.reports.jasper.compilers.JasperCompiler; +import net.sf.jasperreports.engine.JRException; +import net.sf.jasperreports.engine.JasperPrint; +import net.sf.jasperreports.engine.JasperReport; +import org.testng.annotations.Test; + +import java.io.InputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + +public class MonoFillerTest { + + private static final String JASPER_TEMPLATE = "/Jasper/template/report_r20/page2/r20_p2_generics.jrxml"; + + @Test + public void generateTest() throws JRException { + // Compile the report + InputStream templateStream = getClass().getResourceAsStream(JASPER_TEMPLATE); + JasperReport reportTemplate = JasperCompiler.compile(templateStream); + + // Fill with some data + JasperFiller filler = new MonoFiller(reportTemplate, createData(10), new HashMap()); + JasperPrint print = filler.generate(); + assertThat(print).isNotNull(); + assertThat(print.getPages()).isNotEmpty(); + } + + private List> createData(final int numLines) { + List> data = new ArrayList<>(); + for (int num = 0; num < numLines; num++) { + Map map = new HashMap<>(); + map.put("GENERIC_AVEC_RUPTURE", "Generic-" + num); + map.put("ID_PART_AVANT", "Part Avant-" + num); + map.put("ID_PART_APRES", "Part Après-" + num); + data.add(map); + } + return data; + } +} diff --git a/jasper/src/test/java/com/capgemini/reports/jasper/fillers/MultiFillerTest.java b/jasper/src/test/java/com/capgemini/reports/jasper/fillers/MultiFillerTest.java new file mode 100644 index 0000000..22ca70f --- /dev/null +++ b/jasper/src/test/java/com/capgemini/reports/jasper/fillers/MultiFillerTest.java @@ -0,0 +1,87 @@ +package com.capgemini.reports.jasper.fillers; + +import com.capgemini.reports.jasper.compilers.JasperCompiler; +import net.sf.jasperreports.engine.JRException; +import net.sf.jasperreports.engine.JasperPrint; +import net.sf.jasperreports.engine.JasperReport; +import org.testng.annotations.Test; + +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + + +public class MultiFillerTest { + + private static final String SUBREPORT_P1 = "SUBREPORT_P1"; + private static final String JASPER_TEMPLATE_PAGE1 = "/Jasper/template/report_r20/report_r20_p1.jrxml"; + private static final String JASPER_TEMPLATE_MASTER = "/Jasper/template/report_r20/report_r20_master.jrxml"; + + + @Test + public void fillTest() throws JRException, IOException { + InputStream templateStream = getClass().getResourceAsStream(JASPER_TEMPLATE_MASTER); + InputStream page1Stream = getClass().getResourceAsStream(JASPER_TEMPLATE_PAGE1); + JasperReport mainReport = JasperCompiler.compile(templateStream); + JasperReport page1Report = JasperCompiler.compile(page1Stream); + MultiFiller filler = new MultiFiller(mainReport, setupEmptyData(), setupMainParameters()); + filler.addSubReport(SUBREPORT_P1, page1Report, setupPage1Data(5), setupPage1Parameters()); + JasperPrint print = filler.generate(); + assertThat(print.getPages()).isNotEmpty(); + } + + private List> setupEmptyData() { + List> list = new ArrayList<>(); + list.add(new HashMap()); + return list; + } + + private Map setupMainParameters() throws IOException { + Map parametersMap = new HashMap<>(); + try (InputStream imageStream = getClass().getResourceAsStream("/Jasper/images/Snecma_logo.png")) { + BufferedImage image = ImageIO.read(imageStream); + parametersMap.put("SNECMA_LOGO", image); + parametersMap.put("report_title", "Titre rapport principal"); + return parametersMap; + } + } + + private List> setupPage1Data(final int numberOfElements) { + List> lmrMaps = new ArrayList<>(); + for (int num = 0; num < numberOfElements; num++) { + Map lmrMap = new HashMap<>(); + lmrMap.put("CHANGE_REQUEST_APPLI", "APPLI-" + num); + lmrMap.put("CHANGE_REQUEST_IDENTIFIANT", "ID-" + num); + lmrMap.put("CHANGE_REQUEST_NOM", "NOM-" + num); + lmrMap.put("CHANGE_REQUEST_NO_APPRO_SO", "NO_APPRO-" + num); + lmrMaps.add(lmrMap); + } + return lmrMaps; + } + + private Map setupPage1Parameters() { + Map map = new HashMap<>(); + map.put("PRODUIT", "produit"); + map.put("UNIT_AVANT", "30"); + map.put("UNIT_APRES", "40"); + map.put("EXCEPTIONNEL_AVANT", "oui"); + map.put("EXCEPTIONNEL_APRES", "non"); + map.put("TITRE_P1", "titre 1"); + map.put("TITRE_P2", "titre 2"); + map.put("TITRE_P3", "titre 3"); + map.put("TITRE_P4", "titre 4"); + map.put("DOMAINE_PRODUIT_AVANT", "domaine avant"); + map.put("DOMAINE_PRODUIT_APRES", "domaine apres"); + map.put("LIGNE_PRODUIT_AVANT", "ligne produit avant"); + map.put("LIGNE_PRODUIT_APRES", "ligne produit apres"); + map.put("MATRICULE_MOTEUR", "03435841351"); + return map; + } +} diff --git a/jasper/src/test/java/com/capgemini/reports/jasper/printers/JasperPDFPrinterTest.java b/jasper/src/test/java/com/capgemini/reports/jasper/printers/JasperPDFPrinterTest.java new file mode 100644 index 0000000..b1bf7dd --- /dev/null +++ b/jasper/src/test/java/com/capgemini/reports/jasper/printers/JasperPDFPrinterTest.java @@ -0,0 +1,46 @@ +package com.capgemini.reports.jasper.printers; + +import com.capgemini.reports.jasper.compilers.JasperCompiler; +import com.capgemini.reports.jasper.fillers.JasperFiller; +import com.capgemini.reports.jasper.fillers.MonoFiller; +import net.sf.jasperreports.engine.JRException; +import net.sf.jasperreports.engine.JasperPrint; +import net.sf.jasperreports.engine.JasperReport; +import org.testng.annotations.Test; + +import java.io.InputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + + +public class JasperPDFPrinterTest { + + private static final String JASPER_TEMPLATE = "/Jasper/template/report_r20/page2/r20_p2_generics.jrxml"; + + @Test + public void testMulti() throws JRException { + InputStream templateStream = getClass().getResourceAsStream(JASPER_TEMPLATE); + JasperReport reportTemplate = JasperCompiler.compile(templateStream); + + // Fill with some data + JasperFiller filler = new MonoFiller(reportTemplate, setupPage2GenericData(10), new HashMap()); + JasperPrint print = filler.generate(); + assertThat(print.getPages()).isNotEmpty(); + } + + private List> setupPage2GenericData(final int numberOfElements) { + List> lmrMaps = new ArrayList<>(); + for (int num = 0; num < numberOfElements; num++) { + Map lmrMap = new HashMap<>(); + lmrMap.put("GENERIC_AVEC_RUPTURE", "Generic-" + num); + lmrMap.put("ID_PART_AVANT", "Part-Avant-" + num); + lmrMap.put("ID_PART_APREs", "Part-Après-" + num); + lmrMaps.add(lmrMap); + } + return lmrMaps; + } +} diff --git a/jasper/src/test/resources/Jasper/images/Snecma_logo.png b/jasper/src/test/resources/Jasper/images/Snecma_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..e40717b639e8a24db9990e597b390c0d07d49b4d GIT binary patch literal 3973 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 E7agyn3jhEB literal 0 HcmV?d00001 diff --git a/jasper/src/test/resources/Jasper/images/confidentiel_industrie.jpg b/jasper/src/test/resources/Jasper/images/confidentiel_industrie.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3008bffedfa4f4c12577b88d522293572ad7df29 GIT binary patch literal 33675 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 literal 0 HcmV?d00001 diff --git a/jasper/src/test/resources/Jasper/template/dynamic_table/reference.jrxml b/jasper/src/test/resources/Jasper/template/dynamic_table/reference.jrxml new file mode 100644 index 0000000..8ba8eb0 --- /dev/null +++ b/jasper/src/test/resources/Jasper/template/dynamic_table/reference.jrxml @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/jasper/src/test/resources/Jasper/template/dynamic_table/template.jrxml b/jasper/src/test/resources/Jasper/template/dynamic_table/template.jrxml new file mode 100644 index 0000000..509c616 --- /dev/null +++ b/jasper/src/test/resources/Jasper/template/dynamic_table/template.jrxml @@ -0,0 +1,23 @@ + + + [[PARAMETERS]] + + + [[FIELDS]] + + + + + [[HEADERS]] + + + + [[CONTENT]] + + + diff --git a/jasper/src/test/resources/Jasper/template/report_r01.jrxml b/jasper/src/test/resources/Jasper/template/report_r01.jrxml new file mode 100644 index 0000000..96cb852 --- /dev/null +++ b/jasper/src/test/resources/Jasper/template/report_r01.jrxml @@ -0,0 +1,749 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/jasper/src/test/resources/Jasper/template/report_r03.jrxml b/jasper/src/test/resources/Jasper/template/report_r03.jrxml new file mode 100644 index 0000000..ea0509c --- /dev/null +++ b/jasper/src/test/resources/Jasper/template/report_r03.jrxml @@ -0,0 +1,750 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/jasper/src/test/resources/Jasper/template/report_r10.jrxml b/jasper/src/test/resources/Jasper/template/report_r10.jrxml new file mode 100644 index 0000000..bb0d0f2 --- /dev/null +++ b/jasper/src/test/resources/Jasper/template/report_r10.jrxml @@ -0,0 +1,975 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/jasper/src/test/resources/Jasper/template/report_r11.jrxml b/jasper/src/test/resources/Jasper/template/report_r11.jrxml new file mode 100644 index 0000000..2b3390a --- /dev/null +++ b/jasper/src/test/resources/Jasper/template/report_r11.jrxml @@ -0,0 +1,687 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <band height="160" splitType="Stretch"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + <staticText> + <reportElement x="-20" y="100" width="320" height="20" uuid="33d7e186-0b67-416e-8a86-26655b01cf0c"/> + <textElement> + <font size="8"/> + </textElement> + <text><![CDATA[Nombre de repères fonctionnels avec mise en maquette cohérente]]></text> + </staticText> + <staticText> + <reportElement x="-20" y="20" width="320" height="20" uuid="b554ec37-e2af-4344-a385-263bd5dffdab"/> + <textElement> + <font size="8"/> + </textElement> + <text><![CDATA[Nombre de repères fonctionnels mis en maquette :]]></text> + </staticText> + <staticText> + <reportElement x="-20" y="40" width="320" height="20" uuid="4628b4ee-acce-490a-a3cc-5ff1289d5db0"/> + <textElement> + <font size="8"/> + </textElement> + <text><![CDATA[Pourcentage de mise en maquette :]]></text> + </staticText> + <staticText> + <reportElement x="-20" y="60" width="320" height="20" uuid="d2763629-2316-46e2-8d08-bc2f012aa4be"/> + <textElement> + <font size="8"/> + </textElement> + <text><![CDATA[Nombre de repères fonctionnels avec une incohérence de mise en maquette :]]></text> + </staticText> + <staticText> + <reportElement x="-20" y="80" width="320" height="20" uuid="594ca80b-2686-45e1-a831-1d32b7d0e891"/> + <textElement> + <font size="8"/> + </textElement> + <text><![CDATA[Pourcentage de repères fonctionnels mis en maquette incohérente]]></text> + </staticText> + <textField> + <reportElement x="300" y="0" width="80" height="20" uuid="1ad40902-0de9-428b-aa8a-7a6f21d3c998"/> + <textFieldExpression><![CDATA[$P{NOMBRE_REPERE_FONCTIONNEL_METTRE_EN_MAQUETTE}]]></textFieldExpression> + </textField> + <textField> + <reportElement x="300" y="20" width="80" height="20" uuid="dd6c4654-9f34-4bdd-84df-55ef28c91c67"/> + <textFieldExpression><![CDATA[$P{NOMBRE_REPERE_FONCTIONNEL_MAQUETTE}]]></textFieldExpression> + </textField> + <textField> + <reportElement x="300" y="40" width="80" height="20" uuid="6fb1523c-9e69-45aa-b61d-5a8ae9b6ef19"/> + <textFieldExpression><![CDATA[$P{MISE_EN_MAQUETTE_POURCENTAGE}]]></textFieldExpression> + </textField> + <textField> + <reportElement x="300" y="60" width="80" height="20" uuid="a90d110c-893d-4f00-83d6-0ad6a7454926"/> + <textFieldExpression><![CDATA[$P{NOMBRE_REPERE_FONCTIONNEL_INCOHERENT}]]></textFieldExpression> + </textField> + <textField> + <reportElement x="300" y="80" width="80" height="20" uuid="f8c79aed-4af3-44d3-bc43-a4ac7fb08f4d"/> + <textFieldExpression> + <![CDATA[$P{REPERE_FONCTIONNEL_MAQUETTE_INCOHERENTE_POURCENTAGE}]]></textFieldExpression> + </textField> + <staticText> + <reportElement x="-20" y="0" width="320" height="20" uuid="686e3570-9ad2-4202-8d37-a7e6f8cdb515"/> + <textElement> + <font size="8"/> + </textElement> + <text><![CDATA[Nombre de repères fonctionnels à mettre en maquette]]></text> + </staticText> + <staticText> + <reportElement x="-20" y="120" width="320" height="20" uuid="87021f19-7594-4bdd-a6ff-8ea485226e51"/> + <textElement> + <font size="8"/> + </textElement> + <text><![CDATA[Pourcentage de repères fonctionnels mis en maquette cohérente]]></text> + </staticText> + <textField> + <reportElement x="300" y="120" width="80" height="20" uuid="08415e62-0b9f-439f-af0f-0ab21019984b"/> + <textFieldExpression><![CDATA[$P{POURCENTAGE_MAQUETTE_COHERENTE}]]></textFieldExpression> + </textField> + <textField> + <reportElement x="300" y="100" width="80" height="20" uuid="7a9d71de-3528-41f3-a26d-481290de89c6"/> + <textFieldExpression> + <![CDATA[$P{NOMBRE_REPERE_FONCTIONNEL_MISE_EN_MAQUETTE_COHERENTE}]]></textFieldExpression> + </textField> + </band> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/jasper/src/test/resources/Jasper/template/report_r15r16.jrxml b/jasper/src/test/resources/Jasper/template/report_r15r16.jrxml new file mode 100644 index 0000000..c98dd91 --- /dev/null +++ b/jasper/src/test/resources/Jasper/template/report_r15r16.jrxml @@ -0,0 +1,686 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1]]> + + + + + + + + + + + + + <band height="800"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + <image> + <reportElement x="0" y="0" width="180" height="40" uuid="bd1c5457-daa9-4754-9f61-54f1400686ee"> + <property name="local_mesure_unitwidth" value="pixel"/> + <property name="com.jaspersoft.studio.unit.width" value="px"/> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <imageExpression><![CDATA[$P{SNECMA_LOGO}]]></imageExpression> + </image> + <staticText> + <reportElement x="0" y="560" width="150" height="30" uuid="c8e9f5f7-1896-4aaf-b18a-0c09312016cd"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement verticalAlignment="Middle"> + <font isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[MT +MT Number]]></text> + </staticText> + <staticText> + <reportElement x="0" y="590" width="150" height="30" uuid="62981c54-a5b2-48bf-9840-cc4e60859226"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement verticalAlignment="Middle"> + <font isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Date de lancement +Release date]]></text> + </staticText> + <staticText> + <reportElement x="180" y="530" width="300" height="20" uuid="7cd156c7-8245-4fad-bac6-3244c82501c8"/> + <textElement> + <font isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Définition précédente / Previous Definition]]></text> + </staticText> + <textField> + <reportElement x="150" y="590" width="405" height="30" uuid="2c240f3e-0a02-4bcd-a98c-8c894e9e1d19"/> + <textElement verticalAlignment="Middle"> + <font pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{PREVIOUS_RELEASE_DATE}]]></textFieldExpression> + </textField> + <textField> + <reportElement x="150" y="560" width="405" height="30" uuid="2830e066-9f5f-4682-bc32-64bc41b898fa"/> + <textElement verticalAlignment="Middle"> + <font pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{MT_NUMBER}]]></textFieldExpression> + </textField> + <staticText> + <reportElement x="0" y="280" width="150" height="30" uuid="d58f0c3a-9c3f-42a0-9a74-c4b13a4bfc9e"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Dénomination Française +French Designation]]></text> + </staticText> + <textField> + <reportElement x="150" y="280" width="405" height="30" uuid="e5081414-e2bf-40bd-bccc-567131df6a5e"/> + <textElement verticalAlignment="Middle"> + <font pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{FRENCH_DESIGNATION}]]></textFieldExpression> + </textField> + <staticText> + <reportElement x="0" y="490" width="150" height="30" uuid="c71a994c-a413-4f90-a94a-fcadd4a82a17"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Obturation +Obturation]]></text> + </staticText> + <textField> + <reportElement x="150" y="400" width="405" height="30" uuid="48b02918-dd5b-45ea-bce6-6423778e1596"/> + <textElement verticalAlignment="Middle"> + <font pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{LOG_DOCUMENT}]]></textFieldExpression> + </textField> + <textField> + <reportElement x="150" y="160" width="405" height="30" uuid="b8f4eb10-ca2d-498c-94ce-7589f0d24c80"/> + <textElement verticalAlignment="Middle"> + <font pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{PRODUCT_TYPE}]]></textFieldExpression> + </textField> + <textField> + <reportElement x="150" y="190" width="405" height="30" uuid="06a0f02d-35ff-49f5-a0da-43fd541563bb"/> + <textElement verticalAlignment="Middle"> + <font pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{PART_NUMBER}]]></textFieldExpression> + </textField> + <staticText> + <reportElement x="0" y="400" width="150" height="30" uuid="a329c593-2261-491c-8216-3449466dd821"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Document de contrôle +Log Document]]></text> + </staticText> + <staticText> + <reportElement x="0" y="250" width="150" height="30" uuid="c887a61f-5bdf-4759-b01f-ca535f263f7c"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Version de l’article +Part version]]></text> + </staticText> + <staticText> + <reportElement x="0" y="160" width="150" height="30" uuid="0b2fbdcf-2b30-4936-b89a-b237bc00858a"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Type produit +Product Type]]></text> + </staticText> + <textField> + <reportElement x="150" y="490" width="405" height="30" uuid="f9019024-1120-45c1-a3fa-a4f6b6c00eab"/> + <textElement verticalAlignment="Middle"> + <font pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{OBTURATION}]]></textFieldExpression> + </textField> + <textField> + <reportElement x="150" y="220" width="405" height="30" uuid="04f2420a-7fd1-42b0-8da2-422f0b2a99c5"/> + <textElement verticalAlignment="Middle"> + <font pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{MANUFACTURER_CODE}]]></textFieldExpression> + </textField> + <staticText> + <reportElement x="0" y="370" width="150" height="30" uuid="a3f18762-a923-47c2-9dab-0bb02dea7ec5"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Suivi Utilisation +Field OPN serialisation]]></text> + </staticText> + <textField> + <reportElement x="150" y="370" width="405" height="30" uuid="0f42ed3c-21a3-48ab-bab2-7e61699bdc78"/> + <textElement verticalAlignment="Middle"> + <font pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{FIELD_OPN_SERIALISATION}]]></textFieldExpression> + </textField> + <staticText> + <reportElement x="0" y="340" width="150" height="30" uuid="e74a400e-5b28-4206-9538-0e5322e395be"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Classement +Classification]]></text> + </staticText> + <textField> + <reportElement x="150" y="340" width="405" height="30" uuid="5531e836-80a9-4bb9-8216-98637993b852"/> + <textElement verticalAlignment="Middle"> + <font pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{CLASSIFICATION}]]></textFieldExpression> + </textField> + <staticText> + <reportElement x="0" y="190" width="150" height="30" uuid="a760d63d-8652-4c30-a0fc-80032474925f"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Référence de l’article +Part Number]]></text> + </staticText> + <textField> + <reportElement x="150" y="250" width="405" height="30" uuid="7acd17db-c975-482b-b33a-5a50cd7e495e"/> + <textElement verticalAlignment="Middle"> + <font pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{PART_VERSION}]]></textFieldExpression> + </textField> + <staticText> + <reportElement x="0" y="220" width="150" height="30" uuid="56254219-d62f-4d1f-b7e2-e7ba6b55db05"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Code Fabricant +Manufacturer code]]></text> + </staticText> + <textField> + <reportElement x="60" y="80" width="120" height="20" uuid="16a34db8-b544-4ed7-aa30-723bbd0f2c97"> + <property name="local_mesure_unity" value="pixel"/> + <property name="com.jaspersoft.studio.unit.y" value="px"/> + </reportElement> + <box leftPadding="5"> + <topPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <leftPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <bottomPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <rightPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + </box> + <textElement verticalAlignment="Middle"> + <font pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{ITEM_ID}]]></textFieldExpression> + </textField> + <textField> + <reportElement x="200" y="120" width="290" height="20" uuid="5cd5ea2e-370d-4843-86ec-284dd5cc4669"/> + <box leftPadding="5"> + <topPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <leftPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <bottomPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <rightPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + </box> + <textElement verticalAlignment="Middle"> + <font pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{RELEASE_DATE}]]></textFieldExpression> + </textField> + <textField> + <reportElement x="200" y="80" width="290" height="20" uuid="90631035-798d-4f4d-800a-1ae0da7199ce"/> + <box leftPadding="5"> + <topPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <leftPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <bottomPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <rightPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + </box> + <textElement verticalAlignment="Middle"> + <font pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{ITEM_REVISION_ID}]]></textFieldExpression> + </textField> + <textField> + <reportElement x="60" y="120" width="120" height="20" uuid="ae3b956d-b485-4801-81d9-dc75765b5f27"/> + <box leftPadding="5"> + <topPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <leftPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <bottomPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <rightPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + </box> + <textElement verticalAlignment="Middle"> + <font pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{PRODUCT_UNIT}]]></textFieldExpression> + </textField> + <textField isStretchWithOverflow="true"> + <reportElement stretchType="RelativeToTallestObject" x="30" y="681" width="490" height="119" + uuid="0953ec0c-dd4c-4d2b-bfdf-bc17f90863e7"/> + <textElement textAlignment="Center" markup="styled"> + <font size="7" isBold="false" pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{CLAUSE_PROPRIETE}]]></textFieldExpression> + </textField> + <line> + <reportElement x="0" y="680" width="555" height="1" uuid="c8a04261-d21b-476f-a9c8-3513667543fe"> + <property name="local_mesure_unity" value="pixel"/> + <property name="com.jaspersoft.studio.unit.y" value="px"/> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + </line> + <textField> + <reportElement x="520" y="780" width="34" height="20" uuid="f3f0d26b-5d68-4356-88f2-fc0b8d32b880"/> + <textElement textAlignment="Right"> + <font isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <textFieldExpression><![CDATA[$V{PAGE_NUMBER}]]></textFieldExpression> + </textField> + <textField> + <reportElement x="150" y="310" width="405" height="30" uuid="1e3b2e3b-8658-4332-8baa-1492978ab190"/> + <textElement verticalAlignment="Middle"> + <font pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{ENGLISH_DESIGNATION}]]></textFieldExpression> + </textField> + <staticText> + <reportElement x="0" y="310" width="150" height="30" uuid="1026facf-47bb-4163-939d-a87d49e93d9e"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Dénomination Anglaise +English designation]]></text> + </staticText> + <staticText> + <reportElement x="0" y="430" width="150" height="30" uuid="58157510-6554-420b-b0eb-97ade29844ae"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Frontière Avion +Installation Interface]]></text> + </staticText> + <textField> + <reportElement x="150" y="460" width="405" height="30" uuid="a12899e5-d6f2-42f0-9de5-5acdc64ed2a2"/> + <textElement verticalAlignment="Middle"> + <font pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{PARTNER_INTERFACE}]]></textFieldExpression> + </textField> + <staticText> + <reportElement x="0" y="460" width="150" height="30" uuid="5a2f3dcd-1fbd-4e8f-b46f-577c64544d37"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Frontière Coopérant +Partner Interface]]></text> + </staticText> + <textField> + <reportElement x="150" y="430" width="405" height="30" uuid="ab848d3a-8005-4763-8583-384bb8c70cfc"/> + <textElement verticalAlignment="Middle"> + <font pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{INSTALLATION_INTERFACE}]]></textFieldExpression> + </textField> + <textField> + <reportElement x="80" y="40" width="380" height="30" uuid="3f7c9d3f-0877-4237-a0c2-5b2c3e0e561c"/> + <textElement textAlignment="Center" verticalAlignment="Middle" markup="styled"> + <font isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <textFieldExpression><![CDATA[$P{REPORT_TITLE}]]></textFieldExpression> + </textField> + </band> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/jasper/src/test/resources/Jasper/template/report_r17.jrxml b/jasper/src/test/resources/Jasper/template/report_r17.jrxml new file mode 100644 index 0000000..ec33a10 --- /dev/null +++ b/jasper/src/test/resources/Jasper/template/report_r17.jrxml @@ -0,0 +1,621 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1]]> + + + + + + + + + + + + + <band height="800"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + <image> + <reportElement x="0" y="0" width="180" height="40" uuid="bd1c5457-daa9-4754-9f61-54f1400686ee"> + <property name="local_mesure_unitwidth" value="pixel"/> + <property name="com.jaspersoft.studio.unit.width" value="px"/> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <imageExpression><![CDATA[$P{SNECMA_LOGO}]]></imageExpression> + </image> + <staticText> + <reportElement x="0" y="560" width="150" height="30" uuid="c8e9f5f7-1896-4aaf-b18a-0c09312016cd"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement verticalAlignment="Middle"> + <font isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[MT +MT Number]]></text> + </staticText> + <staticText> + <reportElement x="0" y="590" width="150" height="30" uuid="62981c54-a5b2-48bf-9840-cc4e60859226"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement verticalAlignment="Middle"> + <font isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Date de lancement +Release date]]></text> + </staticText> + <staticText> + <reportElement x="180" y="530" width="300" height="20" uuid="7cd156c7-8245-4fad-bac6-3244c82501c8"/> + <textElement> + <font isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Définition précédente / Previous Definition]]></text> + </staticText> + <textField> + <reportElement x="150" y="590" width="405" height="30" uuid="2c240f3e-0a02-4bcd-a98c-8c894e9e1d19"/> + <textElement verticalAlignment="Middle"> + <font pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{PREVIOUS_RELEASE_DATE}]]></textFieldExpression> + </textField> + <textField> + <reportElement x="150" y="560" width="405" height="30" uuid="2830e066-9f5f-4682-bc32-64bc41b898fa"/> + <textElement verticalAlignment="Middle"> + <font pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{MT_NUMBER}]]></textFieldExpression> + </textField> + <staticText> + <reportElement x="0" y="280" width="150" height="30" uuid="d58f0c3a-9c3f-42a0-9a74-c4b13a4bfc9e"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Dénomination Française +French Designation]]></text> + </staticText> + <textField> + <reportElement x="150" y="280" width="405" height="30" uuid="e5081414-e2bf-40bd-bccc-567131df6a5e"/> + <textElement verticalAlignment="Middle"> + <font pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{FRENCH_DESIGNATION}]]></textFieldExpression> + </textField> + <staticText> + <reportElement x="0" y="430" width="150" height="30" uuid="c71a994c-a413-4f90-a94a-fcadd4a82a17"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Obturation +Obturation]]></text> + </staticText> + <textField> + <reportElement x="150" y="400" width="405" height="30" uuid="48b02918-dd5b-45ea-bce6-6423778e1596"/> + <textElement verticalAlignment="Middle"> + <font pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{LOG_DOCUMENT}]]></textFieldExpression> + </textField> + <textField> + <reportElement x="150" y="160" width="405" height="30" uuid="b8f4eb10-ca2d-498c-94ce-7589f0d24c80"/> + <textElement verticalAlignment="Middle"> + <font pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{PRODUCT_TYPE}]]></textFieldExpression> + </textField> + <textField> + <reportElement x="150" y="190" width="405" height="30" uuid="06a0f02d-35ff-49f5-a0da-43fd541563bb"/> + <textElement verticalAlignment="Middle"> + <font pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{PART_NUMBER}]]></textFieldExpression> + </textField> + <staticText> + <reportElement x="0" y="400" width="150" height="30" uuid="a329c593-2261-491c-8216-3449466dd821"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Document de contrôle +Log Document]]></text> + </staticText> + <staticText> + <reportElement x="0" y="250" width="150" height="30" uuid="c887a61f-5bdf-4759-b01f-ca535f263f7c"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Version de l’article +Part version]]></text> + </staticText> + <staticText> + <reportElement x="0" y="160" width="150" height="30" uuid="0b2fbdcf-2b30-4936-b89a-b237bc00858a"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Type produit +Product Type]]></text> + </staticText> + <textField> + <reportElement x="150" y="430" width="405" height="30" uuid="f9019024-1120-45c1-a3fa-a4f6b6c00eab"/> + <textElement verticalAlignment="Middle"> + <font pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{OBTURATION}]]></textFieldExpression> + </textField> + <textField> + <reportElement x="150" y="220" width="405" height="30" uuid="04f2420a-7fd1-42b0-8da2-422f0b2a99c5"/> + <textElement verticalAlignment="Middle"> + <font pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{MANUFACTURER_CODE}]]></textFieldExpression> + </textField> + <staticText> + <reportElement x="0" y="370" width="150" height="30" uuid="a3f18762-a923-47c2-9dab-0bb02dea7ec5"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Suivi Utilisation +Field OPN serialisation]]></text> + </staticText> + <textField> + <reportElement x="150" y="370" width="405" height="30" uuid="0f42ed3c-21a3-48ab-bab2-7e61699bdc78"/> + <textElement verticalAlignment="Middle"> + <font pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{FIELD_OPN_SERIALISATION}]]></textFieldExpression> + </textField> + <staticText> + <reportElement x="0" y="340" width="150" height="30" uuid="e74a400e-5b28-4206-9538-0e5322e395be"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Classement +Classification]]></text> + </staticText> + <textField> + <reportElement x="150" y="340" width="405" height="30" uuid="5531e836-80a9-4bb9-8216-98637993b852"/> + <textElement verticalAlignment="Middle"> + <font pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{CLASSIFICATION}]]></textFieldExpression> + </textField> + <staticText> + <reportElement x="0" y="190" width="150" height="30" uuid="a760d63d-8652-4c30-a0fc-80032474925f"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Référence de l’article +Part Number]]></text> + </staticText> + <textField> + <reportElement x="150" y="250" width="405" height="30" uuid="7acd17db-c975-482b-b33a-5a50cd7e495e"/> + <textElement verticalAlignment="Middle"> + <font pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{PART_VERSION}]]></textFieldExpression> + </textField> + <staticText> + <reportElement x="0" y="220" width="150" height="30" uuid="56254219-d62f-4d1f-b7e2-e7ba6b55db05"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Code Fabricant +Manufacturer code]]></text> + </staticText> + <textField> + <reportElement x="60" y="80" width="120" height="20" uuid="16a34db8-b544-4ed7-aa30-723bbd0f2c97"> + <property name="local_mesure_unity" value="pixel"/> + <property name="com.jaspersoft.studio.unit.y" value="px"/> + </reportElement> + <box leftPadding="5"> + <topPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <leftPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <bottomPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <rightPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + </box> + <textElement verticalAlignment="Middle"> + <font pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{ITEM_ID}]]></textFieldExpression> + </textField> + <textField> + <reportElement x="200" y="120" width="290" height="20" uuid="5cd5ea2e-370d-4843-86ec-284dd5cc4669"/> + <box leftPadding="5"> + <topPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <leftPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <bottomPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <rightPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + </box> + <textElement verticalAlignment="Middle"> + <font pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{RELEASE_DATE}]]></textFieldExpression> + </textField> + <textField> + <reportElement x="200" y="80" width="290" height="20" uuid="90631035-798d-4f4d-800a-1ae0da7199ce"/> + <box leftPadding="5"> + <topPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <leftPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <bottomPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <rightPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + </box> + <textElement verticalAlignment="Middle"> + <font pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{ITEM_REVISION_ID}]]></textFieldExpression> + </textField> + <textField isStretchWithOverflow="true"> + <reportElement stretchType="RelativeToTallestObject" x="30" y="680" width="490" height="120" + uuid="0953ec0c-dd4c-4d2b-bfdf-bc17f90863e7"/> + <textElement textAlignment="Center" markup="styled"> + <font size="7" isBold="false" pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{CLAUSE_PROPRIETE}]]></textFieldExpression> + </textField> + <line> + <reportElement x="0" y="680" width="555" height="1" uuid="c8a04261-d21b-476f-a9c8-3513667543fe"> + <property name="local_mesure_unity" value="pixel"/> + <property name="com.jaspersoft.studio.unit.y" value="px"/> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + </line> + <textField> + <reportElement x="520" y="780" width="34" height="20" uuid="f3f0d26b-5d68-4356-88f2-fc0b8d32b880"/> + <textElement textAlignment="Right"> + <font isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <textFieldExpression><![CDATA[$V{PAGE_NUMBER}]]></textFieldExpression> + </textField> + <staticText> + <reportElement x="0" y="310" width="150" height="30" uuid="7807ccdf-9479-42d0-8a5c-a41805923c37"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Dénomination Anglaise +English designation]]></text> + </staticText> + <textField> + <reportElement x="150" y="310" width="405" height="30" uuid="fdd0ad29-2a8c-4c0a-88f8-da8648ca3f5d"/> + <textElement verticalAlignment="Middle"> + <font pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{ENGLISH_DESIGNATION}]]></textFieldExpression> + </textField> + <rectangle> + <reportElement x="60" y="120" width="120" height="20" uuid="fe8029bb-5c43-450a-bb89-70908609e531"/> + </rectangle> + <textField> + <reportElement x="80" y="40" width="380" height="30" uuid="13308d92-200e-48eb-8dcf-77e6f9f271b9"/> + <textElement textAlignment="Center" verticalAlignment="Middle" markup="styled"> + <font isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <textFieldExpression><![CDATA[$P{REPORT_TITLE}]]></textFieldExpression> + </textField> + </band> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/jasper/src/test/resources/Jasper/template/report_r19.jrxml b/jasper/src/test/resources/Jasper/template/report_r19.jrxml new file mode 100644 index 0000000..0843752 --- /dev/null +++ b/jasper/src/test/resources/Jasper/template/report_r19.jrxml @@ -0,0 +1,518 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/jasper/src/test/resources/Jasper/template/report_r20/page2/r20_p2_generics.jrxml b/jasper/src/test/resources/Jasper/template/report_r20/page2/r20_p2_generics.jrxml new file mode 100644 index 0000000..0bc1aba --- /dev/null +++ b/jasper/src/test/resources/Jasper/template/report_r20/page2/r20_p2_generics.jrxml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/jasper/src/test/resources/Jasper/template/report_r20/page2/r20_p2_impacts.jrxml b/jasper/src/test/resources/Jasper/template/report_r20/page2/r20_p2_impacts.jrxml new file mode 100644 index 0000000..f74f250 --- /dev/null +++ b/jasper/src/test/resources/Jasper/template/report_r20/page2/r20_p2_impacts.jrxml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/jasper/src/test/resources/Jasper/template/report_r20/page2/r20_p2_noimpacts.jrxml b/jasper/src/test/resources/Jasper/template/report_r20/page2/r20_p2_noimpacts.jrxml new file mode 100644 index 0000000..0f1d05d --- /dev/null +++ b/jasper/src/test/resources/Jasper/template/report_r20/page2/r20_p2_noimpacts.jrxml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/jasper/src/test/resources/Jasper/template/report_r20/page3/page3reference.jrxml b/jasper/src/test/resources/Jasper/template/report_r20/page3/page3reference.jrxml new file mode 100644 index 0000000..2aabc7c --- /dev/null +++ b/jasper/src/test/resources/Jasper/template/report_r20/page3/page3reference.jrxml @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + >)$P{CROSS_TABLE}.get("DATA_SUBREPORT0"))]]> + + + + + + >)$P{CROSS_TABLE}.get("DATA_SUBREPORT1"))]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/jasper/src/test/resources/Jasper/template/report_r20/page3/report_r20_p3.jrxml b/jasper/src/test/resources/Jasper/template/report_r20/page3/report_r20_p3.jrxml new file mode 100644 index 0000000..0c8e5ec --- /dev/null +++ b/jasper/src/test/resources/Jasper/template/report_r20/page3/report_r20_p3.jrxml @@ -0,0 +1,114 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + [[SUBTABLES]] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/jasper/src/test/resources/Jasper/template/report_r20/report_r20_master.jrxml b/jasper/src/test/resources/Jasper/template/report_r20/report_r20_master.jrxml new file mode 100644 index 0000000..9938dcc --- /dev/null +++ b/jasper/src/test/resources/Jasper/template/report_r20/report_r20_master.jrxml @@ -0,0 +1,300 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + >)$P{SUBREPORT_P2}.get("DATA"))]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + >)$P{SUBREPORT_P1}.get("DATA"))]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + >)$P{SUBREPORT_P3}.get("DATA"))]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + >)$P{SUBREPORT_P4}.get("DATA"))]]> + + + + + + + + + + + + + Ce document est la propriété de Safran Aircraft Engines. Il ne peut être utilisé, reproduit ou communiqué sans son autorisation.
    F0301"]]>
    +
    +
    +
    + + + + + + + + + +
    diff --git a/jasper/src/test/resources/Jasper/template/report_r20/report_r20_p1.jrxml b/jasper/src/test/resources/Jasper/template/report_r20/report_r20_p1.jrxml new file mode 100644 index 0000000..d9891ed --- /dev/null +++ b/jasper/src/test/resources/Jasper/template/report_r20/report_r20_p1.jrxml @@ -0,0 +1,267 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/jasper/src/test/resources/Jasper/template/report_r20/report_r20_p2.jrxml b/jasper/src/test/resources/Jasper/template/report_r20/report_r20_p2.jrxml new file mode 100644 index 0000000..81fcd01 --- /dev/null +++ b/jasper/src/test/resources/Jasper/template/report_r20/report_r20_p2.jrxml @@ -0,0 +1,119 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + >)$P{SUBREPORT_GENERIC}.get("DATA"))]]> + + + + + + + + + + + + + + + + + + + + + >)$P{SUBREPORT_IMPACTS}.get("DATA"))]]> + + + + + + + + + + + + + + >)$P{SUBREPORT_NOIMPACTS}.get("DATA"))]]> + + + + + + + + + + + + diff --git a/jasper/src/test/resources/Jasper/template/report_r20/report_r20_p4.jrxml b/jasper/src/test/resources/Jasper/template/report_r20/report_r20_p4.jrxml new file mode 100644 index 0000000..d38b7ca --- /dev/null +++ b/jasper/src/test/resources/Jasper/template/report_r20/report_r20_p4.jrxml @@ -0,0 +1,279 @@ + + + + + + + + + + + + + + + + + + + + + + + + <band height="103" splitType="Stretch"> + <staticText> + <reportElement x="0" y="0" width="800" height="30" uuid="92028f51-246a-47f2-8c73-95be69612b49"/> + <textElement textAlignment="Center"> + <font isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[DOCUMENT DE GEL DE UNIT FINAL (ANNEXE) +CALCUL DES REFERENCES TECHNIQUES]]></text> + </staticText> + <staticText> + <reportElement x="0" y="30" width="800" height="20" uuid="75b69c65-ad19-482b-905e-786a7605cd9a"/> + <text> + <![CDATA[L'impact de chaque modification sur les références des assemblages est décrit dans le tableau suivant : ]]></text> + </staticText> + <textField> + <reportElement x="0" y="50" width="800" height="20" uuid="510054a1-5695-4b3c-954e-fc5b312835aa"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textFieldExpression> + <![CDATA["Avant : UNIT " + $P{UNIT_AVANT} + " " + $P{EXCEPTIONNEL_AVANT} + " du produit " + $P{DOMAINE_PRODUIT_AVANT} + " " + $P{LIGNE_PRODUIT_AVANT}]]></textFieldExpression> + </textField> + <textField> + <reportElement x="0" y="70" width="800" height="20" uuid="b9a32778-73b0-4b97-9616-c06f6f4f2c92"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textFieldExpression> + <![CDATA["Après : UNIT " + $P{UNIT_APRES} + " " + $P{EXCEPTIONNEL_APRES} + " du produit " + $P{DOMAINE_PRODUIT_APRES} + " " + $P{LIGNE_PRODUIT_APRES}]]></textFieldExpression> + </textField> + <textField> + <reportElement mode="Opaque" x="0" y="90" width="290" height="13" backcolor="#E3E3E3" + uuid="c4e431d0-0c8a-4266-9c73-97958c24f127"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <box leftPadding="5"> + <topPen lineWidth="0.5"/> + <leftPen lineWidth="0.5"/> + <bottomPen lineWidth="0.5"/> + <rightPen lineWidth="0.5"/> + </box> + <textFieldExpression><![CDATA[$P{LIGNE_PRODUIT_APRES}]]></textFieldExpression> + </textField> + <rectangle> + <reportElement x="290" y="90" width="130" height="13" backcolor="#E3E3E3" + uuid="c0013ff2-080b-4606-869c-e4105272fdbc"/> + <graphicElement> + <pen lineWidth="0.5"/> + </graphicElement> + </rectangle> + <staticText> + <reportElement mode="Opaque" x="420" y="90" width="190" height="13" backcolor="#E3E3E3" + uuid="e43f8acf-e867-4e00-8108-c15fd3ebc4d2"/> + <box> + <topPen lineWidth="0.5"/> + <leftPen lineWidth="0.5"/> + <bottomPen lineWidth="0.5"/> + <rightPen lineWidth="0.5"/> + </box> + <textElement textAlignment="Center"/> + <text><![CDATA[Ancienne référence]]></text> + </staticText> + <staticText> + <reportElement mode="Opaque" x="610" y="90" width="190" height="13" backcolor="#E3E3E3" + uuid="dcdf2e41-3751-4d1c-9950-7bb9b71f7042"/> + <box> + <topPen lineWidth="0.5"/> + <leftPen lineWidth="0.5"/> + <bottomPen lineWidth="0.5"/> + <rightPen lineWidth="0.5"/> + </box> + <textElement textAlignment="Center"/> + <text><![CDATA[Nouvelle référence]]></text> + </staticText> + </band> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/jasper/src/test/resources/Jasper/template/report_r21.jrxml b/jasper/src/test/resources/Jasper/template/report_r21.jrxml new file mode 100644 index 0000000..7bc9c14 --- /dev/null +++ b/jasper/src/test/resources/Jasper/template/report_r21.jrxml @@ -0,0 +1,876 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/jasper/src/test/resources/Jasper/template/report_r22.jrxml b/jasper/src/test/resources/Jasper/template/report_r22.jrxml new file mode 100644 index 0000000..6759368 --- /dev/null +++ b/jasper/src/test/resources/Jasper/template/report_r22.jrxml @@ -0,0 +1,897 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <band height="181"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + <image> + <reportElement x="0" y="0" width="802" height="30" uuid="02f283fc-725c-4091-a6df-64b3fe139563"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <imageExpression><![CDATA[$P{LOGO_SNECMA}]]></imageExpression> + </image> + <staticText> + <reportElement stretchType="RelativeToTallestObject" x="0" y="20" width="802" height="40" + uuid="6f86d0ba-b648-4c52-b7dd-f6882be41c2e"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Center"> + <font fontName="SansSerif" size="24" isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Extraction de nomenclatures sur effectivité par DATE]]></text> + </staticText> + <staticText> + <reportElement x="0" y="60" width="802" height="20" uuid="3ee15cb1-b6f7-4e0a-8ce4-55531cc1cd0c"/> + <textElement textAlignment="Center"> + <font fontName="SansSerif" size="14" isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Bills of material using date effectivity]]></text> + </staticText> + <staticText> + <reportElement x="0" y="80" width="30" height="20" uuid="8213394e-7143-4f85-8259-f11a9e9f6da1"/> + <textElement verticalAlignment="Bottom"> + <font fontName="SansSerif" isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Date :]]></text> + </staticText> + <staticText> + <reportElement x="0" y="100" width="90" height="20" uuid="16268bcd-1f46-436a-8985-139d61ae36ca"/> + <textElement verticalAlignment="Bottom"> + <font fontName="SansSerif" isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Date d'effectivité :]]></text> + </staticText> + <staticText> + <reportElement x="0" y="120" width="90" height="20" uuid="ed387d70-8182-4a54-ad00-903b07d1cf5e"/> + <textElement verticalAlignment="Bottom"> + <font fontName="SansSerif" isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Référence article :]]></text> + </staticText> + <staticText> + <reportElement x="0" y="140" width="40" height="20" uuid="adc6bff6-2abe-41b5-8ed9-296c4ec7649b"/> + <textElement verticalAlignment="Bottom"> + <font fontName="SansSerif" isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Niveau :]]></text> + </staticText> + <staticText> + <reportElement x="0" y="160" width="50" height="20" uuid="223b27bf-23e1-4c1d-bf84-b487debd8fb2"/> + <textElement verticalAlignment="Bottom"> + <font fontName="SansSerif" isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Résultat :]]></text> + </staticText> + <textField evaluationTime="Report"> + <reportElement x="30" y="80" width="772" height="20" uuid="2b6b80bd-3694-4680-9b89-8d80a4369f7c"/> + <textElement verticalAlignment="Bottom"> + <font fontName="SansSerif" pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{DATE_TRAITEMENT}]]></textFieldExpression> + </textField> + <textField evaluationTime="Report"> + <reportElement x="90" y="100" width="712" height="20" uuid="d5cc6967-759a-4822-908b-a0dee6741a2c"/> + <textElement verticalAlignment="Bottom"> + <font fontName="SansSerif" pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{DATE_EFFECTIVITE}]]></textFieldExpression> + </textField> + <textField evaluationTime="Report"> + <reportElement x="90" y="120" width="712" height="20" uuid="d2f8d509-7634-472c-a313-aecb48ed601a"/> + <textElement verticalAlignment="Bottom"> + <font fontName="SansSerif" pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{REFERENCE_ARTICLE}]]></textFieldExpression> + </textField> + <textField evaluationTime="Report"> + <reportElement x="40" y="140" width="762" height="20" uuid="2f49bcdb-558b-45f0-810c-8f20fd157827"/> + <textElement verticalAlignment="Bottom"> + <font fontName="SansSerif" pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[" " + $P{NIVEAU}]]></textFieldExpression> + </textField> + <staticText> + <reportElement x="50" y="160" width="752" height="20" uuid="abcf5995-dfdf-44f2-820a-ecc79f1bf320"/> + <textElement verticalAlignment="Bottom"> + <font fontName="SansSerif" pdfFontName="Helvetica"/> + </textElement> + <text><![CDATA[pdf]]></text> + </staticText> + <break> + <reportElement x="0" y="180" width="96" height="1" uuid="76003345-b03a-4011-b34c-9c3d6a49d511"/> + </break> + </band> + + + + + + 1]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/jasper/src/test/resources/Jasper/template/template_R07.jrxml b/jasper/src/test/resources/Jasper/template/template_R07.jrxml new file mode 100644 index 0000000..e7ded6e --- /dev/null +++ b/jasper/src/test/resources/Jasper/template/template_R07.jrxml @@ -0,0 +1,24 @@ + + + [[PROPERTY]][[STYLE]][[PARAMETERS]][[FIELDS]] + + + + + <band height="[[TITLE_HEIGHT]]" splitType="Stretch">[[TITLE]] + </band> + + + [[HEADERS]] + + + + [[CONTENT]] + + + \ No newline at end of file diff --git a/jasper/src/test/resources/log4j.properties b/jasper/src/test/resources/log4j.properties new file mode 100644 index 0000000..8f372cd --- /dev/null +++ b/jasper/src/test/resources/log4j.properties @@ -0,0 +1,13 @@ +log4j.logger.com.teamcenter.soa=WARN +log4j.logger.org.apache=WARN +log4j.logger.httpclient=WARN + +# Direct log messages to stdout +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.Target=System.out +log4j.appender.stdout.threshold=DEBUG +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %c{1}:%L - %m%n + +# Root logger option +log4j.rootLogger=DEBUG, stdout diff --git a/jasper/src/test/resources/logging.properties b/jasper/src/test/resources/logging.properties new file mode 100644 index 0000000..1983b8d --- /dev/null +++ b/jasper/src/test/resources/logging.properties @@ -0,0 +1,3 @@ +handlers=java.util.logging.ConsoleHandler +java.util.logging.ConsoleHandler.level=FINEST +com.capgemini.level=FINEST diff --git a/jasper/src/test/resources/simplelogger.properties b/jasper/src/test/resources/simplelogger.properties new file mode 100644 index 0000000..e69de29 diff --git a/kurt-ejb/pom.xml b/kurt-ejb/pom.xml new file mode 100644 index 0000000..69f4b5d --- /dev/null +++ b/kurt-ejb/pom.xml @@ -0,0 +1,240 @@ + + + 4.0.0 + kurt-ejb + ejb + kurt-ejb + + + com.capgemini.reports + kurt + 1.32.9 + + + + + + + + + + com.capgemini.reports + kurt-utility + 1.32.9 + + + + + + + + junit + junit + test + + + + org.mockito + mockito-core + test + + + + org.assertj + assertj-core + test + + + + org.slf4j + slf4j-api + + + + org.projectlombok + lombok + + + + org.json + json + + + + org.jboss.spec.javax.annotation + jboss-annotations-api_1.1_spec + + + + + + + + + + + + org.jboss.as + jboss-as-ejb3 + + + + + + org.hornetq + hornetq-core + provided + + + org.hornetq + hornetq-jms + provided + + + org.hornetq + hornetq-logging + 2.2.13.Final + provided + + + + + org.hornetq + hornetq-core-client + provided + + + org.hornetq + hornetq-jms-client + provided + + + + + org.jboss.spec.javax.jms + jboss-jms-api_1.1_spec + + + + + org.hibernate + hibernate-entitymanager + + provided + + + org.hibernate + hibernate-validator + provided + + + org.hibernate + hibernate-core + provided + + + + + mysql + mysql-connector-java + 5.1.15 + + + + + org.jboss.as + jboss-as-jpa + provided + + + + + org.jboss.arquillian.junit + arquillian-junit-container + test + + + org.jboss.arquillian.protocol + arquillian-protocol-servlet + test + + + org.jboss.weld + weld-core-test-arquillian + 1.1.9.Final + + + + org.jboss.as + jboss-as-controller-client + test + + + + joda-time + joda-time + 2.5 + + + + + org.quartz-scheduler + quartz + 2.1.7 + + + org.quartz-scheduler + quartz-jboss + 2.1.7 + + + com.capgemini.reports + teamcenter + 1.32.9 + + + net.lingala.zip4j + zip4j + 1.3.2 + + + com.capgemini.reports + jasper + 1.32.9 + + + + + + + + org.apache.maven.plugins + maven-ejb-plugin + + 3.1 + + + + + + + + + diff --git a/kurt-ejb/src/main/java/com/capgemini/reports/execution/posting/DelayedPostingStategy.java b/kurt-ejb/src/main/java/com/capgemini/reports/execution/posting/DelayedPostingStategy.java new file mode 100644 index 0000000..f42d488 --- /dev/null +++ b/kurt-ejb/src/main/java/com/capgemini/reports/execution/posting/DelayedPostingStategy.java @@ -0,0 +1,56 @@ +package com.capgemini.reports.execution.posting; + +import com.capgemini.reports.execution.AbstractExecutionReport; +import com.capgemini.reports.quartz.SchedulerServer; +import com.capgemini.reports.quartz.TriggerPreparator; +import com.capgemini.reports.quartz.jobs.DelayedJob; +import lombok.AllArgsConstructor; +import org.quartz.*; + +import java.util.HashMap; +import java.util.Map; + +/** This strategy can delay a report execution until a later time in the day, using a combination of Quartz and HornetQ. */ +@AllArgsConstructor +public class DelayedPostingStategy implements IPostingStrategy { + + private final SchedulerServer schedulingServer; + + /** Key linking to an {@link AbstractExecutionReport} in the {@link JobDetail} of a delayed Quartz job. */ + public static final String JOB_DETAIL_KEY_REPORT = "Report"; + + @Override + public void handleRequest(final AbstractExecutionReport report) throws SchedulerException { + // Prepare the Trigger + Trigger trigger = TriggerPreparator.prepareDelayedTrigger(report.getReportTechnicalUid(), report.getPriorityCode()); + + // Prepare the Job + JobDetail job = getDelayedJobDetail(report, trigger); + + // Delay the launch into the queue + try { + schedulingServer.schedule(job, trigger); + } catch (SchedulerException e) { + throw new SchedulerException("Unable to delay the job associated to the report " + report.getReportIdentifier().getReportName() + " " + report.getReportTechnicalUid(), e); + } + } + + /** + * Get the JobDetail for a delayed execution of report. + * + * @param report {@link AbstractExecutionReport} - the implementation of the report + * @param trigger {@link Trigger} - the trigger used for the scheduling + * @return the JobDetail + */ + private JobDetail getDelayedJobDetail(final AbstractExecutionReport report, final Trigger trigger) { + // Initialize the parameter used in the execution of the job + Map paramJob = new HashMap<>(); + paramJob.put(JOB_DETAIL_KEY_REPORT, report); + + // Define the job and tie it to our SimpleJob class + JobKey jobKey = trigger.getJobKey(); + + // The method requestRecovery ask scheduler to re-execute this job + return JobBuilder.newJob(DelayedJob.class).withIdentity(jobKey.getName(), jobKey.getGroup()).requestRecovery().usingJobData(new JobDataMap(paramJob)).build(); + } +} diff --git a/kurt-ejb/src/main/java/com/capgemini/reports/execution/posting/IPostingStrategy.java b/kurt-ejb/src/main/java/com/capgemini/reports/execution/posting/IPostingStrategy.java new file mode 100644 index 0000000..448a4a1 --- /dev/null +++ b/kurt-ejb/src/main/java/com/capgemini/reports/execution/posting/IPostingStrategy.java @@ -0,0 +1,30 @@ +package com.capgemini.reports.execution.posting; + +import javax.jms.JMSException; +import javax.naming.NamingException; + +import org.quartz.SchedulerException; + +import com.capgemini.reports.execution.AbstractExecutionReport; + +/** Strategy interface. Allows several behaviour when receiving a demand. */ +public interface IPostingStrategy { + + /** + * What to do when a request is received to perform a report.
    + * The operation can be any of the following: + *
      + *
    • Post the report immediately into the queue
    • + *
    • Post a delayed job in Quartz, that will hold the report execution until later today, then send it to the queue
    • + *
    • Register a scheduled report to be executed some time in the future.
    • + *
    + * + * @param report the report to perform + * + * @throws SchedulerException if a scheduling operation goes boom + * @throws JMSException if unable to post report in a JMS queue + * @throws NamingException if unable to find the queue in JMS dictionary + */ + void handleRequest(final AbstractExecutionReport report) throws SchedulerException, JMSException, NamingException; + +} diff --git a/kurt-ejb/src/main/java/com/capgemini/reports/execution/posting/ImmediatePostingStrategy.java b/kurt-ejb/src/main/java/com/capgemini/reports/execution/posting/ImmediatePostingStrategy.java new file mode 100644 index 0000000..c4ecf10 --- /dev/null +++ b/kurt-ejb/src/main/java/com/capgemini/reports/execution/posting/ImmediatePostingStrategy.java @@ -0,0 +1,18 @@ +package com.capgemini.reports.execution.posting; + +import javax.jms.JMSException; +import javax.naming.NamingException; + +import com.capgemini.reports.execution.AbstractExecutionReport; +import com.capgemini.reports.queuing.EmbeddedServer; + +/** This strategy posts the job immediately in the queue for execution. */ +public class ImmediatePostingStrategy implements IPostingStrategy { + + @Override + public void handleRequest(final AbstractExecutionReport report) throws JMSException, NamingException { + // Simply post the report into the queues + EmbeddedServer.produce(report); + } + +} diff --git a/kurt-ejb/src/main/java/com/capgemini/reports/execution/posting/SchedulingPostingStrategy.java b/kurt-ejb/src/main/java/com/capgemini/reports/execution/posting/SchedulingPostingStrategy.java new file mode 100644 index 0000000..1b9527a --- /dev/null +++ b/kurt-ejb/src/main/java/com/capgemini/reports/execution/posting/SchedulingPostingStrategy.java @@ -0,0 +1,46 @@ +package com.capgemini.reports.execution.posting; + +import com.capgemini.reports.execution.AbstractExecutionReport; +import com.capgemini.reports.quartz.SchedulerServer; +import com.capgemini.reports.quartz.jobs.ScheduledJob; +import lombok.AllArgsConstructor; +import org.quartz.*; + +/** Class representing the strategy to post a scheduling template into Quartz DB. */ +@AllArgsConstructor +public class SchedulingPostingStrategy implements IPostingStrategy { + + private final SchedulerServer schedulingServer; + private final Trigger trigger; + + @Override + public void handleRequest(final AbstractExecutionReport template) throws SchedulerException { + JobDetail job = getScheduledJobDetail(template, trigger.getJobKey()); + + // Push the job to Quartz + try { + schedulingServer.schedule(job, trigger); + } catch (SchedulerException e) { + throw new SchedulerException("Unable to schedule the job associated to the template " + template.getReportIdentifier().getReportName() + " " + template.getReportTechnicalUid(), e); + } + } + + /** + * Return the needed {@link JobDetail} for a delayed execution of report. + * + * @param report {@link AbstractExecutionReport} - the implementation of the report + * @param jobKey {@link JobKey} - the JobKey used for the scheduling + * @return the JobDetail + */ + public static JobDetail getScheduledJobDetail(final AbstractExecutionReport report, final JobKey jobKey) { + // Begin setting up the JobBuilder + JobBuilder jobBuilder = JobBuilder.newJob(ScheduledJob.class).withIdentity(jobKey.getName(), jobKey.getGroup()); + // The method requestRecovery asks the scheduler to re-execute this job + jobBuilder.requestRecovery(); + // Add kurt data + ScheduledJob.prepareData(jobBuilder, report.getSchedulingId(), report.getReportBuilderClassName()); + // Build the job + return jobBuilder.build(); + } + +} diff --git a/kurt-ejb/src/main/java/com/capgemini/reports/quartz/JobDataKeys.java b/kurt-ejb/src/main/java/com/capgemini/reports/quartz/JobDataKeys.java new file mode 100644 index 0000000..2ebb0cb --- /dev/null +++ b/kurt-ejb/src/main/java/com/capgemini/reports/quartz/JobDataKeys.java @@ -0,0 +1,13 @@ +package com.capgemini.reports.quartz; + +import org.quartz.JobDataMap; + +/** A Bunch of keys to put/retrieve report data on quartz {@link JobDataMap} classes. */ +public enum JobDataKeys { + + /** Key to the scheduling's DB Identifier. Only for scheduled reports. */ + SCHEDULING_ID, + /** Key to the class to invoke, which can instantiate the report once it triggers. Only for scheduled reports. */ + REPORT_BUILDER_CLASS_NAME, + +} diff --git a/kurt-ejb/src/main/java/com/capgemini/reports/quartz/SchedulerServer.java b/kurt-ejb/src/main/java/com/capgemini/reports/quartz/SchedulerServer.java new file mode 100644 index 0000000..186eb1f --- /dev/null +++ b/kurt-ejb/src/main/java/com/capgemini/reports/quartz/SchedulerServer.java @@ -0,0 +1,309 @@ +package com.capgemini.reports.quartz; + +import com.capgemini.framework.common.QuartzHelper; +import com.capgemini.reports.ReportEnum; +import com.capgemini.reports.ReportLaunchTypeEnum; +import com.capgemini.reports.database.javabean.DbSchedulingReport; +import com.capgemini.reports.database.manager.MngSchedulingReport; +import com.capgemini.reports.exceptions.InvalidInputException; +import com.capgemini.reports.execution.AbstractExecutionReport; +import com.capgemini.reports.execution.posting.SchedulingPostingStrategy; +import com.capgemini.reports.periodicity.SchedulingPeriod; +import com.capgemini.reports.quartz.jobs.PurgeJob; +import com.google.common.base.Optional; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import org.hibernate.Session; +import org.quartz.*; +import org.quartz.impl.StdSchedulerFactory; +import org.quartz.impl.matchers.GroupMatcher; + +import javax.annotation.PostConstruct; +import javax.annotation.PreDestroy; +import javax.ejb.Singleton; +import javax.ejb.Startup; +import java.text.SimpleDateFormat; +import java.util.*; +import java.util.Calendar; +import java.util.Map.Entry; + +/** + * Class representing a delayed Scheduler.
    + * This class delayed a job (launching of reports) to a Date parameter. + */ +@Singleton +@Startup +@Slf4j +@Getter +public class SchedulerServer { + + private static final int PLANIF_EXECUTION_SECONDS = 0; + private static final int PLANIF_EXECUTION_MINUTES = 0; + private static final int PLANIF_EXECUTION_HOUR = 6; + + // Internal constants + private static final ReportLaunchTypeEnum SCHEDULED_LAUNCH = ReportLaunchTypeEnum.SCHEDULED; + + // Singleton instance + private Scheduler scheduler; + + /** + * Initialize the Scheduler server. + * + * @throws SchedulerException when unable to initialize the scheduler + */ + @PostConstruct + public void init() throws SchedulerException { + log.info("Initializing Quartz scheduler"); + + // Grab the Scheduler instance from the Factory + try { + // Initialize the Scheduler via the Kurt's quartz.properties file + scheduler = new StdSchedulerFactory(QuartzHelper.getPropertiesFilePath()).getScheduler(); + } + catch (SchedulerException e) { + throw new SchedulerException("Unable to findAll an instance of the default Scheduler", e); + } + + // Start the scheduler + scheduler.start(); + createOrUpdatePurgeJob(); + + // Recalled all the waiting jobs for persistent jobs + try { + scheduler.resumeAll(); + } + catch (SchedulerException e) { + throw new SchedulerException("Unable to start the recover the misfires job and triggers", e); + } + } + + private void createOrUpdatePurgeJob() throws SchedulerException { + log.info("Checking purge job status..."); + JobKey purgeKey = PurgeJob.getPurgeJobKey(); + + // update existing purge job + if (scheduler.checkExists(purgeKey)) { + log.info("Purge job already exists. deleting..."); + try { + scheduler.deleteJob(purgeKey); + log.info("Old Purge job has been deleted"); + } + catch (SchedulerException e) { + String jobName = purgeKey.getName(); + throw new SchedulerException("Unable to delete old " + jobName, e); + } + } + + // Now create purge job from scratch + log.info("Creating purge job"); + JobDetail purgeJobDetail = PurgeJob.getPurgeJobDetail(); + Trigger triggerPurge = PurgeJob.getScheduledTrigger(purgeJobDetail); + try { + scheduler.scheduleJob(purgeJobDetail, triggerPurge); + log.info("Purge job is created, next fire time: {}", triggerPurge.getNextFireTime()); + } + catch (SchedulerException e) { + String jobName = purgeJobDetail.getKey().getName(); + throw new SchedulerException("Unable to create " + jobName, e); + } + } + + /** + * Schedule a Report to a Date parameter. + * + * @param job {@link JobDetail} - the job to execute after the scheduling + * @param trigger {@link Trigger} - the prepared trigger for the scheduled + * @throws SchedulerException when unable to schedule the job + */ + public void schedule(final JobDetail job, final Trigger trigger) throws SchedulerException { + Date startDate = Calendar.getInstance().getTime(); + SimpleDateFormat sdf = new SimpleDateFormat("HH:mm"); + Date nextStart = trigger.getNextFireTime(); + + log.info("Current time : {}", sdf.format(startDate)); + if (nextStart == null) { + log.info("The rapport will never trigger."); + } + else { + log.info("The rapport should first strigger at {}.", sdf.format(nextStart)); + } + + + // Tell quartz to schedule the job using the trigger + scheduler.scheduleJob(job, trigger); + } + + /** + * De-schedule a specific job and all his triggers. + * + * @param jobName String - the unique name of the job + * @param groupName String - the group name of the job + * @throws SchedulerException when unable to deschedule the job + */ + public void deschedule(final String jobName, final String groupName) throws SchedulerException { + try { + // One report is associated to one job + scheduler.deleteJob(new JobKey(jobName, groupName)); + } + catch (SchedulerException e) { + throw new SchedulerException("The job " + jobName + " " + groupName + " cannot be descheduled.", e); + } + } + + /** + * Destroy the Scheduler server. + * + * @throws SchedulerException when a problem occurs during shutdown + */ + @PreDestroy + public void destroy() throws SchedulerException { + log.info("Destroying Quartz scheduler"); + if (scheduler != null) { + try { + scheduler.shutdown(true); + } + catch (SchedulerException e) { + throw new SchedulerException("Unable to shut down the instance of the default Scheduler", e); + } + } + } + + /** + * Deletes a job and all its triggers. + * + * @param schedulingReportId the ID of the scheduling report (same as DB id) + * @throws SchedulerException if anything goes wrong with Quartz + */ + public void deleteScheduledJobAndKeys(final Long schedulingReportId) throws SchedulerException { + JobKey oldJobKey = TriggerPreparator.getScheduledJobKey(schedulingReportId); + scheduler.deleteJob(oldJobKey); + } + + /** + * Updates the functional and temporal execution data of a job, by modifying its JobDetails and Trigger (in Quartz only, same thing should be done you in the DB). + * + * @param schedulingReportId the id of the scheduling to modify in Quartz + * @param report the new parameters are contained in this {@link AbstractExecutionReport} + * @param priorityCode [1-3] the new report priority + * @param period the new periodicity criteria + * @param planifName the name of the scheduling + * @throws SchedulerException if anything goes wrong with Quartz + */ + public void replaceJob(final Long schedulingReportId, final AbstractExecutionReport report, final int priorityCode, + final SchedulingPeriod period, final String planifName) throws SchedulerException { + JobKey oldJobKey = TriggerPreparator.getScheduledJobKey(schedulingReportId); + + // Clean up all traces of this job + scheduler.deleteJob(oldJobKey); + + // Now re-create it all + Trigger trigger; + try { + trigger = TriggerPreparator.prepareScheduledTrigger(schedulingReportId, priorityCode, planifName, period); + } + catch (InvalidInputException e) { + throw new SchedulerException("Unable to understand the scheduling parameters", e); + } + JobDetail jobDetail = SchedulingPostingStrategy.getScheduledJobDetail(report, trigger.getJobKey()); + scheduler.scheduleJob(jobDetail, trigger); + + } + + /** + * Updates the trigger of a job (in Quartz only, same thing should be done in the DB). + * + * @param schedulingReportId the id of the scheduling to modify in Quartz + * @param planifName the new scheduling name + * @param priorityCode [1-3] the new report priority + * @param period the new periodicity criteria + * @throws SchedulerException if anything goes wrong with Quartz + */ + public void updateTemporalParameters(final Long schedulingReportId, final String planifName, final int priorityCode, + final SchedulingPeriod period) throws SchedulerException { + TriggerKey oldTriggerKey = TriggerPreparator.getScheduledTriggerKey(schedulingReportId); + Trigger newTrigger; + try { + newTrigger = TriggerPreparator.prepareScheduledTrigger(schedulingReportId, priorityCode, planifName, period); + } + catch (InvalidInputException e) { + throw new SchedulerException("Unable to understand the scheduling parameters", e); + } + scheduler.rescheduleJob(oldTriggerKey, newTrigger); + } + + /** + * Returns the next {@link Date} at which the job will be triggered.
    + * If no firing will happen in the future (no triggers left, or all triggers are in the past), returns null. + * + * @param schedulingReportId the id of the scheduling to investigate. + * @return the next firing time. May be null if no trigger fires in the future. + * @throws SchedulerException if anything goes wrong with Quartz + */ + public Optional nextExecutionOfJob(final Long schedulingReportId) throws SchedulerException { + final JobKey jobKey = TriggerPreparator.getScheduledJobKey(schedulingReportId); + List jobKeys = scheduler.getTriggersOfJob(jobKey); + Date nextDate = null; + for (Trigger trigger : jobKeys) { + final Date nextFireTime = trigger.getNextFireTime(); + if (nextDate == null || nextFireTime.before(nextDate)) { + nextDate = nextFireTime; + } + } + return Optional.fromNullable(nextDate); + } + + /** + * Lists all jobs that will be executed tonight. + */ + public List listAllScheduledJobsForTonight(Session session) throws SchedulerException { + GroupMatcher matchSchedulingGroup = GroupMatcher.jobGroupEquals(SCHEDULED_LAUNCH.getGroupName()); + Set jobKeys = scheduler.getJobKeys(matchSchedulingGroup); + + // Prepare a date representing tonight (actually tomorrow at 6am so we findAll all nightly executions) + Calendar calTonight = Calendar.getInstance(); + calTonight.add(Calendar.DAY_OF_MONTH, 1); // Tomorrow before opening hours + calTonight.set(Calendar.HOUR_OF_DAY, PLANIF_EXECUTION_HOUR); + calTonight.set(Calendar.MINUTE, PLANIF_EXECUTION_MINUTES); + calTonight.set(Calendar.SECOND, PLANIF_EXECUTION_SECONDS); + final Date tonight = calTonight.getTime(); + + // Request all jobKeys firing before tonight + Map firingTonight = new HashMap<>(); + for (JobKey jobKey : jobKeys) { + List triggers = scheduler.getTriggersOfJob(jobKey); + for (Trigger trigger : triggers) { + if (trigger.getNextFireTime().before(tonight)) { + firingTonight.put(jobKey, trigger); + break; + } + } + } + + // Obtain additional data + List results = new ArrayList<>(firingTonight.size()); + for (Entry jobFiring : firingTonight.entrySet()) { + JobDetail jobDetail = scheduler.getJobDetail(jobFiring.getKey()); + long schedulingId = jobDetail.getJobDataMap().getLong(JobDataKeys.SCHEDULING_ID.toString()); + DbSchedulingReport reportSchedulingEntry = new MngSchedulingReport().searchById(session, schedulingId); + String reportCode = reportSchedulingEntry.getReportCode(); + ReportEnum reportEnum = ReportEnum.fromCode(reportCode); + final String planifName = jobFiring.getValue().getDescription(); // Scheduling name is stored in its description + JobExecution jobExec = new JobExecution(reportEnum, planifName); + results.add(jobExec); + } + + return results; + } + + /** + * Simple holder to carry a report execution's detail: the {@link ReportEnum}, and the scheduling name. + */ + @Getter + @AllArgsConstructor + public static class JobExecution { + private final ReportEnum reportCode; + private final String planificationName; + } +} diff --git a/kurt-ejb/src/main/java/com/capgemini/reports/quartz/TriggerPreparator.java b/kurt-ejb/src/main/java/com/capgemini/reports/quartz/TriggerPreparator.java new file mode 100644 index 0000000..7fa0215 --- /dev/null +++ b/kurt-ejb/src/main/java/com/capgemini/reports/quartz/TriggerPreparator.java @@ -0,0 +1,378 @@ +package com.capgemini.reports.quartz; + +import com.capgemini.framework.common.SettingsHelper; +import com.capgemini.reports.ReportLaunchTypeEnum; +import com.capgemini.reports.exceptions.InvalidInputException; +import com.capgemini.reports.periodicity.*; +import com.capgemini.reports.periodicity.SchedulingPeriod.PeriodVisitor; +import lombok.extern.slf4j.Slf4j; +import org.quartz.*; + +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; + +/** + * Prepare triggers for the {@link SchedulerServer}. + */ +@Slf4j +public final class TriggerPreparator implements PeriodVisitor { + + // Weekend numbers + private static final int NUM_WEEK_5 = 5; + private static final int NUM_WEEK_4 = 4; + private static final int NUM_WEEK_3 = 3; + private static final int NUM_WEEK_2 = 2; + private static final int NUM_WEEK_1 = 1; + + // PSnecma Priority scale + private static final int SNECMA_LOW_PRIORITY = 1; + private static final int SNECMA_HIGH_PRIORITY = 3; + + // Quartz message priority scale + private static final int QUARTZ_LOW_PRIORITY = 1; + private static final int QUARTZ_MEDIUM_PRIORITY = 5; + private static final int QUARTZ_HIGH_PRIORITY = 10; + + // Others configurations + private static final String PREF_TRIGGER_NAME = "trigger_name_"; + private static final String PREF_JOB_NAME = "job_name_"; + private static final String STR_COLON = ":"; + + // Configuration for delayed launch type. Format: HH:MM + private static final String LAUNCH_HOUR_STR; + private static final int LAUNCH_HOUR; + private static final int LAUNCH_MINUTE; + + static { + LAUNCH_HOUR_STR = SettingsHelper.getDelayedLaunchHour(); + String[] tableStrLaunchTime = LAUNCH_HOUR_STR.split(STR_COLON); + LAUNCH_HOUR = Integer.parseInt(tableStrLaunchTime[0]); + LAUNCH_MINUTE = Integer.parseInt(tableStrLaunchTime[1]); + } + + private final int reportPriority; + private final String strSchedulName; + /** + * The ID of the Scheduling as it appears in the DB. + */ + private final Long schedulingReportId; + + /** + * Private constructor - use static methods to obtain an instance. + * + * @param reportPriority the report priority + * @param strSchedulName + * @param schedulingReportId + */ + private TriggerPreparator(final int reportPriority, final String strSchedulName, final Long schedulingReportId) { + this.reportPriority = reportPriority; + this.strSchedulName = strSchedulName; + this.schedulingReportId = schedulingReportId; + } + + /** + * Prepare a delayed Trigger for the Scheduler. + * + * @param reportUid {@link String} - the report uid + * @param reportPriority [1-3] - the report priority + * @return the trigger + */ + public static Trigger prepareDelayedTrigger(final String reportUid, final int reportPriority) { + // In a mis-fire situation, the SimpleTrigger wants to be fired now by Scheduler + final TriggerKey delayedTriggerKey = getDelayedTriggerKey(reportUid); + final JobKey delayedJobKey = getDelayedJobKey(reportUid); + final SimpleScheduleBuilder tonight = SimpleScheduleBuilder.simpleSchedule().withMisfireHandlingInstructionFireNow(); + final int triggerPriorities = giveTriggerPriorities(reportPriority); + return TriggerBuilder.newTrigger().withIdentity(delayedTriggerKey).startAt(makeDelayedHour(LAUNCH_HOUR_STR)).forJob(delayedJobKey) + .withSchedule(tonight).withPriority(triggerPriorities).build(); + } + + /** + * Prepares a Trigger for a scheduled report. + * + * @param schedulingReportId (Long) the ID of the report (as it appears in DB) + * @param reportPriority [1-3] the priority of the scheduling (1-9) + * @param strScheduleName the name given by the requester + * @param period a {@link SchedulingPeriod} for periodicity + * @return the {@link Trigger} + * @throws InvalidInputException if any input is null + */ + public static Trigger prepareScheduledTrigger(final Long schedulingReportId, final int reportPriority, final String strScheduleName, + final SchedulingPeriod period) throws InvalidInputException { + if (schedulingReportId == null) { + throw new InvalidInputException("Invalid report Id (null)"); + } + if (strScheduleName == null) { + throw new InvalidInputException("Invalid schedulign name (null)"); + } + if (period == null) { + throw new InvalidInputException("Invalid period (null)"); + } + return period.accept(new TriggerPreparator(reportPriority, strScheduleName, schedulingReportId)); + } + + /** + * Prepare a Trigger for a specific date.
    + * + * @param schedulingReportId Long - the report ID + * @param reportPriority [1-3] - the priorities of the report + * @param strSchedulName String - the scheduling name + * @param schedulingDate A string for the scheduling DATE. The format of the date is dd-mm-yyyy. + * @return the built trigger + */ + private static Trigger byDate(final Long schedulingReportId, final int reportPriority, final String strSchedulName, final Date schedulingDate) { + final TriggerKey scheduledTriggerKey = getScheduledTriggerKey(schedulingReportId); + final JobKey scheduledJobKey = getScheduledJobKey(schedulingReportId); + final SimpleScheduleBuilder simpleSchedule = SimpleScheduleBuilder.simpleSchedule().withMisfireHandlingInstructionFireNow(); + final int triggerPriorities = giveTriggerPriorities(reportPriority); + return TriggerBuilder.newTrigger().withIdentity(scheduledTriggerKey).withDescription(strSchedulName).startAt(schedulingDate) + .forJob(scheduledJobKey).withSchedule(simpleSchedule).withPriority(triggerPriorities).build(); + } + + /** + * Prepare a scheduled Trigger for the Scheduler.
    + * + * @param schedulingReportId Long - the report ID + * @param reportPriority [1-3] - the priorities of the report + * @param strSchedulName String - the scheduling name + * @param dayInWeek takes the value 1 to 5 for Monday to Friday. The value is 1 for Monday until 5 for Friday. + * @return the built trigger + */ + public static Trigger weekly(final Long schedulingReportId, final int reportPriority, final String strSchedulName, final int dayInWeek) { + final TriggerKey scheduledTriggerKey = getScheduledTriggerKey(schedulingReportId); + final JobKey scheduledJobKey = getScheduledJobKey(schedulingReportId); + final CronScheduleBuilder weeklySchedule = + CronScheduleBuilder.weeklyOnDayAndHourAndMinute(getDayInWeek(dayInWeek), LAUNCH_HOUR, LAUNCH_MINUTE); + final int triggerPriorities = giveTriggerPriorities(reportPriority); + return TriggerBuilder.newTrigger().withIdentity(scheduledTriggerKey).withDescription(strSchedulName).forJob(scheduledJobKey).startNow() + .withSchedule(weeklySchedule).withPriority(triggerPriorities).build(); + } + + /** + * Prepare a scheduled Trigger for the Scheduler.
    + * + * @param schedulingReportId Long - the report ID + * @param reportPriority [1-3] - the priorities of the report + * @param strSchedulName String - the scheduling name + * @return the built trigger + */ + public static Trigger daily(final Long schedulingReportId, final int reportPriority, final String strSchedulName) { + final TriggerKey scheduledTriggerKey = getScheduledTriggerKey(schedulingReportId); + final JobKey scheduledJobKey = getScheduledJobKey(schedulingReportId); + final CronScheduleBuilder dailySchedule = CronScheduleBuilder.dailyAtHourAndMinute(LAUNCH_HOUR, LAUNCH_MINUTE); + final int triggerPriorities = giveTriggerPriorities(reportPriority); + return TriggerBuilder.newTrigger().withIdentity(scheduledTriggerKey).withDescription(strSchedulName).forJob(scheduledJobKey).startNow() + .withSchedule(dailySchedule).withPriority(triggerPriorities).build(); + } + + /** + * Prepare a scheduled Trigger for the Scheduler.
    + * + * @param schedulingReportId Long - the report ID + * @param reportPriority integer - the priorities of the report + * @param strSchedulName String - the scheduling name + * @param monthType An enumeration of monthly type of scheduling ({@link WeekendPeriod}). May contains an integer for DAY_IN_MONTH (the date in month). In this case, the value should be between 1 and 31. + * @return the built trigger + */ + private static Trigger weekend(final Long schedulingReportId, final int reportPriority, final String strSchedulName, + final WeekendPeriod monthType) { + final TriggerKey scheduledTriggerKey = getScheduledTriggerKey(schedulingReportId); + final JobKey scheduledJobKey = getScheduledJobKey(schedulingReportId); + final TriggerBuilder triggerBuilder = + TriggerBuilder.newTrigger().withIdentity(scheduledTriggerKey).withDescription(strSchedulName).forJob(scheduledJobKey).startNow(); + final String cronExpression; + switch (monthType) { + case END_MONTH: + cronExpression = cronEndOfMonth(); + break; + case FIRST_WEEK_END: + cronExpression = cronWeekendByNum(LAUNCH_HOUR, LAUNCH_MINUTE, NUM_WEEK_1); + break; + case SECOND_WEEK_END: + cronExpression = cronWeekendByNum(LAUNCH_HOUR, LAUNCH_MINUTE, NUM_WEEK_2); + break; + case THIRD_WEEK_END: + cronExpression = cronWeekendByNum(LAUNCH_HOUR, LAUNCH_MINUTE, NUM_WEEK_3); + break; + case FOURTH_WEEK_END: + cronExpression = cronWeekendByNum(LAUNCH_HOUR, LAUNCH_MINUTE, NUM_WEEK_4); + break; + case FIFTH_WEEK_END: + cronExpression = cronWeekendByNum(LAUNCH_HOUR, LAUNCH_MINUTE, NUM_WEEK_5); + break; + default: + // This case shoudn't occur + log.error("An error occured during the creation of the trigger because of the value of the period for the scheduled report {}", + schedulingReportId); + return null; + } + ScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression); + final int triggerPriorities = giveTriggerPriorities(reportPriority); + return triggerBuilder.withSchedule(scheduleBuilder).withPriority(triggerPriorities).build(); + } + + private static String cronEndOfMonth() { + return "0 " + LAUNCH_MINUTE + " " + LAUNCH_HOUR + " L * ?"; + } + + /** + * Prepare a scheduled Trigger for the Scheduler.
    + * + * @param schedulingReportId Long - the report ID + * @param reportPriority [1-3] - the priorities of the report + * @param strSchedulName String - the scheduling name + * @param dayInMonth an integer for DAY_IN_MONTH (the date in month). The value should be between 1 and 31 + * @return the built trigger + */ + private static Trigger dayInMonth(final Long schedulingReportId, final int reportPriority, final String strSchedulName, final int dayInMonth) { + final TriggerKey scheduledTriggerKey = getScheduledTriggerKey(schedulingReportId); + final JobKey scheduledJobKey = getScheduledJobKey(schedulingReportId); + ScheduleBuilder scheduleEveryMonth = CronScheduleBuilder.monthlyOnDayAndHourAndMinute(dayInMonth, LAUNCH_HOUR, LAUNCH_MINUTE); + final int triggerPriorities = giveTriggerPriorities(reportPriority); + return TriggerBuilder.newTrigger().withIdentity(scheduledTriggerKey).withDescription(strSchedulName).forJob(scheduledJobKey).startNow() + .withSchedule(scheduleEveryMonth).withPriority(triggerPriorities).build(); + } + + private static String cronWeekendByNum(final int launchHour, final int launchMinute, final int coeffOfWeek) { + return "0 " + launchMinute + " " + launchHour + " ? * 1#" + coeffOfWeek; + } + + /** + * Can return a result adapted to the scheduler to the following format : + *
      + *
    • 2 for Monday. + *
    • 3 for Tuesday. + *
    • 4 for Wednesday. + *
    • 5 for Thursday. + *
    • 6 for Friday. + *
    + * + * @param dayInWeek integer - the received integer value from the IHM + * @return the adapted integer value + */ + private static int getDayInWeek(final int dayInWeek) { + return dayInWeek + 1; + } + + private static Date makeDelayedHour(final String launchDate) { + // Separate hours and minutes (format hour:minute) + String[] tableStrLaunchTime = launchDate.split(STR_COLON); + int launchHour = Integer.parseInt(tableStrLaunchTime[0]); + int launchMinute = Integer.parseInt(tableStrLaunchTime[1]); + + // Retrieve current time + Date startDate = Calendar.getInstance().getTime(); + SimpleDateFormat sdf = new SimpleDateFormat("HH:mm"); + String[] tableStrCurrentTime = sdf.format(startDate).split(STR_COLON); + int currentHour = Integer.parseInt(tableStrCurrentTime[0]); + int currentMinute = Integer.parseInt(tableStrCurrentTime[1]); + + // Compare launch time to current time to customize the Trigger + Date result; + if (launchHour > currentHour) { + result = DateBuilder.todayAt(launchHour, launchMinute, 0); + } else if (launchHour < currentHour) { + result = DateBuilder.tomorrowAt(launchHour, launchMinute, 0); + } else if (launchMinute > currentMinute) { + result = DateBuilder.todayAt(launchHour, launchMinute, 0); + } else { + result = DateBuilder.tomorrowAt(launchHour, launchMinute, 0); + } + return result; + } + + /** + * Returns a scheduled report's {@link TriggerKey}. Can be used to create/retrieve a scheduled job's Trigger in Quartz. + * + * @param schedulingReportId the Id (long) of the report to be scheduled + * @return the prepared {@link TriggerKey} + */ + public static TriggerKey getScheduledTriggerKey(final Long schedulingReportId) { + return new TriggerKey(PREF_TRIGGER_NAME + schedulingReportId, ReportLaunchTypeEnum.SCHEDULED.getGroupName()); + } + + // *********************** Instance *************************** + + /** + * Returns a delayed report's {@link TriggerKey}. Can be used to create/retrieve a delayed job's Trigger in Quartz. + * + * @param delayedReportUID the UID (String) of the report to be delayed + * @return the prepared {@link TriggerKey} + */ + private static TriggerKey getDelayedTriggerKey(final String delayedReportUID) { + return new TriggerKey(PREF_TRIGGER_NAME + delayedReportUID, ReportLaunchTypeEnum.DELAYED.getGroupName()); + } + + /** + * Returns a scheduled report's {@link JobKey}. Can be used to create/retrieve a scheduled job in Quartz. + * + * @param schedulingReportId the Id (long) of the report to be scheduled + * @return the prepared {@link JobKey} + */ + public static JobKey getScheduledJobKey(final Long schedulingReportId) { + return new JobKey(PREF_JOB_NAME + schedulingReportId, ReportLaunchTypeEnum.SCHEDULED.getGroupName()); + } + + /** + * Returns a delayed report's {@link JobKey}. Can be used to create/retrieve a delayed job in Quartz. + * + * @param schedulingUID the UID (String) of the report to be scheduled + * @return the prepared {@link JobKey} + */ + private static JobKey getDelayedJobKey(final String schedulingUID) { + return new JobKey(PREF_JOB_NAME + schedulingUID, ReportLaunchTypeEnum.DELAYED.getGroupName()); + } + + /** + * Translate the priorities of the reporting.properties file into the Quartz language to the scheduler.
    + * For the settings file :
    + *
      + *
    • 1 correspond to a high priority + *
    • 2 correspond to a medium priority + *
    • 3 correspond to a low priority + *
    + * For a TriggerBuilder of Quartz : + *
      + *
    • 1 is the highest priority + *
    • 5 is the medium priority + *
    • 10 is the lowest priority + *
    + */ + private static int giveTriggerPriorities(final int reportPriorities) { + switch (reportPriorities) { + case SNECMA_LOW_PRIORITY: + return QUARTZ_LOW_PRIORITY; + case SNECMA_HIGH_PRIORITY: + return QUARTZ_HIGH_PRIORITY; + default: + return QUARTZ_MEDIUM_PRIORITY; + } + } + + // *********************** Visitor Pattern *************************** + @Override + public Trigger visit(final DayInMonth dayInMonth) { + return dayInMonth(schedulingReportId, reportPriority, strSchedulName, dayInMonth.getDayInMonth()); + } + + @Override + public Trigger visit(final WeekendPeriod weekend) { + return weekend(schedulingReportId, reportPriority, strSchedulName, weekend); + } + + @Override + public Trigger visit(final SpecificDay specificDay) { + return byDate(schedulingReportId, reportPriority, strSchedulName, specificDay.getDay()); + } + + @Override + public Trigger visit(final WeeklyPeriod dayInWeek) { + return weekly(schedulingReportId, reportPriority, strSchedulName, dayInWeek.getDayInWeek()); + } + + @Override + public Trigger visit(final DailyPeriod uselessParam) { + return daily(schedulingReportId, reportPriority, strSchedulName); + } +} diff --git a/kurt-ejb/src/main/java/com/capgemini/reports/quartz/jobs/DelayedJob.java b/kurt-ejb/src/main/java/com/capgemini/reports/quartz/jobs/DelayedJob.java new file mode 100644 index 0000000..a3627aa --- /dev/null +++ b/kurt-ejb/src/main/java/com/capgemini/reports/quartz/jobs/DelayedJob.java @@ -0,0 +1,65 @@ +package com.capgemini.reports.quartz.jobs; + +import com.capgemini.reports.database.DataBaseReportHelper; +import com.capgemini.reports.exceptions.NotFoundException; +import com.capgemini.reports.execution.AbstractExecutionReport; +import com.capgemini.reports.execution.posting.DelayedPostingStategy; +import com.capgemini.reports.queuing.EmbeddedServer; +import lombok.NoArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.quartz.*; + +import javax.jms.JMSException; +import javax.naming.NamingException; +import java.io.Serializable; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; + +/** This Quartz {@link Job} posts a report into the queue for execution. */ +@PersistJobDataAfterExecution +@DisallowConcurrentExecution +@Slf4j +// Required for Quartz +@NoArgsConstructor +public class DelayedJob implements Job, Serializable { + + private static final long serialVersionUID = -4459018522846677264L; + + /** + * Executes the requested job. The job is a report execution.
    + * This method is triggered automatically by Quartz when the time comes.
    + * An {@link AbstractExecutionReport} instance is obtained, and sent to the HornetQ queue through the {@link EmbeddedServer}. + * + * @param jobExecutionContext a {@link JobExecutionContext} containing a {@link JobDataMap} that explains what report to execute. + */ + @Override + public void execute(final JobExecutionContext jobExecutionContext) throws JobExecutionException { + // Initialize variable + JobDataMap dataMap = jobExecutionContext.getMergedJobDataMap(); + + // Retrieve the Report + AbstractExecutionReport report = (AbstractExecutionReport) dataMap.get(DelayedPostingStategy.JOB_DETAIL_KEY_REPORT); + + // Log the start + Date startDate = Calendar.getInstance().getTime(); + SimpleDateFormat sdf = new SimpleDateFormat("HH:mm"); + log.info("Execution of the scheduled job for the report {} at {}.", report.getReportIdentifier().getReportName(), sdf.format(startDate)); + + // Put the report in the queues + try { + EmbeddedServer.produce(report); + } catch (JMSException | NamingException e) { + String msg = "Unable to send the report in the queues."; + log.error(msg, e); + throw new JobExecutionException(e); + } + + // Save progress in database + try { + DataBaseReportHelper.updateDelayedLaunch(report.getReportTechnicalUid()); + } catch (NotFoundException e) { + log.warn("Unable to update launch satus of delayed report, UID = " + report.getReportTechnicalUid(), e); + } + } +} diff --git a/kurt-ejb/src/main/java/com/capgemini/reports/quartz/jobs/PurgeJob.java b/kurt-ejb/src/main/java/com/capgemini/reports/quartz/jobs/PurgeJob.java new file mode 100644 index 0000000..8c2084d --- /dev/null +++ b/kurt-ejb/src/main/java/com/capgemini/reports/quartz/jobs/PurgeJob.java @@ -0,0 +1,210 @@ +package com.capgemini.reports.quartz.jobs; + +import com.capgemini.framework.common.DateHelper; +import com.capgemini.framework.common.FileHelper; +import com.capgemini.framework.common.SettingsHelper; +import com.capgemini.framework.common.StringHelper; +import com.capgemini.reports.database.manager.MngReport; +import com.capgemini.reports.database.manager.MngReport.RemovedReportEntry; +import lombok.NoArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.quartz.*; + +import java.io.File; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.List; + +/** Class managing the purge jobs for deleting old report files. */ +@PersistJobDataAfterExecution +@DisallowConcurrentExecution +@Slf4j +// Required for Quartz +@NoArgsConstructor +public class PurgeJob implements Job { + + private final boolean isDevMode = SettingsHelper.isDevMode(); + + /** CRON expression for when the schedule should trigger at every instance of this field (every month / every year etc. */ + private static final String CRON_EVERY = "*"; + /** CRON expression for when the schedule should not take the field into consideration (no month constraint, or no day in week constraints etc). */ + private static final String CRON_DOES_NOT_MATTER = "?"; + + private static final boolean FAIL_ON_RECOVERY = true; + + private static final String HUMAN_DESCRIPTION_FOR_PURGE = "Purge des rapports classiques et planfies"; + private static final String JOB_NAME = "job_purge"; + private static final String JOB_GROUP_NAME = "purge_group_name"; + private static final String STR_COLON = ":"; + + // Properties for report and schedulings + private static final int REPORT_NB_DAYS = SettingsHelper.getPurgeDelayReports(); + private static final int SCHEDULING_REPORT_NB_DAYS = SettingsHelper.getPurgeDelayScheduling(); + private static final File REPORT_OUTPUT_FOLDER = new File(SettingsHelper.getReportLocation()); + private static final File SCHEDULING_REPORT_OUTPUT_FOLDER_HISTORY = new File(SettingsHelper.getSchedulingHistoryLocation()); + + private static final String FORMAT_DATE = "dd/MM/yyyy HH:mm"; + + private static final CronScheduleBuilder CRON_SCHEDULE; + + static { + // Configuration for purge launch type (Pattern HH:mm) + String startTimePurge = SettingsHelper.getPurgeHour(); + String purgeSecond = "0"; + String purgeMinute = startTimePurge.split(STR_COLON)[1]; + String purgeHour = startTimePurge.split(STR_COLON)[0]; + + // Cron trigger for purge job + String fullCron = StringHelper.implode(" ", purgeSecond, purgeMinute, purgeHour, CRON_EVERY, CRON_EVERY, CRON_DOES_NOT_MATTER, CRON_EVERY); + + // Space-separated cron expressions + CRON_SCHEDULE = CronScheduleBuilder.cronSchedule(fullCron); + } + + @Override + public void execute(final JobExecutionContext jobExecutionContext) throws JobExecutionException { + if (isDevMode) { + return; // Skip + } + try { + log.info("############################################################################################################"); + log.info("Démarrage de la purge le {}", DateHelper.getDate()); + purgeReportsBefore(); + purgeScheduledReportsBefore(); + // write log to directory + log.info("La purge s'est terminee avec succès...."); + log.info("############################################################################################################"); + } catch (Exception e) { + log.error("An exception occured during purge ", e); + } + } + + private void purgeReportsBefore() { + Calendar deadlineReports = DateHelper.offsetDays(-REPORT_NB_DAYS); + log.info("Nombre de jours définis pour les rapports classiques [" + REPORT_NB_DAYS + "] "); + log.info("Démarrage de la purge des rapports classiques terminés avant le {}", new SimpleDateFormat().format(deadlineReports.getTime())); + + // Delete related data from DB + log.info("Suppression des entrées dans la base de données"); + List removed = new MngReport().deleteReportsBeforeDate(deadlineReports); + for (RemovedReportEntry removedReportsData : removed) { + log.info("\tTrouvé {} datant du [{}], nom du fichier[{}]", removedReportsData.getReport().getReportCode(), + removedReportsData.getReport().getEndGenerationDate(), removedReportsData.getReport().getFileName()); + } + log.info("{} entrées supprimée(s) dans la BDD", removed.size()); + + // Delete all files anterior to the deadline + log.info("Répertoire des rapports classiques [" + REPORT_OUTPUT_FOLDER + "] "); + List deletedReports = deleteFilesBefore(REPORT_OUTPUT_FOLDER, deadlineReports); + log.info("{} fichier(s) ont été supprimés:\n", deletedReports.size()); + log.info(StringHelper.implode("\n + ", deletedReports.toArray(new String[deletedReports.size()]))); + } + + private void purgeScheduledReportsBefore() { + Calendar deadlineSchedulings = DateHelper.offsetDays(-SCHEDULING_REPORT_NB_DAYS); + log.info("Nombre de jours définis pour les rapports planifies [{}]", SCHEDULING_REPORT_NB_DAYS); + log.info("Démarrage de la purge des rapports planifies terminés avant le {}", new SimpleDateFormat().format(deadlineSchedulings.getTime())); + log.info("Répertoire d'archivage des rapports planifiés [{}]", SCHEDULING_REPORT_OUTPUT_FOLDER_HISTORY); + + log.info("Suppression des entrées planifiées dans la base de donnée"); + List removed = new MngReport().deleteScheduledReportsBeforeDate(deadlineSchedulings); + for (RemovedReportEntry removedReportsData : removed) { + log.info("\tTrouvé {} datant du [{}], nom du fichier[{}] (planifié)", removedReportsData.getReport().getReportCode(), + removedReportsData.getReport().getEndGenerationDate(), removedReportsData.getReport().getFileName()); + } + log.info("{} entrées planifiéessupprimée(s) dans la BDD", removed.size()); + + // List files + List toBeDeletedFromHistory = listSchedulingFiles(deadlineSchedulings); + // Delete files + FileHelper.deleteFiles(toBeDeletedFromHistory); + log.info("{} fichier(s) ont été supprimés de l'historique:\n", toBeDeletedFromHistory.size()); + for (File file : toBeDeletedFromHistory) { + log.info(" + {}", file.getName()); + } + } + + private List listSchedulingFiles(Calendar deadlineSchedulings) { + List toBeDeletedFromHistory = FileHelper.listFilesBefore(SCHEDULING_REPORT_OUTPUT_FOLDER_HISTORY, deadlineSchedulings); + if (toBeDeletedFromHistory.isEmpty()) { + log.info("\tAucun fichier de rapport planifié n'est candidat pour la suppression avant la date [{}]", deadlineSchedulings); + return new ArrayList<>(); + } + return toBeDeletedFromHistory; + } + + /** + * Deletes all the files in a folder that have been modified before the provided date. + * + * @param folder the folder + * @param deadlineReports the deadline + * @return a list of all the deleted files' names + */ + private static List deleteFilesBefore(final File folder, final Calendar deadlineReports) { + SimpleDateFormat sdf = new SimpleDateFormat(FORMAT_DATE); + List deletedFileNames = new ArrayList<>(); + for (File file : folder.listFiles()) { + if (!file.isFile()) { + continue; // Looking for a file, not a folder + } + String fileName = file.getName(); + Calendar fileMod = Calendar.getInstance(); + long lastModified = file.lastModified(); + fileMod.setTime(new Date(lastModified)); + if (fileMod.after(deadlineReports)) { + continue; // looking for older files, from BEFORE the deadline + } + if (file.delete()) { + log.info("Le fichier [{}] modifié le [{}] a été supprimé ", fileName, sdf.format(lastModified)); + deletedFileNames.add(fileName); + } else { + log.warn("Le fichier [{}] modifié le [{}] n'a pas pu être supprimé ", fileName, sdf.format(lastModified)); + } + } + return deletedFileNames; + } + + /** + * Build a job detail for Purge job. + * + * @return jobDetail + */ + public static JobDetail getPurgeJobDetail() { + JobKey purgeKey = getPurgeJobKey(); + return JobBuilder.newJob(PurgeJob.class).withIdentity(purgeKey).withDescription(HUMAN_DESCRIPTION_FOR_PURGE).requestRecovery(FAIL_ON_RECOVERY) + .storeDurably(true).build(); + } + + /** + * Build a job trigger for Purge job. + * + * @param jobDetail the requested job + * + * @return trigger + */ + public static Trigger getScheduledTrigger(final JobDetail jobDetail) { + TriggerKey purgeTriggerKey = getPurgeTriggerKey(); + return TriggerBuilder.newTrigger().withIdentity(purgeTriggerKey).forJob(jobDetail).withSchedule(CRON_SCHEDULE).build(); + } + + /** + * Build a job detail for Purge job. + * + * @return jobDetail + */ + public static JobKey getPurgeJobKey() { + return new JobKey(JOB_NAME, JOB_GROUP_NAME); + } + + /** + * Build a job detail for Purge job. + * + * @return jobDetail + */ + private static TriggerKey getPurgeTriggerKey() { + return new TriggerKey(JOB_NAME, JOB_GROUP_NAME); + } + +} diff --git a/kurt-ejb/src/main/java/com/capgemini/reports/quartz/jobs/ScheduledJob.java b/kurt-ejb/src/main/java/com/capgemini/reports/quartz/jobs/ScheduledJob.java new file mode 100644 index 0000000..063a962 --- /dev/null +++ b/kurt-ejb/src/main/java/com/capgemini/reports/quartz/jobs/ScheduledJob.java @@ -0,0 +1,212 @@ +package com.capgemini.reports.quartz.jobs; + +import com.capgemini.framework.common.TeamcenterDateFormatter; +import com.capgemini.framework.common.activedirectory.ActiveDirectory; +import com.capgemini.reports.builder.ReportBuilder; +import com.capgemini.reports.database.DataBaseReportHelper; +import com.capgemini.reports.database.HibernateUtil; +import com.capgemini.reports.database.javabean.DbReport; +import com.capgemini.reports.database.javabean.DbSchedulingReport; +import com.capgemini.reports.database.javabean.DbUser; +import com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum; +import com.capgemini.reports.database.manager.MngCriteriaVal.CriteriaValue; +import com.capgemini.reports.database.manager.MngSchedulingCriteriaVal; +import com.capgemini.reports.database.manager.MngSchedulingReport; +import com.capgemini.reports.exceptions.InsufficientParametersException; +import com.capgemini.reports.exceptions.InvalidUserInputException; +import com.capgemini.reports.execution.AbstractExecutionReport; +import com.capgemini.reports.execution.strategies.ScheduledExecutionStrategy; +import com.capgemini.reports.logging.ReportLoggerHelper; +import com.capgemini.reports.quartz.JobDataKeys; +import com.capgemini.reports.queuing.EmbeddedServer; +import com.google.common.base.Joiner; +import lombok.NoArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.quartz.*; + +import javax.jms.JMSException; +import javax.naming.NamingException; +import java.io.Serializable; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.List; +import java.util.Map; + +/** + * This Quartz {@link Job} begins the execution of a scheduled report according to a template.
    + * The {@link ScheduledJob#execute(JobExecutionContext) execute} method will be invoked automatically by Quartz when the time is right. + */ +@PersistJobDataAfterExecution +@DisallowConcurrentExecution +@Slf4j +// Required for Quartz +@NoArgsConstructor +public class ScheduledJob implements Job, Serializable { + + private static final long serialVersionUID = -7297770969201094324L; + + private static Long getTemplateID(JobDataMap dataMap) throws JobExecutionException { + if (!dataMap.containsKey(JobDataKeys.SCHEDULING_ID.toString())) { + throw new JobExecutionException("Missing template ID for ScheduledJob execution"); + } + else { + return dataMap.getLong(JobDataKeys.SCHEDULING_ID.toString()); + } + } + + /** + * Configure the {@link JobBuilder} to execute a report. + * + * @param builder the quartz {@link JobBuilder} to configure + * @param templateID the scheduling ID + * @param reportBuilderClassName the name of the class to use to instantiate the report using DB data. + */ + public static void prepareData(JobBuilder builder, Long templateID, String reportBuilderClassName) { + builder.usingJobData(JobDataKeys.SCHEDULING_ID.toString(), templateID).usingJobData(JobDataKeys.REPORT_BUILDER_CLASS_NAME.toString(), + reportBuilderClassName); + } + + /** + * Executes the requested job. The job is a scheduled report's execution.
    + * This method is triggered automatically by Quartz when the time comes. + *

    + * An {@link AbstractExecutionReport} instance is obtained from the {@link JobExecutionContext}, which represent the report template.
    + * It is cloned, the quick checks are performed, and if successful the report is sent to the HornetQ queue.
    + * If the quick checks are unsuccessful, an email is sent to every admin. + * + * @param jobExecutionContext a {@link JobExecutionContext} containing a {@link JobDataMap} that explains what report to execute. + * @throws JobExecutionException when the job could not be performed + */ + @Override + public void execute(final JobExecutionContext jobExecutionContext) throws JobExecutionException { + SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); + Session session = sessionFactory.openSession(); + try { + // Obtain general info on his job & scheduling + JobDataMap dataMap = jobExecutionContext.getMergedJobDataMap(); + log.trace("Received a ScheduledJob request: " + Joiner.on(", ").withKeyValueSeparator("=").join(dataMap.getWrappedMap())); + Long templateID = getTemplateID(dataMap); + DbSchedulingReport dbTemplate = new MngSchedulingReport().searchById(session, templateID); + + // Get report params from DB + Map templateData = new MngSchedulingCriteriaVal().getFunctionalMap(templateID); + + // Construct the Report + AbstractExecutionReport report = constructReport(dataMap, templateData, dbTemplate); + + log.trace("ScheduledJob: Received report template: {}", dbTemplate.getSchedulingName()); + + report.setExecutionStrategy(new ScheduledExecutionStrategy()); // Override default execution strategy so emails are redirected to admins etc. + log.trace("ScheduledJob: ExecutionStrategy set"); + + // Find the name of the scheduling + String schedulingName = dbTemplate.getSchedulingName(); + // Register scheduling name to treat specific scheduled behaviors without called database + report.setScheduling(templateID, schedulingName); + + // Register current time as the posting time + report.setPostingTime(TeamcenterDateFormatter.getCurrentTime()); + + // Others parameters of the report + List launchData = report.getLaunchData(); + String reportCode = report.getReportIdentifier().getReportCode(); + String reportUid = report.getReportTechnicalUid(); + log.info("Server received a request to perform the scheduled {} report {} with parameters: {}", reportCode, reportUid, + Joiner.on(',').join(launchData)); + + // All the administrators should be subscribed to a scheduled report + List dbAdministrators = ActiveDirectory.getAdminsReportUpdateDatabase(); + log.trace("ScheduledJob: Listed {} administrators", dbAdministrators.size()); + + // Save progress in database + // Record the report launch in the database, and log this + // The user recorded in database is the user which has submitted the report + // Record the report launch in the database, and log this + DbReport theReportEntry = DataBaseReportHelper.registerScheduledLaunch(report, dbAdministrators, templateID); + log.trace("ScheduledJob: Scheduling recorded in DB"); + + // Log the report request + ReportLoggerHelper.logSchedulingRequest(theReportEntry, report); + + // Put the report in the queues for immediate execution + postReportInQueue(report); + log.trace("ScheduledJob: Scheduling posted in queue. Job done."); + } + catch (JobExecutionException e) { + log.error("An error occurred while execution Scheduled Job", e); + throw e; + } + catch (InvalidUserInputException e) { + log.error(e.getMessage(), e); + } + finally { + session.close(); + } + } + + private AbstractExecutionReport constructReport(JobDataMap dataMap, Map templateData, + DbSchedulingReport dbTemplate) throws JobExecutionException { + // Obtain the class name + String reportBuilderClassName = (String) dataMap.get(JobDataKeys.REPORT_BUILDER_CLASS_NAME.toString()); + ReportBuilder builder = obtainBuilder(reportBuilderClassName); + try { + return builder.build(templateData); + } + catch (InsufficientParametersException e) { + throw new JobExecutionException("Insufficient parameters to build a valid report from template " + dbTemplate.getId() + + " (" + dbTemplate.getReportCode() + ")", e); + } + } + + @SuppressWarnings("unchecked") + private ReportBuilder obtainBuilder(String reportBuilderClassName) throws JobExecutionException { + // Obtain the incoming Class object. + Class theClass; + try { + theClass = Class.forName(reportBuilderClassName); + } + catch (SecurityException | ClassNotFoundException e) { + throw new JobExecutionException("Unable to find a class with name " + reportBuilderClassName, e); + } + + // Cast to the ReportBuilder class. + Class reportBuilderClass; + try { + reportBuilderClass = (Class) theClass; + } + catch (ClassCastException e) { + throw new JobExecutionException( + "The provided class " + reportBuilderClassName + " is not a sub-class of " + ReportBuilder.class.getName(), e); + } + // Request a constructor (no-args, no Class params) + Constructor cstr; + try { + cstr = reportBuilderClass.getConstructor(); // Requesting a no-args constructor! + } + catch (SecurityException | NoSuchMethodException e) { + throw new JobExecutionException("Unable to locate a no-args constructor for " + reportBuilderClassName, e); + } + + // Obtain an instance of the Builder + try { + return cstr.newInstance(); + } + catch (SecurityException | InstantiationException | IllegalAccessException | InvocationTargetException e) { + throw new JobExecutionException("Unable to create an instance from constructor of " + reportBuilderClassName, e); + } + } + + private void postReportInQueue(final AbstractExecutionReport report) throws JobExecutionException { + try { + EmbeddedServer.produce(report); + } + catch (JMSException | NamingException e) { + String msg = "Unable to send the report in the queues."; + log.error(msg, e); + throw new JobExecutionException(msg, e); + } + } + +} diff --git a/kurt-ejb/src/main/java/com/capgemini/reports/queuing/EmbeddedServer.java b/kurt-ejb/src/main/java/com/capgemini/reports/queuing/EmbeddedServer.java new file mode 100644 index 0000000..9f5c884 --- /dev/null +++ b/kurt-ejb/src/main/java/com/capgemini/reports/queuing/EmbeddedServer.java @@ -0,0 +1,115 @@ +package com.capgemini.reports.queuing; + +import javax.annotation.PostConstruct; +import javax.annotation.PreDestroy; +import javax.ejb.Singleton; +import javax.ejb.Startup; +import javax.jms.JMSException; +import javax.jms.MessageProducer; +import javax.jms.ObjectMessage; +import javax.jms.Queue; +import javax.jms.QueueConnection; +import javax.jms.QueueConnectionFactory; +import javax.jms.QueueSession; +import javax.jms.Session; +import javax.naming.InitialContext; +import javax.naming.NamingException; + +import com.capgemini.reports.execution.AbstractExecutionReport; + +import lombok.extern.slf4j.Slf4j; + +/** This class is responsible for the setup of the Queues, the producers and the consumers. **/ +@Startup +@Singleton +@Slf4j +public class EmbeddedServer { + + private static final int LOW_PRIORITY_VALUE = 3; + private static final int MED_PRIORITY_VALUE = 5; + private static final int HIGH_PRIORITY_VALUE = 7; + + private static QueueConnection jmsConnection; + + /** + * On construction, the connection is set up and started. + * + * @throws JMSException if unable to obtain queue name from JMS + * @throws NamingException of queue name does not exist in JMS + */ + @PostConstruct + public void init() throws JMSException, NamingException { + log.info("Initializing HornetQ session, queues, producers and consumers"); + InitialContext initialContext = new InitialContext(); + + /* + * In standalone-xxxx.xml, there should be a connection factory with an named entry: + * <-- this could be in-vm (accessible from same VM as the server, no outside request) + * [...] + * + * + * + * + */ + QueueConnectionFactory connectionFactory = (QueueConnectionFactory) initialContext.lookup("/ConnectionFactory"); + createQueueConnection(connectionFactory); + + // Begin + jmsConnection.start(); + } + + private static void createQueueConnection(final QueueConnectionFactory connectionFactory) throws JMSException { + EmbeddedServer.jmsConnection = connectionFactory.createQueueConnection(); + } + + /** + * On destroy, the producers, consumers, sessions and the connection to the JMS will be closed. + * + * @throws JMSException if unable to close to jms conection properly + */ + @PreDestroy + public void destroy() throws JMSException { + log.info("Destroying HonetQ session"); + + // Close the connection + jmsConnection.close(); + } + + /** + * Sends a report through to hornetQ for queuing. + * + * @param report the report to post in queue + * @throws JMSException if unable to talk to JMS + * @throws NamingException if unable to find queue in JMS + */ + public static void produce(final AbstractExecutionReport report) throws JMSException, NamingException { + // Open a session just for sending this message + QueueSession jmsSession = jmsConnection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); + try { + InitialContext initialContext = new InitialContext(); + Queue queue = (Queue) initialContext.lookup("/queues/kurtQueue"); + + ObjectMessage message = jmsSession.createObjectMessage(report); + + // Setup producers and their priorities + MessageProducer producer = jmsSession.createProducer(queue); + switch (report.getReportPriority()) { + case HIGH_PRIORITY: + producer.setPriority(HIGH_PRIORITY_VALUE); + break; + case MED_PRIORITY: + producer.setPriority(MED_PRIORITY_VALUE); + break; + default: + producer.setPriority(LOW_PRIORITY_VALUE); + break; + } + producer.send(message); + } finally { + // We're done sending messages until next request. But the underlying Connection is of course still open. + if (jmsSession != null) { + jmsSession.close(); + } + } + } +} diff --git a/kurt-ejb/src/main/java/com/capgemini/reports/queuing/consumer/ReportConsumer.java b/kurt-ejb/src/main/java/com/capgemini/reports/queuing/consumer/ReportConsumer.java new file mode 100644 index 0000000..059a2a4 --- /dev/null +++ b/kurt-ejb/src/main/java/com/capgemini/reports/queuing/consumer/ReportConsumer.java @@ -0,0 +1,96 @@ +package com.capgemini.reports.queuing.consumer; + +import com.capgemini.framework.common.SettingsHelper; +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.NoTeamcenterConnectionException; +import com.capgemini.reports.exceptions.InvalidUserInputException; +import com.capgemini.reports.exceptions.NoConfChangesException; +import com.capgemini.reports.execution.AbstractExecutionReport; +import org.jboss.ejb3.annotation.ResourceAdapter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.ejb.ActivationConfigProperty; +import javax.ejb.MessageDriven; +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.MessageListener; +import javax.jms.ObjectMessage; + +/** + * This class represents a generic Consumer of messages.
    + * It is a Message-Driven Bean (MDB) whose properties are also defined in ejb-jar.xml (in the war's WEB-INF folder) . + */ +@MessageDriven(name = "jobConsumer", activationConfig = { + @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"), + @ActivationConfigProperty(propertyName = "destination", propertyValue = "/queues/kurtQueue"), + @ActivationConfigProperty(propertyName = "consumerWindowSize", propertyValue = "0")}) +@ResourceAdapter("hornetq-ra.rar") +public class ReportConsumer implements MessageListener { + private static final Logger LOGGER = LoggerFactory.getLogger(ReportConsumer.class); + + /** + * This method processes incoming messages containing reports to be performed.
    + * + * @param message a {@link Message} containing an {@link AbstractExecutionReport} to perform. + */ + @Override + public void onMessage(final Message message) { + AbstractExecutionReport report; + + try { + report = obtainReport(message); + } + catch (UnsupportedOperationException e) { + LOGGER.warn("Unable to handle report request, dropping the request", e); + return; + } + + // If CLEANUP is set, ignore the incoming reports. Treat them as a Technical errors in the DB. + if (SettingsHelper.isCleanup()) { + final String optionalStartTime = report.getStartTime() != null ? " Start:" + report.getStartTime() : ""; + LOGGER.error("[CLEANUP] {} {}", report.getReportTechnicalUid(), optionalStartTime); + report.getExecutionStrategy().handleTechnicalError(report, new Throwable("Report cleaned up")); + return; + } + + try (TcSession session = new TcSession()) { + session.login(); + report.doStart(session); + } + catch (NoTeamcenterConnectionException e) { + // Unable to create a connection to the server dispatcher in the first place + report.getExecutionStrategy().handleTechnicalError(report, e); + } + catch (NoConfChangesException e) { + report.getExecutionStrategy().handleFunctionalError(report, e); + } + catch (InvalidUserInputException e) { + report.getExecutionStrategy().handleFunctionalError(report, e); + } + catch (Exception e) { + LOGGER.error("Exception encountered", e); + // This Throwable is caught in order for this message to NOT be re-posted immediately and indefinitely by HornetQ, who thinks the message has not been delivered correctly! + report.getExecutionStrategy().handleTechnicalError(report, e); + } + } + + private AbstractExecutionReport obtainReport(final Message message) { + if (!(message instanceof ObjectMessage)) { + throw new UnsupportedOperationException("onMessage() received an unhandled message: " + message.getClass().getName() + ", expecting an ObjectMessage"); + } + try { + Object object = ((ObjectMessage) message).getObject(); + if (!(AbstractExecutionReport.class.isInstance(object))) { + throw new UnsupportedOperationException("onMessage() received an unhandled object inside the message: " + object.toString() + " of type " + object.getClass().getName() + ", expecting an AbstractExecutionReport"); + } + else { + // message.acknowledge(); <-- No need because the queue was set up using AUTO_ACKNOWLEDGE + return (AbstractExecutionReport) object; + } + } + catch (JMSException e) { + throw new UnsupportedOperationException("onMessage() could not obtain the Object packed inside the message", e); + } + } +} diff --git a/kurt-ejb/src/main/resources/META-INF/beans.xml b/kurt-ejb/src/main/resources/META-INF/beans.xml new file mode 100644 index 0000000..3738086 --- /dev/null +++ b/kurt-ejb/src/main/resources/META-INF/beans.xml @@ -0,0 +1,27 @@ + + + + + + diff --git a/kurt-ejb/src/main/resources/log4j.properties b/kurt-ejb/src/main/resources/log4j.properties new file mode 100644 index 0000000..6d5fed6 --- /dev/null +++ b/kurt-ejb/src/main/resources/log4j.properties @@ -0,0 +1,21 @@ +log4j.logger.com.teamcenter.soa=WARN, stdout +log4j.additivity.com.teamcenter.soa=false +log4j.logger.com.teamcenter.soa.client.Connection=INFO, stdout +log4j.additivity.com.teamcenter.soa.client.Connection=false +log4j.logger.org.apache=WARN, stdout +log4j.logger.httpclient=WARN, stdout +log4j.logger.com.capgemini=DEBUG, stdout + +# Direct log messages to stdout +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.Target=System.out +log4j.appender.stdout.threshold=DEBUG +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %c{1}:%L - %m%n + +# Root logger option +log4j.rootLogger=ERROR, stdout + +# Remove Arjuna Warnings +log4j.logger.com.arjuna.ats.jta=ERROR + diff --git a/kurt-ejb/src/test/resources/log4j.properties b/kurt-ejb/src/test/resources/log4j.properties new file mode 100644 index 0000000..8f372cd --- /dev/null +++ b/kurt-ejb/src/test/resources/log4j.properties @@ -0,0 +1,13 @@ +log4j.logger.com.teamcenter.soa=WARN +log4j.logger.org.apache=WARN +log4j.logger.httpclient=WARN + +# Direct log messages to stdout +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.Target=System.out +log4j.appender.stdout.threshold=DEBUG +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %c{1}:%L - %m%n + +# Root logger option +log4j.rootLogger=DEBUG, stdout diff --git a/kurt-ejb/src/test/resources/logging.properties b/kurt-ejb/src/test/resources/logging.properties new file mode 100644 index 0000000..1983b8d --- /dev/null +++ b/kurt-ejb/src/test/resources/logging.properties @@ -0,0 +1,3 @@ +handlers=java.util.logging.ConsoleHandler +java.util.logging.ConsoleHandler.level=FINEST +com.capgemini.level=FINEST diff --git a/kurt-ejb/src/test/resources/quartz.properties b/kurt-ejb/src/test/resources/quartz.properties new file mode 100644 index 0000000..435f06e --- /dev/null +++ b/kurt-ejb/src/test/resources/quartz.properties @@ -0,0 +1,58 @@ +#========================================================================== +# Configure Main Scheduler Properties +#========================================================================== +org.quartz.scheduler.instanceName: DefaultQuartzScheduler +org.quartz.scheduler.rmi.export: false +org.quartz.scheduler.rmi.proxy: false +org.quartz.scheduler.wrapJobExecutionInUserTransaction: false +org.quartz.scheduler.batchTriggerAcquisitionMaxCount = 100 +org.quartz.scheduler.batchTriggerAcquisitionFireAheadTimeWindow =1 + +# Amount of time in milliseconds that the scheduler will wait before re-queries for available triggers when the scheduler is otherwise idle +org.quartz.scheduler.idleWaitTime: 1000 + +# Amount of time in milliseconds that the scheduler will wait between re-tries when it has detected a loss of connectivity to the database (obviously not meaningful with RamJobStore) +org.quartz.scheduler.dbFailureRetryInterval: 3600 + +#========================================================================== +# Configure ThreadPool +#========================================================================== +org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool + +# Number of threads that are available for concurrent execution of jobs +org.quartz.threadPool.threadCount: 100 + +# Thread priority (Can be any int between Thread.MIN_PRIORITY (which is 1) and Thread.MAX_PRIORITY (which is 10). The default is Thread.NORM_PRIORITY (5)) +org.quartz.threadPool.threadPriority: 5 + +org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread: true + +#========================================================================== +# Configure JobStore +#========================================================================== +org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX +org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate +org.quartz.jobStore.dataSource = myDS +org.quartz.jobStore.tablePrefix =QRTZ_ +org.quartz.jobStore.useProperties = false +org.quartz.jobStore.misfireThreshold = 60000 +org.quartz.jobStore.isClustered = false +org.quartz.jobStore.maxMisfiresToHandleAtATime = 20 +org.quartz.jobStore.dontSetAutoCommitFalse = false + +# "{0}" is replaced during run-time with the TABLE_PREFIX that you configured above and "{1}" with the scheduler's name +org.quartz.jobStore.selectWithLockSQL = "SELECT * FROM {0}LOCKS WHERE SCHED_NAME = {1} AND LOCK_NAME = ? FOR UPDATE" + +org.quartz.jobStore.txIsolationLevelSerializable = false +org.quartz.jobStore.acquireTriggersWithinLock = true + +#========================================================================== +# Configure Datasources +#========================================================================== +org.quartz.dataSource.myDS.driver = oracle.jdbc.driver.OracleDriver +org.quartz.dataSource.myDS.URL = jdbc:oracle:thin:@10.24.192.36:1521:TC +org.quartz.dataSource.myDS.user =TAC +org.quartz.dataSource.myDS.password =TAC + +# Be configured to be at least the number of worker threads in the thread pool plus three +org.quartz.dataSource.myDS.maxConnections = 103 diff --git a/kurt-ejb/src/test/resources/simplelogger.properties b/kurt-ejb/src/test/resources/simplelogger.properties new file mode 100644 index 0000000..e69de29 diff --git a/kurt-ejb/src/test/resources/test_policy.xml b/kurt-ejb/src/test/resources/test_policy.xml new file mode 100644 index 0000000..e0c3961 --- /dev/null +++ b/kurt-ejb/src/test/resources/test_policy.xml @@ -0,0 +1,213 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/pom.xml b/kurt-utility/pom.xml new file mode 100644 index 0000000..6ccb1e8 --- /dev/null +++ b/kurt-utility/pom.xml @@ -0,0 +1,209 @@ + + + 4.0.0 + kurt-utility + jar + kurt-utility + + + com.capgemini.reports + kurt + 1.32.9 + + + + + com.capgemini.reports + teamcenter + 1.32.9 + + + + com.capgemini.reports + jasper + 1.32.9 + + + + junit + junit + test + + + + org.mockito + mockito-core + test + + + + org.assertj + assertj-core + test + + + + + org.slf4j + slf4j-api + + + + org.projectlombok + lombok + + + + org.jboss.spec.javax.annotation + jboss-annotations-api_1.1_spec + + + + commons-io + commons-io + + + com.sun.mail + javax.mail + 1.4.7 + + + commons-net + commons-net + 3.1 + + + + org.hibernate + hibernate-core + + + + com.oracle + ojdbc6 + 11.2.0.3 + provided + + + + com.google.guava + guava + + + + + com.hp.gagawa + gagawa + 1.0.1 + + + + net.lingala.zip4j + zip4j + 1.3.2 + + + com.opencsv + opencsv + 3.10 + + + + org.testng + testng + 6.8 + test + + + org.apache.poi + poi + 3.17 + test + + + org.apache.poi + poi-ooxml + 3.17 + test + + + + + + + + + + + + src/main/resources + true + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + test-jar + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + src/val/resources/testng.yaml + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 3.0.0 + + + add-integration-test-source + generate-test-sources + + add-test-source + + + + src/val/java + + + + + add-integration-test-resources + generate-test-resources + + add-test-resource + + + + + + + src/val/resources + true + + + + + + + + + + diff --git a/kurt-utility/src/main/java/com/capgemini/framework/common/AbstractPropertiesManager.java b/kurt-utility/src/main/java/com/capgemini/framework/common/AbstractPropertiesManager.java new file mode 100644 index 0000000..f99c980 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/framework/common/AbstractPropertiesManager.java @@ -0,0 +1,241 @@ +package com.capgemini.framework.common; + +import lombok.extern.slf4j.Slf4j; + +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.Map.Entry; +import java.util.Properties; + +/** + * Property manager pattern for managing settings.
    + * All methods are protected, please extend this class to present a specific getter method of the right type for each parameter. + **/ +@Slf4j +public abstract class AbstractPropertiesManager { + + private static final String UNEXPECTED_FORMAT_OF_PROPERTY = "Unexpected format of property: "; + + /** File path to the property file. **/ + final String propertyFilePath; + + /** Prefix that should be appended at the beginning of all properties. **/ + private final String propertyCommonPrefix; + + /** Properties resource bundle corresponding to the propertyFilePath. **/ + private final Properties propertyFile; + + /** + * Constructor : load the properties from the property file. + * + * @param aPropertyFilePath File path to the property file + **/ + AbstractPropertiesManager(final String aPropertyFilePath) { + propertyFilePath = aPropertyFilePath; + propertyCommonPrefix = getPropPrefix(); + propertyFile = new Properties(); + // load file + try { + loadServerPopertiesFile(); + } catch (IOException e) { + log.error("Unable to load properties from file: " + propertyFilePath, e); + } + // log properties reado + if (log.isDebugEnabled()) { + log.debug("-- First startup of Properties Manager --"); + for (Entry entry : propertyFile.entrySet()) { + log.debug(String.format(" + Key: %-70s Value: %s", entry.getKey(), entry.getValue())); + } + } + } + + /** + * Get Boolean value from settings. + * + * @param aKey Searched setting key + * @return boolean value matching with searched setting key + */ + protected boolean getBooleanValue(final String aKey) { + boolean theBoolValue = false; + String theValue = getStringValue(aKey); + if ((theValue != null) && (isTrue(theValue))) { + theBoolValue = true; + } + return theBoolValue; + } + + /** + * Check if current value match with a value considered as "true". + * + * @param aValue String value which should be analyzed + * @return Boolean interpretation of current String value + **/ + private static boolean isTrue(final String aValue) { + boolean theStatus = false; + final String[] trueValueArray = {"true", "TRUE", "True", "1"}; + for (String aCurrentValue : trueValueArray) { + if (aCurrentValue.equals(aValue)) { + theStatus = true; + break; + } + } + return theStatus; + } + + /** + * Get Integer value from settings. + * + * @param aKey Searched setting key + * @return integer value matching with searched setting key + */ + int getIntegerValue(final String aKey) { + int theIntValue = 0; + try { + String theValue = getStringValue(aKey); + if (theValue != null) { + theIntValue = Integer.valueOf(theValue); + } + } catch (NumberFormatException e) { + log.error(UNEXPECTED_FORMAT_OF_PROPERTY + aKey + " (it should be an integer)", e); + } + return theIntValue; + } + + /** + * Get a string value from settings. + * + * @param aKey Searched setting key + * @return String value matching with searched setting key + */ + String getStringValue(final String aKey) { + // Read property value + String thePropertyValue = getProperty(aKey); + + // Log warning when a property has not been found + if (thePropertyValue == null) { + log.error("Setting reference: \"" + aKey + "\" has not been found"); + } + + return thePropertyValue; + } + + /** + * Get a property from the reference parameter and set a default value if the reference is not found. + * + * @param aRef Setting key + * @param aDefaultValue Default returned value when setting is not defined + * @return string value matching with searched setting key or default value when key has not been found + */ + String getPropertyWithDefaultValueImpl(final String aRef, final String aDefaultValue) { + // Read property value + String thePropertyValue = getProperty(aRef); + + if (thePropertyValue == null) { + thePropertyValue = aDefaultValue; + } + return thePropertyValue; + } + + /** + * Get a property from the reference parameter and set a default value if the reference is not found. + * + * @param aRef Setting key + * @param aDefaultValue Default returned boolean when setting is not defined + * @return string value matching with searched setting key or default value when key has not been found + */ + boolean getBooleanWithDefaultValueImpl(final String aRef, final boolean aDefaultValue) { + // Read property value + String thePropertyValue = getProperty(aRef); + if (thePropertyValue == null) { + return aDefaultValue; + } else { + return isTrue(thePropertyValue); + } + } + + /** + * Attempt to load server properties. If failed, loads internal EAR properties. + * + * @throws IOException if even the internal file couldn't be read + */ + private void loadServerPopertiesFile() throws IOException { + String theJbossConfPath = System.getenv("JBOSS_HOME") + "/standalone/configuration/" + propertyFilePath; + boolean isConfFile = FileHelper.fileExist(theJbossConfPath); + if (isConfFile) { + log.debug("JBOSS configuration file has been found in: " + theJbossConfPath); + try (FileInputStream thePropStream = new FileInputStream(theJbossConfPath)) { + readPropertiesFile(thePropStream); + } catch (IOException e) { + log.error("JBOSS configuration file has been found but is not readable : " + theJbossConfPath + + " defaulting to internal porperties file", e); + loadinternalPropertiesFile(); + } + } else { + log.info("EAR file will be used, no configuration file found in " + theJbossConfPath); + loadinternalPropertiesFile(); + } + } + + /** + * Loads the internal EAR file. + * @throws IOException if unable to read the file + */ + private void loadinternalPropertiesFile() throws IOException { + try (InputStream stream = AbstractPropertiesManager.class.getResourceAsStream(propertyFilePath)) { + readPropertiesFile(stream); + } + } + + /** + * Reads any {@link InputStream} into a {@link Properties} file using the correct {@link Charset}. + * @param stream the stream to the file + * @throws IOException if unable to load the file + */ + private void readPropertiesFile(InputStream stream) throws IOException { + Reader reader = new InputStreamReader(stream, StandardCharsets.ISO_8859_1); + propertyFile.load(reader); + } + + /** + * Insert a required prefix at the beginning of property reference. Then obtains the value associated with it. Return may be null. + * + * @param aPropRef Property reference to find + * @return String content of searched property, null if no such key found + */ + private String getProperty(final String aPropRef) { + // filter invalid characters in the key + String filteredKey = aPropRef.replaceAll(StringHelper.REGEXP_ALPHANUM, ""); + + // Insert common prefix if not present + String thePropRefWithPrefix; + if ((propertyCommonPrefix != null) && !filteredKey.startsWith(propertyCommonPrefix)) { + thePropRefWithPrefix = propertyCommonPrefix + filteredKey; + } else { + thePropRefWithPrefix = filteredKey; + } + + // Get property content + String propertyValue = propertyFile.getProperty(thePropRefWithPrefix); + if (propertyValue == null) { + return null; + } else { + return new String(propertyValue.getBytes(), StandardCharsets.ISO_8859_1); + } + } + + Properties getPropertyFile() { + return propertyFile; + } + + /** + * Getter for prefix that should be appended at the beginning of all properties. + * + * @return The common prefix value + **/ + protected abstract String getPropPrefix(); +} diff --git a/kurt-utility/src/main/java/com/capgemini/framework/common/DateHelper.java b/kurt-utility/src/main/java/com/capgemini/framework/common/DateHelper.java new file mode 100644 index 0000000..cb4bf03 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/framework/common/DateHelper.java @@ -0,0 +1,136 @@ +package com.capgemini.framework.common; + +import lombok.extern.slf4j.Slf4j; + +import java.sql.Date; +import java.sql.Time; +import java.sql.Timestamp; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Calendar; + +/** + * This class is able to creates dates in a specific format (dd-MM-yyyy HH:mm). + */ +@Slf4j +public final class DateHelper { + + private static final String STD_YEAR_MONTH_FORMAT = "yyyy-MM"; + private static final String STD_DATE_FORMAT = "dd-MM-yyyy"; + + private DateHelper() { + // Private constructor to make this an utility class + } + + /** + * Converts a {@link Calendar} to a sql {@link Timestamp}. + * + * @param cal the {@link Calendar} to convert + * @return the {@link Timestamp} + */ + public static Timestamp toTimestamp(final Calendar cal) { + return new Timestamp(cal.getTime().getTime()); + } + + /** + * Extract current SQL date. + * + * @return the {@link Date} + **/ + public static Date getCurrentSqlDate() { + java.util.Date currentUtilDate = new java.util.Date(); + return new Date(currentUtilDate.getTime()); + } + + /** + * Extract current SQL time stamp. + * + * @return the {@link Time} + **/ + public static Timestamp getCurrentSqlTimestamp() { + java.util.Date currentUtilDate = new java.util.Date(); + return new Timestamp(currentUtilDate.getTime()); + } + + /** + * Compute the code for the current month period (year + "-" + month). + * + * @return the {@link Time} + **/ + public static String getMonthPeriod() { + return new SimpleDateFormat(STD_YEAR_MONTH_FORMAT).format(getCurrentSqlDate()); + } + + /** + * Returns a Date that references today, at 00:00 am. + * + * @return the date of today with the following format (ex : 01-01-2015) + */ + public static String getDate() { + java.util.Date today = new java.util.Date(); + return new SimpleDateFormat(STD_DATE_FORMAT).format(today); + } + + /** + * Returns a Calendar representing the current date, offset by the number of days provided. + * + * @param nbDays nb ofdays to offset from today. psoitive: offset in the future. + * @return a {@link Calendar} + */ + public static Calendar offsetDays(final int nbDays) { + Calendar cal = Calendar.getInstance(); + cal.add(Calendar.DAY_OF_MONTH, nbDays); + return cal; + } + + /** + * Returns tomorrow, at 00:00m. + * + * @return date + */ + public static String getDatePlusOne() { + Calendar today = Calendar.getInstance(); + today.add(Calendar.DATE, 1); + return today.get(Calendar.DATE) + "-" + (today.get(Calendar.MONTH) + 1) + "-" + today.get(Calendar.YEAR); + } + + /** + * Returns the reference date, offset by the provided number of days (positive in the future, negativ ein the past). + * + * @param dateReference the reference date + * @return date +1 + */ + public static Calendar getDatePlusOneWithReferenceCalendar(final Calendar dateReference) { + Calendar aujourdhui = Calendar.getInstance(); + if (dateReference != null) { + aujourdhui.setTime(dateReference.getTime()); + } + aujourdhui.add(Calendar.DATE, 1); + return aujourdhui; + } + + /** + * Allow to findAll the date + 1 of a date which is entry in parameter. + * + * @param ref the reference date + * @return date the input date, offset by the requested amount and formatted + */ + public static String getDatePlusOneWithReferenceString(final String ref) { + SimpleDateFormat curFormater = new SimpleDateFormat(STD_DATE_FORMAT); + Calendar theDate = Calendar.getInstance(); + + try { + java.util.Date dateObj = curFormater.parse(ref); + theDate.setTime(dateObj); + } + catch (ParseException e) { + log.error("Unable to parse the Date : '" + ref + "', defaulting to tomorrow", e); + } + theDate.add(Calendar.DATE, 1); + return theDate.get(Calendar.DATE) + "-" + (theDate.get(Calendar.MONTH) + 1) + "-" + theDate.get(Calendar.YEAR); + } + + public static java.util.Date parseDate(final String ref) throws ParseException { + return new SimpleDateFormat(STD_DATE_FORMAT).parse(ref); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/framework/common/DoubleFormatter.java b/kurt-utility/src/main/java/com/capgemini/framework/common/DoubleFormatter.java new file mode 100644 index 0000000..0951ecc --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/framework/common/DoubleFormatter.java @@ -0,0 +1,116 @@ +package com.capgemini.framework.common; + +/** Formats a double to String, allowing specification of a number of significant digits. */ +public final class DoubleFormatter { + + private static final String MINUS = "-"; + private static final String EMPTY_STRING = ""; + private static final String DOT = "."; + private static final char ZERO_CHAR = '0'; + private static final int TEN = 10; + /** Limited by the java Long used to represent the mantissa. */ + private static final int MAX_SIGNIFICANT_DIGITS = 16; + + private DoubleFormatter() { + // nothing in here + } + + /** + * Rounds a double value to a number of significant digits. + *

    + * Examples: + *

      + *
    • {@code toSignificantDigits(20001054, 9)} gives {@code "20001054"}
    • + *
    • {@code toSignificantDigits(-20001054, 9)} gives {@code "-20001054"}
    • + *
    • {@code toSignificantDigits(200010.54, 9)} gives {@code "200010.54"}
    • + *
    • {@code toSignificantDigits(200010.54, 8)} gives {@code "200010.54"}
    • + *
    • {@code toSignificantDigits(200010.54, 3)} gives {@code "200000"}
    • + *
    • {@code toSignificantDigits(200010.54, 7)} gives {@code "200010.5"}
    • + *
    • {@code toSignificantDigits(200010.54, 7)} gives {@code "200010.6"}
    • + *
    • {@code toSignificantDigits(0.00020051024, 6)} gives {@code "0.00020051"}
    • + *
    • {@code toSignificantDigits(-0.00020051054, 3)} gives {@code "-0.000201"}
    • + *
    + * + * @param value the value to be rounded + * @param someSignificantDigits MUST be lower or equal to 16 (limited by the java Long used to represent the mantissa) + * @return the {@link String} representation of the value, with the required digits + */ + public static String toSignificantDigits(final double value, final int someSignificantDigits) { + if (value == 0) { + return "0"; + } + int significantDigits = Math.min(someSignificantDigits, MAX_SIGNIFICANT_DIGITS); + + // Extract sub-components: sign, mantissa and exponent + double abs = Math.abs(value); + int power = (int) Math.floor(Math.log10(abs)); + double mantissa = abs * Math.pow(TEN, -power); + String mantissaStr = Double.toString(mantissa); + + // Exctract the coma position + int numDigits; + String mantissaWithoutDot; + if (mantissaStr.contains(DOT)) { + numDigits = mantissaStr.length() - 1; + mantissaWithoutDot = mantissaStr.replace(DOT, EMPTY_STRING); + } + else { + numDigits = 1; + mantissaWithoutDot = mantissaStr; + } + + // Mantissa cannot exceed 2^63 (about 10^18) which is max value for long + if (mantissaWithoutDot.length() > MAX_SIGNIFICANT_DIGITS) { + mantissaWithoutDot = mantissaWithoutDot.substring(0, MAX_SIGNIFICANT_DIGITS); + numDigits = MAX_SIGNIFICANT_DIGITS; + } + + // Round to the number of significant digits IF there are more digits than significant digits + String truncatedMantissaWithoutDot; + if (numDigits > significantDigits) { + long trueValue = Long.valueOf(mantissaWithoutDot); + double powToRound = (long) Math.pow(TEN, mantissaWithoutDot.length() - significantDigits); + long roundedFinalNumber = Math.round(trueValue / powToRound) * (long) powToRound; + truncatedMantissaWithoutDot = String.valueOf(roundedFinalNumber); + } + else { // No need to round + truncatedMantissaWithoutDot = mantissaWithoutDot; + } + // Remove uneeded zeroes in the mantissa + while (truncatedMantissaWithoutDot.length() > 1 && truncatedMantissaWithoutDot.charAt(truncatedMantissaWithoutDot.length() - 1) == ZERO_CHAR) { + truncatedMantissaWithoutDot = truncatedMantissaWithoutDot.substring(0, truncatedMantissaWithoutDot.length() - 1); + } + + return compileTheNumber(value, power, truncatedMantissaWithoutDot); + } + + private static String compileTheNumber(final double value, final int power, final String truncatedMantissaWithoutDot) { + // Write the number using its sign, mantissa and power + String signum = Math.signum(value) >= 0 ? EMPTY_STRING : MINUS; + if (power >= 0) { + if (power < truncatedMantissaWithoutDot.length() - 1) { + // fractional number 'ABC.XYZ' + String intPart = truncatedMantissaWithoutDot.substring(0, power + 1); + String fracPart = truncatedMantissaWithoutDot.substring(power + 1); + return signum + intPart + DOT + fracPart; + } + else { + // Integer number (significant mantisse is shorter than power) of the form 'ABCXYZ000' + StringBuilder builder = new StringBuilder(signum).append(truncatedMantissaWithoutDot); + for (int additionalZeroes = 0; additionalZeroes < power + 1 - truncatedMantissaWithoutDot.length(); additionalZeroes++) { + builder.append(ZERO_CHAR); + } + return builder.toString(); + } + } + else { + // Leading zeroes, then full significant mantissa: '0.000ABCXYZ' + StringBuilder builder = new StringBuilder(signum).append("0."); + for (int additionalZeroes = 0; additionalZeroes < -power - 1; additionalZeroes++) { + builder.append(ZERO_CHAR); + } + builder.append(truncatedMantissaWithoutDot); + return builder.toString(); + } + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/framework/common/DynamicErrorTemplateHelper.java b/kurt-utility/src/main/java/com/capgemini/framework/common/DynamicErrorTemplateHelper.java new file mode 100644 index 0000000..aca1337 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/framework/common/DynamicErrorTemplateHelper.java @@ -0,0 +1,37 @@ +package com.capgemini.framework.common; + +import lombok.Getter; + +/** + * Customizable messages (using tags). + */ +@Getter +public class DynamicErrorTemplateHelper { + + private String refError; + private final String[] tags; + + /** + * Constructor. + * + * @param refError a reference error message (with tags) + * @param tags a list of known tags + */ + public DynamicErrorTemplateHelper(final String refError, final String... tags) { + this.refError = refError; + this.tags = tags; + } + + /** + * Resolve a dynamic error.
    + * Put each tags in theirs places. + * + * @return refErrorString + */ + public String resolve() { + for (String tag : tags) { + refError = refError.replaceFirst("\\{\\}", tag); + } + return refError; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/framework/common/FileHelper.java b/kurt-utility/src/main/java/com/capgemini/framework/common/FileHelper.java new file mode 100644 index 0000000..71f83db --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/framework/common/FileHelper.java @@ -0,0 +1,210 @@ +package com.capgemini.framework.common; + +import com.capgemini.reports.exceptions.NotFoundException; +import com.google.common.io.Files; +import lombok.extern.slf4j.Slf4j; + +import java.io.*; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.List; + +/** + * Class for common file management. + **/ +@Slf4j +public final class FileHelper { + + /** + * Default char set (ISO format). + **/ + private static final String CHARSET_ISO = "ISO-8859-1"; + private static final String FILE_DOES_NOT_EXIST = "File does not exist: "; + + /** + * Constructor. + **/ + private FileHelper() { + // Constructor of helper classes must be private + } + + /** + * Return the default character encoding. + * + * @return Charset encoding + **/ + private static Charset getDefaultCharset() { + return Charset.forName(CHARSET_ISO); + } + + /** + * Check file existence (with verbose mode by default). + * + * @param aFilePath File which must be checked + * @return True when the file exists + */ + public static boolean fileExist(final String aFilePath) { + return fileExist(aFilePath, true); + } + + /** + * Check file existence. + * + * @param aFilePath File which must be checked + * @param isVerbose True for verbose mode, else the silent mode is used + * @return True when the file exists + */ + public static boolean fileExist(final String aFilePath, final boolean isVerbose) { + boolean status = true; + + if (aFilePath == null) { + if (isVerbose) { + log.debug("File name is null"); + } + return false; + } + + File theFile = new File(aFilePath); + if (!theFile.exists() || theFile.isDirectory()) { + if (isVerbose) { + log.debug(FILE_DOES_NOT_EXIST + theFile.getAbsolutePath()); + } + status = false; + } + + return status; + } + + /** + * Read a text file and findAll its content. + * + * @param aSourceFilePath parsed source file path + * @return string with text file content + */ + public static String read(final String aSourceFilePath) { + + // Check file existence + if (!fileExist(aSourceFilePath)) { + log.error(FILE_DOES_NOT_EXIST + aSourceFilePath); + return null; + } + + // Read file content + return read(getStream(aSourceFilePath)); + } + + /** + * Read a text file and findAll its content. + * + * @param aFileReader File reader + * @return string with text file content + */ + public static String read(final InputStreamReader aFileReader) { + StringBuilder theContent = new StringBuilder(); + + try (BufferedReader reader = new BufferedReader(aFileReader)) { + + // Browse lines of file + String theCurrentLine = reader.readLine(); + while (theCurrentLine != null) { + theContent.append(theCurrentLine); + theContent.append(StringHelper.LINE_FEED); + theCurrentLine = reader.readLine(); + + } + } catch (IOException e) { + log.error("Unable to read file", e); + } finally { + try { + if (aFileReader != null) { + aFileReader.close(); + } + } catch (IOException e) { + log.error("Unable to close the file", e); + } + } + + // Return lines list + return theContent.toString(); + } + + /** + * Instantiate an input stream from a specific input file path. + * + * @param aSourceFilePath File path of the stream + * @return Created instance of InputStreamReader + **/ + private static InputStreamReader getStream(final String aSourceFilePath) { + InputStreamReader theFileReader = null; + try (FileInputStream theInputStream = new FileInputStream(aSourceFilePath)) { + // Do not use FileReader it use default encoding of platform + theFileReader = new InputStreamReader(theInputStream, getDefaultCharset()); + } catch (IOException e) { + log.error("Unable to access file: " + aSourceFilePath, e); + } + // Do not close theFileReader stream, it should be closed later by calling method + + return theFileReader; + } + + /** + * Deletes all the files in a folder that have been modified before the provided date. + * + * @param files a {@link List} of {@link File}s + * @return a list of all the deleted files' names + */ + public static List deleteFiles(final List files) { + List deletedFileNames = new ArrayList<>(); + for (File file : files) { + if (file.isFile()) { + final String fileName = file.getName(); + if (file.delete()) { + log.info("Le fichier [{}] a été supprimé ", fileName); + deletedFileNames.add(fileName); + } else { + log.warn("Le fichier [{}] n'a pas pu être supprimé ", fileName); + } + } + } + return deletedFileNames; + } + + /** + * Lists all the {@link File}s in a folder that have been modified before the provided date. + * + * @param folder the flder + * @param deadline the deadline + * @return a list of all the {@link File}s + */ + public static List listFilesBefore(final File folder, final Calendar deadline) { + List listing = new ArrayList<>(); + for (File file : folder.listFiles()) { + if (file.isFile()) { + Calendar fileMod = Calendar.getInstance(); + final long lastModified = file.lastModified(); + fileMod.setTime(new Date(lastModified)); + if (fileMod.before(deadline)) { + listing.add(file); + } + } + } + return listing; + } + + /** + * Copy an original file to a target location. + * + * @param original the original {@link File} + * @param target the target {@link File} + * @throws NotFoundException if the original does not exist or similar kind of I/O error occurs + */ + public static void copy(final File original, final File target) throws NotFoundException { + try { + Files.copy(original, target); + } catch (IOException e) { + throw new NotFoundException("Unable to copy the file from " + original.toString() + " to " + target.toString(), e); + } + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/framework/common/FileTemplate.java b/kurt-utility/src/main/java/com/capgemini/framework/common/FileTemplate.java new file mode 100644 index 0000000..c18deea --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/framework/common/FileTemplate.java @@ -0,0 +1,137 @@ +package com.capgemini.framework.common; + +import com.capgemini.reports.exceptions.FileLoadingException; +import lombok.extern.slf4j.Slf4j; + +import java.util.HashMap; +import java.util.Map; + +/** + * Class managing substitutions of certain tags found in a template file. + **/ +@Slf4j +public class FileTemplate { + + /** + * Starting separator for query parameter. + **/ + private static final String PARAM_START = "[["; + + /** + * Ending separator for query parameter. + **/ + private static final String PARAM_END = "]]"; + + /** + * Mapping between tags and their values. + **/ + private Map tagValues = new HashMap<>(); + + /** + * Template file path. + **/ + private String templateFilePath; + + /** + * Template content. + **/ + private String templateContent; + + /** + * Default empty constructor. + **/ + protected FileTemplate() { + // Nothing to do + } + + /** + * Compute a tag from its name. + * + * @param aTagName Name of the tag + * @return Name encapsulated by starting and ending markers + **/ + private static String getTag(final String aTagName) { + return PARAM_START + aTagName + PARAM_END; + } + + /** + * Generate file content for a specific class. + * + * @return Template code + **/ + public String generateCode() { + // Check if template is correctly initialized + if (templateContent == null) { + log.error("Unable to generate the code, the template content is empty"); + return null; + } + + String theFinalContent = templateContent; + + // Replace template tags + for (String theCurrentTag : tagValues.keySet()) { + // Get next tag value + String currentTagValue = tagValues.get(theCurrentTag); + + // Check if tag value is set properly + if (currentTagValue == null) { + log.warn("Tag value is null for " + theCurrentTag); + } else { + // Replace current tag with its value + theFinalContent = theFinalContent.replace(getTag(theCurrentTag), currentTagValue); + } + } + + // Check content after tag replacement and display a warning if there is a missing tag value + isMissingTag(theFinalContent); + return theFinalContent; + } + + /** + * Add a new parameter. + * + * @param aTagName Parameter name + * @param aReplacedValue Parameter value + */ + protected void setTagValue(final String aTagName, final String aReplacedValue) { + tagValues.put(aTagName, aReplacedValue); + } + + /** + * Check if there is a remaining tag value which has not been replaced. + * + * @param aTemplateContent Template code + * @return True when a missing tag has been detected + **/ + private boolean isMissingTag(final String aTemplateContent) { + boolean isMissing = false; + int theStartPos = aTemplateContent.indexOf(PARAM_START); + int theEndPos = aTemplateContent.indexOf(PARAM_END); + if ((theStartPos >= 0) && (theEndPos > 0)) { + String theTagName = aTemplateContent.substring(theStartPos + PARAM_START.length(), theEndPos); + log.warn("Tag value is missing for {} in file {}", theTagName, templateFilePath); + isMissing = true; + } + return isMissing; + } + + /** + * Setter for template file. + * + * @param aTemplateFilePath Template file path + **/ + protected final void setTemplateFilePath(final String aTemplateFilePath) { + templateFilePath = aTemplateFilePath; + if (templateFilePath != null) { + try { + templateContent = ResourceHelper.getResourceContent(aTemplateFilePath); + } catch (FileLoadingException e) { + log.error("Unable to initialize template, the required file at: " + templateFilePath + " is missing", e); + } + } + } + + protected final void setTemplateContent(final String content) { + this.templateContent = content; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/framework/common/FolderHelper.java b/kurt-utility/src/main/java/com/capgemini/framework/common/FolderHelper.java new file mode 100644 index 0000000..f7a93e0 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/framework/common/FolderHelper.java @@ -0,0 +1,112 @@ +package com.capgemini.framework.common; + +import lombok.extern.slf4j.Slf4j; + +import java.io.File; + +/** Class for folder management. **/ +@Slf4j +public final class FolderHelper { + + /** Constructor. **/ + private FolderHelper() { + // Constructor of helper classes must be private + } + + /** + * Check directory existence. + * + * @param aDirPath Directory which must be checked + * @return True when the file exists + */ + private static boolean dirExist(final String aDirPath) { + return dirExist(aDirPath, true); + } + + /** + * Check directory existence with logger option. + * + * @param isVerbose True for verbose mode, else the silent mode is used + * @param aDirPath Directory which must be checked + * @return True when the file exists + */ + private static boolean dirExist(final String aDirPath, final boolean isVerbose) { + + boolean status = true; + + if (aDirPath == null) { + if (isVerbose) { + log.debug("Directory name is null"); + } + return false; + } + + File theDir = new File(aDirPath); + if (!theDir.exists() || theDir.isFile()) { + if (isVerbose) { + log.debug("Directory does not exist: " + theDir.getAbsolutePath()); + } + status = false; + } + + return status; + } + + /** + * Delete all files and sub-directories from a directory. + * + * @param aDirectoryPath Path of the directory + * @return True if delete operation is successful + */ + public static boolean delete(final String aDirectoryPath) { + + boolean isSuccess = true; + + /* Check if folder has not been already deleted */ + if (dirExist(aDirectoryPath)) { + + File theMainDirectory = new File(aDirectoryPath); + + String[] theFileEntries = theMainDirectory.list(); + for (String currentFileEntry : theFileEntries) { + File currentFile = new File(theMainDirectory.getPath(), currentFileEntry); + if (currentFile.isDirectory()) { + isSuccess = isSuccess && delete(currentFile.getPath()); + isSuccess = isSuccess && currentFile.delete(); + } + else { + isSuccess = isSuccess && currentFile.delete(); + } + } + } + + return isSuccess; + } + + /** + * Create all directories if needed, return true when they already exist. + * + * @param aDirectory path for created directory + * @return false when create operation has failed + */ + public static boolean mkdir(final File aDirectory) { + + boolean status = true; + + if (!aDirectory.isDirectory()) { + + /* Recursive creation if needed */ + File theParentDirectory = aDirectory.getParentFile(); + if ((theParentDirectory != null) && !theParentDirectory.isDirectory()) { + status = mkdir(theParentDirectory); + } + + status &= aDirectory.mkdirs(); + if (!status) { + log.error("Unable to create parent directory: " + aDirectory.getAbsolutePath()); + } + } + + return status; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/framework/common/HashMapComparingStringIDs.java b/kurt-utility/src/main/java/com/capgemini/framework/common/HashMapComparingStringIDs.java new file mode 100644 index 0000000..32af60d --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/framework/common/HashMapComparingStringIDs.java @@ -0,0 +1,226 @@ +package com.capgemini.framework.common; + +import lombok.extern.slf4j.Slf4j; + +import java.io.Serializable; +import java.util.*; + +/** + * This class is a {@link Map} which authorizes a weak object comparison, that is provided by an {@link IdMaker} object.
    + * This class allows you to bypass your key's implementation of equals(Object), and make it change according to your needs. + *

    + * You can for instance keep your key object's compare method as a comparator of all the key's relevant fields (Item id + item rev + uid +...), but by providing this map with an IdMaker which uses only the item id, two objects with differing revisions but same item id will be considered the same + * (the map will have unique Items as Keys, not unique ItemRevisions as keys). + * + * @param this Map's Keys type + * @param This Map's Values type + */ +@Slf4j +public class HashMapComparingStringIDs, V> implements Map, Serializable { + + private static final String VALUE_IS_NOT_OF_THE_CORRECT_TYPE = "Value is not of the correct type"; + private static final String KEY_IS_NOT_OF_THE_CORRECT_TYPE = "Key is not of the correct type"; + + private static final long serialVersionUID = 3826358508367637107L; + + private final HashMap stringToKey = new HashMap<>(); + private final HashMap stringToValue = new HashMap<>(); + private final Class keyClass; + private final Class valueClass; + private final IdMaker idMaker; + + /** + * This interface provides a way to make a unique identifier for a Key, to be used in the {@link HashMapComparingStringIDs}. + * + * @param the Keys type + */ + public interface IdMaker extends Serializable { + + /** + * Provides a unique {@link String} identifier for any key. + * + * @param key the key for which this class should make an identifier. + * @return the identifier String + */ + String makeId(final K key); + } + + /** + * Creates an instance of this HashMap. + * + * @param idMaker this object will be use to identify any incoming key.
    + * If two different Keys produce the same Identifier through this IdMaker, the keys will be considered equal. This way, the key's own eqauls method is bypassed. + * @param keyClass the common class instance of all the Key. + * @param valueClass the common class instance of all the Values. + */ + public HashMapComparingStringIDs(final IdMaker idMaker, final Class keyClass, final Class valueClass) { + this.keyClass = keyClass; + this.valueClass = valueClass; + this.idMaker = idMaker; + } + + @Override + public boolean isEmpty() { + return stringToKey.isEmpty(); + } + + @Override + public int size() { + return stringToKey.size(); + } + + @Override + public boolean containsKey(final Object key) { + if (isEmpty()) { + return false; + } + try { + K aKey = keyClass.cast(key); + String strKey = idMaker.makeId(aKey); + return stringToKey.containsKey(strKey); + } catch (ClassCastException e) { + log.trace(KEY_IS_NOT_OF_THE_CORRECT_TYPE, e); + return false; // wrong type + } + } + + @Override + public boolean containsValue(final Object value) { + if (isEmpty()) { + return false; + } + try { + V aValue = valueClass.cast(value); + return stringToValue.containsValue(aValue); + } catch (ClassCastException e) { + log.trace(VALUE_IS_NOT_OF_THE_CORRECT_TYPE, e); + return false; // wrong type + } + } + + @Override + public V get(final Object key) { + if (isEmpty()) { + return null; + } + try { + K aKey = keyClass.cast(key); + String strKey = idMaker.makeId(aKey); + return stringToValue.get(strKey); + } catch (ClassCastException e) { + log.trace(KEY_IS_NOT_OF_THE_CORRECT_TYPE, e); + return null; // wrong type + } + } + + @Override + public V put(final K key, final V value) { + String identifier = idMaker.makeId(key); + if (containsKey(key)) { + return stringToValue.put(identifier, value); + } else { + stringToKey.put(identifier, key); + stringToValue.put(identifier, value); + return null; + } + } + + @Override + public V remove(final Object key) { + if (isEmpty()) { + return null; + } + try { + if (containsKey(key)) { + K aKey = keyClass.cast(key); + String identifier = idMaker.makeId(aKey); + stringToKey.remove(identifier); + return stringToValue.remove(identifier); + } + } catch (ClassCastException e) { + log.trace(KEY_IS_NOT_OF_THE_CORRECT_TYPE, e); + } + return null; // Not found or ClassCastException + } + + @Override + public void putAll(final Map map) { + for (Entry entry : map.entrySet()) { + String identifier = idMaker.makeId(entry.getKey()); + K key = entry.getKey(); + stringToKey.put(identifier, key); + stringToValue.put(identifier, entry.getValue()); + } + } + + @Override + public void clear() { + stringToKey.clear(); + stringToValue.clear(); + } + + @Override + public Set keySet() { + return new TreeSet<>(stringToKey.values()); // This set is also sorted + } + + @Override + public Collection values() { + return stringToValue.values(); + } + + @Override + public Set> entrySet() { // This set is also sorted + Set> entrySet = new TreeSet<>(); + for (Entry keyEntry : stringToKey.entrySet()) { + K key = keyEntry.getValue(); + String identifier = keyEntry.getKey(); + V value = stringToValue.get(identifier); + entrySet.add(new MyEntry(key, value, identifier, this)); + } + return entrySet; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder("{"); + for (Entry entry : entrySet()) { + builder.append(entry.getKey()).append(':').append(entry.getValue()).append(", "); + } + return builder.append("}").toString(); + } + + private class MyEntry implements Entry, Comparable { + private final K key; + private final V value; + private final String identifier; + private final HashMapComparingStringIDs theBackingMap; + + protected MyEntry(final K key, final V value, final String identifier, final HashMapComparingStringIDs theBackingMap) { + this.key = key; + this.value = value; + this.identifier = identifier; + this.theBackingMap = theBackingMap; + } + + @Override + public K getKey() { + return key; + } + + @Override + public V getValue() { + return value; + } + + @Override + public V setValue(final V value) { + return theBackingMap.stringToValue.put(identifier, value); + } + + @Override + public int compareTo(final MyEntry other) { + return key.compareTo(other.getKey()); + } + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/framework/common/MailHelper.java b/kurt-utility/src/main/java/com/capgemini/framework/common/MailHelper.java new file mode 100644 index 0000000..da020ed --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/framework/common/MailHelper.java @@ -0,0 +1,156 @@ +package com.capgemini.framework.common; + +import lombok.extern.slf4j.Slf4j; + +import javax.mail.*; +import javax.mail.internet.AddressException; +import javax.mail.internet.InternetAddress; +import javax.mail.internet.MimeMessage; +import java.util.List; +import java.util.Properties; + +/** + * Utility class for sending email. + **/ +@Slf4j +public final class MailHelper { + /** + * Default email destinator for administration messages. + **/ + public static final List DEFAULT_DESTINATORS = SettingsHelper.getDefaultDestinatorEmail(); + private static final String MAIL_SMTP_PASSWORD = "mail.smtp.password"; + private static final String MAIL_SMTP_USER = "mail.smtp.user"; + private static final String MAIL_SMTP_AUTH = "mail.smtp.auth"; + private static final String MAIL_TRANSPORT_PROTOCOL = "mail.transport.protocol"; + private static final String MAIL_SMTP_SSL_TRUST = "mail.smtp.ssl.trust"; + private static final String MAIL_SMTP_PORT = "mail.smtp.port"; + private static final String MAIL_SMTP_HOST = "mail.smtp.host"; + private static final String MAIL_SMTP_ENABLE_STARTTLS = "mail.smtp.starttls.enable"; + private static final String FALSE = "false"; + private static final String TRUE = "true"; + // Standard connection settings + private static final String DEFAULT_MAIL_USER = SettingsHelper.getDefaultExpeditorMailUsername(); + private static final String DEFAULT_MAIL_PASS = SettingsHelper.getDefaultExpeditorMailPassword(); + private static final String DEFAULT_SMTP_HOST = SettingsHelper.getDefaultSmtpHost(); + private static final String DEFAULT_SMTP_PORT = SettingsHelper.getDefaultSmtpPort(); + + /** + * Private constructor. + **/ + private MailHelper() { + // Hide constructor of utility classes + } + + /** + * Method sending email from the default sender. + * + * @param aDestinatorMail Email of the destinator + * @param aSubject Text content for the email subject + * @param aContent Text for the email content + **/ + public static void send(final String aDestinatorMail, final String aSubject, final String aContent) { + log.debug("Sending an email to user " + aDestinatorMail); + + // Check argument + if (aDestinatorMail.isEmpty()) { + log.warn("The mail destinator is empty, no message will be sent"); + return; + } + + // Define JAVAX required properties + Properties props = setupMailProperties(); + + // For some specific servers, the authenticator should be set too + Authenticator auth = new MailAuthenticator(); + + // Set session + Session theJavaxSession = Session.getInstance(props, auth); + Transport transport = null; + try { + // Format email message + MimeMessage message = new MimeMessage(theJavaxSession); + message.setFrom(new InternetAddress(DEFAULT_MAIL_USER)); + message.addRecipient(Message.RecipientType.TO, new InternetAddress(aDestinatorMail)); + message.setSubject(aSubject); + message.setContent(aContent, "text/html"); + message.saveChanges(); + + // Set connection to SMTP server + if (isAuthenticationMode()) { + transport = theJavaxSession.getTransport("smtp"); + transport.connect(DEFAULT_SMTP_HOST, DEFAULT_MAIL_USER, DEFAULT_MAIL_PASS); + transport.sendMessage(message, message.getAllRecipients()); + } + else { + Transport.send(message); + } + + // When no error occurred at this point, the email has been sent properly + log.debug("Mail sent to: {}", aDestinatorMail); + } + catch (AddressException e) { + log.error("Unable to send email one of email adresses is invalid: " + DEFAULT_MAIL_USER + " or " + aDestinatorMail, e); + } + catch (MessagingException e) { + log.error("Unable to send email", e); + } + finally { + if (transport != null) { + try { + transport.close(); + } + catch (MessagingException e) { + log.error("Unable to close transport connection", e); + } + } + } + } + + /** + * Method for batch-sending an email to several destinators. + * + * @param destinators List containing the Email of all the destinators + * @param aSubject Text content for the email subject + * @param aContent Text for the email content + **/ + public static void sendAll(final List destinators, final String aSubject, final String aContent) { + for (String destinator : destinators) { + MailHelper.send(destinator, aSubject, aContent); + } + } + + private static Properties setupMailProperties() { + Properties props = new Properties(); + props.put(MAIL_SMTP_ENABLE_STARTTLS, TRUE); + props.put(MAIL_SMTP_HOST, DEFAULT_SMTP_HOST); + props.put(MAIL_SMTP_PORT, DEFAULT_SMTP_PORT); + props.put(MAIL_SMTP_SSL_TRUST, DEFAULT_SMTP_HOST); + props.put(MAIL_TRANSPORT_PROTOCOL, "smtp"); + + if (isAuthenticationMode()) { + props.put(MAIL_SMTP_AUTH, TRUE); + props.put(MAIL_SMTP_USER, DEFAULT_MAIL_USER); + props.put(MAIL_SMTP_PASSWORD, DEFAULT_MAIL_PASS); + } + else { + props.put(MAIL_SMTP_AUTH, FALSE); + } + return props; + } + + /** + * Check a user and a password are defined for the SMTP connection. + * + * @return True when the user should be authenticated + */ + private static boolean isAuthenticationMode() { + return !DEFAULT_MAIL_USER.isEmpty() && !DEFAULT_MAIL_PASS.isEmpty(); + } + + private static final class MailAuthenticator extends Authenticator { + @Override + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication(DEFAULT_MAIL_USER, DEFAULT_MAIL_PASS); + } + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/framework/common/MapHelper.java b/kurt-utility/src/main/java/com/capgemini/framework/common/MapHelper.java new file mode 100644 index 0000000..98c5287 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/framework/common/MapHelper.java @@ -0,0 +1,55 @@ +package com.capgemini.framework.common; + +import java.util.*; + +/** + * Utility class for Maps. + **/ +public final class MapHelper { + + /** + * Constructor. + **/ + private MapHelper() { + // Constructor of helper classes must be private + } + + /** + * String displaying of a Map. + * + * @param aMap Map which should be displayed + * @return String representation of the map + **/ + public static String toString(final Map aMap) { + + StringBuilder theStringBuilder = new StringBuilder(); + + // Get map key values and sort them + Set theKeySet = aMap.keySet(); + List theSortedSet = sortSet(theKeySet); + + // Browse sorted values + for (String currentKey : theSortedSet) { + theStringBuilder.append(currentKey).append('=').append(aMap.get(currentKey)).append(StringHelper.LINE_FEED); + } + + return theStringBuilder.toString(); + } + + /** + * Sort a set of strings. + * + * @param aValuesSet Set to sort + * @return sorted list + */ + private static List sortSet(final Set aValuesSet) { + + String[] stArray = aValuesSet.toArray(new String[aValuesSet.size()]); + + // Convert array of elements to sort to a list + List sortedList = Arrays.asList(stArray); + + Collections.sort(sortedList); + return sortedList; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/framework/common/MemoryHelper.java b/kurt-utility/src/main/java/com/capgemini/framework/common/MemoryHelper.java new file mode 100644 index 0000000..a2a2c8b --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/framework/common/MemoryHelper.java @@ -0,0 +1,75 @@ +package com.capgemini.framework.common; + +import com.capgemini.reports.database.manager.MngMemMonitor; + +import java.math.BigDecimal; + +/** + * Utility class for memory monitoring. + **/ +public final class MemoryHelper { + + private static final double TO_PERCENT = 100D; + private static final double BYTES_TO_MB = 1024D * 1024D; + + private MemoryHelper() { + // Makes this class static + } + + /** + * Log debug message when memory monitoring is enabled. + * + * @return Memory message state + **/ + public static String monitorMemory() { + Double theTotalMemory = formatByte(Runtime.getRuntime().totalMemory()); + Double theMaxMemory = formatByte(Runtime.getRuntime().maxMemory()); + Double theFreeMemory = getFreeMemory(); + + Double theUsedMemory = floor(theMaxMemory - theFreeMemory, 1); + Double theMaxPercent = floor(theUsedMemory / theMaxMemory, 1) * TO_PERCENT; + + /* Persist current memory state. */ + MngMemMonitor theMemMonitorManager = new MngMemMonitor(); + theMemMonitorManager.insert(theFreeMemory, theUsedMemory, theMaxMemory, theMaxPercent, theTotalMemory); + return "Mémoire consommée : " + theUsedMemory + " (" + theMaxPercent + "% max)
    Allouée : " + theTotalMemory + + " / Capacité maximale : " + theMaxMemory; + } + + /** + * Get the available memory amount by MBytes. + **/ + private static Double getFreeMemory() { + + /* Get the available memory in allocated space */ + Double freeMemory = floor(Runtime.getRuntime().freeMemory() / BYTES_TO_MB, 1); + + /* Add complementary memory which could be allocated (when XMS is different than XMX) */ + freeMemory += floor((Runtime.getRuntime().maxMemory() - Runtime.getRuntime().totalMemory()) / BYTES_TO_MB, 1); + + return freeMemory; + } + + /** + * Format memory value from Bytes to MegaBytes. + * + * @param aValue with Mbs + * @return Formated value + */ + private static Double formatByte(final double aValue) { + return floor(aValue / BYTES_TO_MB, 0); + } + + /** + * Round numeric value to lower value. + * + * @param aValue Converted value. + * @param aScale Preserved values. + * @return Round value. + */ + private static double floor(final double aValue, final int aScale) { + BigDecimal bigD = BigDecimal.valueOf(aValue); + BigDecimal bigD2 = bigD.setScale(aScale, BigDecimal.ROUND_DOWN); + return bigD2.doubleValue(); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/framework/common/QuartzHelper.java b/kurt-utility/src/main/java/com/capgemini/framework/common/QuartzHelper.java new file mode 100644 index 0000000..2f153f7 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/framework/common/QuartzHelper.java @@ -0,0 +1,45 @@ +package com.capgemini.framework.common; + +import lombok.EqualsAndHashCode; + +/** Static class managing all properties from quartz.properties file. **/ +@EqualsAndHashCode(callSuper = true) +public class QuartzHelper extends AbstractPropertiesManager { + + /** Singleton instance. **/ + private static QuartzHelper instance; + + /** Prefix that should be appended at the beginning of all properties. **/ + private static final String PROP_PREFIX = "org.quartz."; + + /** Constructor : load the properties from the property file. **/ + private QuartzHelper() { + super("/quartz.properties"); + } + + /** @return the instance. **/ + public static synchronized QuartzHelper getInstance() { + if (instance == null) { + instance = new QuartzHelper(); + } + return instance; + } + + @Override + protected String getPropPrefix() { + return PROP_PREFIX; + } + + /** + * Get the file path of the quartz.properties file. + * + * @return string value of the file path + */ + public static String getPropertiesFilePath() { + return getInstance().getPropertiesFilePathImpl(); + } + + private String getPropertiesFilePathImpl() { + return propertyFilePath; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/framework/common/ReportFolderOutputHelper.java b/kurt-utility/src/main/java/com/capgemini/framework/common/ReportFolderOutputHelper.java new file mode 100644 index 0000000..cf8a44e --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/framework/common/ReportFolderOutputHelper.java @@ -0,0 +1,117 @@ +package com.capgemini.framework.common; + +import com.capgemini.reports.ReportLaunchTypeEnum; +import com.capgemini.reports.database.HibernateUtil; +import com.capgemini.reports.database.javabean.DbReport; +import com.capgemini.reports.database.manager.MngReport; +import com.capgemini.reports.exceptions.NotFoundException; +import org.apache.commons.io.FileUtils; +import org.hibernate.Session; +import org.hibernate.SessionFactory; + +import java.io.File; +import java.io.IOException; +import java.util.List; + +/** + * Helper used for returning the appropriate location of folder. + */ +public final class ReportFolderOutputHelper { + + /** + * The default location of the folder which contains all the IMMEDIATE or DELAYED reports.
    + * This value is loaded in the reporting.properties file. + */ + private static final String DEFAULT_LOCATION_OUTPUT = SettingsHelper.getReportLocation(); + /** + * The specific location of the folder which contains the recent scheduled reports.
    + * This value is loaded in the reporting.properties file. + */ + public static final String SCHEDULING_LOCATION_OUTPUT = SettingsHelper.getSchedulingLocation(); + /** + * The specific location of a specific folder which have to record all the scheduled reports.
    + * This value is loaded in the reporting.properties file. + */ + private static final String SCHEDULING_HISTORY_LOCATION_OUTPUT = SettingsHelper.getSchedulingHistoryLocation(); + + /** + * Private constructor. + **/ + private ReportFolderOutputHelper() { + // Hide constructor of utility classes + } + + /** + * Return the appropriate location of folder associated to the report.
    + * The main purpose is to separate scheduled reports's folder with the other folder. + * + * @param launchType {@link ReportLaunchTypeEnum} - the launch type of a report + * @return the String location of folder + */ + public static String getStorageFolderLocation(final ReportLaunchTypeEnum launchType) { + if (ReportLaunchTypeEnum.SCHEDULED.equals(launchType)) { + return SCHEDULING_LOCATION_OUTPUT; + } + else { + return DEFAULT_LOCATION_OUTPUT; + } + } + + /** + * Check if the report has already been launched before in database. + * + * @param schedulingId Long - the ID of the scheduled report + * @return true if the report has already been launched before, else false. + */ + public static boolean checkIfAlreadyLaunched(final Long schedulingId) { + SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); + Session session = sessionFactory.openSession(); + try { + List schedulingReports = new MngReport().searchBySchedulingId(schedulingId, session); + return schedulingReports != null && schedulingReports.size() > 1; // At least two entries + } + finally { + session.close(); + } + } + + /** + * Delete a specific scheduled report in the scheduled output. + * + * @param reportFileName String - the name of the file to delete + * @throws NotFoundException if unable to delete the file + */ + public static void deleteScheduledReportFile(final String reportFileName) throws NotFoundException { + deleteFile(SCHEDULING_LOCATION_OUTPUT, reportFileName); + } + + /** + * Delete a report from his file name in the entry folder location. + * + * @param folderLocation String - the folder location + * @param reportFileName String - the name of the file to delete + * @throws NotFoundException if unable to delete the file + */ + private static void deleteFile(final String folderLocation, final String reportFileName) throws NotFoundException { + File fileToDelete = new File(folderLocation + reportFileName); + + // Try to delete the file and return true if it is done + if (!fileToDelete.delete()) { + throw new NotFoundException("Unable to delete the file " + reportFileName + " in folder " + folderLocation); + } + } + + /** + * Copy a generated scheduled report in the archive folder.
    + * This scheduled report should have be printed before and should be located in the scheduled output. + * + * @param original the file to copy + * @param reportFileName String - the name of the report + * @throws IOException may occur if the copy or the creation of the file doesn't work + */ + public static void copyToHistoryFolder(File original, final String reportFileName) throws IOException { + File archive = new File(SCHEDULING_HISTORY_LOCATION_OUTPUT + reportFileName); + FileUtils.copyFile(original, archive); + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/framework/common/ResourceHelper.java b/kurt-utility/src/main/java/com/capgemini/framework/common/ResourceHelper.java new file mode 100644 index 0000000..ab7fc27 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/framework/common/ResourceHelper.java @@ -0,0 +1,134 @@ +package com.capgemini.framework.common; + +import com.capgemini.reports.exceptions.FileLoadingException; +import lombok.extern.slf4j.Slf4j; + +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; + +/** Helper clas which can load resource files in various forms. */ +@Slf4j +public final class ResourceHelper { + + /** + * 4 double-dots: starting at src / main / resources / com / capgemini/ framework / common.
    + * After that, the Resource Loader will be at the root of src/main/resources + */ + private static final String PATH_TO_SRC_MAIN_RESOURCES = "../../../.."; + + /** Private constructor to make the class "static". */ + private ResourceHelper() { + + } + + /** + * Returns a URL to a resource in src/main/resources/*ABSOLUTEPATH*. + * + * @param absolutePath the path with the src/main/resources + * @return the {@link URL} + * @throws FileLoadingException if the file could not be loaded + */ + private static URL getResourceAsURL(final String absolutePath) throws FileLoadingException { + URL resource = ResourceHelper.class.getResource(PATH_TO_SRC_MAIN_RESOURCES + absolutePath); + if (resource == null) { + throw new FileLoadingException("Could not find file at : " + absolutePath); + } + return resource; + } + + /** + * Returns the {@link InputStream} for a resource in src/main/resources/*ABSOLUTEPATH*. + * + * @param absolutePath the path with the src/main/resources + * @return the {@link InputStream} + * @throws FileLoadingException if the file could not be loaded + */ + public static InputStream getResourceAsStream(final String absolutePath) throws FileLoadingException { + InputStream resourceAsStream = ResourceHelper.class.getResourceAsStream(PATH_TO_SRC_MAIN_RESOURCES + absolutePath); + if (resourceAsStream == null) { + throw new FileLoadingException("Could not load InputStream : " + absolutePath); + } + return resourceAsStream; + } + + /** + * Returns a {@link URI} to a resource in src/main/resources/*ABSOLUTEPATH*. + * + * @param absolutePath the path with the src/main/resources + * @return the {@link URI} + * @throws FileLoadingException thrown when the file could not be read. + */ + private static URI getResourceAsURI(final String absolutePath) throws FileLoadingException { + try { + return getResourceAsURL(absolutePath).toURI(); + } catch (URISyntaxException e) { + throw new FileLoadingException("Could not load URI " + absolutePath, e); + } + } + + /** + * Returns a {@link File} linking to a resource in src/main/resources/*ABSOLUTEPATH*. + * + * @param absolutePath the path with the src/main/resources + * @return the {@link File} + * @throws FileLoadingException thrown when the file could not be read. + */ + public static File getResourceAsFile(final String absolutePath) throws FileLoadingException { + return new File(getResourceAsURI(absolutePath)); + + } + + /** + * Returns a String with the full content of a resource in src/main/resources/*ABSOLUTEPATH*. + * + * @param absolutePath the path with the src/main/resources + * @return the content + * @throws FileLoadingException if the file could not be loaded + */ + public static String getResourceContent(final String absolutePath) throws FileLoadingException { + try (InputStream stream = getResourceAsStream(absolutePath); InputStreamReader reader = new InputStreamReader(stream)) { + return FileHelper.read(reader); + } catch (IOException e) { + throw new FileLoadingException("Something happened while trying to close a reader to " + absolutePath, e); + } + } + + /** + * Returns an image ({@link BufferedImage}) located in resource in src/main/resources/*IMAGEPATH*. + * + * @param imagePath the path with the src/main/resources + * @return the content + * @throws FileLoadingException if the file could not be loaded + */ + public static BufferedImage loadImage(final String imagePath) throws FileLoadingException { + try (InputStream imageStream = ResourceHelper.getResourceAsStream(imagePath)) { + return readImage(imageStream); + } catch (IOException e) { + throw new FileLoadingException("Could not close an image resource properly", e); + } + } + + /** + * Reads the content of a Stream, expecting an image and generating a {@link BufferedImage}.
    + * This does NOT close the inputStream, it is the responsibility of the caller to perform the close. + * + * @param imageStream + * @return the {@link BufferedImage} + * @throws FileLoadingException if the stream could not be read as an image + */ + private static BufferedImage readImage(final InputStream imageStream) throws FileLoadingException { + try { + return ImageIO.read(imageStream); + } catch (IOException e) { + throw new FileLoadingException("Unable to read InputStream into an image", e); + } + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/framework/common/SerializationHelper.java b/kurt-utility/src/main/java/com/capgemini/framework/common/SerializationHelper.java new file mode 100644 index 0000000..a7a792d --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/framework/common/SerializationHelper.java @@ -0,0 +1,53 @@ +package com.capgemini.framework.common; + +import lombok.extern.slf4j.Slf4j; + +import java.io.*; + +/** Serialization of a BOMLineHolder tree for tests. */ +@Slf4j +public final class SerializationHelper { + + private SerializationHelper() { + // Nothing to do! + } + + /** + * Serialize an Object.
    + * + * @param object Object the object to serialize. + * @param filePath String the chosen file path, starting from the root of the project (explicitly needs src/main/resource/etc) + * + * @throws FileNotFoundException if the provided file path does not point to a readable file (or it may not exist) + * @throws IOException if the file read fails, or the serialization fails + */ + public static void serialize(final Object object, final String filePath) throws IOException { + // Opening of a Stream on a file + File file = new File(filePath); + try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file))) { + // Serialization of the object + oos.writeObject(object); + log.info("File written at: " + file.getCanonicalPath()); + } + } + + /** + * Deserialize an {@link Object}. + * + * @param filePath String the file path, starting from the root of the project (explicitly needs src/main/resource/etc) + * @return the serialized object + * + * @throws FileNotFoundException if the provided file path does not point to a readable file (or it may not exist) + * @throws IOException if the file read fails or deserialization fails + * @throws ClassNotFoundException if the class of the object is no longer found/available/compatible + */ + public static Object deserialize(final String filePath) throws IOException, ClassNotFoundException { + File file = new File(filePath); + Object obj; + try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file))) { // Opening of the flows on a file + // Deserialization of the object + obj = ois.readObject(); + return obj; + } + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/framework/common/SettingsHelper.java b/kurt-utility/src/main/java/com/capgemini/framework/common/SettingsHelper.java new file mode 100644 index 0000000..ac121d5 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/framework/common/SettingsHelper.java @@ -0,0 +1,577 @@ +package com.capgemini.framework.common; + +import com.capgemini.framework.common.security.AesEncoded; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.reports.ReportEnum; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Properties; +import java.util.TreeMap; + +/** + * Static class managing all properties from reporting.properties file. + **/ +@EqualsAndHashCode(callSuper = true) +@Slf4j +public final class SettingsHelper extends AbstractPropertiesManager { + + + /** + * Domain name (e.g. snecma.local). + */ + private static final String KEY_DOMAIN_NAME = "authent.domain"; + /** + * Prefix that should be appended at the beginning of all properties. + **/ + private static final String PROP_PREFIX = "com.capgemini.report."; + // Global modes + private static final String KEY_CLEANUP = "report.cleanup"; + private static final String KEY_DEV_MODE = "devmode"; + private static final String KEY_VAL_MODE = "valmode"; + // Memory monitor + private static final String KEY_MEM_MAX_MONITOR_TRACE_COUNT = "MngMemMonitor.maxTraceCount"; + private static final String KEY_MEM_FREQUENCY = "MngMemMonitor.frequency"; + // Email + private static final String KEY_DEFAULT_DESTINATOR_EMAIL = "common.MailHelper.defaultDestinatorMail"; + private static final String KEY_DEFAULT_MAIL_USER = "common.MailHelper.defaultExpeditorMail"; + private static final String KEY_DEFAULT_MAIL_PASS = "common.MailHelper.defaultExpeditorPassword"; + private static final String KEY_DEFAULT_SMTP_HOST = "common.MailHelper.defaultSmtpHost"; + private static final String KEY_DEFAULT_SMTP_PORT = "common.MailHelper.defaultSmtpPort"; + // File retrieval + private static final String KEY_DOWNLOAD_URL = "download.URL"; + // JSP Presentation + private static final String KEY_JSP_PAGING = "jsp.defaultPaging"; + // Purge + private static final String KEY_PURGE_DELAY_REPORTS = "nb.days"; + private static final String KEY_PURGE_DELAY_SCHEDULING = "nb.days.scheduling"; + // Launch times + private static final String KEY_PURGE_HOUR = "common.launch.purge.hour"; + private static final String KEY_DELAYED_LAUNCH_HOUR = "common.launch.delayed.hour"; + private static final String KEY_DEFAULT_LAUNCH_TYPE = "common.launch.launchType.default"; + // Scheduling save location + private static final String KEY_OUTPUT_FOLDER_REPORT = "location.default.output"; + private static final String KEY_OUTPUT_FOLDER_SCHEDULING = "location.scheduling.output"; + private static final String KEY_OUTPUT_FOLDER_SCHEDULING_HISTORY = "location.scheduling.history.output"; + // Functional values + private static final String KEY_PRODUCT_LIST = "product.list"; + private static final String KEY_DEFAULT_REVISION_RULE = "common.bom.revisionRule.default"; + private static final String KEY_PREFIX_REPORT_TITLE = "title."; + private static final String KEY_TECH_LOGIN = "authent.tech.login"; + private static final String KEY_TECH_PASSWORD = "authent.tech.password"; + /** + * Provider URL+port. Ex: "LDAP://snecmadc.snecma.local:389/". + */ + private static final String KEY_PROVIDER_URL = "authent.provider.url"; + private static final String KEY_PROVIDER_PORT = "authent.provider.port"; + /** + * Organisational unit for user OU. e.g. 'OU=TechnicalAccounts'. + */ + private static final String KEY_MAIL_ATTRIBUTE = "authent.user.attributes.email"; + private static final String KEY_LOGIN_ATTRIBUTE = "authent.user.attributes.login"; + private static final String KEY_FIRST_NAME_ATTRIBUTE = "authent.user.attributes.firstName"; + private static final String KEY_LAST_NAME_ATTRIBUTE = "authent.user.attributes.lastname"; + // ACTIVE DIRECTORY : Admin data + private static final String KEY_ADMIN_GROUP = "authent.admin.group"; + private static final String KEY_ADMIN_ORGANISATIONAL_UNIT = "authent.admin.organisationalunit"; + + private static final String KEY_OPTIMIZED_FOLDER_R23 = "optimized.folder.R23"; + private static final String KEY_OPTIMIZED_FOLDER_R24 = "optimized.folder.R24"; + /** + * Singleton instance. + **/ + private static AbstractPropertiesManager instance; + + /** + * Constructor : load the properties from the property file. + **/ + private SettingsHelper() { + super("/reporting.properties"); + } + + /** + * Returns the current dev mode status. + * + * @return true is the dev mode is active, false otherwise + */ + public static boolean isDevMode() { + return Boolean.parseBoolean(System.getProperty(KEY_DEV_MODE)); + } + + /** + * Returns the current val mode status. + * + * @return true is the val mode is active, false otherwise + */ + public static boolean isValMode() { + return Boolean.parseBoolean(System.getProperty(KEY_VAL_MODE)); + } + + /** + * Returns the current cleanup mode. If mode is unspecified, defaults to false. + * + * @return true iff the cleanup is activated + */ + public static boolean isCleanup() { + return getBooleanWithDefaultValue(KEY_CLEANUP, false); + } + + /** + * The max number of traces to keep in DB for {@link MemoryHelper}. + * + * @return an int + */ + public static int getMemoryMaxCount() { + return getInteger(KEY_MEM_MAX_MONITOR_TRACE_COUNT); + } + + /** + * The memory update frequency for {@link MemoryHelper}. + * + * @return an int + */ + public static int getMemoryFrequency() { + return getInteger(KEY_MEM_FREQUENCY); + } + + /** + * Maximum number of JSP result per page, when said page contains a table. + * + * @return number of rows + */ + public static int getJspPaging() { + return Integer.parseInt(System.getProperty(KEY_JSP_PAGING)); + } + + /** + * Returns the number of days after which usual reports are considered stale and will be deleted. + * + * @return a number of days (positive) + */ + public static int getPurgeDelayReports() { + return Integer.parseInt(System.getProperty(KEY_PURGE_DELAY_REPORTS)); + } + + /** + * Returns the number of days after which scheduled reports kept in history are considered stale and will be deleted. + * + * @return a number of days (positive) + */ + public static int getPurgeDelayScheduling() { + return Integer.parseInt(System.getProperty(KEY_PURGE_DELAY_SCHEDULING)); + } + + /** + * REturns the full title of the report. + * + * @param reportEnum the report whose title is requested + * @return the title + */ + public static String getTitle(ReportEnum reportEnum) { + return getInstance().getStringValue(KEY_PREFIX_REPORT_TITLE + reportEnum.toString()); + } + + /** + * The Default launch type (immediate). + * + * @return the folder + */ + public static String getDefaultLaunchType() { + return getInstance().getStringValue(KEY_DEFAULT_LAUNCH_TYPE); + } + + /** + * The folder location where reports are kept. + * + * @return the folder + */ + public static String getReportLocation() { + return System.getProperty(KEY_OUTPUT_FOLDER_REPORT); + } + + /** + * The folder location where the latest report of each scheduling is kept. + * + * @return the folder + */ + public static String getSchedulingLocation() { + return System.getProperty(KEY_OUTPUT_FOLDER_SCHEDULING); + } + + /** + * The folder location where scheduling history is kept. + * + * @return the folder + */ + public static String getSchedulingHistoryLocation() { + return System.getProperty(KEY_OUTPUT_FOLDER_SCHEDULING_HISTORY); + } + + /** + * The time a which the purge begins every day. format "HH:mm". + * + * @return the String time + */ + public static String getPurgeHour() { + return System.getProperty(KEY_PURGE_HOUR); + } + + // FTP CREDENTIALS FOR VALIDATION, NOT PRODUCTION + + /** + * The time a which the purge begins every day. format "HH:mm". + * + * @return the String time + */ + public static String getDelayedLaunchHour() { + return System.getProperty(KEY_DELAYED_LAUNCH_HOUR); + } + + /** + * The default email recipients when no email address is found. + * + * @return a String {@link List} + */ + public static List getDefaultDestinatorEmail() { + return getStringList(KEY_DEFAULT_DESTINATOR_EMAIL); + } + + + // ACTIVE DIRECTORY CREDENTIALS + + // ACTIVE DIRECTORY : Technical account data + + /** + * The default email recipients when no email address is found. + * + * @return a String with all recipients, com-separated + */ + public static String getDefaultDestinatorEmailFull() { + return System.getProperty(KEY_DEFAULT_DESTINATOR_EMAIL); + } + + /** + * Obtain a report's priority. + * + * @param report the report to investigate + * @return its priority : 1(high) - 3(low) + */ + public static int getPriority(ReportEnum report) { + String completeReportKey = "priority." + report.toString(); + return getInteger(completeReportKey); + } + + /** + * Reads the properties file, to obtain the list of product types.
    + * The list must be comma-separated, without spaces, like 120,238,410,700,80C,80E,850,8LM,900,970 + * + * @return the individual product types that are authorized, in a {@link List}. They are non-null, not empty. + */ + public static List getProductTypes() { + return getStringList(KEY_PRODUCT_LIST); + } + + /** + * Obtain the URL at which documents may be retrieved. The URL must still be appended with the document name. + * + * @return the root download URL. + */ + public static String getDownloadUrlRoot() { + return getString(KEY_DOWNLOAD_URL); + } + + /** + * Obtain the URL at which documents may be retrieved. The URL must still be appended with the document name. + * + * @return the root download URL. + */ + public static String getDefaultRevisionRule() { + return getInstance().getStringValue(KEY_DEFAULT_REVISION_RULE); + } + + // ACTIVE DIRECTORY : User informations + + /** + * Obtain the username of the expeditor for mails, when none is provided. + * + * @return the username. + */ + public static String getDefaultExpeditorMailUsername() { + return getString(KEY_DEFAULT_MAIL_USER); + } + + /** + * Obtain the password of the expeditor for mails, when none is provided. + * + * @return the password. + */ + public static String getDefaultExpeditorMailPassword() { + return getString(KEY_DEFAULT_MAIL_PASS); + } + + /** + * Obtain the SMTP host for emailing. + * + * @return the host. + */ + public static String getDefaultSmtpHost() { + return getString(KEY_DEFAULT_SMTP_HOST); + } + + /** + * Obtain the SMTP port for emailing. + * + * @return the port. + */ + public static String getDefaultSmtpPort() { + return getString(KEY_DEFAULT_SMTP_PORT); + } + + public static String getOptimizedFolderR23() { + return getString(KEY_OPTIMIZED_FOLDER_R23); + } + + public static String getOptimizedFolderR24() { + return getString(KEY_OPTIMIZED_FOLDER_R24); + } + + + /** + * Obtain the credentials to access the ActiveDirectory for authentication. + * + * @return the credentials + */ + public static ActiveDirectoryCredentials getActiveDirectoryCredentials() { + // Domain name. Ex: "snecma.local". + String domain = System.getProperty(KEY_DOMAIN_NAME); + String login = System.getProperty(KEY_TECH_LOGIN); + String pass; + try { + pass = new AesEncoded(System.getProperty(KEY_TECH_PASSWORD)).decode(); + } + catch (KurtException e) { + log.error("Error decoding " + KEY_TECH_PASSWORD, e); + pass = ""; + } + // Provider URL. Ex: "LDAP://snecmadc.snecma.local". + String providerURL = System.getProperty(KEY_PROVIDER_URL); + // Provider port. Ex: "389". + String providerPort = System.getProperty(KEY_PROVIDER_PORT); + return new ActiveDirectoryCredentials(domain, login, pass, providerURL, providerPort); + } + + /** + * Obtain the ActiveDirectory Attributes names to request some data. + * + * @return the attibutes names + */ + public static ActiveDirectoryAttributes getActiveDirectoryAttributes() { + String mail = System.getProperty(KEY_MAIL_ATTRIBUTE); + String login = System.getProperty(KEY_LOGIN_ATTRIBUTE); + String firstName = System.getProperty(KEY_FIRST_NAME_ATTRIBUTE); + String lastName = System.getProperty(KEY_LAST_NAME_ATTRIBUTE); + return new ActiveDirectoryAttributes(mail, login, firstName, lastName); + } + + /** + * Obtain the ActiveDirectory Attributes names to request some data. + * + * @return the attibutes names + */ + public static ActiveDirectoryAdministration getActiveDirectoryAdministration() { + String group = System.getProperty(KEY_ADMIN_GROUP); + String organisationalUnit = System.getProperty(KEY_ADMIN_ORGANISATIONAL_UNIT); + return new ActiveDirectoryAdministration(group, organisationalUnit); + } + + /** + * Returns a {@link List} of comma-separated values. The values are trimmed, and empty values are omitted. + * + * @param aKey Searched setting key + * @return a List of non-empty values + */ + private static List getStringList(String aKey) { + String rawList = System.getProperty(aKey); + if (rawList == null) { + log.warn("Could not find the property list " + aKey); + return new ArrayList<>(); + } + // Trim and split + String[] split = rawList.trim().split(","); + // Browse values + List list = new ArrayList<>(); + for (String elem : split) { + if (elem != null) { // Remove null + String trimmedElem = elem.trim(); // Trim + if (!trimmedElem.isEmpty()) { // Remove empty values + list.add(elem); + } + } + } + return list; + } + + /** + * Get Integer value from settings. + * + * @param aKey Searched setting key + * @return integer value matching with searched setting key + */ + public static int getInteger(final String aKey) { + return getInstance().getIntegerValue(aKey); + } + + /** + * Get a string value from settings. + * + * @param aKey Searched setting key + * @return String value matching with searched setting key + */ + public static String getString(final String aKey) { + return System.getProperty(aKey); + } + + /** + * Get a property from the reference parameter and set a default value if the reference is not found. + * + * @param aRef Setting key + * @param aDefaultValue Default returned value when setting is not defined + * @return string value matching with searched setting key or default value when key has not been found + */ + public static String getPropertyWithDefaultValue(final String aRef, final String aDefaultValue) { + return getInstance().getPropertyWithDefaultValueImpl(aRef, aDefaultValue); + } + + /** + * Get a boolean from the reference parameter and set a default value if the reference is not found. + * + * @param aRef Setting key + * @param aDefaultValue Default returned value when setting is not defined + * @return boolean value matching with searched setting key or default value when key has not been found + */ + private static boolean getBooleanWithDefaultValue(final String aRef, final boolean aDefaultValue) { + return getInstance().getBooleanWithDefaultValueImpl(aRef, aDefaultValue); + } + + /** + * @return the instance. + **/ + private static synchronized AbstractPropertiesManager getInstance() { + if (instance == null) { + instance = new SettingsHelper(); + } + return instance; + } + + /** + * Getter for the properties common prefixes. + * + * @return PROP_PREFIX value + **/ + @Override + protected String getPropPrefix() { + return PROP_PREFIX; + } + + /** + * Display the string content of a property file. + * + * @return String representation of sorted properties + **/ + @Override + public String toString() { + + StringBuilder thePropValues = new StringBuilder(); + + // Browse all properties for sorting them in memory + Map theSortedMap = new TreeMap<>(); + Properties propertyFile2 = getPropertyFile(); + for (Entry currentEntry : propertyFile2.entrySet()) { + theSortedMap.put(currentEntry.getKey().toString(), currentEntry.getValue().toString()); + } + + // Browse all sorted properties + for (Entry currentEntry : theSortedMap.entrySet()) { + thePropValues.append(currentEntry.getKey()).append('=').append(currentEntry.getValue()).append(StringHelper.LINE_FEED); + } + + return thePropValues.toString(); + } + + /** + * POJO holding ActiveDirectory credential data. + */ + @Getter + public static final class ActiveDirectoryCredentials { + /** + * Domain name (e.g. snecma.local). + */ + private final String domainName; + private final String techLogin; + private final String techPassword; + private final String providerURL; + private final String providerPort; + + public ActiveDirectoryCredentials(String domainName, String techLogin, String techPassword, String providerURL, String providerPort) { + this.domainName = domainName; + this.techLogin = techLogin; + this.techPassword = techPassword; + this.providerURL = providerURL; + this.providerPort = providerPort; + } + } + + /** + * POJO holding ActiveDirectory credential data. + */ + public static final class ActiveDirectoryAttributes { + private final String email; + private final String login; + private final String firstName; + private final String lastName; + + public ActiveDirectoryAttributes(String email, String login, String firstName, String lastName) { + this.email = email; + this.login = login; + this.firstName = firstName; + this.lastName = lastName; + } + + public String getEmail() { + return email; + } + + public String getLogin() { + return login; + } + + public String getFirstName() { + return firstName; + } + + public String getLastName() { + return lastName; + } + + } + + /** + * POJO holding ActiveDirectory credential data. + */ + @Getter + public static final class ActiveDirectoryAdministration { + private final String adminGroup; + private final String adminOU; + + public ActiveDirectoryAdministration(String adminGroup, String adminOU) { + this.adminGroup = adminGroup; + this.adminOU = adminOU; + } + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/framework/common/TimeHelper.java b/kurt-utility/src/main/java/com/capgemini/framework/common/TimeHelper.java new file mode 100644 index 0000000..1568eea --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/framework/common/TimeHelper.java @@ -0,0 +1,103 @@ +package com.capgemini.framework.common; + +/** + * Class for time management (conversions...). + **/ +public final class TimeHelper { + + /** + * Milliseconds count by second. + **/ + private static final long MS_TO_SEC = 1000L; + /** + * Seconds count per hour. + **/ + private static final long SEC_PER_HOUR = 3600L; + /** + * Seconds count per minute. + **/ + private static final long SEC_PER_MIN = 60L; + private static final int TWO_DIGITS = 2; + private static final int THREE_DIGITS = 3; + + private TimeHelper() { + // Nothing to do + } + + /** + * Set default unit for timeStamp. + * + * @param aDuration long value (seconds) + * @return formated duration (by hours, minutes...) + */ + public static String formatDuration(final Long aDuration) { + return formatDuration(aDuration, false); + } + + /** + * Return the current date with a timeStamp. + * + * @param aDuration long value (seconds) + * @param isMsUnit Flag setting if milliseconds should be displayed + * @return formated duration (by hours, minutes...) + */ + private static String formatDuration(final Long aDuration, final boolean isMsUnit) { + + double nbMilliseconds = 0; + StringBuilder theStringValue = new StringBuilder(); + + /* Manage null values */ + if (aDuration == null) { + return StringHelper.EMPTY; + } + + long remainingSeconds = aDuration; + + /* Only required to parse milliseconds */ + if (isMsUnit) { + nbMilliseconds = remainingSeconds % MS_TO_SEC; + remainingSeconds = remainingSeconds / MS_TO_SEC; + } + + /* Compute duration components */ + long nbHours = remainingSeconds / SEC_PER_HOUR; + remainingSeconds = remainingSeconds % SEC_PER_HOUR; + long nbMinutes = remainingSeconds / SEC_PER_MIN; + remainingSeconds = remainingSeconds % SEC_PER_MIN; + + /* Hours */ + if (nbHours > 0) { + theStringValue.append(nbHours).append('h'); + } + + /* Minutes */ + if ((nbMinutes > 0) || (nbHours > 0)) { + theStringValue.append(StringHelper.fixedDigits(nbMinutes, TWO_DIGITS)).append('m'); + } + + /* Seconds */ + if (!((remainingSeconds == 0) && isMsUnit)) { + + if (nbMinutes > 0) { + theStringValue.append(StringHelper.fixedDigits(remainingSeconds, TWO_DIGITS)); + } else { + theStringValue.append(remainingSeconds); + } + theStringValue.append('s'); + } + + /* Milliseconds */ + if (isMsUnit) { + + String theMsValue; + if (aDuration > MS_TO_SEC) { + theMsValue = StringHelper.fixedDigits(nbMilliseconds, THREE_DIGITS); + } else { + theMsValue = String.valueOf((int) nbMilliseconds); + } + theStringValue.append(theMsValue).append("ms"); + } + + return theStringValue.toString(); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/framework/common/activedirectory/ActiveDirectory.java b/kurt-utility/src/main/java/com/capgemini/framework/common/activedirectory/ActiveDirectory.java new file mode 100644 index 0000000..343a299 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/framework/common/activedirectory/ActiveDirectory.java @@ -0,0 +1,409 @@ +package com.capgemini.framework.common.activedirectory; + +import com.capgemini.framework.common.SettingsHelper; +import com.capgemini.framework.common.SettingsHelper.ActiveDirectoryAdministration; +import com.capgemini.framework.common.SettingsHelper.ActiveDirectoryAttributes; +import com.capgemini.framework.common.SettingsHelper.ActiveDirectoryCredentials; +import com.capgemini.framework.common.StringHelper; +import com.capgemini.reports.database.HibernateUtil; +import com.capgemini.reports.database.javabean.DbUser; +import com.capgemini.reports.database.javabean.DbUser.UserData; +import com.capgemini.reports.database.manager.MngUser; +import com.capgemini.reports.exceptions.InvalidActiveDirectorySearchException; +import com.capgemini.reports.exceptions.InvalidInputException; +import com.capgemini.reports.exceptions.NoConnectionToActiveDirectoryException; +import lombok.extern.slf4j.Slf4j; +import org.hibernate.Session; +import org.hibernate.SessionFactory; + +import javax.naming.Context; +import javax.naming.NamingEnumeration; +import javax.naming.NamingException; +import javax.naming.PartialResultException; +import javax.naming.directory.Attribute; +import javax.naming.directory.Attributes; +import javax.naming.directory.DirContext; +import javax.naming.directory.InitialDirContext; +import javax.naming.directory.SearchControls; +import javax.naming.directory.SearchResult; +import java.io.Closeable; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; + +/** + * Query Active Directory for user data. + */ +@Slf4j +public class ActiveDirectory implements Closeable { + + /** + * The default login for non-authenticated users. + */ + public static final String GUEST_LOGIN = "Invité(e)"; + // Attribute names + static final ActiveDirectoryAttributes ATTRIBUTES = SettingsHelper.getActiveDirectoryAttributes(); + // Admin data + static final ActiveDirectoryAdministration ADMINISTRATION = SettingsHelper.getActiveDirectoryAdministration(); + private static final int SEARCH_TIMEOUT = 30000; // 30s + private static final String AD_SEPARATOR = ": "; + // Technical account data + private static final ActiveDirectoryCredentials CREDENTIALS = SettingsHelper.getActiveDirectoryCredentials(); + /** + * Domain Controller. Ex: "DC=SNECMA,DC=LOCAL". + */ + static final String DOMAIN_CONTROLLER = getDomainBase(CREDENTIALS.getDomainName()); + private static final String MEMBER_OF_ATTRIBUTE = "memberOf"; // Default value for this attribute in LDAP + private static final String[] REQUESTED_ATTRIBUTES = + {ATTRIBUTES.getLogin(), ATTRIBUTES.getEmail(), ATTRIBUTES.getFirstName(), ATTRIBUTES.getLastName(), MEMBER_OF_ATTRIBUTE}; + // Guest + private static final String DEFAULT_DESTINATOR_EMAIL = SettingsHelper.getDefaultDestinatorEmailFull(); + private static final UserData GUEST = new UserData(GUEST_LOGIN, DEFAULT_DESTINATOR_EMAIL, "Not", "Found", false); + // required private variables + private final DirContext dirContext; + + /* + * Working request exemple: + * + * ========= REQUEST ========== + * Base DN : DC=SNECMA,DC=LOCAL + * Filter : (&(objectClass=user)(cn=snecmauser)) + * Scope : Subtree + * Attributes: cn;mail; + * ========= RESPONSE ========= + * Result: + * Searching... + * ldap_search_s(ld, "DC=SNECMA,DC=LOCAL", 2, "(&(objectClass=user)(cn=snecmauser))", attrList, 0, &msg) + * Getting 1 entries: + * Dn: CN=SnecmaUser,OU=Snecma,OU=Utilisateurs,DC=snecma,DC=local + * cn: SnecmaUser; + * mail: SnecmaUser@snecma.local; + */ + + /** + * Constructor with parameter for initializing a LDAP context. + */ + protected ActiveDirectory() throws NoConnectionToActiveDirectoryException { + Properties properties = new Properties(); + + // Provider URL+port. Ex: "LDAP://snecmadc.snecma.local:389/" + String providerUrlBase = CREDENTIALS.getProviderURL() + ":" + CREDENTIALS.getProviderPort() + "/"; + String providerURL = providerUrlBase + DOMAIN_CONTROLLER; + // Precise security login. Ex: "sa-bind@snecma.local" + String securityPrincipal = CREDENTIALS.getTechLogin() + "@" + CREDENTIALS.getDomainName(); + + properties.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); + properties.put(Context.PROVIDER_URL, providerURL); + properties.put(Context.SECURITY_AUTHENTICATION, "simple"); + properties.put(Context.SECURITY_PRINCIPAL, securityPrincipal); + properties.put(Context.SECURITY_CREDENTIALS, CREDENTIALS.getTechPassword()); + properties.put("sun.security.krb5.debug", SettingsHelper.getPropertyWithDefaultValue("devmode", "false")); + properties.put("java.naming.ldap.derefAliases", "never"); + properties.put("java.naming.ldap.version", "3"); + + // Initializing active directory LDAP connection + try { + dirContext = new InitialDirContext(properties); + } + catch (NamingException e) { + throw new NoConnectionToActiveDirectoryException("Could not connect the app to the Active Directory", e); + } + } + + /** + * Returns the GUEST user, to be used when authentication failed, for any reason. + * + * @return the GUEST user. + */ + public static UserData getGuestUser() { + return GUEST; + } + + /** + * Returns the user's email address. + * + * @param userLogin the user login + * @return the user data. Never null, would (throw an exception first but may contain null fields + * @throws NoConnectionToActiveDirectoryException thrown if no connection could be found (appli might not be in same doain as AD?) + * @throws InvalidActiveDirectorySearchException thrown if search was rejected by AD (check syntax?) + * @throws InvalidInputException thrown if provided username was null: no data may be retrieved then + */ + public static UserData obtainUserData(final String userLogin) + throws NoConnectionToActiveDirectoryException, InvalidActiveDirectorySearchException, InvalidInputException { + if (userLogin == null) { + throw new InvalidInputException("Null login received from request header. Cannot identify the user."); + } + + // Connect to the AD + try (ActiveDirectory activeDirectory = new ActiveDirectory()) { + + // Search the user + SearchFilter searchLogin = SearchFilter.searchLogin(userLogin); + + // Obtain user data + UserData userData; + Attributes attrs = activeDirectory.getUserAttributes(searchLogin); + if (attrs == null) { + log.info("Obtained no results from ActiveDirectory search for login '{}', defaulting to GUEST", userLogin); + userData = GUEST; + } + else { + // Retrieve AD login, because teamcenter uses lower case, but in AD its Capitalization may vary! + String loginAD = getAttribute(attrs, ATTRIBUTES.getLogin()); + String firstName = getAttribute(attrs, ATTRIBUTES.getFirstName()); + String lastName = getAttribute(attrs, ATTRIBUTES.getLastName()); + String userEmail = getAttribute(attrs, ATTRIBUTES.getEmail()); + + // If the user was found, keep searching for its potential admin status + boolean adminStatus = isAdmin(activeDirectory, searchLogin); + + userData = new UserData(loginAD, userEmail, firstName, lastName, adminStatus); // Use only AD-provided data + log.info("Identified user: {}={}, {}={}, {}={}", ATTRIBUTES.getLogin(), userLogin, ATTRIBUTES.getFirstName(), firstName, + ATTRIBUTES.getLastName(), lastName, ATTRIBUTES.getEmail(), userEmail); + } + return userData; + } + } + + /** + * Connect to Active Directory and return a list of Admins Report. + * + * @return List DbUser + * @throws NoConnectionToActiveDirectoryException if unable to connect to the AD + * @throws InvalidActiveDirectorySearchException if the search for the admin group is ill-formed + * @throws NamingException if the name of the admin group is invalid + */ + private static List obtainAdminReport() + throws NoConnectionToActiveDirectoryException, InvalidActiveDirectorySearchException, NamingException { + List adminDbUserList = new ArrayList<>(); + + // Connect to the AD + try (ActiveDirectory activeDirectory = new ActiveDirectory()) { + + // Filter Search in Group Administrator + NamingEnumeration searchEnum = activeDirectory.search(SearchFilter.searchInGroup(ADMINISTRATION.getAdminGroup())); + + while (searchEnum.hasMoreElements()) { + Attributes attrs = searchEnum.next().getAttributes(); + + if (attrs == null) { + log.info("Obtained no results from ActiveDirectory search for users of ou='{}' ou='{}' ", ADMINISTRATION.getAdminOU(), + ADMINISTRATION.getAdminGroup()); + } + else { + String login = getAttribute(attrs, ATTRIBUTES.getLogin()); + String firstName = getAttribute(attrs, ATTRIBUTES.getFirstName()); + String lastName = getAttribute(attrs, ATTRIBUTES.getLastName()); + String email = getAttribute(attrs, ATTRIBUTES.getEmail()); + UserData admin = new UserData(login, email, firstName, lastName, true); // these are all admins of course + + // add to list admin report + adminDbUserList.add(admin); + } + } + } + return adminDbUserList; + } + + private static boolean isAdmin(final ActiveDirectory activeDirectory, final SearchFilter searchLogin) + throws InvalidActiveDirectorySearchException { + SearchFilter searchInAdminGroup = SearchFilter.searchInGroup(ADMINISTRATION.getAdminGroup()); + NamingEnumeration adminResult = activeDirectory.search(searchLogin, searchInAdminGroup); + return adminResult.hasMoreElements(); + } + + private static String getAttribute(final Attributes attrs, final String attribute) { + if (!isValidAttribute(attribute)) { + log.warn("Attribute '{}' is asked from the Active Directory search results, but is not part of the attributes list", attribute); + } + Attribute keyValue = attrs.get(attribute); + if (keyValue == null) { + return StringHelper.EMPTY; + } + else { + String userEmailResponse = keyValue.toString(); + String email; + if (userEmailResponse.contains(AD_SEPARATOR)) { + // expecting 'KEY: VALUE' pair from AD (note the double double dots, AND the whitespace) + email = userEmailResponse.substring(userEmailResponse.indexOf(AD_SEPARATOR) + AD_SEPARATOR.length()); + } + else { + email = StringHelper.EMPTY; + } + return email; + } + } + + private static boolean isValidAttribute(final String attribute) { + for (String requestedAttribute : REQUESTED_ATTRIBUTES) { + if (requestedAttribute.equals(attribute)) { + return true; + } + } + return false; + } + + /** + * Creating a domain base value (e.g. DC=SNECMA,DC=LOCAL) from domain controller name (e.g. snecma.local) + * + * @param domain a {@link String} object - name of the domain controller + * @return a {@link String} object - base name for eg. DC=SNECMA,DC=LOCAL + */ + private static String getDomainBase(final String domain) { + return makeBase(domain, "DC"); + } + + /** + * Creating a Organisational Unit base value.
    + * ex: + *

      + *
    • 'TechnicalAccounts' becomes 'OU=TECHNICALACCOUNTS'
    • + *
    • 'snecma.utilisateurs' becomes 'OU=Snecma,OU=Utilisateurs'
    • + *
    + * + * @param organisationalUnit a {@link String} object - name of the domain controller + * @return a {@link String} object - base name for eg. DC=SNECMA,DC=LOCAL + */ + static String getOrganisationalUnitBase(final String organisationalUnit) { + return makeBase(organisationalUnit, "OU"); + } + + private static String makeBase(final String original, final String key) { + String separator = ',' + key + '='; + StringBuilder result = new StringBuilder(key).append('='); + String upper = original.toUpperCase(); + result.append(upper.replace(".", separator)); + return result.toString(); + } + + /** + * Return list contains object {@link DbUser} which are administrators report, quiet fail.
    + * If unable to connect to active directory, or unable to obtain a user from ActiveDirectory, returns the default user (Guest). + * + * @return a {@link List} of admins {@link DbUser}s + */ + public static List getAdminsReportUpdateDatabase() { + SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); + Session session = sessionFactory.openSession(); + try { + try { + List adAdmins = ActiveDirectory.obtainAdminReport(); + List dbAdmins = new MngUser().fetchOrUpdateOrCreateUsers(session, adAdmins); + if (!dbAdmins.isEmpty()) { + return dbAdmins; + } + else { + log.warn("No administrators retrieved from AD! inserting default user (guest)"); + } + } + catch (NoConnectionToActiveDirectoryException e) { + log.warn("Could not connect to the AD to findAll the list of Administrators ", e); + } + catch (NamingException e) { + log.warn("AD Could not locate the Administrators group in the AD", e); + } + catch (InvalidActiveDirectorySearchException e) { + log.warn("Could not perform a search on the AD, to findAll the list of Administrators", e); + } + // Use default user (something happened) + ArrayList defaultUsers = new ArrayList<>(); + defaultUsers.add(new MngUser().fetchOrUpdateOrCreateUser(session, ActiveDirectory.getGuestUser())); + return defaultUsers; + } + finally { + session.close(); + } + } + + private Attributes getUserAttributes(final SearchFilter searchLogin) throws InvalidActiveDirectorySearchException { + NamingEnumeration result = search(searchLogin); + if (result == null) { + log.debug("Filter '{}' provided null results from the Active Directory, defaulting to GUEST", searchLogin.makeFilterComponent()); + return null; + } + // Parse the results + try { + if (result.hasMoreElements()) { + SearchResult searchResult = result.next(); + return searchResult.getAttributes(); + } + else { + log.info("Filter '{}' provided no result from the Active Directory, defaulting to GUEST", searchLogin.makeFilterComponent()); + return null; + } + } + catch (PartialResultException pre) { + // If a result exists, it is correctly handled in the 'try' above. if the user was not found, we will end up here upon calling hasMore() + String errorMsg = "PartialResultException caught while obtaining data from the Active Directory"; + throw new InvalidActiveDirectorySearchException(errorMsg, pre); + } + catch (NamingException e) { + String errorMsg = "Could not obtain further results from the Active Directory search results"; + throw new InvalidActiveDirectorySearchException(errorMsg, e); + } + } + + /** + * Search the Active directory by username/email id for given search base. + * + * @param searchValues one or more {@link SearchFilter}s - to search things like login, group membership etc. + * @return search result a {@link javax.naming.NamingEnumeration} object - active directory search result + * @throws InvalidActiveDirectorySearchException if the search is ill-formed + */ + + public NamingEnumeration search(final SearchFilter... searchValues) throws InvalidActiveDirectorySearchException { + String filter = getFilter(searchValues); + log.trace("Trying to perform a search with filter: " + filter); + // Initializing search controls + SearchControls searchCtls = new SearchControls(); + searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE); + searchCtls.setReturningAttributes(REQUESTED_ATTRIBUTES); + searchCtls.setTimeLimit(SEARCH_TIMEOUT); + + if (this.dirContext == null) { + log.warn("Trying to perform an ActiveDirectory search, but DirContext is null"); + return null; + } + else { + try { + log.info("Performing search Using filter: " + filter); + return this.dirContext.search("", filter, searchCtls); + } + catch (NamingException e) { + throw new InvalidActiveDirectorySearchException("Could not perform a login search in the Active Directory", e); + } + } + } + + /** + * Closes the LDAP connection with Domain controller. + */ + @Override + public void close() { + if (dirContext != null) { + try { + dirContext.close(); + } + catch (NamingException e) { + log.warn("Could not close LDAP connection properly", e); + } + } + } + + /** + * Active directory filter. + * + * @param searchBy a series of {@link SearchFilter} object - scope of search by username or email id + * @return a {@link String} object - filter string + */ + private String getFilter(final SearchFilter... searchBy) { + // Open filter: search for a user + StringBuilder filter = new StringBuilder("(&(objectClass=User)"); // <-- verifier avec SNECMA + for (SearchFilter criteria : searchBy) { + filter.append(criteria.makeFilterComponent()); + } + // End filter + filter.append(')'); + return filter.toString(); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/framework/common/activedirectory/SearchCriteria.java b/kurt-utility/src/main/java/com/capgemini/framework/common/activedirectory/SearchCriteria.java new file mode 100644 index 0000000..01db836 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/framework/common/activedirectory/SearchCriteria.java @@ -0,0 +1,6 @@ +package com.capgemini.framework.common.activedirectory; + +enum SearchCriteria { + LOGIN, + GROUP +} diff --git a/kurt-utility/src/main/java/com/capgemini/framework/common/activedirectory/SearchFilter.java b/kurt-utility/src/main/java/com/capgemini/framework/common/activedirectory/SearchFilter.java new file mode 100644 index 0000000..484ef98 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/framework/common/activedirectory/SearchFilter.java @@ -0,0 +1,58 @@ +package com.capgemini.framework.common.activedirectory; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; + +/** + * Helper class to generate filters for Active Directory, e.g. looking for a specific username, etc. + */ +@AllArgsConstructor(access = AccessLevel.PRIVATE) +class SearchFilter { + + private final String value; + private final SearchCriteria criteria; + + /** + * Restricts the Search to a user login. + * + * @param login the user's login + * @return a search filter + */ + public static SearchFilter searchLogin(final String login) { + return new SearchFilter(login, SearchCriteria.LOGIN); + } + + /** + * Restricts the search to a specific Group (such as admin group). + * + * @param group the name of the group + * @return a search filter + */ + public static SearchFilter searchInGroup(final String group) { + return new SearchFilter(group, SearchCriteria.GROUP); + } + + /** + * Makes a filter component. Various filter components may be chained inside parentheses to construct a powerful filter.
    + * For example, a filter component for filtering logins might look like:
    + * (cn=THE_LOGIN) + * + * @return the filter component + */ + public String makeFilterComponent() { + String filterComp; + switch (criteria) { + case LOGIN: + filterComp = "(" + ActiveDirectory.ATTRIBUTES.getLogin() + "=" + value + ")"; + break; + case GROUP: + String orgUnitFilter = ActiveDirectory.getOrganisationalUnitBase(ActiveDirectory.ADMINISTRATION.getAdminOU()); + filterComp = "(memberOf=CN=" + value + "," + orgUnitFilter + "," + ActiveDirectory.DOMAIN_CONTROLLER + ")"; + break; + default: + filterComp = ""; + break; + } + return filterComp; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/JasperTemplate.java b/kurt-utility/src/main/java/com/capgemini/reports/JasperTemplate.java new file mode 100644 index 0000000..f8d57fc --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/JasperTemplate.java @@ -0,0 +1,68 @@ +package com.capgemini.reports; + +import lombok.Getter; + +/** Enumeration of the different Jasper's templates. */ +@Getter +public enum JasperTemplate { + + // Some useful file locations + /** The template of the R01 report. */ + TEMPLATE_R01("/Jasper/template/report_r01.jrxml"), + /** The template of the R03 report. */ + TEMPLATE_R03("/Jasper/template/report_r03.jrxml"), + /** The template of the R10 report. */ + TEMPLATE_R10("/Jasper/template/report_r10.jrxml"), + /** The template of the R11 report. */ + TEMPLATE_R11("/Jasper/template/report_r11.jrxml"), + /** The template of the R13 report for a CR object. */ + TEMPLATE_R13_CR("/Jasper/template/report_r13/report_r13_cr.jrxml"), + /** The template of the R13 report fro a FPP object. */ + TEMPLATE_R13_FPP("/Jasper/template/report_r13/report_r13_fpp.jrxml"), + /** The template of the R15 and R16 reports. */ + TEMPLATE_R15R16("/Jasper/template/report_r15r16.jrxml"), + /** The template of the R17 report. */ + TEMPLATE_R17("/Jasper/template/report_r17.jrxml"), + /** The template of the R19 report. */ + TEMPLATE_R19("/Jasper/template/report_r19.jrxml"), + // Template R20 resource files + /** The template of the R20 report, page 1. */ + TEMPLATE_R20_PAGE1("/Jasper/template/report_r20/report_r20_p1.jrxml"), + /** The template of the R20 report, page 2 master. */ + TEMPLATE_R20_PAGE2("/Jasper/template/report_r20/report_r20_p2.jrxml"), + /** The template of the R20 report, page 4. */ + TEMPLATE_R20_PAGE4("/Jasper/template/report_r20/report_r20_p4.jrxml"), + /** The template of the R20 report, page 2 part 1. */ + TEMPLATE_R20_PAGE2_GENERIC("/Jasper/template/report_r20/page2/r20_p2_generics.jrxml"), + /** The template of the R20 report, page 2 part 2. */ + TEMPLATE_R20_PAGE2_IMPACTS("/Jasper/template/report_r20/page2/r20_p2_impacts.jrxml"), + /** The template of the R20 report, page 2 part 3. */ + TEMPLATE_R20_PAGE2_NOIMPACTS("/Jasper/template/report_r20/page2/r20_p2_noimpacts.jrxml"), + /** The Master template of the R20 report. */ + TEMPLATE_R20_MASTER("/Jasper/template/report_r20/report_r20_master.jrxml"), + /** The template of the R21 report. */ + TEMPLATE_R21("/Jasper/template/report_r21.jrxml"), + /** The template of the R22 report. */ + TEMPLATE_R22("/Jasper/template/report_r22.jrxml"), + /** The template of the R23 report. */ + TEMPLATE_R23("/Jasper/template/report_r23.jrxml"), + /** The template of the R24 report. */ + TEMPLATE_R24("/Jasper/template/report_r24.jrxml"), + /** The template of the R25 report. */ + TEMPLATE_R25("/Jasper/template/report_r25.jrxml"), + /** The Master template of the R26 report. */ + TEMPLATE_R26_MASTER("/Jasper/template/report_r26/report_r26_master.jrxml"), + /** The sub report template of the R26 report. */ + TEMPLATE_R26_SUBREPORT("/Jasper/template/report_r26/report_r26_subreport.jrxml"), + /** The template of the R27 report. */ + TEMPLATE_R27("/Jasper/template/report_r27.jrxml"), + /** The template of the R28 report. */ + TEMPLATE_R28("/Jasper/template/report_r28.jrxml"); + + + private final String filepath; + + JasperTemplate(final String filepath) { + this.filepath = filepath; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/ReportEnum.java b/kurt-utility/src/main/java/com/capgemini/reports/ReportEnum.java new file mode 100644 index 0000000..90f6381 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/ReportEnum.java @@ -0,0 +1,106 @@ +package com.capgemini.reports; + +import com.capgemini.framework.common.SettingsHelper; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.ArrayList; +import java.util.List; + +/** + * Lists all existing reports, using the format REPORT_Rxy. + */ +@AllArgsConstructor +@Getter +public enum ReportEnum { + REPORT_R01(null), + REPORT_R03(null), + REPORT_R05(null), + REPORT_R06(null), + REPORT_R07(null), + REPORT_R10(null), + REPORT_R11(null), + REPORT_R13(null), + REPORT_R15(null), + REPORT_W15("autoR15real"), + REPORT_R16(null), + REPORT_R17(null), + REPORT_R19(null), + REPORT_R20(null), + REPORT_R21(null), + REPORT_R22(null), + REPORT_W22("autoR22"), + REPORT_R23(null), + REPORT_R24(null), + REPORT_R25(null), + REPORT_R26(null), + REPORT_R27(null), + REPORT_R28(null); + + private final String urlForAutomaticGeneration; + + /** + * Returns the corresponding report Code (i.e. 'RB1', or 'R07'). + * + * @return the report code + */ + public String getReportCode() { + return toString().replace("REPORT_", ""); + } + + /** + * Returns the report short name, in french.
    + * Exemple with the R01: 'Rapport R01'. + * + * @return the report code + */ + public StringBuilder getReportName() { + String reportCode = getReportCode(); + return new StringBuilder("Rapport ").append(reportCode.toUpperCase()); + } + + /** + * Returns the official report title.
    + * Exemple for R01: 'BOM assemblage PU'.
    + * Title is extracted from the reporting.properties file. + * + * @return the report title + */ + public String getReportTitle() { + return SettingsHelper.getTitle(this); + } + + /** + * Returns the full report identifier and title.
    + * Exemple for R01: 'Rapport R01 "BOM assemblage PU"' + * + * @return the report identifier + */ + public StringBuilder buildCompleteReportName() { + return getReportName().append(" \"").append(getReportTitle()).append('"'); + } + + /** + * Returns the {@link ReportEnum} of this report, if you provide its report Code. + * + * @param reportCode the report code, like 'R01' or 'RB1' + * @return the matching {@link ReportEnum} + */ + public static ReportEnum fromCode(final String reportCode) { + return valueOf("REPORT_" + reportCode.toUpperCase()); + } + + /** + * Returns the official list of report code.
    + * Exemple : Rxx + * + * @return list + */ + public static List getListReportCode() { + List allReportCode = new ArrayList<>(); + for (ReportEnum value : ReportEnum.values()) { + allReportCode.add(value.getReportCode()); + } + return allReportCode; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/ReportLaunchTypeEnum.java b/kurt-utility/src/main/java/com/capgemini/reports/ReportLaunchTypeEnum.java new file mode 100644 index 0000000..d3f96c0 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/ReportLaunchTypeEnum.java @@ -0,0 +1,57 @@ +package com.capgemini.reports; + +import com.capgemini.framework.common.SettingsHelper; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; + +/** Enumeration of the different launch type of a report. */ +@Slf4j +@Getter +@AllArgsConstructor(access = AccessLevel.PRIVATE) +public enum ReportLaunchTypeEnum { + + /** The immediate launch type. */ + IMMEDIATE("immediate", "none"), + /** The delayed launch type. */ + DELAYED("delayed", "delayed"), + /** The scheduled launch type. */ + SCHEDULED("scheduled", "scheduled"), + /** The scheduled launch type. */ + AUTOMATIC("automatic", "immediate"); + + private final String launchType; + private final String groupName; + + private static final String DEFAULT_LAUNCH_TYPE = SettingsHelper.getDefaultLaunchType(); + + /** + * Give the appropriate {@link ReportLaunchTypeEnum} associate to the string value.
    + * Else return null. + * + * @param personnalizeValueIfExist String - the string value + * @return the appropriate {@link ReportLaunchTypeEnum}. Return null if the string value doesn't exist. + */ + public static ReportLaunchTypeEnum getReportLaunchType(final String personnalizeValueIfExist) { + // Determine the string value of the type + String realValue = SettingsHelper.getPropertyWithDefaultValue(personnalizeValueIfExist, DEFAULT_LAUNCH_TYPE); + + // Determine the enumeration value + ReportLaunchTypeEnum launchType; + if ("immediate".equals(realValue)) { + launchType = ReportLaunchTypeEnum.IMMEDIATE; + } else if ("delayed".equals(realValue)) { + launchType = ReportLaunchTypeEnum.DELAYED; + } else if ("scheduled".equals(realValue)) { + launchType = ReportLaunchTypeEnum.SCHEDULED; + } else if ("automatic".equals(realValue)) { + launchType = ReportLaunchTypeEnum.AUTOMATIC; + } else { + log.error("No status found. The string {} is not valid.", realValue); + launchType = null; + } + return launchType; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/builder/AbstractR13Builder.java b/kurt-utility/src/main/java/com/capgemini/reports/builder/AbstractR13Builder.java new file mode 100644 index 0000000..324d0f7 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/builder/AbstractR13Builder.java @@ -0,0 +1,40 @@ +package com.capgemini.reports.builder; + +import com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum; +import com.capgemini.reports.definition.r13report.execution.AbstractExecutionR13; +import com.capgemini.reports.exceptions.InsufficientParametersException; +import com.capgemini.reports.reports.parameters.EffectivityDate; + +import java.util.Map; + +/** + * Reconstructs a R13 (CR) report from two delimiter dates. + * + * @param the sub-type of R13 report (CR/FPP) + */ +public abstract class AbstractR13Builder> implements ReportBuilder { + + @Override + public T build(Map data) throws InsufficientParametersException { + // Get the request raw data + String dateDebutStr = data.get(ReportCriteriaEnum.DATE_DEBUT); + String dateFinStr = data.get(ReportCriteriaEnum.DATE_FIN); + + // no mandatory args + EffectivityDate dateDebut = dateDebutStr == null ? null : new EffectivityDate(dateDebutStr); // defautlt is null + EffectivityDate dateFin = dateFinStr == null ? new EffectivityDate() : new EffectivityDate(dateFinStr); // default is no args Ctor + + // Build the report + return this.make(dateDebut, dateFin); + } + + /** + * Create an Execution instance of the right type, using the verified parameters as-is. + * + * @param dateDebut a beginning date (checked) + * @param dateFinStr an end date (checked) + * @return the Execution. + */ + protected abstract T make(EffectivityDate dateDebut, EffectivityDate dateFinStr); + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/builder/AbstractR15R16R17Builder.java b/kurt-utility/src/main/java/com/capgemini/reports/builder/AbstractR15R16R17Builder.java new file mode 100644 index 0000000..b3f3a44 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/builder/AbstractR15R16R17Builder.java @@ -0,0 +1,34 @@ +package com.capgemini.reports.builder; + +import com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum; +import com.capgemini.reports.definition.r15r16r17reports.AbstractExecutionR15R16R17; +import com.capgemini.reports.exceptions.InsufficientParametersException; +import com.google.common.base.Joiner; + +import java.util.Map; + +/** + * Mother class for R15/16/17 Report Builders. Language parameters is safely extracted here. + * + * @param the real report type (R15/16/17) + */ +public abstract class AbstractR15R16R17Builder> implements ReportBuilder { + + @Override + public T build(Map data) throws InsufficientParametersException { + // Get the request raw data + String language = data.get(ReportCriteriaEnum.LANGUAGE); + + // Check presence of all required args + if (language == null) { + String dataStr = Joiner.on('|').withKeyValueSeparator("=").useForNull("null").join(data); + throw new InsufficientParametersException("Missing parameter for R15/16/17 launch. Obtained: " + dataStr); + } + + // Build the report + return make(data, language); + } + + protected abstract T make(Map data, String language) throws InsufficientParametersException; + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/builder/AbstractR15R17Builder.java b/kurt-utility/src/main/java/com/capgemini/reports/builder/AbstractR15R17Builder.java new file mode 100644 index 0000000..d461ec9 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/builder/AbstractR15R17Builder.java @@ -0,0 +1,35 @@ +package com.capgemini.reports.builder; + +import com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum; +import com.capgemini.reports.definition.r15r16r17reports.r15r17reports.AbstractExecutionR15R17; +import com.capgemini.reports.exceptions.InsufficientParametersException; +import com.google.common.base.Joiner; + +import java.util.Map; + +/** + * Mother class for R15/17 Report Builders. Part id & revision are safely extracted here. + * + * @param the real report type (R15/17) + */ +public abstract class AbstractR15R17Builder> extends AbstractR15R16R17Builder { + + @Override + protected T make(Map data, String language) throws InsufficientParametersException { + // Get the request raw data + String partId = data.get(ReportCriteriaEnum.PART_ID); + String partRevision = data.get(ReportCriteriaEnum.PART_REVISION); + + // Check presence of all required args + if (partId == null || partRevision == null) { + String dataStr = Joiner.on('|').withKeyValueSeparator("=").useForNull("null").join(data); + throw new InsufficientParametersException("Missing parameter for R15/R17 launch. Obtained: " + dataStr); + } + + // Build the report + return make(language, partId, partRevision); + } + + protected abstract T make(String language, String partId, String partRevision); + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/builder/R01Builder.java b/kurt-utility/src/main/java/com/capgemini/reports/builder/R01Builder.java new file mode 100644 index 0000000..eba8c87 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/builder/R01Builder.java @@ -0,0 +1,50 @@ +package com.capgemini.reports.builder; + +import com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum; +import com.capgemini.reports.definition.r01report.ExecutionR01; +import com.capgemini.reports.exceptions.InsufficientParametersException; +import com.capgemini.reports.reports.parameters.EffectivityDate; +import com.capgemini.reports.reports.parameters.Generics; +import com.capgemini.reports.reports.parameters.MonoMulti; +import com.capgemini.reports.reports.parameters.ProductUnit; +import com.google.common.base.Joiner; + +import java.util.Map; + +/** Reconstructs a R01 report from BOM parameters. Generic parameters are optional. */ +public class R01Builder implements ReportBuilder { + + @Override + public ExecutionR01 build(Map data) throws InsufficientParametersException { + // Get the request raw data + String product = data.get(ReportCriteriaEnum.PRODUCT); + String unitStr = data.get(ReportCriteriaEnum.UNIT); + String monoMultiStr = data.get(ReportCriteriaEnum.MONO_MULTI); + String generic = data.get(ReportCriteriaEnum.GENERIC); + String genericAssemb = data.get(ReportCriteriaEnum.GENERIC_ASSEMB); + String effectivityStr = data.get(ReportCriteriaEnum.EFFECTIVITY_DATE); + String superModelStr = data.get(ReportCriteriaEnum.SUPERMODEL); + + + // Check presence of all required args + if (product == null || unitStr == null || monoMultiStr == null) { + String dataStr = Joiner.on('|').withKeyValueSeparator("=").useForNull("null").join(data); + throw new InsufficientParametersException("Missing parameter for R01 launch. Obtained: " + dataStr); + } + int unit; + try { + unit = Integer.parseInt(unitStr); + } catch (NumberFormatException e) { + throw new InsufficientParametersException("Unit parameter is not an int: " + unitStr, e); + } + ProductUnit aProductUnit = new ProductUnit(product, unit); + Generics aGeneric = new Generics(aProductUnit, generic, genericAssemb); + MonoMulti aMonoMulti = MonoMulti.build(monoMultiStr); + EffectivityDate anEffectivity = new EffectivityDate(effectivityStr); + boolean isSuperModelBOM = Boolean.parseBoolean(superModelStr); + + // Build the report + return new ExecutionR01(aProductUnit, aGeneric, aMonoMulti, anEffectivity, isSuperModelBOM); + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/builder/R03Builder.java b/kurt-utility/src/main/java/com/capgemini/reports/builder/R03Builder.java new file mode 100644 index 0000000..f100c2a --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/builder/R03Builder.java @@ -0,0 +1,29 @@ +package com.capgemini.reports.builder; + +import com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum; +import com.capgemini.reports.definition.r03report.ExecutionR03; +import com.capgemini.reports.exceptions.InsufficientParametersException; +import com.google.common.base.Joiner; + +import java.util.Map; + +/** Reconstructs a R03 report from Part Id and rev. */ +public class R03Builder implements ReportBuilder { + + @Override + public ExecutionR03 build(Map data) throws InsufficientParametersException { + // Get the request raw data + String partId = data.get(ReportCriteriaEnum.PART_ID); + String partRev = data.get(ReportCriteriaEnum.PART_REVISION); + + // Check presence of all required args + if (partId == null || partRev == null) { + String dataStr = Joiner.on('|').withKeyValueSeparator("=").useForNull("null").join(data); + throw new InsufficientParametersException("Missing parameter for R03 launch. Obtained: " + dataStr); + } + + // Build the report + return new ExecutionR03(partId, partRev); + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/builder/R07Builder.java b/kurt-utility/src/main/java/com/capgemini/reports/builder/R07Builder.java new file mode 100644 index 0000000..4b8cc1a --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/builder/R07Builder.java @@ -0,0 +1,50 @@ +package com.capgemini.reports.builder; + +import com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum; +import com.capgemini.reports.definition.r07report.ExecutionR07; +import com.capgemini.reports.exceptions.InsufficientParametersException; +import com.capgemini.reports.reports.parameters.Generics; +import com.capgemini.reports.reports.parameters.ProductUnit; +import com.google.common.base.Joiner; + +import java.util.Map; + +/** Reconstructs a R01 report from two BOM configuration parameters. Generic parameters are optional. */ +public class R07Builder implements ReportBuilder { + + @Override + public ExecutionR07 build(Map data) throws InsufficientParametersException { + // Get the request raw data + String product = data.get(ReportCriteriaEnum.PRODUCT); + String unitStr1 = data.get(ReportCriteriaEnum.UNIT_CONFIGURATION_1); + String unitStr2 = data.get(ReportCriteriaEnum.UNIT_CONFIGURATION_2); + String generic = data.get(ReportCriteriaEnum.GENERIC); + String genericAssemb = data.get(ReportCriteriaEnum.GENERIC_ASSEMB); + + // Check presence of all required args + if (product == null || unitStr1 == null || unitStr2 == null) { + String dataStr = Joiner.on('|').withKeyValueSeparator("=").useForNull("null").join(data); + throw new InsufficientParametersException("Missing parameter for R07 launch. Obtained: " + dataStr); + } + int unit1; + try { + unit1 = Integer.parseInt(unitStr1); + } catch (NumberFormatException e) { + throw new InsufficientParametersException("Unit parameter 1 is not an int: " + unitStr1, e); + } + int unit2; + try { + unit2 = Integer.parseInt(unitStr2); + } catch (NumberFormatException e) { + throw new InsufficientParametersException("Unit parameter 2 is not an int: " + unitStr2, e); + } + ProductUnit aProductUnit1 = new ProductUnit(product, unit1); + ProductUnit aProductUnit2 = new ProductUnit(product, unit2); + Generics gen1 = new Generics(aProductUnit1, generic, genericAssemb); // only difference should be unit # + Generics gen2 = new Generics(aProductUnit2, generic, genericAssemb); // Generics are optional + + // Build the report + return new ExecutionR07(gen1, gen2); + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/builder/R10Builder.java b/kurt-utility/src/main/java/com/capgemini/reports/builder/R10Builder.java new file mode 100644 index 0000000..c9c2953 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/builder/R10Builder.java @@ -0,0 +1,47 @@ +package com.capgemini.reports.builder; + +import com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum; +import com.capgemini.reports.definition.r10report.ExecutionR10; +import com.capgemini.reports.exceptions.InsufficientParametersException; +import com.capgemini.reports.reports.parameters.EffectivityDate; +import com.capgemini.reports.reports.parameters.Generics; +import com.capgemini.reports.reports.parameters.MonoMulti; +import com.capgemini.reports.reports.parameters.ProductUnit; +import com.google.common.base.Joiner; + +import java.util.Map; + +/** Reconstructs a R10 report from BOM parameters. Generic parameters are optional. */ +public class R10Builder implements ReportBuilder { + + @Override + public ExecutionR10 build(Map data) throws InsufficientParametersException { + // Get the request raw data + String product = data.get(ReportCriteriaEnum.PRODUCT); + String unitStr = data.get(ReportCriteriaEnum.UNIT); + String monoMultiStr = data.get(ReportCriteriaEnum.MONO_MULTI); + String generic = data.get(ReportCriteriaEnum.GENERIC); + String genericAssemb = data.get(ReportCriteriaEnum.GENERIC_ASSEMB); + String effectivityStr = data.get(ReportCriteriaEnum.EFFECTIVITY_DATE); + + // Check presence of all required args + if (product == null || unitStr == null || monoMultiStr == null) { + String dataStr = Joiner.on('|').withKeyValueSeparator("=").useForNull("null").join(data); + throw new InsufficientParametersException("Missing parameter for R10 launch. Obtained: " + dataStr); + } + int unit; + try { + unit = Integer.parseInt(unitStr); + } catch (NumberFormatException e) { + throw new InsufficientParametersException("Unit parameter is not an int: " + unitStr, e); + } + ProductUnit aProductUnit = new ProductUnit(product, unit); + Generics aGeneric = new Generics(aProductUnit, generic, genericAssemb); + MonoMulti aMonoMulti = MonoMulti.build(monoMultiStr); + EffectivityDate anEffectivity = new EffectivityDate(effectivityStr); + + // Build the report + return new ExecutionR10(aGeneric, aMonoMulti, anEffectivity); + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/builder/R11Builder.java b/kurt-utility/src/main/java/com/capgemini/reports/builder/R11Builder.java new file mode 100644 index 0000000..6333126 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/builder/R11Builder.java @@ -0,0 +1,48 @@ +package com.capgemini.reports.builder; + +import com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum; +import com.capgemini.reports.definition.r11report.ExecutionR11; +import com.capgemini.reports.exceptions.InsufficientParametersException; +import com.capgemini.reports.reports.parameters.EffectivityDate; +import com.capgemini.reports.reports.parameters.Generics; +import com.capgemini.reports.reports.parameters.MonoMulti; +import com.capgemini.reports.reports.parameters.ProductUnit; +import com.google.common.base.Joiner; + +import java.util.Map; + + +/** Reconstructs a R11 report from BOM parameters. Generic parameters are optional. */ +public class R11Builder implements ReportBuilder { + + @Override + public ExecutionR11 build(Map data) throws InsufficientParametersException { + // Get the request raw data + String product = data.get(ReportCriteriaEnum.PRODUCT); + String unitStr = data.get(ReportCriteriaEnum.UNIT); + String monoMultiStr = data.get(ReportCriteriaEnum.MONO_MULTI); + String generic = data.get(ReportCriteriaEnum.GENERIC); + String genericAssemb = data.get(ReportCriteriaEnum.GENERIC_ASSEMB); + String effectivityStr = data.get(ReportCriteriaEnum.EFFECTIVITY_DATE); + + // Check presence of all required args + if (product == null || unitStr == null || monoMultiStr == null || effectivityStr == null) { + String dataStr = Joiner.on('|').withKeyValueSeparator("=").useForNull("null").join(data); + throw new InsufficientParametersException("Missing parameter for R11 launch. Obtained: " + dataStr); + } + int unit; + try { + unit = Integer.parseInt(unitStr); + } catch (NumberFormatException e) { + throw new InsufficientParametersException("Unit parameter is not an int: " + unitStr, e); + } + ProductUnit aProductUnit = new ProductUnit(product, unit); + Generics aGeneric = new Generics(aProductUnit, generic, genericAssemb); + MonoMulti aMonoMulti = MonoMulti.build(monoMultiStr); + EffectivityDate anEffectivity = new EffectivityDate(effectivityStr); + + // Build the report + return new ExecutionR11(aGeneric, aMonoMulti, anEffectivity); + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/builder/R13CrBuilder.java b/kurt-utility/src/main/java/com/capgemini/reports/builder/R13CrBuilder.java new file mode 100644 index 0000000..3ec9e86 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/builder/R13CrBuilder.java @@ -0,0 +1,14 @@ +package com.capgemini.reports.builder; + +import com.capgemini.reports.definition.r13report.execution.ExecutionR13CR; +import com.capgemini.reports.reports.parameters.EffectivityDate; + +/** Reconstructs a R13 (CR) report from two delimiter dates. */ +public class R13CrBuilder extends AbstractR13Builder { + + @Override + protected ExecutionR13CR make(EffectivityDate beginDate, EffectivityDate finalDate) { + return new ExecutionR13CR(finalDate, beginDate); + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/builder/R13FppBuilder.java b/kurt-utility/src/main/java/com/capgemini/reports/builder/R13FppBuilder.java new file mode 100644 index 0000000..bd4ce7b --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/builder/R13FppBuilder.java @@ -0,0 +1,14 @@ +package com.capgemini.reports.builder; + +import com.capgemini.reports.definition.r13report.execution.ExecutionR13FPP; +import com.capgemini.reports.reports.parameters.EffectivityDate; + +/** Reconstructs a R13 (CR) report from two delimiter dates. */ +public class R13FppBuilder extends AbstractR13Builder { + + @Override + protected ExecutionR13FPP make(EffectivityDate beginDate, EffectivityDate finalDate) { + return new ExecutionR13FPP(finalDate, beginDate); + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/builder/R15Builder.java b/kurt-utility/src/main/java/com/capgemini/reports/builder/R15Builder.java new file mode 100644 index 0000000..3e77584 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/builder/R15Builder.java @@ -0,0 +1,14 @@ +package com.capgemini.reports.builder; + +import com.capgemini.reports.definition.r15r16r17reports.r15r17reports.r15report.ExecutionR15; + +/** Builds a R15 Report from language, part Id & rev. */ +public class R15Builder extends AbstractR15R17Builder { + + @Override + protected ExecutionR15 make(String language, String partId, String partRevision) { + return new ExecutionR15(partId, partRevision, language); + } + + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/builder/R16Builder.java b/kurt-utility/src/main/java/com/capgemini/reports/builder/R16Builder.java new file mode 100644 index 0000000..516d8ca --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/builder/R16Builder.java @@ -0,0 +1,40 @@ +package com.capgemini.reports.builder; + +import com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum; +import com.capgemini.reports.definition.r15r16r17reports.r16report.ExecutionR16; +import com.capgemini.reports.exceptions.InsufficientParametersException; +import com.capgemini.reports.reports.parameters.ProductUnit; +import com.google.common.base.Joiner; + +import java.util.Map; + +/** Builds a R15 Report from language, part Id, product, unit, and "type d'impression". */ +public class R16Builder extends AbstractR15R16R17Builder { + + @Override + protected ExecutionR16 make(Map data, String language) throws InsufficientParametersException { + // Get the request raw data + String idTopGeneric = data.get(ReportCriteriaEnum.PART_ID); // It's actually a Gen for R16 + String product = data.get(ReportCriteriaEnum.PRODUCT); + String unitStr = data.get(ReportCriteriaEnum.UNIT); + String typeImpression = data.get(ReportCriteriaEnum.TYPE_IMPRESSION); + + // Check presence of all required args + if (idTopGeneric == null || product == null || unitStr == null || typeImpression == null) { + String dataStr = Joiner.on('|').withKeyValueSeparator("=").useForNull("null").join(data); + throw new InsufficientParametersException("Missing parameter for R01 launch. Obtained: " + dataStr); + } + int unit; + try { + unit = Integer.parseInt(unitStr); + } catch (NumberFormatException e) { + throw new InsufficientParametersException("Unit parameter is not an int: " + unitStr, e); + } + ProductUnit aProductUnit = new ProductUnit(product, unit); + + // Build the report + return new ExecutionR16(aProductUnit, idTopGeneric, typeImpression, language); + } + + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/builder/R17Builder.java b/kurt-utility/src/main/java/com/capgemini/reports/builder/R17Builder.java new file mode 100644 index 0000000..969a481 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/builder/R17Builder.java @@ -0,0 +1,14 @@ +package com.capgemini.reports.builder; + +import com.capgemini.reports.definition.r15r16r17reports.r15r17reports.r17report.ExecutionR17; + +/** Builds a R15 Report from language, part Id & rev. */ +public class R17Builder extends AbstractR15R17Builder { + + @Override + protected ExecutionR17 make(String language, String partId, String partRevision) { + return new ExecutionR17(partId, partRevision, language); + } + + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/builder/R19Builder.java b/kurt-utility/src/main/java/com/capgemini/reports/builder/R19Builder.java new file mode 100644 index 0000000..75c4bbe --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/builder/R19Builder.java @@ -0,0 +1,46 @@ +package com.capgemini.reports.builder; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.NoTeamcenterConnectionException; +import com.capgemini.framework.teamcenter.queries.saved.modelobject.ItemRevisionQuery; +import com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum; +import com.capgemini.reports.definition.r19report.ExecutionR19; +import com.capgemini.reports.exceptions.InsufficientParametersException; +import com.google.common.base.Joiner; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +import java.util.List; +import java.util.Map; + +/** + * Builds a R19 Report from document ID, Document revision, and document type. + */ +public class R19Builder implements ReportBuilder { + + @Override + public ExecutionR19 build(Map data) throws InsufficientParametersException { + // Get the request raw data + String documentId = data.get(ReportCriteriaEnum.DOCUMENT_ID); + String documentRev = data.get(ReportCriteriaEnum.DOCUMENT_REVISION); + String documentType = data.get(ReportCriteriaEnum.TYPE_OBJET); + + // Check presence of all required args + if (documentId == null || documentRev == null || documentType == null) { + String dataStr = Joiner.on('|').withKeyValueSeparator("=").useForNull("null").join(data); + throw new InsufficientParametersException("Missing parameter for R19 launch. Obtained: " + dataStr); + } + + try (TcSession session = new TcSession()) { + session.login(); + ItemRevisionQuery query = new ItemRevisionQuery(session); + query.searchType(documentType); + query.searchIDAndRevision(documentId, documentRev); + List results = query.findAll(); + ItemRevision doc = results.get(0); + return new ExecutionR19(documentId, documentRev, documentType, doc.getUid()); + } catch (NoTeamcenterConnectionException e) { + String dataStr = Joiner.on('|').withKeyValueSeparator("=").useForNull("null").join(data); + throw new InsufficientParametersException("Unable to retrieve document UID from id+rev. Request : " + dataStr, e); + } + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/builder/R20Builder.java b/kurt-utility/src/main/java/com/capgemini/reports/builder/R20Builder.java new file mode 100644 index 0000000..10670eb --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/builder/R20Builder.java @@ -0,0 +1,104 @@ +package com.capgemini.reports.builder; + +import com.capgemini.framework.common.StringHelper; +import com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum; +import com.capgemini.reports.definition.r20report.Classe; +import com.capgemini.reports.definition.r20report.ConjointUnique; +import com.capgemini.reports.definition.r20report.ExecutionR20; +import com.capgemini.reports.definition.r20report.MajorMinor; +import com.capgemini.reports.exceptions.InsufficientParametersException; +import com.capgemini.reports.reports.parameters.ProductUnit; +import com.google.common.base.Joiner; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +/** Builds a R20 Report from product/unit before & after, a String LMR list, plus various printing data. */ +public class R20Builder implements ReportBuilder { + + private static final String NO_LMR = "-"; + + @Override + public ExecutionR20 build(Map data) throws InsufficientParametersException { + // Get the request raw data + String productBefore = data.get(ReportCriteriaEnum.PRODUCT_BEFORE); + String productAfter = data.get(ReportCriteriaEnum.PRODUCT_AFTER); + String unitBeforeStr = data.get(ReportCriteriaEnum.UNIT_BEFORE); + String unitAfterStr = data.get(ReportCriteriaEnum.UNIT_AFTER); + String matricule = data.get(ReportCriteriaEnum.MATRICULE); + String lmrStr = data.get(ReportCriteriaEnum.LMR); + String classeStr = data.get(ReportCriteriaEnum.CLASSE); + String majorMinorStr = data.get(ReportCriteriaEnum.MAJOR_MINOR); + String conjointUniqueStr = data.get(ReportCriteriaEnum.CONJOINT_UNIQUE); + + // Check presence of all required args + if (productBefore == null || productAfter == null || unitBeforeStr == null || unitAfterStr == null || lmrStr == null || classeStr == null + || majorMinorStr == null || conjointUniqueStr == null) { + String dataStr = Joiner.on('|').withKeyValueSeparator("=").useForNull("null").join(data); + throw new InsufficientParametersException("Missing parameter for R20 launch. Obtained: " + dataStr); + } + + // Replacing null optional values by empty + if (matricule == null) { + matricule = StringHelper.EMPTY; + } + + // Present args in correct format + int unitBefore; + try { + unitBefore = Integer.parseInt(unitBeforeStr); + } catch (NumberFormatException e) { + throw new InsufficientParametersException("Unit Before is not an int: " + unitBeforeStr, e); + } + int unitAfter; + try { + unitAfter = Integer.parseInt(unitAfterStr); + } catch (NumberFormatException e) { + throw new InsufficientParametersException("Unit After is not an int: " + unitAfterStr, e); + } + MajorMinor majorMinor = MajorMinor.parse(majorMinorStr); + ProductUnit aProductUnitBefore = new ProductUnit(productBefore, unitBefore); + ProductUnit aProductUnitAfter = new ProductUnit(productAfter, unitAfter); + ConjointUnique conjointUnique = ConjointUnique.parse(conjointUniqueStr); + Classe classe = Classe.parse(classeStr); + List lmr = unpackLMR(lmrStr); + + // Build the report + return new ExecutionR20(aProductUnitBefore, aProductUnitAfter, matricule, lmr, classe, majorMinor, conjointUnique); + } + + private static final String LMR_SEPARATOR = ";"; // A semicolon (;) character + + + /** + * Unpacks a {@link #packLMR(List) packed} LMR list from the DB back to a {@link List} of strings. + * @param allLmrs a single String of all LMRs separated by a semicolon (or a simple dash if no LMR are found) + * @return a {@link List} of {@link String} MOD names + */ + private static List unpackLMR(final String allLmrs) { + List lmrList = new ArrayList<>(); + if (allLmrs == null || allLmrs.isEmpty() || NO_LMR.equals(allLmrs)) { + return lmrList; + } + String[] list = allLmrs.split(LMR_SEPARATOR); + Collections.addAll(lmrList, list); + return lmrList; + } + + /** + * Takes a List of String MOD names, packs it all in a single String to be saved to DB.
    + * Use {@link #unpackLMR(String)} to recover the original List. + * @param lmr the {@link List} of MOD names, as {@link String}s + * @return a single String with every LMR semicolon-separated (';'). If no LMRs, then outputs a dash '-'. + */ + public static String packLMR(final List lmr) { + String strLmr = ""; + for (String aMod : lmr) { + strLmr = aMod + LMR_SEPARATOR; + } + return strLmr.isEmpty() ? NO_LMR : strLmr; + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/builder/R21Builder.java b/kurt-utility/src/main/java/com/capgemini/reports/builder/R21Builder.java new file mode 100644 index 0000000..0aed29e --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/builder/R21Builder.java @@ -0,0 +1,46 @@ +package com.capgemini.reports.builder; + +import com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum; +import com.capgemini.reports.definition.r21report.ExecutionR21; +import com.capgemini.reports.exceptions.InsufficientParametersException; +import com.capgemini.reports.reports.parameters.DualGenerics; +import com.capgemini.reports.reports.parameters.EffectivityDate; +import com.capgemini.reports.reports.parameters.ProductUnit; +import com.google.common.base.Joiner; + +import java.util.Map; + +/** Builds a R21 Report from BOM Configuration. Both Gen & GenAssemb must be there. */ +public class R21Builder implements ReportBuilder { + + @Override + public ExecutionR21 build(Map data) throws InsufficientParametersException { + // Get the request raw data + String product = data.get(ReportCriteriaEnum.PRODUCT); + String unitStr = data.get(ReportCriteriaEnum.UNIT); + String generic = data.get(ReportCriteriaEnum.GENERIC); + String genericAssemb = data.get(ReportCriteriaEnum.GENERIC_ASSEMB); + String effectivityStr = data.get(ReportCriteriaEnum.EFFECTIVITY_DATE); + + // Check presence of all required args + if (product == null || unitStr == null || generic == null || genericAssemb == null) { + String dataStr = Joiner.on('|').withKeyValueSeparator("=").useForNull("null").join(data); + throw new InsufficientParametersException("Missing parameter for R21 launch. Obtained: " + dataStr); + } + + // Present args in correct format + int unit; + try { + unit = Integer.parseInt(unitStr); + } catch (NumberFormatException e) { + throw new InsufficientParametersException("Unit parameter is not an int: " + unitStr, e); + } + ProductUnit aProductUnit = new ProductUnit(product, unit); + DualGenerics aGeneric = new DualGenerics(aProductUnit, generic, genericAssemb); + EffectivityDate anEffectivity = new EffectivityDate(effectivityStr); + + // Build the report + return new ExecutionR21(aProductUnit, aGeneric, anEffectivity); + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/builder/R22Builder.java b/kurt-utility/src/main/java/com/capgemini/reports/builder/R22Builder.java new file mode 100644 index 0000000..53bf5d0 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/builder/R22Builder.java @@ -0,0 +1,29 @@ +package com.capgemini.reports.builder; + +import com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum; +import com.capgemini.reports.definition.r22report.ExecutionR22; +import com.capgemini.reports.exceptions.InsufficientParametersException; +import com.google.common.base.Joiner; + +import java.util.Map; + +/** Builds a R22 Report from Part Id & rev. */ +public class R22Builder implements ReportBuilder { + + @Override + public ExecutionR22 build(Map data) throws InsufficientParametersException { + // Get the request raw data + String partId = data.get(ReportCriteriaEnum.PART_ID); + String partRevision = data.get(ReportCriteriaEnum.PART_REVISION); + + // Check presence of all required args + if (partId == null || partRevision == null) { + String dataStr = Joiner.on('|').withKeyValueSeparator("=").useForNull("null").join(data); + throw new InsufficientParametersException("Missing parameter for R22 launch. Obtained: " + dataStr); + } + + // Build the report + return new ExecutionR22(partId, partRevision); + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/builder/R23Builder.java b/kurt-utility/src/main/java/com/capgemini/reports/builder/R23Builder.java new file mode 100644 index 0000000..704efb4 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/builder/R23Builder.java @@ -0,0 +1,52 @@ +package com.capgemini.reports.builder; + +import com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum; +import com.capgemini.reports.definition.r23report.ExecutionR23; +import com.capgemini.reports.exceptions.InsufficientParametersException; +import com.capgemini.reports.reports.parameters.EffectivityDate; +import com.capgemini.reports.reports.parameters.Generics; +import com.capgemini.reports.reports.parameters.MonoMulti; +import com.capgemini.reports.reports.parameters.ProductUnit; +import com.google.common.base.Joiner; + +import java.util.Map; + +/** + * Reconstructs a R23 report from BOM parameters. Generic parameters are optional. + */ +public class R23Builder implements ReportBuilder { + + @Override + public ExecutionR23 build(Map data) throws InsufficientParametersException { + // Get the request raw data + String product = data.get(ReportCriteriaEnum.PRODUCT); + String monoMultiStr = data.get(ReportCriteriaEnum.MONO_MULTI); + String generic = data.get(ReportCriteriaEnum.GENERIC); + String genericAssemb = data.get(ReportCriteriaEnum.GENERIC_ASSEMB); + String effectivityStr = data.get(ReportCriteriaEnum.EFFECTIVITY_DATE); + String superModelStr = data.get(ReportCriteriaEnum.SUPERMODEL); + String isWithFrozenUnitStr = data.get(ReportCriteriaEnum.WITH_FROZEN_UNIT); + String unitStr = data.get(ReportCriteriaEnum.UNIT); + String fromUnitStr = data.get(ReportCriteriaEnum.FROM_UNIT); + String frozenSinceLessThanStr = data.get(ReportCriteriaEnum.UNITS_FROZEN_SINCE_LESS_THAN); + + // Check presence of all required args + if (product == null || monoMultiStr == null) { + String dataStr = Joiner.on('|').withKeyValueSeparator("=").useForNull("null").join(data); + throw new InsufficientParametersException("Missing parameter for R23 launch. Obtained: " + dataStr); + } + ProductUnit aProductUnit = new ProductUnit(product, null); + Generics aGeneric = new Generics(aProductUnit, generic, genericAssemb); + MonoMulti aMonoMulti = MonoMulti.build(monoMultiStr); + EffectivityDate anEffectivity = new EffectivityDate(effectivityStr); + boolean isSuperModelBOM = Boolean.parseBoolean(superModelStr); + boolean isWithFrozenUnit = Boolean.parseBoolean(isWithFrozenUnitStr); + ProductUnit productUnitForUnit = new ProductUnit(product, unitStr); + ProductUnit productUnitFromUnit = new ProductUnit(product, fromUnitStr); + + + // Build the report + return new ExecutionR23(aProductUnit, aGeneric, aMonoMulti, anEffectivity, isSuperModelBOM, isWithFrozenUnit, productUnitForUnit, productUnitFromUnit, frozenSinceLessThanStr); + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/builder/R24Builder.java b/kurt-utility/src/main/java/com/capgemini/reports/builder/R24Builder.java new file mode 100644 index 0000000..60b2650 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/builder/R24Builder.java @@ -0,0 +1,52 @@ +package com.capgemini.reports.builder; + +import com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum; +import com.capgemini.reports.definition.r24report.ExecutionR24; +import com.capgemini.reports.exceptions.InsufficientParametersException; +import com.capgemini.reports.execution.AbstractExecutionReport; +import com.capgemini.reports.reports.parameters.ProductUnit; +import com.google.common.base.Joiner; + +import java.util.Map; + +/** Builds a R24 Report from language, part Id, product, unit, and "type d'impression". */ +public class R24Builder implements ReportBuilder { + + @Override + public AbstractExecutionReport build(Map data) throws InsufficientParametersException { + // Get the request raw data + String language = data.get(ReportCriteriaEnum.LANGUAGE); + + // Check presence of all required args + if (language == null) { + String dataStr = Joiner.on('|').withKeyValueSeparator("=").useForNull("null").join(data); + throw new InsufficientParametersException("Missing parameter for R24 launch. Obtained: " + dataStr); + } + + // Build the report + return make(data, language); + } + + protected ExecutionR24 make(Map data, String language) throws InsufficientParametersException { + /* Get the request raw data */ + String product = data.get(ReportCriteriaEnum.PRODUCT); + String unitStr = data.get(ReportCriteriaEnum.UNIT); + String typeImpression = data.get(ReportCriteriaEnum.TYPE_IMPRESSION); + + /* Check presence of all required args */ + if (product == null || unitStr == null || typeImpression == null) { + String dataStr = Joiner.on('|').withKeyValueSeparator("=").useForNull("null").join(data); + throw new InsufficientParametersException("Missing parameter for R24 launch. Obtained: " + dataStr); + } + int unit; + try { + unit = Integer.parseInt(unitStr); + } catch (NumberFormatException e) { + throw new InsufficientParametersException("Unit parameter is not an int: " + unitStr, e); + } + ProductUnit aProductUnit = new ProductUnit(product, unit); + + /* Build the report */ + return new ExecutionR24(aProductUnit, typeImpression, language); + } +} \ No newline at end of file diff --git a/kurt-utility/src/main/java/com/capgemini/reports/builder/R25Builder.java b/kurt-utility/src/main/java/com/capgemini/reports/builder/R25Builder.java new file mode 100644 index 0000000..1244123 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/builder/R25Builder.java @@ -0,0 +1,46 @@ +package com.capgemini.reports.builder; + +import com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum; +import com.capgemini.reports.definition.r25report.ExecutionR25; +import com.capgemini.reports.exceptions.InsufficientParametersException; +import com.capgemini.reports.execution.AbstractExecutionReport; +import com.capgemini.reports.reports.parameters.ProductUnit; +import com.google.common.base.Joiner; + +import java.util.Map; + +/** Builds a R25 Report from language, part Id, product, unit, and "type d'impression". */ +public class R25Builder implements ReportBuilder { + + @Override + public AbstractExecutionReport build(Map data) throws InsufficientParametersException { + // Get the request raw data + String language = data.get(ReportCriteriaEnum.LANGUAGE); + + // Check presence of all required args + if (language == null) { + String dataStr = Joiner.on('|').withKeyValueSeparator("=").useForNull("null").join(data); + throw new InsufficientParametersException("Missing parameter for R25 launch. Obtained: " + dataStr); + } + + // Build the report + return make(data, language); + } + + + protected ExecutionR25 make(Map data, String language) throws InsufficientParametersException { + /* Get the request raw data */ + String product = data.get(ReportCriteriaEnum.PRODUCT); + String unitStr = data.get(ReportCriteriaEnum.UNIT); + String typeImpression = data.get(ReportCriteriaEnum.TYPE_IMPRESSION); + ProductUnit aProductUnit = new ProductUnit(product, unitStr); + + /* Check presence of all required args */ + if (product == null || typeImpression == null) { + String dataStr = Joiner.on('|').withKeyValueSeparator("=").useForNull("null").join(data); + throw new InsufficientParametersException("Missing parameter for R25 launch. Obtained: " + dataStr); + } + return new ExecutionR25(aProductUnit, typeImpression, language); + + } +} \ No newline at end of file diff --git a/kurt-utility/src/main/java/com/capgemini/reports/builder/R26Builder.java b/kurt-utility/src/main/java/com/capgemini/reports/builder/R26Builder.java new file mode 100644 index 0000000..8c2e322 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/builder/R26Builder.java @@ -0,0 +1,31 @@ +package com.capgemini.reports.builder; + +import com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum; +import com.capgemini.reports.definition.r26report.ExecutionR26; +import com.capgemini.reports.exceptions.InsufficientParametersException; +import com.capgemini.reports.reports.parameters.EffectivityDate; +import com.google.common.base.Joiner; + +import java.util.Map; + +/** Builds a R26 report from part Id and effectivity date (initialized to sysdate). */ +public class R26Builder implements ReportBuilder { + + @Override + public ExecutionR26 build(Map data) throws InsufficientParametersException { + // Get the request raw data + String component = data.get(ReportCriteriaEnum.PART_ID); + String effectivityStr = data.get(ReportCriteriaEnum.EFFECTIVITY_DATE); + + // Check presence of all required args + if (component == null) { + String dataStr = Joiner.on('|').withKeyValueSeparator("=").useForNull("null").join(data); + throw new InsufficientParametersException("Missing parameter for R26 launch. Obtained: " + dataStr); + } + + EffectivityDate anEffectivity = new EffectivityDate(effectivityStr); + + // Build the report + return new ExecutionR26(component, anEffectivity); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/builder/R27Builder.java b/kurt-utility/src/main/java/com/capgemini/reports/builder/R27Builder.java new file mode 100644 index 0000000..09c62b6 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/builder/R27Builder.java @@ -0,0 +1,19 @@ +package com.capgemini.reports.builder; + +import com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum; +import com.capgemini.reports.definition.r27report.ExecutionR27; + +import java.util.Map; + +/** + * Reconstructs a R27 report. + */ +public class R27Builder implements ReportBuilder { + + + @Override + public ExecutionR27 build(Map data) { + return new ExecutionR27(); + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/builder/R28Builder.java b/kurt-utility/src/main/java/com/capgemini/reports/builder/R28Builder.java new file mode 100644 index 0000000..897d86d --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/builder/R28Builder.java @@ -0,0 +1,19 @@ +package com.capgemini.reports.builder; + +import com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum; +import com.capgemini.reports.definition.r28report.ExecutionR28; + +import java.util.Map; + +/** + * Reconstructs a R28 report. + */ +public class R28Builder implements ReportBuilder { + + + @Override + public ExecutionR28 build(Map data) { + return new ExecutionR28(); + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/builder/ReportBuilder.java b/kurt-utility/src/main/java/com/capgemini/reports/builder/ReportBuilder.java new file mode 100644 index 0000000..b4e4c11 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/builder/ReportBuilder.java @@ -0,0 +1,26 @@ +package com.capgemini.reports.builder; + +import com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum; +import com.capgemini.reports.exceptions.InsufficientParametersException; +import com.capgemini.reports.execution.AbstractExecutionReport; + +import java.util.Map; + +/** + * This interface allows creating a report from a map of functional {@link ReportCriteriaEnum}s and values.
    + * All ReportBuilders will be accessed via Reflection, so for future compatibility DO NOT move this package.
    + * Otherwise the fully-qualified class names (saved in DB for scheduled reports) will be lost.
    + * Also, all implementations must have a no-args constructor. + */ +public interface ReportBuilder { + /** + * Re-construct a report from its DB parameters. + * + * @param data the necessary data for reconstructing the report, obtained from the DB. + * + * @return the re-constructed report. + * + * @throws InsufficientParametersException if some required arguments are missing/non-understandable. + */ + AbstractExecutionReport build(Map data) throws InsufficientParametersException; +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/checkdata/CheckingDataHelper.java b/kurt-utility/src/main/java/com/capgemini/reports/checkdata/CheckingDataHelper.java new file mode 100644 index 0000000..20638ea --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/checkdata/CheckingDataHelper.java @@ -0,0 +1,77 @@ +package com.capgemini.reports.checkdata; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.InvalidConfigurationException; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.reports.database.DataBaseReportHelper; +import com.capgemini.reports.database.javabean.enumeration.ReportErrorTypeEnum; +import com.capgemini.reports.exceptions.FileLoadingException; +import com.capgemini.reports.exceptions.InvalidUserInputException; +import com.capgemini.reports.exceptions.UserInputErrorEnum; +import com.capgemini.reports.execution.AbstractExecutionReport; +import com.capgemini.reports.reports.parameters.IChecker; +import lombok.extern.slf4j.Slf4j; + +/** This class allow to make a control on the user input parameters. */ +@Slf4j +public final class CheckingDataHelper { + private static final String COULD_NOT_LOAD_PROPERTY_POLICIES = "Could not load property policies"; + + private CheckingDataHelper() { + // nothing to do... + } + + /** + * Perform a quick check on each of the user input parameters.
    + * This method must return quickly, so the check may not be thorough. + * + * @param session the teamcenter session to use to check the parameters. + * @param abstractExecutionReport the report used to check parameters + * @throws FileLoadingException if unable to read policies + * @throws InvalidUserInputException if anything goes wrong with the checks + */ + public static void doQuickCheck(final TcSession session, final AbstractExecutionReport abstractExecutionReport) + throws InvalidUserInputException, FileLoadingException { + PolicyLocation propertyPolicyForChecks = abstractExecutionReport.getPropertyPolicyForLongChecks(); + + try { + session.setObjectPropPolicy(propertyPolicyForChecks); + } catch (InvalidConfigurationException e) { + throw new InvalidUserInputException(UserInputErrorEnum.INTERNAL_ERROR, e); + } + + // Perform each quick check + for (IChecker parameter : abstractExecutionReport.getQuickChecks()) { + parameter.check(session); + } + } + + /** + * Perform some in-depth checks of each of the user input parameters.
    + * + * @param session the teamcenter session to use to check the parameters. + * @param aAbstractExecutionReport the report on which the tests should be made + * @throws InvalidUserInputException if the checks failed (wrong parameters, or >maybe< the tc servers were busy) + */ + public static void doLongCheck(final TcSession session, + final AbstractExecutionReport aAbstractExecutionReport) throws InvalidUserInputException { + try { + session.setObjectPropPolicy(aAbstractExecutionReport.getPropertyPolicyForLongChecks()); + } catch (InvalidConfigurationException e) { + log.error(COULD_NOT_LOAD_PROPERTY_POLICIES); + throw new InvalidUserInputException(UserInputErrorEnum.INTERNAL_ERROR, e); + } + try { + /* Execute each long check */ + for (IChecker parameter : aAbstractExecutionReport.getLongChecks()) { + parameter.check(session); + } + } catch (InvalidUserInputException e) { + log.error("Some Long check highlighted anF error in the user-provided parameters", e); + DataBaseReportHelper.registerError(e.getErrorMessageForUser(), ReportErrorTypeEnum.FUNCTIONAL, + aAbstractExecutionReport.getReportTechnicalUid()); + throw e; + } + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/database/DataBaseReportHelper.java b/kurt-utility/src/main/java/com/capgemini/reports/database/DataBaseReportHelper.java new file mode 100644 index 0000000..aa720dd --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/database/DataBaseReportHelper.java @@ -0,0 +1,282 @@ +package com.capgemini.reports.database; + +import com.capgemini.framework.common.DateHelper; +import com.capgemini.reports.ReportEnum; +import com.capgemini.reports.ReportLaunchTypeEnum; +import com.capgemini.reports.database.javabean.DbReport; +import com.capgemini.reports.database.javabean.DbSchedulingReport; +import com.capgemini.reports.database.javabean.DbUser; +import com.capgemini.reports.database.javabean.enumeration.ReportErrorTypeEnum; +import com.capgemini.reports.database.javabean.enumeration.ReportStateEnum; +import com.capgemini.reports.database.manager.AbstractHibernateManager; +import com.capgemini.reports.database.manager.MngReport; +import com.capgemini.reports.database.manager.MngSchedulingCriteriaVal; +import com.capgemini.reports.database.manager.MngSchedulingCriteriaVal.SchedulingCriteriaValue; +import com.capgemini.reports.database.manager.MngSchedulingReport; +import com.capgemini.reports.exceptions.InvalidUserInputException; +import com.capgemini.reports.exceptions.NotFoundException; +import com.capgemini.reports.execution.AbstractExecutionReport; +import com.capgemini.reports.periodicity.SchedulingPeriod; +import lombok.extern.slf4j.Slf4j; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.Transaction; + +import java.util.List; + +/** + * This class will allow to record every steps of the report's execution. + */ +@Slf4j +public final class DataBaseReportHelper { + + private DataBaseReportHelper() { + // Nothing to do here... + } + + /** + * Create the database record for the launch of this immediate or delayed report.
    + * This method is called in the report's servlet and save an image of this report in database after submitting it via the IHM. + * + * @param aAbstractExecutionReport will provide the report concerned + * @param userWhoRequestedTheLaunch the user that requested the launch + * @return the saved Report (image of the DB) + */ + public static DbReport registerLaunch(final AbstractExecutionReport aAbstractExecutionReport, final DbUser userWhoRequestedTheLaunch) { + DbReport theCreatedReport = null; + MngReport theReportManager = new MngReport(); + String theCode = aAbstractExecutionReport.getReportIdentifier().getReportCode(); + String theUid = aAbstractExecutionReport.getReportTechnicalUid(); + ReportLaunchTypeEnum launchType = aAbstractExecutionReport.getLaunchType(); + + // Specific status : must be WAIT or delayed reports or READY for immediate reports + ReportStateEnum reportState = (ReportLaunchTypeEnum.DELAYED.equals(launchType)) ? ReportStateEnum.WAIT : ReportStateEnum.READY; + + // Insert data in database + try { + theCreatedReport = theReportManager.insertWithCriteriaAndOwner(theCode, theUid, reportState, aAbstractExecutionReport.getLaunchData(), + userWhoRequestedTheLaunch); + String launchTypeStr = null; + switch (launchType) { + case DELAYED: + launchTypeStr = "Delayed report "; + break; + case IMMEDIATE: + launchTypeStr = "Report "; + break; + case SCHEDULED: + launchTypeStr = "Scheduled report "; + break; + case AUTOMATIC: + launchTypeStr = "Automatic report "; // Shouldn't happen + break; + } + log.info(launchTypeStr + theCode + " saved in database with UID: " + theUid); + } + catch (InvalidUserInputException e) { + log.error("Unable to store the report in database", e); + } + + return theCreatedReport; + } + + /** + * Update the database record of the delayed report.
    + * This method is called after waiting in Quartz queue. + * + * @param aReportTechnicalUid gives the report technical ID + * @return the saved Report (image of the DB) + * @throws NotFoundException if the report could not be found in the DB + */ + public static DbReport updateDelayedLaunch(final String aReportTechnicalUid) throws NotFoundException { + SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); + Session session = sessionFactory.openSession(); + try { + Transaction transaction = session.beginTransaction(); + MngReport theReportManager = new MngReport(); + // Find the report to update + DbReport theExecutingReport = theReportManager.searchByUid(aReportTechnicalUid, session); + theExecutingReport.setState(ReportStateEnum.READY.toString()); + theReportManager.update(session, theExecutingReport); + transaction.commit(); + return theExecutingReport; + } + finally { + session.close(); + } + } + + /** + * Create the database record for the launch of this scheduled report.
    + * This method is called in the scheduled servlet of the report and save an image of the scheduling template of report in database after submitting it via the IHM. + * + * @param aAbstractExecutionReport will provide the report concerned + * @param userWhoRequestedTheLaunch the user that requested the launch + * @param schedulingCriteriaValues List<{@link SchedulingCriteriaValue}> - all the criteria associated to the report + * @param schedulingName String - the unique scheduling name + * @return the saved Report (image of the DB) + */ + public static DbSchedulingReport registerScheduledTemplate(final AbstractExecutionReport aAbstractExecutionReport, + final DbUser userWhoRequestedTheLaunch, final List schedulingCriteriaValues, final String schedulingName) { + MngSchedulingReport theReportManager = new MngSchedulingReport(); + ReportEnum theCode = aAbstractExecutionReport.getReportIdentifier(); + String theUid = aAbstractExecutionReport.getReportTechnicalUid(); + + // Insert data in database + DbSchedulingReport theCreatedReport = theReportManager.insertSchedulingReportWithCriteriaAndOwner(schedulingName, schedulingCriteriaValues, + aAbstractExecutionReport.getLaunchData(), userWhoRequestedTheLaunch, theCode); + + log.info("Scheduled report {} saved in database with UID: {}", theCode, theUid); + return theCreatedReport; + } + + /** + * Create the database record for the launch of this immediate or delayed report.
    + * This method is called in the report's servlet and save an image of this report in database after submitting it via the IHM. + * + * @param aAbstractExecutionReport will provide the report concerned + * @param usersWhoRequestedTheLaunch all the users that requested the launch + * @param schedulingReportId Long - the id of the scheduling if it exists + * @return the saved Report (image of the DB) + */ + public static DbReport registerScheduledLaunch(final AbstractExecutionReport aAbstractExecutionReport, + final List usersWhoRequestedTheLaunch, final Long schedulingReportId) throws InvalidUserInputException { + String theCode = aAbstractExecutionReport.getReportIdentifier().getReportCode(); + String theUid = aAbstractExecutionReport.getReportTechnicalUid(); + + // Insert data in database + SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); + Session session = sessionFactory.openSession(); + try { + Transaction transaction = session.beginTransaction(); + DbReport theCreatedReport = new MngReport().insertWithCriteriaAndOwners(session, theCode, theUid, ReportStateEnum.READY, aAbstractExecutionReport.getLaunchData(), + usersWhoRequestedTheLaunch, schedulingReportId); + transaction.commit(); + log.info("Scheduled report saved in database with UID: " + theUid); + return theCreatedReport; + } + finally { + session.close(); + } + } + + /** + * Create the database record for the start of the execution of this report. + * + * @param theReportManager the {@link MngReport} which will provide this report's UID in the DB, and is able to update its infos. + * @param aReportTechnicalUid gives the report technical ID + * @return the saved Report (image of the DB), never null + * @throws NotFoundException if the report Entry could not be found in the DB + */ + public static DbReport registerStart(final MngReport theReportManager, final String aReportTechnicalUid) throws NotFoundException { + SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); + Session session = sessionFactory.openSession(); + try { + Transaction transaction = session.beginTransaction(); + DbReport theExecutingReport = theReportManager.searchByUid(aReportTechnicalUid, session); + theExecutingReport.setStartGenerationDate(DateHelper.getCurrentSqlTimestamp()); + theExecutingReport.setState(ReportStateEnum.EXECUTING.toString()); + theReportManager.update(session, theExecutingReport); + transaction.commit(); + return theExecutingReport; + } + finally { + session.close(); + } + } + + /** + * Create the database record for the successful completion of the execution of this report. + * + * @param theExecutingReport the dbReport entry + * @param fileNameWithExtension the file name of the created report + * @param theReportManager the {@link MngReport} which is able to update the report's infos. + */ + public static void registerCompletion(final DbReport theExecutingReport, final String fileNameWithExtension, final AbstractHibernateManager theReportManager) { + if (theExecutingReport != null) { + SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); + Session session = sessionFactory.openSession(); + try { + Transaction transaction = session.beginTransaction(); + theExecutingReport.setEndGenerationDate(DateHelper.getCurrentSqlTimestamp()); + theExecutingReport.setState(ReportStateEnum.FINISHED.toString()); + theExecutingReport.setFileName(fileNameWithExtension); + theReportManager.update(session, theExecutingReport); + transaction.commit(); + } + finally { + session.close(); + } + } + } + + /** + * Save an error message for an executed report in the SB. + * + * @param anErrorMessage Content of the error message for the current executed report + * @param anErrorType Type of error (FUNCTIONAL or TECHNICAL) + * @param aReportTechnicalUid gives the report technical ID + */ + public static void registerError(final String anErrorMessage, final ReportErrorTypeEnum anErrorType, final String aReportTechnicalUid) { + SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); + Session session = sessionFactory.openSession(); + try { + Transaction transaction = session.beginTransaction(); + MngReport theReportManager = new MngReport(); + DbReport theExecutingReport = theReportManager.searchByUid(aReportTechnicalUid, session); + theExecutingReport.setErrorMessage(anErrorMessage); + theExecutingReport.setErrorType(anErrorType.toString()); + theExecutingReport.setState(ReportStateEnum.FAILED.toString()); + theExecutingReport.setEndGenerationDate(DateHelper.getCurrentSqlTimestamp()); + theReportManager.update(session, theExecutingReport); + transaction.commit(); + } + catch (NotFoundException e) { + log.warn("Unable to find report " + aReportTechnicalUid + ", could not register this error: " + + anErrorMessage, e); + } + finally { + session.close(); + } + } + + /** + * Update the database record of a scheduled report. + * + * @param aSchedulingTemplateId the ID of the schedulingReport entry + * @param report the execution + * @param schedulingName the name of the scheduling (will overwrite the existing name + * @param period a {@link SchedulingPeriod} that will replace the existing periodicity + * @param dbUser the user who created r last updated the scheduling + * @return the saved {@link DbSchedulingReport} (image of the DB) + */ + public static DbSchedulingReport updateScheduling(final Long aSchedulingTemplateId, final AbstractExecutionReport report, + final String schedulingName, final SchedulingPeriod period, DbUser dbUser) { + log.debug("Updating scheduling: {}({}) at {} for {}({})", aSchedulingTemplateId, schedulingName, period.toString(), dbUser.getId(), + dbUser.getLogin()); + SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); + Session session = sessionFactory.openSession(); + try { + Transaction transaction = session.beginTransaction(); + // Find the report to update with the scheduling id received from the IHM (selected by the user) + MngSchedulingReport theReportManager = new MngSchedulingReport(); + DbSchedulingReport theScheduledReport = theReportManager.searchById(session, aSchedulingTemplateId); + theScheduledReport.setLastUpdate(DateHelper.getCurrentSqlTimestamp()); // Update LastUpdate time + theScheduledReport.setSchedulingName(schedulingName); // May have changed? Overwrite anyway + theScheduledReport.setAdminResponsibleId(dbUser.getId()); // Update responsible user + theReportManager.update(session, theScheduledReport); + + // Update all old criteria + MngSchedulingCriteriaVal theSchedulingCriteriaValManager = new MngSchedulingCriteriaVal(); + theSchedulingCriteriaValManager.updatePeriod(session, aSchedulingTemplateId, period); + theSchedulingCriteriaValManager.updateFunctionalParameters(session, aSchedulingTemplateId, report.getLaunchData()); + + // Commit all changes in DB + transaction.commit(); + return theScheduledReport; + } + finally { + session.close(); + } + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/database/DbInit.java b/kurt-utility/src/main/java/com/capgemini/reports/database/DbInit.java new file mode 100644 index 0000000..04c7e7e --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/database/DbInit.java @@ -0,0 +1,107 @@ +package com.capgemini.reports.database; + +import com.capgemini.framework.common.SettingsHelper; +import com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum; +import com.capgemini.reports.database.manager.*; +import lombok.extern.slf4j.Slf4j; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.Transaction; + +/** + * Database initialization using Hibernate. + **/ +@Slf4j +public class DbInit { + + private final MngCriteria criteriaManager; + private final MngCriteriaVal criteriaValManager; + private final MngReportType reportTypeManager; + private final MngReportOwner reportOwnerManager; + private final MngReport reportManager; + private final MngUser userManager; + + private static final String[] reports = + new String[]{"R01", "R03", "R05", "R06", "R07", "R10", "R11", "R13", "R15", "R16", "R17", "R19", "R20", "R21", "R22", "R23", "R24", "R26", "R27", "R28"}; + + /** + * Main entry point for initializer. + * + * @param args JAVA command arguments (should be empty) + */ + public static void main(final String[] args) { + SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); + Session session = sessionFactory.openSession(); + Transaction transaction = session.beginTransaction(); + try { + DbInit theInitializer = new DbInit(); + log.info("Create all objects"); + theInitializer.createAllObjects(session); + + log.info("Commit transaction"); + transaction.commit(); + + log.info("Display record count"); + theInitializer.displayRecordCount(session); + } + catch (Exception e) { + log.error("Unexpected error occured during database initialization", e); + log.warn("Rollback transaction"); + transaction.rollback(); + } + finally { + log.info("End of initialization"); + session.close(); + } + } + + private DbInit() { + criteriaManager = new MngCriteria(); + criteriaValManager = new MngCriteriaVal(); + reportManager = new MngReport(); + reportTypeManager = new MngReportType(); + userManager = new MngUser(); + reportOwnerManager = new MngReportOwner(); + } + + /** + * Sample objects creation. + */ + private void createAllObjects(Session session) { + log.info("Create users"); + userManager.insert(session, "infodba", "System", "Administrator", SettingsHelper.getDefaultExpeditorMailPassword()); + + log.info("Create criteria"); + for (ReportCriteriaEnum currentEnum : ReportCriteriaEnum.values()) { + String currentType = "string"; + String currentStrValue = currentEnum.toString(); + if (currentStrValue.startsWith("Unit")) { + currentType = "integer"; + } + else if (currentStrValue.startsWith("Date")) { + currentType = "date"; + } + criteriaManager.insert(session, currentEnum, currentType); + } + + log.info("Create report types"); + String defaultRevRule = SettingsHelper.getDefaultRevisionRule(); + for (String report : reports) { + reportTypeManager.insert(session, report, SettingsHelper.getString("title.REPORT_" + report), + Long.valueOf(SettingsHelper.getString("priority.REPORT_" + report)), + SettingsHelper.getPropertyWithDefaultValue("common.bom.revisionRule.REPORT_" + report, defaultRevRule)); + } + } + + /** + * Display a summary of loaded objects. + * + * @param session*/ + private void displayRecordCount(Session session) { + log.info("Loaded user(s) count: " + reportManager.getList(session).size()); + log.info("Loaded criteria(s) count: " + criteriaManager.getList(session).size()); + log.info("Loaded criteria value(s) count: " + criteriaValManager.getList(session).size()); + log.info("Loaded report(s) count: " + userManager.getList(session).size()); + log.info("Loaded reportOwner(s) count: " + reportOwnerManager.getList(session).size()); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/database/HibernateUtil.java b/kurt-utility/src/main/java/com/capgemini/reports/database/HibernateUtil.java new file mode 100644 index 0000000..930fbdc --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/database/HibernateUtil.java @@ -0,0 +1,35 @@ +package com.capgemini.reports.database; + +import org.hibernate.SessionFactory; +import org.hibernate.cfg.Configuration; +import org.hibernate.service.ServiceRegistryBuilder; + +/** + * Utility class for Hibernate accesses. + **/ +public final class HibernateUtil { + private static final SessionFactory SESSION_FACTORY = buildSessionFactory(); + + private HibernateUtil() { + // Nothing to do... + } + + /** + * Creating a session factory, if not already loaded. + **/ + private static SessionFactory buildSessionFactory() { + Configuration configuration = new Configuration(); + configuration.configure(); + return configuration.buildSessionFactory(new ServiceRegistryBuilder().applySettings(configuration.getProperties()).buildServiceRegistry()); + } + + /** + * Getter for the factory instance. + * + * @return Factory instance + **/ + public static SessionFactory getSessionFactory() { + return SESSION_FACTORY; + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/database/javabean/DbCriteria.java b/kurt-utility/src/main/java/com/capgemini/reports/database/javabean/DbCriteria.java new file mode 100644 index 0000000..5e46fe7 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/database/javabean/DbCriteria.java @@ -0,0 +1,34 @@ +package com.capgemini.reports.database.javabean; + +import java.io.Serializable; + +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +/** Persisted object in table CRITERIA. **/ +@Getter +@Setter +@ToString +public class DbCriteria implements Serializable, IPersistedObject { + + /** Required by serialization. **/ + private static final long serialVersionUID = 1L; + + /** Unique identifier recommended for using all features from Hibernate. **/ + private Long id; + + /** Criteria label. **/ + private String criteriaName; + + /** Data type. **/ + private String criteriaType; + + /** Data type. default false **/ + private String isTemporel; + + /** JAVA convention requires an empty constructor for each JAVA bean. **/ + public DbCriteria() { + // Nothing to see, move along... + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/database/javabean/DbCriteriaVal.java b/kurt-utility/src/main/java/com/capgemini/reports/database/javabean/DbCriteriaVal.java new file mode 100644 index 0000000..1e01dd2 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/database/javabean/DbCriteriaVal.java @@ -0,0 +1,34 @@ +package com.capgemini.reports.database.javabean; + +import java.io.Serializable; + +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +/** Persisted object in table CRITERIA_VAL for criteria values. **/ +@Getter +@Setter +@ToString +public class DbCriteriaVal implements Serializable, IPersistedObject { + + /** Required by serialization. **/ + private static final long serialVersionUID = 1L; + + /** Unique identifier recommended for using all features from Hibernate. **/ + private Long id; + + /** Linked criteria. **/ + private DbCriteria criteria; + + /** Criteria value. **/ + private String criteriaValue; + + /** Identifier of the linked report. **/ + private Long reportId; + + /** JAVA convention requires an empty constructor for each JAVA bean. **/ + public DbCriteriaVal() { + // Nothing to see, move along... + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/database/javabean/DbMemMonitor.java b/kurt-utility/src/main/java/com/capgemini/reports/database/javabean/DbMemMonitor.java new file mode 100644 index 0000000..ec4b4a2 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/database/javabean/DbMemMonitor.java @@ -0,0 +1,39 @@ +package com.capgemini.reports.database.javabean; + +import java.io.Serializable; +import java.sql.Timestamp; + +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +/** Persisted object in table MEM_MONITOR. **/ +@Getter +@Setter +@ToString +public class DbMemMonitor implements Serializable, IPersistedObject { + + /** Required by serialization. **/ + private static final long serialVersionUID = 1L; + + /** Unique identifier recommended for using all features from Hibernate. **/ + private Long id; + + /** Current date when the trace has been saved in database. **/ + private Timestamp monitorDate; + + /** Global amount of reserved memory. **/ + private Double totalMemory; + + /** Maximum amount of memory which could be reserved. **/ + private Double maxMemory; + + /** Current amount of free memory. **/ + private Double freeMemory; + + /** Current amount of used memory. **/ + private Double usedMemory; + + /** Percent of memory used compared to maximum limit. **/ + private Double maxPercent; +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/database/javabean/DbReport.java b/kurt-utility/src/main/java/com/capgemini/reports/database/javabean/DbReport.java new file mode 100644 index 0000000..4cfc0c1 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/database/javabean/DbReport.java @@ -0,0 +1,77 @@ +package com.capgemini.reports.database.javabean; + +import java.io.Serializable; +import java.sql.Timestamp; + +import com.capgemini.framework.common.DateHelper; + +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +/** Persisted object in table REPORT. **/ +@Getter +@Setter +@ToString +public class DbReport implements Serializable, IPersistedObject { + + /** Required by serialization. **/ + private static final long serialVersionUID = 1L; + + /** Unique identifier recommended for using all features from Hibernate. **/ + private Long id; + + /** Identification code for the report, ie: R01, R22... **/ + private String reportCode; + + /** Date when the generation started. **/ + private Timestamp startGenerationDate; + + /** Date when the generation ended. **/ + private Timestamp endGenerationDate; + + /** Duration of the generation. **/ + private Long generationDuration; + + /** Unique identifier of the report. **/ + private String reportUid; + + /** Current report state (WAITING, INWORK, FAILED, COMPLETED). **/ + private String state; + + /** Content of error message when state is "FAILED". **/ + private String errorMessage; + + /** Type of the error: FUNCTIONAL or TECHNICAL (ie: JAVA Exception). **/ + private String errorType; + + /** Physical file name on disk. **/ + private String fileName; + + /** Technical field only for filtering for statistics. **/ + private String monthPeriod; + + /** Identifier of the scheduling report. **/ + private Long schedulingReportId; + + /** JAVA convention requires an empty constructor for each JAVA bean. **/ + public DbReport() { + // Nothing to see, move along... + } + + /** + * Override of the lombok setter. + * + * @param aTimestamp Set value + **/ + public void setEndGenerationDate(final Timestamp aTimestamp) { + + endGenerationDate = aTimestamp; + setMonthPeriod(DateHelper.getMonthPeriod()); + + /* Compute duration */ + if ((startGenerationDate != null) && (endGenerationDate != null)) { + generationDuration = endGenerationDate.getTime() - startGenerationDate.getTime(); + } + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/database/javabean/DbReportOwner.java b/kurt-utility/src/main/java/com/capgemini/reports/database/javabean/DbReportOwner.java new file mode 100644 index 0000000..4f48a6d --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/database/javabean/DbReportOwner.java @@ -0,0 +1,50 @@ +package com.capgemini.reports.database.javabean; + +import java.io.Serializable; +import java.sql.Timestamp; + +import com.capgemini.framework.common.DateHelper; + +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +/** Persisted object in table REP_USER. **/ +@Getter +@Setter +@ToString +public class DbReportOwner implements Serializable, IPersistedObject { + + /** Required by serialization. **/ + private static final long serialVersionUID = 4697006911693586324L; + + /** Unique identifier recommended for using all features from Hibernate. **/ + private Long id; + + /** User ID: must be unique in database. **/ + private Long userId; + + /** Report Id: must be unique in database. **/ + private Long reportId; + + /** Date of the last connection of the user, matching with the last LDAP data synchronization. **/ + private Timestamp requestDate; + + /** Technical field only for filtering for statistics. **/ + private String monthPeriod; + + /** + * Override of the lombok setter. + * + * @param aTimestamp Set value + **/ + public void setRequestDate(final Timestamp aTimestamp) { + requestDate = aTimestamp; + setMonthPeriod(DateHelper.getMonthPeriod()); + } + + /** JAVA convention requires an empty constructor for each JAVA bean. **/ + public DbReportOwner() { + // Nothing to see, move along... + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/database/javabean/DbReportType.java b/kurt-utility/src/main/java/com/capgemini/reports/database/javabean/DbReportType.java new file mode 100644 index 0000000..ac11d6b --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/database/javabean/DbReportType.java @@ -0,0 +1,43 @@ +package com.capgemini.reports.database.javabean; + +import java.io.Serializable; + +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +/** Persisted object in table REPORT_TYPE. **/ +@Getter +@Setter +@ToString +public class DbReportType implements Serializable, IPersistedObject { + + /** Required by serialization. **/ + private static final long serialVersionUID = 1L; + + /** Unique identifier recommended for using all features from Hibernate. **/ + private Long id; + + /** Identification code for the report, ie: R01, R22... **/ + private String code; + + /** Priority in queue. **/ + private Long priority; + + /** Title of the report. **/ + private String title; + + /** Name of the revision rule. **/ + private String revisionRule; + + /** If 'TRUE' then the report can be launched interactively by the users. Defaults to 'TRUE' **/ + private String reportAuthorized; + + /** If 'TRUE' then the report can be launched scheduled. Defaults to 'FALSE'. **/ + private String isCandidateForScheduling; + + /** JAVA convention requires an empty constructor for each JAVA bean. **/ + public DbReportType() { + // Nothing to see, move along... + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/database/javabean/DbSchedulingCriteriaVal.java b/kurt-utility/src/main/java/com/capgemini/reports/database/javabean/DbSchedulingCriteriaVal.java new file mode 100644 index 0000000..bb92052 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/database/javabean/DbSchedulingCriteriaVal.java @@ -0,0 +1,35 @@ +package com.capgemini.reports.database.javabean; + +import java.io.Serializable; + +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + + +/** Persisted object in table CRITERIA. **/ +@Getter +@Setter +@ToString +public class DbSchedulingCriteriaVal implements Serializable, IPersistedObject { + + /** Required by serialization. **/ + private static final long serialVersionUID = -7663074318747139689L; + + /** Identifier of the linked report. **/ + private Long id; + + /** Linked dbSchedulignCriteria. **/ + private DbCriteria dbCriteria; + + /** Criteria value. **/ + private String criteriaValue; + + /** Identifier of the linked report. **/ + private Long schedulingReportId; + + /** JAVA convention requires an empty constructor for each JAVA bean. **/ + public DbSchedulingCriteriaVal() { + // Nothing to do + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/database/javabean/DbSchedulingReport.java b/kurt-utility/src/main/java/com/capgemini/reports/database/javabean/DbSchedulingReport.java new file mode 100644 index 0000000..fc88cb3 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/database/javabean/DbSchedulingReport.java @@ -0,0 +1,38 @@ +package com.capgemini.reports.database.javabean; + +import java.io.Serializable; +import java.sql.Timestamp; + +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +/** Persisted object in table SCHEDULING_REPORT. **/ +@Getter +@Setter +@ToString +public class DbSchedulingReport implements Serializable, IPersistedObject { + + /** Required by serialization. **/ + private static final long serialVersionUID = -451309740204083348L; + + /** Unique identifier recommended for using all features from Hibernate. **/ + private Long id; + + /** name of scheduling must be unique. **/ + private String schedulingName; + + /** Code of scheduling report. **/ + private String reportCode; + + /** Date when an admin last updated this. **/ + private Timestamp lastUpdate; + + /** ID of responsible admin. **/ + private Long adminResponsibleId; + + /** JAVA convention requires an empty constructor for each JAVA bean. **/ + public DbSchedulingReport() { + // Nothing to do, hihihi.... + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/database/javabean/DbUser.java b/kurt-utility/src/main/java/com/capgemini/reports/database/javabean/DbUser.java new file mode 100644 index 0000000..b73daf7 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/database/javabean/DbUser.java @@ -0,0 +1,89 @@ +package com.capgemini.reports.database.javabean; + +import com.capgemini.framework.common.activedirectory.ActiveDirectory; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +import java.io.Serializable; +import java.sql.Date; + +/** Persisted object in table REP_USER. **/ +@Getter +@Setter +@ToString +public class DbUser implements Serializable, IPersistedObject { + + /** Required by serialization. **/ + private static final long serialVersionUID = 1L; + + /** Unique identifier recommended for using all features from Hibernate. **/ + private Long id; + + /** User login: must be unique in database. **/ + private String login; + + /** User email (synchronized with the LDAP). **/ + private String email; + + /** User surname (synchronized with the LDAP). **/ + private String surname; + + /** User first name (synchronized with the LDAP). **/ + private String firstname; + + /** Date of the last connection of the user, matching with the last LDAP data synchronization. **/ + private Date lastConnectionDate; + + /** user role, default to false. **/ + private String isAdmin = "FALSE"; + + /** JAVA convention requires an empty constructor for each JAVA bean. isAdmin **/ + public DbUser() { + // Nothing to see, move along... + } + + /** + * Returns true if both this DB entry and the provided user data match (all fields must be equal). + * + * @param user the {@link UserData} to be compared to this + * @return true if they are the same, false otherwise + */ + public boolean sameAs(final UserData user) { + if (user == null) { + return false; + } + boolean loginOk = login != null && login.equals(user.login); + boolean emailOk = email != null && email.equals(user.email); + boolean surnameOk = surname != null && surname.equals(user.surname); + boolean firstNameOk = firstname != null && firstname.equals(user.firstName); + return loginOk && emailOk && surnameOk && firstNameOk; + } + + /** POJO containing various information on a user. */ + @Getter + public static class UserData { + private final String login; + private final String email; + private final String firstName; + private final String surname; + private final boolean admin; + + public UserData(String login, String email, String firstName, String surname, boolean admin) { + this.login = login; + this.email = email; + this.firstName = firstName; + this.surname = surname; + this.admin = admin; + } + } + + /** + * Returns true if the user is Guest (identified by login='Invité(e)'). + * + * @return true if the user is a guest + */ + public boolean isGuest() { + return ActiveDirectory.GUEST_LOGIN.equals(login); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/database/javabean/IPersistedObject.java b/kurt-utility/src/main/java/com/capgemini/reports/database/javabean/IPersistedObject.java new file mode 100644 index 0000000..227a969 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/database/javabean/IPersistedObject.java @@ -0,0 +1,6 @@ +package com.capgemini.reports.database.javabean; + +/** Common interface for all JAVA beans persisted through Hibernate. **/ +public interface IPersistedObject { + // This interface is just to regroup all DB elements +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/database/javabean/enumeration/ReportCriteriaEnum.java b/kurt-utility/src/main/java/com/capgemini/reports/database/javabean/enumeration/ReportCriteriaEnum.java new file mode 100644 index 0000000..d398ed4 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/database/javabean/enumeration/ReportCriteriaEnum.java @@ -0,0 +1,136 @@ +package com.capgemini.reports.database.javabean.enumeration; + +import com.capgemini.reports.database.javabean.DbCriteria; +import com.capgemini.reports.database.javabean.DbSchedulingCriteriaVal; + +import java.util.HashMap; +import java.util.Map; + + +/** List of criteria values. Any change made to this class must be mirrored in the installation script of the database. **/ +public enum ReportCriteriaEnum { + + /** + * TcEffectivity date. + */ + EFFECTIVITY_DATE("Date d'effectivité"), + /** Generic ID. */ + GENERIC("Générique"), + /** Generic Assemb ID. */ + GENERIC_ASSEMB("Générique montage"), + /** Nomenclature explosion level (MONO/MULTI). */ + MONO_MULTI("Niveau"), + /** Part ID. */ + PART_ID("Numéro d'article"), + /** Revision of the item. */ + PART_REVISION("Révision"), + /** Document ID. */ + DOCUMENT_ID("Numéro document"), + /** Revision of the document. */ + DOCUMENT_REVISION("Document Révision"), + /** Product ID. */ + PRODUCT("Produit"), + /** Unit number. */ + UNIT("Unit"), + /** Unit before. */ + UNIT_BEFORE("Unit précédent"), + /** unit after. */ + UNIT_AFTER("Unit suivant"), + /** Product before. */ + PRODUCT_BEFORE("Produit précédent"), + /** Product after. */ + PRODUCT_AFTER("Produit suivant"), + /** Engine number. */ + MATRICULE("Matricule moteur"), + /** List of removed modifications. */ + LMR("LMR"), + /** Class. */ + CLASSE("Classe"), + /** Major/Minor. */ + MAJOR_MINOR("Majeur mineur"), + /** Conjoint/Unique. */ + CONJOINT_UNIQUE("Conjoint unique"), + /** Language. */ + LANGUAGE("Langue"), + /** Print type. */ + TYPE_IMPRESSION("Type d'impression"), + /** Start date. */ + DATE_DEBUT("Date de début"), + /** End date. */ + DATE_FIN("Date de fin"), + /** Object type. */ + TYPE_OBJET("Type d'objet"), + /** Unit number in configuration 1. */ + UNIT_CONFIGURATION_1("Unit configuration 1"), + /** Unit number in configuration 2. */ + UNIT_CONFIGURATION_2("Unit configuration 2"), + /** Règle de révision. */ + REVISION_RULE("Règle de révision"), + /** Item */ + ITEM("Item"), + /** Supermodel */ + SUPERMODEL("SuperModel"), + /** Avec le(s) unit(s) gelé(s) */ + WITH_FROZEN_UNIT("Avec le(s) unit(s) gelé(s)"), + /** A partir de Unit */ + FROM_UNIT("A partir de Unit"), + /** Units gelés il y a moins de */ + UNITS_FROZEN_SINCE_LESS_THAN("Units gelés il y a moins de"); + + /** Human readable value for the enumeration. **/ + private final String criteriaValue; + + /** Enumeration cache for conversions. **/ + private static Map enumMap; + + /** Enumeration constructor. **/ + ReportCriteriaEnum(final String aCriteriaValue) { + criteriaValue = aCriteriaValue; + } + + /** + * Getter for object string value. + * + * @return String value with readable format + **/ + @Override + public String toString() { + return criteriaValue; + } + + /** + * Conversion from String to SnecmaObjectTypeEnum. + * + * @param aCriteriaValue String value of the criteria + * @return Enumeration instance for the requested value + **/ + public static synchronized ReportCriteriaEnum getEnum(final String aCriteriaValue) { + if (enumMap == null) { + enumMap = new HashMap<>(); + for (ReportCriteriaEnum currentEnum : ReportCriteriaEnum.values()) { + enumMap.put(currentEnum.toString(), currentEnum); + } + } + return enumMap.get(aCriteriaValue); + } + + /** + * Conversion from {@link DbSchedulingCriteriaVal} to {@link ReportCriteriaEnum}. Uses the enum's criteriaValue property for string matching. + * + * @param criteria String value of the criteria + * @return Enumeration instance for the requested value + **/ + public static synchronized ReportCriteriaEnum valueOf(final DbSchedulingCriteriaVal criteria) { + return getEnum(criteria.getDbCriteria().getCriteriaName()); + } + + /** + * Conversion from {@link DbCriteria} to {@link ReportCriteriaEnum}. Uses the enum's criteriaValue property for string matching. + * + * @param criteria a {@link DbCriteria} + * @return Enumeration instance for the requested value + **/ + public static synchronized ReportCriteriaEnum valueOf(final DbCriteria criteria) { + return getEnum(criteria.getCriteriaName()); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/database/javabean/enumeration/ReportErrorTypeEnum.java b/kurt-utility/src/main/java/com/capgemini/reports/database/javabean/enumeration/ReportErrorTypeEnum.java new file mode 100644 index 0000000..d5199eb --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/database/javabean/enumeration/ReportErrorTypeEnum.java @@ -0,0 +1,9 @@ +package com.capgemini.reports.database.javabean.enumeration; + +/** The type of report errors: Technical errors (bug in the code) or Functional (user doesn't know what he/she's doing. */ +public enum ReportErrorTypeEnum { + /** The user doesn't know what he's doing. */ + FUNCTIONAL, + /** Bug in the code / environment. */ + TECHNICAL +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/database/javabean/enumeration/ReportStateEnum.java b/kurt-utility/src/main/java/com/capgemini/reports/database/javabean/enumeration/ReportStateEnum.java new file mode 100644 index 0000000..0b4d746 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/database/javabean/enumeration/ReportStateEnum.java @@ -0,0 +1,31 @@ +package com.capgemini.reports.database.javabean.enumeration; + +/** + * Represents the state of a report execution. + */ +public enum ReportStateEnum { + /** + * The report has been submitted and its parameters have been checked. The report is delayed or scheduled and is still waiting for being putting in the Queue. + */ + WAIT, + /** + * The report has been submitted and its parameters have been checked. It is waiting in a Queue. + */ + READY, + /** + * The report is being executed, it just got out of its queue. + */ + EXECUTING, + /** + * During the execution, the report generated an error. + */ + FAILED, + /** + * The report has successfully completed. It generated a file, which is awaiting for download. + */ + FINISHED, + /** + * The report State is unknown. + */ + UNKNOWN +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/database/javabean/enumeration/SchedulingEnum.java b/kurt-utility/src/main/java/com/capgemini/reports/database/javabean/enumeration/SchedulingEnum.java new file mode 100644 index 0000000..adb6e1c --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/database/javabean/enumeration/SchedulingEnum.java @@ -0,0 +1,59 @@ +package com.capgemini.reports.database.javabean.enumeration; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.HashMap; +import java.util.Map; + +/** KEYS of CriteriaValue in DB. Please use {@link SchedulingEnum#getEnum(String)} to obtain an instance from its DB value. */ +@AllArgsConstructor +@Getter +public enum SchedulingEnum { + + /** Key to the declared periodicity. Values are 'daily', 'weekly', 'weekend', 'date'. */ + PERIOD("period"), + /** Key to schedule every days (Monday to Sunday). No value required. */ + DAILY("daily"), + /** Key to schedule once every week (Monday to Friday only). Values available: 1, 2, 3, 4, 5. */ + WEEKLY("weekly"), + /** Key to schedule a specific day of every month. Values availble: 1, 2, 3... 31, 'we_1', 'we_2', 'we_3', 'we_4', 'we_5', 'we_6' <-- for end of month. */ + WEEKEND("weekend"), + /** scheduling by date. */ + DATE("date"), + /** value of month. */ + DAY_IN_MONTH_VALUE("day_in_month_value"); + + /** Human readable name for the enumeration. **/ + private final String criteriaName; + + /** Enumeration cache for conversions. **/ + private static final Map enumMap; + + static { + enumMap = new HashMap<>(); + for (SchedulingEnum currentEnum : SchedulingEnum.values()) { + enumMap.put(currentEnum.toString(), currentEnum); + } + } + + /** + * Getter for object string value. + * + * @return String value with readable format + **/ + @Override + public String toString() { + return criteriaName; + } + + /** + * Conversion from String to SchedulingEnum. + * + * @param aSchedulingCriteriaValue String value of the criteria + * @return Enumeration instance for the requested value + **/ + public static synchronized SchedulingEnum getEnum(final String aSchedulingCriteriaValue) { + return enumMap.get(aSchedulingCriteriaValue); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/database/manager/AbstractHibernateManager.java b/kurt-utility/src/main/java/com/capgemini/reports/database/manager/AbstractHibernateManager.java new file mode 100644 index 0000000..b2178bf --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/database/manager/AbstractHibernateManager.java @@ -0,0 +1,106 @@ +package com.capgemini.reports.database.manager; + +import com.capgemini.reports.database.javabean.IPersistedObject; +import org.hibernate.Query; +import org.hibernate.Session; +import org.hibernate.Transaction; + +import java.util.ArrayList; +import java.util.List; + +/** + * Common methods for all Hibernate managers. + * + * @param The type of {@link IPersistedObject} which is meing managed + **/ +public abstract class AbstractHibernateManager { + + private static final String KEY_COLUMN_VALUE = "colValue1"; + private static final String FROM = "FROM "; + + /** + * Common method for searching object by its ID. + */ + public T searchById(Session session, final Long aTechnicalId) { + @SuppressWarnings("unchecked") + T entry = (T) session.load(getManagedClass(), aTechnicalId); + return entry; + } + + /** + * Parent method for coding easily a search query on a specific column. + */ + T searchBy(Session session, final String aColumn, final String aColumnValue) { + Query query = session.createQuery(FROM + getManagedClass().getName() + " r where r." + aColumn + "= :" + KEY_COLUMN_VALUE); + query.setString(KEY_COLUMN_VALUE, aColumnValue); + + List list = query.list(); + T theResult = null; + if (!list.isEmpty()) { + theResult = getManagedClass().cast(list.get(0)); + } + return theResult; + } + + /** + * Parent method for coding easily a search query on a specific column. + */ + List searchAndReturnAllValues(Session session, final String aColumn, final Long aColumnValue) { + Query query = session.createQuery(FROM + getClassName() + " r where r." + aColumn + " = :" + KEY_COLUMN_VALUE); + query.setLong(KEY_COLUMN_VALUE, aColumnValue); + List list = query.list(); + if (!list.isEmpty()) { + @SuppressWarnings("unchecked") + List typedList = (List) list; + return typedList; + } + else { + return new ArrayList<>(); + } + } + + /** + * List all objects of the managed type. + */ + public List getList(Session session) { + return castAll(session.createQuery(FROM + getClassName()).list()); + } + + List castAll(final List rawList) { + List typedList = new ArrayList<>(); + for (Object obj : rawList) { + typedList.add(getManagedClass().cast(obj)); + } + return typedList; + } + + /** + * Update the referenced object. + */ + public void update(Session session, final T aPersistedObj) { + session.update(aPersistedObj); + } + + /** + * Delete the referenced object. + */ + public void delete(Session session, final T aPersistedObj) { + session.delete(aPersistedObj); + } + + /** + * Getter for the class name of the current object. + * + * @return The class name value (without package) + */ + private String getClassName() { + return getManagedClass().getSimpleName(); + } + + /** + * Getter for the JAVA bean class managed by this Hibernate manager instance. + * + * @return The class value (without package) + */ + protected abstract Class getManagedClass(); +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/database/manager/MngCriteria.java b/kurt-utility/src/main/java/com/capgemini/reports/database/manager/MngCriteria.java new file mode 100644 index 0000000..15597d6 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/database/manager/MngCriteria.java @@ -0,0 +1,35 @@ +package com.capgemini.reports.database.manager; + +import com.capgemini.reports.database.javabean.DbCriteria; +import com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum; +import org.hibernate.Session; + +/** Hibernate manager for DBCriteria JAVA bean. **/ +public class MngCriteria extends AbstractHibernateManager { + + @Override + public Class getManagedClass() { + return DbCriteria.class; + } + + /** + * Create a new persistent object for criteria. + */ + public DbCriteria insert(Session session, final ReportCriteriaEnum aCriteriaName, final String aType) { + DbCriteria theCriteria = new DbCriteria(); + // Set specific attribute values + theCriteria.setCriteriaName(aCriteriaName.toString()); + theCriteria.setCriteriaType(aType); + + // Persist object + session.save(theCriteria); + return theCriteria; + } + + /** + * Search query for retrieving Criteria using its name. + */ + DbCriteria searchByName(Session session, final String aName) { + return searchBy(session, "criteriaName", aName); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/database/manager/MngCriteriaVal.java b/kurt-utility/src/main/java/com/capgemini/reports/database/manager/MngCriteriaVal.java new file mode 100644 index 0000000..b147e09 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/database/manager/MngCriteriaVal.java @@ -0,0 +1,145 @@ +package com.capgemini.reports.database.manager; + +import com.capgemini.reports.database.HibernateUtil; +import com.capgemini.reports.database.javabean.DbCriteria; +import com.capgemini.reports.database.javabean.DbCriteriaVal; +import com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import org.hibernate.Query; +import org.hibernate.Session; +import org.hibernate.SessionFactory; + +import java.util.ArrayList; +import java.util.List; + +/** + * Hibernate manager for DbCriteriaVal JAVA bean. + **/ +@Slf4j +public class MngCriteriaVal extends AbstractHibernateManager { + + // Keys + private static final String KEY_REPORT_UID = "reportUID"; + private static final String KEY_REPORT_ID = "reportId"; + + // Queries + private static final String QUERY_CRITERIA_BY_REPORT_UID; + private static final String QUERY_CRITERIA_BY_REPORT_ID; + + static { + String select = "select T2.criteriaName, T1.criteriaValue "; + String from = "from DbReport T0, DbCriteriaVal T1, DbCriteria T2 "; + String whereCoherence = "where T0.id = T1.reportId and T1.criteria = T2.id "; + String whereReportUID = "and T0.reportUid = :" + KEY_REPORT_UID + " "; + String whereReportID = "and T0.id = :" + KEY_REPORT_ID + " "; + String orderBy = "order by T2.id"; + QUERY_CRITERIA_BY_REPORT_UID = select + from + whereCoherence + whereReportUID + orderBy; + QUERY_CRITERIA_BY_REPORT_ID = select + from + whereCoherence + whereReportID + orderBy; + } + + @Override + public Class getManagedClass() { + return DbCriteriaVal.class; + } + + /** + * Create a new criteria value. + */ + private DbCriteriaVal insert(Session session, final DbCriteria aCriteria, final String aCriteriaValue, final Long aReportId) { + log.trace("Inserting DbCriteria entry {}({}) = {} for report {}", aCriteria.getId(), aCriteria.getCriteriaName(), aCriteriaValue, aReportId); + DbCriteriaVal theCriteriaVal = new DbCriteriaVal(); + + theCriteriaVal.setCriteria(aCriteria); + theCriteriaVal.setCriteriaValue(aCriteriaValue); + theCriteriaVal.setReportId(aReportId); + + // Persist object + session.save(theCriteriaVal); + + return theCriteriaVal; + } + + /** + * Create a new criteria value using the criteria name as key. + */ + DbCriteriaVal insertByCriteriaName(Session session, final String aCriteriaName, final String aCriteriaValue, final Long aReportId) { + // Search the corresponding criteria using its name + DbCriteria theCriteria = new MngCriteria().searchByName(session, aCriteriaName); + + return insert(session, theCriteria, aCriteriaValue, aReportId); + } + + /** + * Search in database the list of criteria for a specific report using its UID. + */ + public List searchCriteriasByReportUID(final String aReportUid) { + SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); + Session session = sessionFactory.openSession(); + try { + Query theQuery = session.createQuery(QUERY_CRITERIA_BY_REPORT_UID); + theQuery.setString(KEY_REPORT_UID, aReportUid); + + List result = new ArrayList<>(); + for (Object[] reportData : (List) theQuery.list()) { + result.add(new CriteriaValue((String) reportData[0], (String) reportData[1])); + } + return result; + } + finally { + session.close(); + } + } + + /** + * Search in database the list of criteria for a specific report using its identifier. + */ + List searchCriteriasByReportID(Session session, final long aReportID) { + Query theQuery = session.createQuery(QUERY_CRITERIA_BY_REPORT_ID); + theQuery.setLong(KEY_REPORT_ID, aReportID); + + List result = new ArrayList<>(); + for (Object[] reportData : (List) theQuery.list()) { + result.add(new CriteriaValue((String) reportData[0], (String) reportData[1])); + } + return result; + } + + /** + * Bean object carrying a report criteria's name and value. + */ + @Getter + public static class CriteriaValue { + + private static final String NULL_STRING = "null"; + private final String name; + private final String value; + + /** + * Builds a Criteria Name-Value object. + * + * @param name if null, will be 'null' + * @param value if null, will be 'null' + */ + protected CriteriaValue(final String name, final String value) { + this.name = name == null ? NULL_STRING : name; + this.value = (value == null || value.isEmpty() || "null".equals(value)) ? NULL_STRING : value; + } + + /** + * Builds a Criteria Name-Value object. + * + * @param criteria if null, will be 'null' + * @param value if null, will be 'null' + */ + public CriteriaValue(final ReportCriteriaEnum criteria, final String value) { + this.name = criteria == null ? NULL_STRING : criteria.toString(); + this.value = value == null ? NULL_STRING : value; + } + + @Override + public String toString() { + return name + " = " + value; + } + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/database/manager/MngMemMonitor.java b/kurt-utility/src/main/java/com/capgemini/reports/database/manager/MngMemMonitor.java new file mode 100644 index 0000000..8990983 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/database/manager/MngMemMonitor.java @@ -0,0 +1,97 @@ +package com.capgemini.reports.database.manager; + +import com.capgemini.framework.common.DateHelper; +import com.capgemini.framework.common.SettingsHelper; +import com.capgemini.reports.database.HibernateUtil; +import com.capgemini.reports.database.javabean.DbMemMonitor; +import org.hibernate.Query; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.Transaction; + +import java.sql.Timestamp; +import java.util.Date; +import java.util.List; + +/** + * Hibernate manager for DBReport JAVA bean. + **/ +public class MngMemMonitor extends AbstractHibernateManager { + + private static final int THOUSAND = 1000; + private static final int FIVE = 5; + /** + * Quantity of trace displayed. + **/ + private static final int MAX_MONITOR_TRACE_COUNT = SettingsHelper.getMemoryMaxCount(); + /** + * Elapsed seconds between each trace. + **/ + private static final int MONITOR_FREQUENCY = SettingsHelper.getMemoryFrequency(); + + @Override + public Class getManagedClass() { + return DbMemMonitor.class; + } + + /** + * Create a memory monitoring trace. + * + * @param aFreeMemory free memory + * @param anUsedMemory used memory + * @param aMaxMemory max memory in session + * @param aMaxPercent max memory percent + * @param aTotalMemory total memory + * @return Monitoring trace object + */ + public DbMemMonitor insert(final Double aFreeMemory, final Double anUsedMemory, final Double aMaxMemory, final Double aMaxPercent, + final Double aTotalMemory) { + SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); + Session session = sessionFactory.openSession(); + try { + Transaction transaction = session.beginTransaction(); + DbMemMonitor theMemMonitor = new DbMemMonitor(); + + // Assign default attribute values + theMemMonitor.setMonitorDate(DateHelper.getCurrentSqlTimestamp()); + + // Assign specific attribute values + theMemMonitor.setFreeMemory(aFreeMemory); + theMemMonitor.setMaxMemory(aMaxMemory); + theMemMonitor.setMaxPercent(aMaxPercent); + theMemMonitor.setTotalMemory(aTotalMemory); + theMemMonitor.setUsedMemory(anUsedMemory); + + // Persist object + session.save(theMemMonitor); + transaction.commit(); + + return theMemMonitor; + } + finally { + session.close(); + } + } + + /** + * Search last memory monitor traces. + */ + public List searchMemMonitor() { + SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); + Session session = sessionFactory.openSession(); + try { + String theHqlQuery = "select T0 from DbMemMonitor T0 where monitorDate > :paramMonitorDate order by T0.id desc"; + Query theQuery = session.createQuery(theHqlQuery); + + long theSecDelta = MAX_MONITOR_TRACE_COUNT * MONITOR_FREQUENCY + FIVE; + long theMsDelta = theSecDelta * THOUSAND; + theQuery.setTimestamp("paramMonitorDate", new Timestamp(new Date().getTime() - theMsDelta)); + theQuery.setMaxResults(MAX_MONITOR_TRACE_COUNT); + + return castAll(theQuery.list()); + } + finally { + session.close(); + } + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/database/manager/MngReport.java b/kurt-utility/src/main/java/com/capgemini/reports/database/manager/MngReport.java new file mode 100644 index 0000000..8bd9dc9 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/database/manager/MngReport.java @@ -0,0 +1,659 @@ +package com.capgemini.reports.database.manager; + +import com.capgemini.framework.common.DateHelper; +import com.capgemini.framework.common.SettingsHelper; +import com.capgemini.framework.common.StringHelper; +import com.capgemini.reports.ReportEnum; +import com.capgemini.reports.database.HibernateUtil; +import com.capgemini.reports.database.javabean.DbCriteriaVal; +import com.capgemini.reports.database.javabean.DbReport; +import com.capgemini.reports.database.javabean.DbReportOwner; +import com.capgemini.reports.database.javabean.DbReportType; +import com.capgemini.reports.database.javabean.DbUser; +import com.capgemini.reports.database.javabean.enumeration.ReportStateEnum; +import com.capgemini.reports.database.manager.MngCriteriaVal.CriteriaValue; +import com.capgemini.reports.exceptions.InvalidUserInputException; +import com.capgemini.reports.exceptions.NotFoundException; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.ToString; +import lombok.extern.slf4j.Slf4j; +import org.hibernate.Query; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.Transaction; + +import java.sql.Timestamp; +import java.text.SimpleDateFormat; +import java.util.*; + +/** + * Hibernate manager for DBReport JAVA bean. + **/ +@Getter +@Slf4j +public class MngReport extends AbstractHibernateManager { + + private static final int QUERY_DBREPORT_POS = 0; + private static final int QUERY_LOGIN_POS = 1; + private static final int QUERY_SURNAME_POS = 2; + private static final int QUERY_FIRST_NAME_POS = 3; + private static final int QUERY_PRIORITY_POS = 4; + private static final int QUERY_REQUEST_DATE_POS = 5; + + // Constants + private static final String DATEFORMAT_DD_MM_YYYY_HH_MM_SS = "dd/MM/yyyy HH:mm:ss"; + + // Settings + private static final int MAX_JSP_PAGE_SIZE = SettingsHelper.getJspPaging(); + + // Queries + private static final String QUERY_USER_REPORTS_COUNT; + private static final String QUERY_RUNNING_REPORTS_DATA; + private static final String QUERY_WAITING_REPORTS_DATA; + private static final String QUERY_USER_REPORTS_DATA; + private static final String QUERY_ALL_USERS_AND_REPORTS; + private static final String QUERY_WAITING_REPORTS_DATA_WITH_TYPE; + private static final String QUERY_ALL_REPORTS_SCHEDULING; + + // Query keys (internal use only) + private static final String COLUMN_SCHEDULING_ID = "schedulingReportId"; + private static final String KEY_REPORT_UID = "reportUid"; + private static final String KEY_DB_USER_LOGIN = "DbUserLogin"; + private static final String KEY_DEADLINE = "deadline"; + private static final String KEY_REPORT_CODE = "reportCode"; + private static final String KEY_START_PERIOD = "startPeriod"; + private static final String KEY_END_PERIOD = "endPeriod"; + + static { + String selectData = "select DISTINCT T0, T2.login, T2.surname, T2.firstname, T3.priority, T1.requestDate "; + String from0123 = "from " + DbReport.class.getName() + " T0, " + DbReportOwner.class.getName() + " T1, " + DbUser.class.getName() + " T2, " + DbReportType.class.getName() + " T3 "; + String whereCoherence0123 = "where T0.id = T1.reportId AND T1.userId = T2.id AND T0.reportCode = T3.code "; + String readyOrWait = "and (T0.state = '" + ReportStateEnum.READY + "' OR T0.state = '" + ReportStateEnum.WAIT + "') "; + String readyOrExecuting = "and (T0.state = '" + ReportStateEnum.READY + "' OR T0.state = '" + ReportStateEnum.EXECUTING + "') "; + String andUserLogin = "and T2.login = :" + KEY_DB_USER_LOGIN + " "; + String andReportCode = "and T0.reportCode = :" + KEY_REPORT_CODE + " "; + String orderBy = "order by T0.startGenerationDate desc, T1.requestDate desc"; + QUERY_RUNNING_REPORTS_DATA = StringHelper.concatToString(selectData, from0123, whereCoherence0123, readyOrExecuting, orderBy); + QUERY_WAITING_REPORTS_DATA = StringHelper.concatToString(selectData, from0123, whereCoherence0123, readyOrWait, orderBy); + QUERY_WAITING_REPORTS_DATA_WITH_TYPE = + StringHelper.concatToString(selectData, from0123, whereCoherence0123, readyOrWait, andReportCode, orderBy); + QUERY_USER_REPORTS_DATA = StringHelper.concatToString(selectData, from0123, whereCoherence0123, andUserLogin, orderBy); + } + + static { + String select = "select T2.surname, T2.firstname, T0.reportCode, count(DISTINCT T1.reportId) "; + String from = "from DbReport T0, DbReportOwner T1, DbUser T2 "; + String whereCoherence = "where T0.id = T1.reportId and T1.userId = T2.id "; + String andWhereCriteria = "and T1.requestDate between TO_DATE(:" + KEY_START_PERIOD + ") and TO_DATE(:" + KEY_END_PERIOD + ") + 1 "; + String andIsNotReportScheduling = "and T0.schedulingReportId IS NULL "; + String groupBy = "group by T0.reportCode, T2.surname, T2.firstname "; + String orderBy = "order by T2.surname, T2.firstname, T0.reportCode "; + QUERY_ALL_USERS_AND_REPORTS = select + from + whereCoherence + andWhereCriteria + andIsNotReportScheduling + groupBy + orderBy; + } + + static { + String selectCount = "select count(*) "; + String selectStats = "select 'Administrateur', 'planification', T0.reportCode, count(DISTINCT T1.reportId) "; + String from012 = "from DbReport T0, DbReportOwner T1, DbUser T2 "; + String whereCoherence012 = "where T0.id = T1.reportId and T1.userId = T2.id "; + String andLogin = "and T2.login = :" + KEY_DB_USER_LOGIN + " "; + String andPeriod = "and T1.requestDate between TO_DATE(:" + KEY_START_PERIOD + ") and TO_DATE(:" + KEY_END_PERIOD + ") + 1 "; + String andIsReportScheduling = "and T0.schedulingReportId IS NOT NULL "; + String groupBy = "group by T0.reportCode "; + String orderBy = "order by T0.reportCode "; + QUERY_ALL_REPORTS_SCHEDULING = + StringHelper.concatToString(selectStats, from012, whereCoherence012, andPeriod, andIsReportScheduling, groupBy, orderBy); + QUERY_USER_REPORTS_COUNT = StringHelper.concatToString(selectCount, from012, whereCoherence012, andLogin); + } + + /** + * Create a new report in database setting its mandatory attributes. + * + * @param session + * @param aReportCode String - Code of the report (ie: "R01", "R21"...) + * @param uuid String - the Universal Unique Identifier of the Report Execution + * @param aState {@link ReportStateEnum} - State of the report + * @param schedulingReportId String - the id of the scheduling if it exists (mandatory for a scheduling).
    + * Else, this is not a scheduling and the value should be null or empty string. + * @return The created report instance + */ + private DbReport insert(Session session, final String aReportCode, final String uuid, final ReportStateEnum aState, final Long schedulingReportId) { + log.debug("Inserting DbReport entry UID={} {}", uuid, schedulingReportId == null ? "" : ("for Scheduling " + schedulingReportId)); + DbReport theReport = new DbReport(); + + // Assign default attribute values + theReport.setReportUid(uuid); + theReport.setState(aState.toString()); + if (schedulingReportId != null) { + theReport.setSchedulingReportId(schedulingReportId); + } + + // Set specific attribute values + theReport.setReportCode(aReportCode); + + // Persist object + session.save(theReport); + + return theReport; + } + + /** + * Create a new report in database setting its mandatory attributes and inject its associated criteria list and list of users data. + * + * @param session + * @param aReportCode String - Code of the report (ie: "R01", "R21"...) + * @param uuid String - the Universal Unique Identifier of the Report Execution + * @param aState {@link ReportStateEnum} - State of the report + * @param criteriaList List<{@link CriteriaValue}> - list containing all {@link CriteriaValue}s + * @param theUsers List<{@link DbUser}> - all the users asking for the report generation + * @param schedulingReportId Long - the id of the scheduling if it exists (mandatory for a scheduling).
    + * Else, this is not a scheduling and the value should be null or empty string. + * @return The created report instance + * @throws InvalidUserInputException Occurs only when the login of the request sender is unknown in database + */ + public DbReport insertWithCriteriaAndOwners(Session session, final String aReportCode, final String uuid, final ReportStateEnum aState, + final List criteriaList, final List theUsers, final Long schedulingReportId) throws InvalidUserInputException { + // Create the report + DbReport theNewReport = insert(session, aReportCode, uuid, aState, schedulingReportId); + + MngReportOwner mngReportOwner = new MngReportOwner(); + for (DbUser user : theUsers) { + // Assign the execution request entry to all the users + mngReportOwner.insert(session, theNewReport, user); + } + + // Create all criteria + Long theReportId = theNewReport.getId(); + MngCriteriaVal theCriteriaValManager = new MngCriteriaVal(); + for (CriteriaValue criterion : criteriaList) { + theCriteriaValManager.insertByCriteriaName(session, criterion.getName(), criterion.getValue(), theReportId); + } + + return theNewReport; + } + + /** + * Create a new report in database setting its mandatory attributes and inject its associated criteria list and user data. + * + * @param aReportCode String - Code of the report (ie: "R01", "R21"...) + * @param uuid String - the Universal Unique Identifier of the Report Execution + * @param aState {@link ReportStateEnum} - State of the report + * @param criteriaList List<{@link CriteriaValue}> - list containing all {@link CriteriaValue}s + * @param theUser {@link DbUser} - the user asking for the report generation + * @return The created report instance + * @throws InvalidUserInputException Occurs only when the login of the request sender is unknown in database + */ + public DbReport insertWithCriteriaAndOwner(final String aReportCode, final String uuid, final ReportStateEnum aState, + final List criteriaList, final DbUser theUser) throws InvalidUserInputException { + SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); + Session session = sessionFactory.openSession(); + try { + Transaction transaction = session.beginTransaction(); + + // Create the report + // This report is not scheduled + DbReport theNewReport = insert(session, aReportCode, uuid, aState, null); + + // Assign the execution request entry + MngReportOwner mngReportOwner = new MngReportOwner(); + mngReportOwner.insert(session, theNewReport, theUser); + + // Create all criteria + Long theReportId = theNewReport.getId(); + MngCriteriaVal theCriteriaValManager = new MngCriteriaVal(); + for (CriteriaValue criterion : criteriaList) { + theCriteriaValManager.insertByCriteriaName(session, criterion.getName(), criterion.getValue(), theReportId); + } + transaction.commit(); + return theNewReport; + } + finally { + session.close(); + } + } + + /** + * Search query for retrieving Report using its UUID. + */ + public DbReport searchByUid(final String aReportUid, Session session) throws NotFoundException { + DbReport report = searchBy(session, KEY_REPORT_UID, aReportUid); + if (report == null) { + throw new NotFoundException("Unable to find a matching entry in the DB for this report:" + aReportUid); + } + return report; + } + + /** + * Search query for retrieving all the reports using this scheduling name. + */ + public List searchBySchedulingId(final Long aSchedulingId, Session session) { + return searchAndReturnAllValues(session, COLUMN_SCHEDULING_ID, aSchedulingId); + } + + /** + * Search in database the list of reports that belong to a provided user (using its login as search criteria). + */ + public List searchUserReports(Session session, final String aUserLogin, final int aPageNumber) { + Query theQuery = session.createQuery(QUERY_USER_REPORTS_DATA); + theQuery.setMaxResults(MAX_JSP_PAGE_SIZE); + theQuery.setFirstResult(MAX_JSP_PAGE_SIZE * (aPageNumber - 1)); + theQuery.setString(KEY_DB_USER_LOGIN, aUserLogin); + List result = new ArrayList<>(); + List rawResults = theQuery.list(); + for (Object[] reportData : rawResults) { + final DbReport dbReport = (DbReport) reportData[QUERY_DBREPORT_POS]; + final String login = (String) reportData[QUERY_LOGIN_POS]; + final String surname = (String) reportData[QUERY_SURNAME_POS]; + final String firstName = (String) reportData[QUERY_FIRST_NAME_POS]; + final Long priority = (Long) reportData[QUERY_PRIORITY_POS]; + final Timestamp requestDate = (Timestamp) reportData[QUERY_REQUEST_DATE_POS]; + final String requestDateStr = new SimpleDateFormat(DATEFORMAT_DD_MM_YYYY_HH_MM_SS).format(requestDate); + result.add(new RunningReportEntry(dbReport, login, surname, firstName, priority, requestDateStr)); + } + return result; + } + + /** + * Count in database the report list of a specific user using its login as search criteria. + * + * @param session + * @param aUserLogin String - Login of the searched user + * @return DbReport list + */ + public Long countUserReports(Session session, final String aUserLogin) { + Query theQuery = session.createQuery(QUERY_USER_REPORTS_COUNT); + theQuery.setString(KEY_DB_USER_LOGIN, aUserLogin); + return (Long) theQuery.uniqueResult(); + } + + /** + * Search in database the executing reports. + * + * @param session + * @return List of report entries, each of them being containing:
    + *
      + *
    • DbReport list
    • + *
    • Surname
    • + *
    • First name
    • + *
    • Report priority
    • + *
    + */ + public List searchRunningReports(Session session) { + Query theQuery = session.createQuery(QUERY_RUNNING_REPORTS_DATA); + List result = new ArrayList<>(); + for (Object[] reportData : (List) theQuery.list()) { + DbReport report = (DbReport) reportData[QUERY_DBREPORT_POS]; + String login = (String) reportData[QUERY_LOGIN_POS]; + String surname = (String) reportData[QUERY_SURNAME_POS]; + String firstName = (String) reportData[QUERY_FIRST_NAME_POS]; + Long priority = (Long) reportData[QUERY_PRIORITY_POS]; + Timestamp requestDate = (Timestamp) reportData[QUERY_REQUEST_DATE_POS]; + String requestDateStr = new SimpleDateFormat(DATEFORMAT_DD_MM_YYYY_HH_MM_SS).format(requestDate); + RunningReportEntry rep = new RunningReportEntry(report, login, surname, firstName, priority, requestDateStr); + result.add(rep); + } + return result; + } + + /** + * Search in database the reports which are on the READY (ready to run in queue) or WAITING (scheduled) state. + */ + public List searchWaitingReports(Session session) { + Query theQuery = session.createQuery(QUERY_WAITING_REPORTS_DATA); + List result = new ArrayList<>(); + for (Object[] reportData : (List) theQuery.list()) { + final DbReport dbReport = (DbReport) reportData[QUERY_DBREPORT_POS]; + final String login = (String) reportData[QUERY_LOGIN_POS]; + final String surname = (String) reportData[QUERY_SURNAME_POS]; + final String firstName = (String) reportData[QUERY_FIRST_NAME_POS]; + final Long priority = (Long) reportData[QUERY_PRIORITY_POS]; + final Timestamp requestDate = (Timestamp) reportData[QUERY_REQUEST_DATE_POS]; + final String requestDateStr = new SimpleDateFormat(DATEFORMAT_DD_MM_YYYY_HH_MM_SS).format(requestDate); + final RunningReportEntry fullReportEntry = new RunningReportEntry(dbReport, login, surname, firstName, priority, requestDateStr); + result.add(fullReportEntry); + } + return result; + } + + /** + * Get reports by report code and user login in a specific period. + * + * @param session + * @param aStartPeriod Starting period + * @param aEndPeriod End period + * @return List of {@link ReportLaunchByUser} + */ + public List searchUsersReports(Session session, final Date aStartPeriod, final Date aEndPeriod) { + Query theQuery = session.createQuery(QUERY_ALL_USERS_AND_REPORTS); + theQuery.setDate(KEY_START_PERIOD, aStartPeriod); + theQuery.setDate(KEY_END_PERIOD, aEndPeriod); + return parseStatisticsData(theQuery); + } + + /** + * Get report scheduling count by report code and admin in a specific period. + * + * @param session + * @param aStartPeriod Starting period + * @param aEndPeriod End period + * @return List of report entries, each of them being an array containing:
    + *
      + *
    • Index 0: Surname

    • + *
    • Index 1: First name

    • + *
    • Index 2: Report code

    • + *
    • Index 3: Report count
    • + *
    • Index 4[0]: year
    • + *
    • Index 4[1]: month
    • + *
    + */ + public List searchAdminSchedulingReports(Session session, final Date aStartPeriod, final Date aEndPeriod) { + Query theQuery = session.createQuery(QUERY_ALL_REPORTS_SCHEDULING); + theQuery.setDate(KEY_START_PERIOD, aStartPeriod); + theQuery.setDate(KEY_END_PERIOD, aEndPeriod); + return parseStatisticsData(theQuery); + } + + /** + * Executes the query and browses the results.
    + * Expecting an array containing: + *
      + *
    • Index 0: Surname

    • + *
    • Index 1: First name

    • + *
    • Index 2: Report code

    • + *
    • Index 3: Report count
    • + *
    • Index 4[0]: year
    • + *
    • Index 4[1]: month
    • + *
    + * + * @param theQuery the query to execute + * @return the browsed {@link List} + */ + private List parseStatisticsData(final Query theQuery) { + List result = new ArrayList<>(); + for (Object[] reportData : (List) theQuery.list()) { + final String surname = (String) reportData[QUERY_DBREPORT_POS]; + final String firstName = (String) reportData[QUERY_LOGIN_POS]; + final String reportCode = (String) reportData[QUERY_SURNAME_POS]; + final Long reportCount = (Long) reportData[QUERY_FIRST_NAME_POS]; + final ReportLaunchByUser launch = new ReportLaunchByUser(reportCode, surname, firstName, reportCount); + result.add(launch); + } + return result; + } + + /** + * Searches the DB to find all report of the specified type that match the provided list of criteria. + */ + public List searchQueuedReportsWithCriteria(Session session, final ReportEnum reportEnum, final List requestedCriteriaList) { + // First search all Waiting report executions + List recentReports = searchWaitingReportsInstances(session, reportEnum); + + // Prepare requested Criteria: put them in a map for fast retrieval + Map requestedCriteriaMap = new HashMap<>(); + for (CriteriaValue requestedCriteria : requestedCriteriaList) { + requestedCriteriaMap.put(requestedCriteria.getName(), requestedCriteria.getValue()); + } + + // Then for each recent executions check if the criteria were the same + List duplicates = new ArrayList<>(); + for (RunningReportEntry report : recentReports) { + List criteriaValues = new MngCriteriaVal().searchCriteriasByReportID(session, report.getReport().getId()); + if (hasSameCriteria(requestedCriteriaMap, criteriaValues)) { + duplicates.add(report); + } + } + return duplicates; + } + + private List searchWaitingReportsInstances(Session session, final ReportEnum reportEnum) { + Query theQuery = session.createQuery(QUERY_WAITING_REPORTS_DATA_WITH_TYPE); + theQuery.setString(KEY_REPORT_CODE, reportEnum.getReportCode()); + List result = new ArrayList<>(); + for (Object[] reportData : (List) theQuery.list()) { + DbReport dbreport = (DbReport) reportData[QUERY_DBREPORT_POS]; + String login = (String) reportData[QUERY_LOGIN_POS]; + String surname = (String) reportData[QUERY_SURNAME_POS]; + String firstname = (String) reportData[QUERY_FIRST_NAME_POS]; + Long priority = (Long) reportData[QUERY_PRIORITY_POS]; + Timestamp requestDate = (Timestamp) reportData[QUERY_REQUEST_DATE_POS]; + String requestDateStr = new SimpleDateFormat(DATEFORMAT_DD_MM_YYYY_HH_MM_SS).format(requestDate); + RunningReportEntry rep = new RunningReportEntry(dbreport, login, surname, firstname, priority, requestDateStr); + result.add(rep); + } + return result; + } + + private boolean hasSameCriteria(final Map requestedCriteriaMap, final List criteriaValues) { + // Check both list have at least same size + if (criteriaValues.size() != requestedCriteriaMap.size()) { + return false; + } + // Search if DB entries all exist in requested Criteria + for (CriteriaValue criteriaValue : criteriaValues) { + if (!isCriteriaInList(criteriaValue, requestedCriteriaMap)) { + return false; + } + } + // One set is inside the other set, and both are same size: so both sets are equal! + return true; + } + + private boolean isCriteriaInList(final CriteriaValue criteria, final Map requestedCriteriaMap) { + boolean noValue = criteria.getValue() == null || criteria.getValue().isEmpty() || "null".equals(criteria.getValue()); + boolean keyISInMap = requestedCriteriaMap.containsKey(criteria.getName()); + if (keyISInMap) { + String value = requestedCriteriaMap.get(criteria.getName()); + if (value == null || value.isEmpty() || "null".equals(value)) { + // If no value requested and no value obtained, it's ok. + return noValue; + } + else { + return value.equals(criteria.getValue()); + } + } + else { + // Key is not in the map, if value is absent then it's normal + return noValue; + } + } + + /** + * Search for all reports which were executed before a provided deadline. + */ + private List searchReportsBeforeDate(Session session, final Timestamp deadline) { + Query theQuery = session.createQuery( + "SELECT T0 " + + "FROM DbReport T0 " + + "WHERE T0.schedulingReportId IS NULL " + + "AND (T0.startGenerationDate IS NULL AND T0.endGenerationDate IS NULL) " + + "OR (T0.startGenerationDate IS NOT NULL AND T0.startGenerationDate < :deadline) " + + "OR (T0.endGenerationDate IS NOT NULL AND T0.endGenerationDate < :deadline) " + + "ORDER BY T0.reportUid"); + theQuery.setTimestamp(KEY_DEADLINE, deadline); + return castAll(theQuery.list()); + } + + /** + * Search for all reports which were executed before a provided deadline. + */ + private List searchScheduledReportsBeforeDate(Session session, final Timestamp deadline) { + Query theQuery = session.createQuery( + "SELECT T0 " + + "FROM DbReport T0 " + + "WHERE T0.schedulingReportId IS NOT NULL " + + "AND (T0.startGenerationDate IS NULL AND T0.endGenerationDate IS NULL) " + + "OR (T0.startGenerationDate IS NOT NULL AND T0.startGenerationDate < :deadline) " + + "OR (T0.endGenerationDate IS NOT NULL AND T0.endGenerationDate < :deadline) " + + "ORDER BY T0.reportUid"); + theQuery.setTimestamp(KEY_DEADLINE, deadline); + return castAll(theQuery.list()); + } + + /** + * Deletes all reports in the DB that were started before the deadline. + * + * @param deadline the deadline (literally!) + * @return the {@link List} of removed Entries + */ + public List deleteReportsBeforeDate(final Calendar deadline) { + SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); + Session session = sessionFactory.openSession(); + try { + Transaction transaction = session.beginTransaction(); + List reports = new MngReport().searchReportsBeforeDate(session, DateHelper.toTimestamp(deadline)); + List removed = deleteCascade(session, reports); + transaction.commit(); + return removed; + } + finally { + session.close(); + } + } + + /** + * Deletes all scheduling reports in the DB that were started before the deadline. + * + * @param deadline the deadline (literally!) + * @return the {@link List} of removed Entries + */ + public List deleteScheduledReportsBeforeDate(final Calendar deadline) { + SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); + Session session = sessionFactory.openSession(); + try { + Transaction transaction = session.beginTransaction(); + // HQL cannot delete from multiple tables, so let's SELECT first... + List reports = new MngReport().searchScheduledReportsBeforeDate(session, DateHelper.toTimestamp(deadline)); + List removed = deleteCascade(session, reports); + transaction.commit(); + return removed; + } + finally { + session.close(); + } + } + + // HQL cannot delete from multiple tables, so we need to browse and delete the entries one by one + private List deleteCascade(Session session, List reports) { + List removed = new ArrayList<>(); + log.trace("Deleting {} DbReport entries and all their associated owners and criteria values", reports.size()); + MngReportOwner mngReportOwner = new MngReportOwner(); + MngCriteriaVal mngCriteriaVal = new MngCriteriaVal(); + for (DbReport dbReport : reports) { + log.trace(" + Deleting DbRport with Id {} (generated on {})", dbReport.getId(), dbReport.getStartGenerationDate()); + + // Search all owners + List owners = mngReportOwner.searchAndReturnAllValues(session, "reportId", dbReport.getId()); + log.trace(" ->Deleting {} DbReportOwner entries", owners.size()); + for (DbReportOwner dbReportOwner : owners) { + log.trace(" + Deleting DbRportOwner {} of Report {} user ID = {} ", dbReportOwner.getId(), dbReportOwner.getReportId(), + dbReportOwner.getUserId()); + session.delete(dbReportOwner); // Delete each owner + } + + // Search all criteria + List criteria = mngCriteriaVal.searchAndReturnAllValues(session, "reportId", dbReport.getId()); + log.trace(" ->Deleting {} DbCriteriaVal entries", criteria.size()); + for (DbCriteriaVal criteriaValue : criteria) { + log.trace(" + Deleting DbCriteriaVal {} of Report {} for value {}", criteriaValue.getId(), criteriaValue.getReportId(), + criteriaValue.getCriteriaValue()); + session.delete(criteriaValue); // Delete each criteria value + } + + // Delete the report now + log.trace(" ->Deleting the DbReport {} itself", dbReport.getId()); + session.delete(dbReport); // Delete the report + removed.add(new RemovedReportEntry(dbReport, owners, criteria)); + } + return removed; + } + + @Override + public Class getManagedClass() { + return DbReport.class; + } + + /** + * Updates the file name of a report. Usually overwriting classical filename with scheduling filename. + * + * @param reportTechnicalUid the report UID + * @param scheduledReportFileName the filename + * @throws NotFoundException if the report entry wasn't found + */ + public void updateFileName(String reportTechnicalUid, String scheduledReportFileName) throws NotFoundException { + SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); + Session session = sessionFactory.openSession(); + try { + Transaction transaction = session.beginTransaction(); + DbReport dbReport = searchByUid(reportTechnicalUid, session); + dbReport.setFileName(scheduledReportFileName); + update(session, dbReport); + transaction.commit(); + } + finally { + session.close(); + } + } + + /** + * Simple data class. + */ + @Getter + @ToString + @AllArgsConstructor(access = AccessLevel.PRIVATE) + public static class RemovedReportEntry { + private final DbReport report; + private final List owner; + private final List criteria; + } + + /** + * Represents a report entry in the DB, specifically from the logged-in user's point of view.
    + * Contains reference to a {@link DbReport}, the login/surname/firstname of its owner, the priority, and theoriginal request date + */ + @AllArgsConstructor + @Getter + public class RunningReportEntry { + private final DbReport report; + private final String login; + private final String surname; + private final String firstName; + private final Long reportPriority; + private final String requestDate; + + /** + * Returns a 'safe' username: 'Name Surname' or, if any is unavailable, then returns the login. + * + * @return a safe name, which always contains relevant information even with missing naming data + */ + public String getSafeName() { + boolean fistNameIsNull = isNull(firstName); + boolean surNameIsNull = isNull(surname); + return (fistNameIsNull || surNameIsNull) ? login : firstName + " " + surname; + } + + private boolean isNull(final String string) { + return string == null || string.isEmpty() || "null".equals(string); + } + } + + /** + * Represents a report entry in the DB. + */ + @AllArgsConstructor + @Getter + public class ReportLaunchByUser { + private final String reportCode; + private final String surname; + private final String firstName; + private final Long reportCount; + + @Override + public String toString() { + return "ReportLaunchByUser [reportCode=" + reportCode + ", surname=" + surname + ", firstName=" + firstName + ", reportCount=" + + reportCount + "]"; + } + + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/database/manager/MngReportOwner.java b/kurt-utility/src/main/java/com/capgemini/reports/database/manager/MngReportOwner.java new file mode 100644 index 0000000..ef9cd66 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/database/manager/MngReportOwner.java @@ -0,0 +1,63 @@ +package com.capgemini.reports.database.manager; + +import com.capgemini.framework.common.DateHelper; +import com.capgemini.reports.database.javabean.DbReport; +import com.capgemini.reports.database.javabean.DbReportOwner; +import com.capgemini.reports.database.javabean.DbUser; +import com.capgemini.reports.database.manager.MngReport.RunningReportEntry; +import lombok.extern.slf4j.Slf4j; +import org.hibernate.Query; +import org.hibernate.Session; + +import java.util.List; + +/** + * Hibernate manager for DBReport JAVA bean. + **/ +@Slf4j +public class MngReportOwner extends AbstractHibernateManager { + + private static final String SELECT_REPORT_OWNERS; + + static { + SELECT_REPORT_OWNERS = "from DbReportOwner where reportId = :DbReportId order by id desc"; + } + + @Override + public Class getManagedClass() { + return DbReportOwner.class; + } + + /** + * Create a new affectation of a report execution to a user in database. + */ + protected DbReportOwner insert(Session session, final DbReport aReport, final DbUser aUser) { + log.debug("Inserting DbReportOwner entry report={}({}) - owner={}({})", aReport.getId(), aReport.getReportCode(), aUser.getId(), aUser.getLogin()); + DbReportOwner theReportOwner = new DbReportOwner(); + + // Assign default attribute values + theReportOwner.setReportId(aReport.getId()); + theReportOwner.setUserId(aUser.getId()); + theReportOwner.setRequestDate(DateHelper.getCurrentSqlTimestamp()); + + // Persist object + session.save(theReportOwner); + return theReportOwner; + } + + /** + * Search for all the {@link DbReportOwner}s that subscribed to the report whose ID is provided. A result page number above 0 can be provided to browse further results. + */ + public List searchReportOwners(Session session, final Long aReportId) { + Query theQuery = session.createQuery(SELECT_REPORT_OWNERS); + theQuery.setLong("DbReportId", aReportId); + return castAll(theQuery.list()); + } + + /** + * Creates and persists a {@link DbReportOwner} instance linking the provided {@link DbUser} to the provided report. + */ + public void subscribe(Session session, final DbUser dbUser, final RunningReportEntry report) { + insert(session, report.getReport(), dbUser); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/database/manager/MngReportType.java b/kurt-utility/src/main/java/com/capgemini/reports/database/manager/MngReportType.java new file mode 100644 index 0000000..5d7ba36 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/database/manager/MngReportType.java @@ -0,0 +1,110 @@ +package com.capgemini.reports.database.manager; + +import com.capgemini.reports.ReportEnum; +import com.capgemini.reports.database.HibernateUtil; +import com.capgemini.reports.database.javabean.DbReportType; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.Transaction; + +import java.util.List; + +/** + * Hibernate manager for DBReportType JAVA bean. + **/ +public class MngReportType extends AbstractHibernateManager { + + private static final String QUERY_ALL_SCHEDULABLE_REPORT_TYPES; + + static { + String select = "select T0.code "; + String from = "from " + DbReportType.class.getName() + " T0 "; + String whereSchedulable = "where T0.isCandidateForScheduling = 'TRUE' "; + String orderBy = "order by T0.code asc "; + QUERY_ALL_SCHEDULABLE_REPORT_TYPES = select + from + whereSchedulable + orderBy; + } + + @Override + public Class getManagedClass() { + return DbReportType.class; + } + + /** + * Create a new report type in database setting its mandatory attributes. + */ + public DbReportType insert(Session session, final String aReportCode, final String aTitle, final Long aPriority, final String aRevisionRule) { + DbReportType theReport = new DbReportType(); + + // Assign default attribute values + theReport.setCode(aReportCode); + theReport.setTitle(aTitle); + theReport.setPriority(aPriority); + theReport.setRevisionRule(aRevisionRule); + + // Persist object + session.save(theReport); + return theReport; + } + + /** + * Search query for retrieving Report type using {@link ReportEnum}. + */ + public DbReportType search(Session session, final ReportEnum report) { + return searchBy(session, "code", report.getReportCode()); + } + + /** + * Search query for retrieving Report type using its code. + */ + private DbReportType searchByUid(Session session, final String aCode) { + return searchBy(session, "code", aCode); + } + + /** + * Return true or false if current report is authorized. + */ + public boolean isAuthorized(Session session, final String aCode) { + return Boolean.valueOf(searchByUid(session, aCode).getReportAuthorized().toLowerCase()); + } + + /** + * Return true or false if current report is authorized. + */ + public boolean isAuthorized(final ReportEnum aReport) { + SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); + Session session = sessionFactory.openSession(); + try { + return Boolean.valueOf(searchByUid(session, aReport.getReportCode()).getReportAuthorized().toLowerCase()); + } + finally { + session.close(); + } + } + + /** + * Obtain all the report types which are marked as Schedulable in the DB. + */ + public List getAllSchedulableReportTypes(Session session) { + return session.createQuery(QUERY_ALL_SCHEDULABLE_REPORT_TYPES).list(); + } + + + /** + * Changes the 'authorization' status of a Report Type. + */ + public DbReportType setReportActivation(final String reportCode, final String reportAuthorized) { + SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); + Session session = sessionFactory.openSession(); + try { + Transaction transaction = session.beginTransaction(); + DbReportType dbReportType = searchBy(session, "code", reportCode); + dbReportType.setReportAuthorized(reportAuthorized); + update(session, dbReportType); + transaction.commit(); + return dbReportType; + } + finally { + session.close(); + } + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/database/manager/MngSchedulingCriteriaVal.java b/kurt-utility/src/main/java/com/capgemini/reports/database/manager/MngSchedulingCriteriaVal.java new file mode 100644 index 0000000..59214b9 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/database/manager/MngSchedulingCriteriaVal.java @@ -0,0 +1,300 @@ +package com.capgemini.reports.database.manager; + +import com.capgemini.reports.database.HibernateUtil; +import com.capgemini.reports.database.javabean.DbCriteria; +import com.capgemini.reports.database.javabean.DbSchedulingCriteriaVal; +import com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum; +import com.capgemini.reports.database.javabean.enumeration.SchedulingEnum; +import com.capgemini.reports.database.manager.MngCriteriaVal.CriteriaValue; +import com.capgemini.reports.exceptions.InvalidInputException; +import com.capgemini.reports.periodicity.PeriodFactory; +import com.capgemini.reports.periodicity.SchedulingPeriod; +import com.google.common.base.Joiner; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import org.hibernate.Query; +import org.hibernate.Session; +import org.hibernate.SessionFactory; + +import java.util.ArrayList; +import java.util.EnumMap; +import java.util.List; +import java.util.Map; + +/** + * Hibernate manager for {@link DbSchedulingCriteriaVal} JAVA bean. + **/ +@Slf4j +public class MngSchedulingCriteriaVal extends AbstractHibernateManager { + + private static final String COLUMN_SCHEDULING_REPORT_ID = "schedulingReportId"; + private static final String KEY_REPORT_ID = "schedulingReportId"; + + private static final String QUERY_SELECT_CRITERIAS_VALUES; + private static final String QUERY_SELECT_FUNCTIONAL_CRITERIAS_VALUES; + private static final String QUERY_SELECT_FUNCTIONAL_CRITERIAS_DATA; + private static final String QUERY_SELECT_TEMPORAL_CRITERIAS_VALUES; + private static final String QUERY_SELECT_TEMPORAL_CRITERIAS_DATA; + private static final String QUERY_DELETE_CRITERIAS_VALUES_OF_SCHEDULING; + private static final String QUERY_SELECT_PERIOD; + private static final String QUERY_DELETE_TEMPORAL_CRITERIAS_VALUES_OF_SCHEDULING; + private static final String QUERY_DELETE_FUNCTIONAL_CRITERIAS_VALUES_OF_SCHEDULING; + + static { + String select = "SELECT DISTINCT T0.criteriaName, T1.criteriaValue "; + String from = "FROM DbSchedulingCriteriaVal T1, DbCriteria T0 "; + String whereCoherence = "WHERE T1.dbCriteria = T0.id "; + String andReportId = "AND T1.schedulingReportId = :" + KEY_REPORT_ID + " "; + String andIsFunctional = "AND T0.isTemporel = 'FALSE' "; + String andIsTemporal = "AND T0.isTemporel = 'TRUE' "; + String orderBy = "ORDER BY T0.criteriaName ASC"; + QUERY_SELECT_FUNCTIONAL_CRITERIAS_DATA = select + from + whereCoherence + andReportId + andIsFunctional + orderBy; + QUERY_SELECT_TEMPORAL_CRITERIAS_DATA = select + from + whereCoherence + andReportId + andIsTemporal + orderBy; + } + + static { + String select = "SELECT T0 "; + String selectID = "SELECT T0.id "; + String from = "FROM DbSchedulingCriteriaVal T0, DbCriteria T1 "; + String whereCoherence = "WHERE T0.dbCriteria = T1.id "; + String andReportId = "AND T0.schedulingReportId = :" + KEY_REPORT_ID + " "; + String andIsPeriodicity = "AND T1.criteriaName ='period' "; + String andIsFunctional = "AND T1.isTemporel = 'FALSE' "; + String andIsTemporal = "AND T1.isTemporel = 'TRUE' "; + QUERY_SELECT_CRITERIAS_VALUES = select + from + whereCoherence + andReportId; + QUERY_SELECT_PERIOD = select + from + whereCoherence + andReportId + andIsPeriodicity; + QUERY_SELECT_FUNCTIONAL_CRITERIAS_VALUES = select + from + whereCoherence + andReportId + andIsFunctional; + QUERY_SELECT_TEMPORAL_CRITERIAS_VALUES = select + from + whereCoherence + andReportId + andIsTemporal; + + String delete = "DELETE DbSchedulingCriteriaVal "; + String whereIn = "WHERE id in ("; + String endWhere = ")"; + final String selectValueID = selectID + from + whereCoherence + andReportId; + QUERY_DELETE_CRITERIAS_VALUES_OF_SCHEDULING = delete + whereIn + selectValueID + endWhere; + QUERY_DELETE_FUNCTIONAL_CRITERIAS_VALUES_OF_SCHEDULING = delete + whereIn + selectValueID + andIsFunctional + endWhere; + QUERY_DELETE_TEMPORAL_CRITERIAS_VALUES_OF_SCHEDULING = delete + whereIn + selectValueID + andIsTemporal + endWhere; + } + + @Override + protected Class getManagedClass() { + return DbSchedulingCriteriaVal.class; + } + + /** + * Create a new scheduling criteria value. + */ + private DbSchedulingCriteriaVal insert(Session session, final DbCriteria dbCriteria, final String criteriaValue, final Long schedulingReportId) { + log.debug("Insert SchedulingCriteriaVal: {}({}) = {} for {}", dbCriteria.getId(), dbCriteria.getCriteriaName(), criteriaValue, + schedulingReportId); + + DbSchedulingCriteriaVal theSchedulingCriteriaVal = new DbSchedulingCriteriaVal(); + + theSchedulingCriteriaVal.setCriteriaValue(criteriaValue); + theSchedulingCriteriaVal.setDbCriteria(dbCriteria); + theSchedulingCriteriaVal.setSchedulingReportId(schedulingReportId); + + // Persist object + session.save(theSchedulingCriteriaVal); + + return theSchedulingCriteriaVal; + } + + /** + * Create a new scheduling criteria value using the criteria name as key. + */ + DbSchedulingCriteriaVal insertByCriteriaName(Session session, final String criteriaName, final String criteriaValue, final Long schedulingReportId) { + // Search the corresponding criteria using its name + DbCriteria theCriteria = new MngCriteria().searchByName(session, criteriaName); + + return insert(session, theCriteria, criteriaValue, schedulingReportId); + } + + /** + * Returns a {@link Map} of all {@link ReportCriteriaEnum} to their values, for a given report (whose ID is provided). + */ + public Map getFunctionalMap(final Long schedulingReportId) { + SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); + Session session = sessionFactory.openSession(); + try { + List result = searchFunctionalCriteria(session, schedulingReportId); + Map theFunctionalValues = new EnumMap<>(ReportCriteriaEnum.class); + for (DbSchedulingCriteriaVal criteria : result) { + theFunctionalValues.put(ReportCriteriaEnum.valueOf(criteria), criteria.getCriteriaValue()); + } + return theFunctionalValues; + } + finally { + session.close(); + } + } + + /** + * Search functional criteria values or scheduling report. + */ + public List searchFunctional(final Long schedulingReportId) { + SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); + Session session = sessionFactory.openSession(); + try { + Query theQuery = session.createQuery(QUERY_SELECT_FUNCTIONAL_CRITERIAS_DATA); + theQuery.setLong(KEY_REPORT_ID, schedulingReportId); + + List result = new ArrayList<>(); + for (Object[] reportData : (List) theQuery.list()) { + result.add(new SchedulingCriteriaValue((String) reportData[0], (String) reportData[1])); + } + return result; + } + finally { + session.close(); + } + } + + /** + * Search functional {@link DbSchedulingCriteriaVal} of scheduling report. + */ + private List searchFunctionalCriteria(Session session, final Long schedulingReportId) { + Query theQuery = session.createQuery(QUERY_SELECT_FUNCTIONAL_CRITERIAS_VALUES); + theQuery.setLong(KEY_REPORT_ID, schedulingReportId); + return castAll(theQuery.list()); + } + + /** + * Search Temporal {@link DbSchedulingCriteriaVal} of scheduling report. + */ + private List searchTemporalCriteria(Session session, final Long schedulingReportId) { + Query theQuery = session.createQuery(QUERY_SELECT_TEMPORAL_CRITERIAS_VALUES); + theQuery.setLong(KEY_REPORT_ID, schedulingReportId); + return castAll(theQuery.list()); + } + + /** + * Search All {@link DbSchedulingCriteriaVal} of scheduling report. + */ + public List searchCriteria(Session session, final Long schedulingReportId) { + Query theQuery = session.createQuery(QUERY_SELECT_CRITERIAS_VALUES); + theQuery.setLong(KEY_REPORT_ID, schedulingReportId); + return castAll(theQuery.list()); + } + + /** + * Builds a SchedulingPeriod representing the scheduling parameters of the ReportSchedulig whose ID is passed as parameters. + */ + public SchedulingPeriod getPeriod(Session session, final Long schedulingReportId) throws InvalidInputException { + List result = searchTemporalCriteria(session, schedulingReportId); + return PeriodFactory.fromDbSchedulingCriteria(result); + } + + /** + * Obtain the criteria which describe the period of a report. + */ + public SchedulingCriteriaValue getPeriodOfSchedulingReportById(Session session, final Long schedulingReportId) { + Query theQuery = session.createQuery(QUERY_SELECT_PERIOD); + theQuery.setLong(KEY_REPORT_ID, schedulingReportId); + + // Construct query result + List result = new ArrayList<>(); + for (DbSchedulingCriteriaVal reportData : (List) theQuery.list()) { + String periodicityStr = reportData.getDbCriteria().getCriteriaName(); + SchedulingEnum periodicity = SchedulingEnum.getEnum(periodicityStr); + String criteriaValue = reportData.getCriteriaValue(); + result.add(new SchedulingCriteriaValue(periodicity, criteriaValue)); + } + + if (!result.isEmpty()) { + return result.get(0); + } + else { + return new SchedulingCriteriaValue("", ""); + } + } + + /** + * Updates the period of a scheduled report. + */ + public void updatePeriod(Session session, final Long aSchedulingTemplateId, final SchedulingPeriod period) { + log.trace("Updating scheduling temporal params: {} to {}", aSchedulingTemplateId, period.toString()); + deleteTemporalCriteriaValueBySchedulingReportId(session, aSchedulingTemplateId); + for (SchedulingCriteriaValue cts : period.asCriteriaValues()) { + insertByCriteriaName(session, cts.getName(), cts.getValue(), aSchedulingTemplateId); + } + } + + /** + * Update the functional criteria of a scheduled report.
    + * Deletes the old ones, replaces by the provided list of values. + */ + public void updateFunctionalParameters(Session session, final Long aSchedulingTemplateId, final List launchData) { + if (log.isTraceEnabled()) { + log.trace("Updating scheduling functional params: schedulingID={} to {}", aSchedulingTemplateId, Joiner.on(", ").join(launchData)); + } + deleteFunctionalCriteriaValueBySchedulingReportId(session, aSchedulingTemplateId); + for (CriteriaValue criteriaValue : launchData) { + insertByCriteriaName(session, criteriaValue.getName(), criteriaValue.getValue(), aSchedulingTemplateId); + } + } + + /** + * Delete all scheduling criteria value by scheduling report id (both functional and temporal). + */ + private int deleteFunctionalCriteriaValueBySchedulingReportId(Session session, final Long schedulingReportId) { + Query theQuery = session.createQuery(QUERY_DELETE_FUNCTIONAL_CRITERIAS_VALUES_OF_SCHEDULING); + theQuery.setLong(KEY_REPORT_ID, schedulingReportId); + return theQuery.executeUpdate(); + } + + /** + * Delete all scheduling criteria value by scheduling report id (both functional and temporal). + */ + private int deleteTemporalCriteriaValueBySchedulingReportId(Session session, final Long schedulingReportId) { + Query theQuery = session.createQuery(QUERY_DELETE_TEMPORAL_CRITERIAS_VALUES_OF_SCHEDULING); + theQuery.setLong(KEY_REPORT_ID, schedulingReportId); + return theQuery.executeUpdate(); + } + + /** + * Delete all scheduling criteria value by scheduling report id (both functional and temporal). + */ + int deleteAllSchedulingCriteriaValueBySchedulingReportId(Session session, final Long schedulingReportId) { + Query theQuery = session.createQuery(QUERY_DELETE_CRITERIAS_VALUES_OF_SCHEDULING); + theQuery.setLong(KEY_REPORT_ID, schedulingReportId); + return theQuery.executeUpdate(); + } + + /** + * A Simple POJO class to bundle scheduling periodicity name - value pair. + */ + @Getter + public static class SchedulingCriteriaValue { + + private static final String NULL_STRING = "null"; + private final String name; + private final String value; + + /** + * Builds a SchedulingCriteria Name-Value object. + * + * @param name if null, will be 'null' + * @param value if null, will be 'null' + */ + public SchedulingCriteriaValue(final String name, final String value) { + this.name = name == null ? NULL_STRING : name; + this.value = (value == null || value.isEmpty() || "null".equals(value)) ? NULL_STRING : value; + } + + /** + * Builds a SchedulingCriteria Name-Value object. + * + * @param criteria if null, will be 'null' + * @param value if null, will be 'null' + */ + public SchedulingCriteriaValue(final SchedulingEnum criteria, final String value) { + this.name = criteria == null ? NULL_STRING : criteria.toString(); + this.value = value == null ? NULL_STRING : value; + } + + @Override + public String toString() { + return name + " = " + value; + } + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/database/manager/MngSchedulingReport.java b/kurt-utility/src/main/java/com/capgemini/reports/database/manager/MngSchedulingReport.java new file mode 100644 index 0000000..f484833 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/database/manager/MngSchedulingReport.java @@ -0,0 +1,239 @@ +package com.capgemini.reports.database.manager; + +import com.capgemini.framework.common.DateHelper; +import com.capgemini.framework.common.SettingsHelper; +import com.capgemini.reports.ReportEnum; +import com.capgemini.reports.database.HibernateUtil; +import com.capgemini.reports.database.javabean.DbCriteriaVal; +import com.capgemini.reports.database.javabean.DbSchedulingCriteriaVal; +import com.capgemini.reports.database.javabean.DbSchedulingReport; +import com.capgemini.reports.database.javabean.DbUser; +import com.capgemini.reports.database.manager.MngCriteriaVal.CriteriaValue; +import com.capgemini.reports.database.manager.MngSchedulingCriteriaVal.SchedulingCriteriaValue; +import com.capgemini.reports.exceptions.NotFoundException; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import org.hibernate.HibernateException; +import org.hibernate.Query; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.Transaction; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + + +/** + * Hibernate manager for {@link DbSchedulingReport} JAVA bean. + **/ +@Getter +@Slf4j +public class MngSchedulingReport extends AbstractHibernateManager { + + private static final int REPORT_CODE_POS = 0; + private static final int END_GENERATION_DATE_POS = 1; + private static final int FILE_NAME_POS = 2; + + // Column name in Db + private static final String COLUMN_SCHEDULING_NAME = "schedulingName"; + + // Key values + private static final String KEY_REPORT_CODE = "reportCode"; + private static final String KEY_UPPER_DATE = "upperDate"; + + private static final int MAX_JSP_PAGE_SIZE = SettingsHelper.getJspPaging(); + + // Reports and their owners + private static final String QUERY_ALL_SCHEDULING_REPORTS_AND_OWNERS; + private static final String QUERY_SCHEDULING_REPORTS_BY_TYPE; + + // Reports by their periodicity + private static final String QUERY_SCHEDULING_REPORTS_COUNT; + private static final String QUERY_SCHEDULING_REPORTS_COUNT_BY_REPORT_CODE; + private static final String QUERY_DELETE_SCHEDULING_REPORT_AND_CRITERIA_VAL; + private static final String QUERY_SELECT_SCHEDULING_REPORT_AND_CRITERIA_VAL; + + static { + String select = "SELECT count(*) "; + String from = "FROM DbSchedulingReport T0 "; + String whereReportCode = "WHERE T0.reportCode = :" + KEY_REPORT_CODE; + QUERY_SCHEDULING_REPORTS_COUNT = select + from; + QUERY_SCHEDULING_REPORTS_COUNT_BY_REPORT_CODE = QUERY_SCHEDULING_REPORTS_COUNT + whereReportCode; + } + + static { + String delete = "DELETE T0, T3"; + String select = "SELECT DISTINCT T0.reportCode ,T0.endGenerationDate, T0.fileName "; + String from = "FROM DbReport T0, DbReportOwner T1,DbCriteriaVal T3 "; + String whereCoherence = "WHERE T0.id = T1.reportId AND T0.id = T3.reportId "; + String andBefore = "AND T0.endGenerationDate < :" + KEY_UPPER_DATE; + String andIsaReportScheduling = "AND T0.schedulingReportId IS NOT NULL "; + + final String allSchedulingReports = from + whereCoherence + andBefore + andIsaReportScheduling; + QUERY_DELETE_SCHEDULING_REPORT_AND_CRITERIA_VAL = delete + allSchedulingReports; + QUERY_SELECT_SCHEDULING_REPORT_AND_CRITERIA_VAL = select + allSchedulingReports; + } + + static { + String select = "SELECT DISTINCT T0, concat(T1.firstname, ', ', T1.surname) "; + String from = "FROM DbSchedulingReport T0, DbUser T1 "; + String whereCoherence = "WHERE T0.adminResponsibleId = T1.id "; + String andReportCode = "AND T0.reportCode = :reportCode "; + String orderBy = "ORDER BY T0.lastUpdate DESC "; + + QUERY_SCHEDULING_REPORTS_BY_TYPE = select + from + whereCoherence + andReportCode + orderBy; + QUERY_ALL_SCHEDULING_REPORTS_AND_OWNERS = select + from + whereCoherence + orderBy; + } + + /** + * Count in database the scheduling report list by report code . + */ + public Long countSchedulingReportsByReportCode(Session session, final ReportEnum report) { + Query theQuery = session.createQuery(QUERY_SCHEDULING_REPORTS_COUNT_BY_REPORT_CODE); + theQuery.setString(KEY_REPORT_CODE, report.getReportCode()); + return (Long) theQuery.uniqueResult(); + } + + /** + * Count in database all scheduling report list . + */ + public Long countAllSchedulingReport(Session session) { + Query theQuery = session.createQuery(QUERY_SCHEDULING_REPORTS_COUNT); + return (Long) theQuery.uniqueResult(); + } + + /* Create a scheduling report */ + private DbSchedulingReport insert(Session session, final String schedulingName, final DbUser theAdminResponsible, final ReportEnum reportCode) { + DbSchedulingReport schedulingReport = new DbSchedulingReport(); + + schedulingReport.setSchedulingName(schedulingName); + schedulingReport.setLastUpdate(DateHelper.getCurrentSqlTimestamp()); + schedulingReport.setAdminResponsibleId(theAdminResponsible.getId()); + schedulingReport.setReportCode(reportCode.getReportCode()); + // Persist object + session.save(schedulingReport); + return schedulingReport; + } + + /** + * Insert a SchedulingReport in the DB.
    + * The related {@link DbSchedulingReport}, {@link DbSchedulingCriteriaVal}s, {@link DbCriteriaVal}s will be created accordingly. + * + * @param schedulingName the name of the scheduling, as asked by the user + * @param schedulingCriteriaValues the temporal criterias of the scheduling + * @param criteriaValues the functional criteria of the report's execution + * @param requestor the user making the request + * @param reportCode the required report's type + * @return the entry in the DB + */ + public DbSchedulingReport insertSchedulingReportWithCriteriaAndOwner(final String schedulingName, + final List schedulingCriteriaValues, final List criteriaValues, final DbUser requestor, + final ReportEnum reportCode) { + SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); + Session session = sessionFactory.openSession(); + try { + Transaction transaction = session.beginTransaction(); + DbSchedulingReport dbSchedulingReport = this.insert(session, schedulingName, requestor, reportCode); + Long schedulingReportId = dbSchedulingReport.getId(); + + // save temporal criteria values + MngSchedulingCriteriaVal theSchedulingCriteriaValManager = new MngSchedulingCriteriaVal(); + for (SchedulingCriteriaValue schedulingCriterion : schedulingCriteriaValues) { + theSchedulingCriteriaValManager.insertByCriteriaName(session, schedulingCriterion.getName(), schedulingCriterion.getValue(), schedulingReportId); + } + + // save functional criteria values + MngSchedulingCriteriaVal theCriteriaValManager = new MngSchedulingCriteriaVal(); + for (CriteriaValue criterion : criteriaValues) { + theCriteriaValManager.insertByCriteriaName(session, criterion.getName(), criterion.getValue(), schedulingReportId); + } + transaction.commit(); + return dbSchedulingReport; + } + finally { + session.close(); + } + } + + /** + * Returns all data on all the scheduling report entries..
    + * Returns a {@link Map} whose keys are all the {@link DbSchedulingReport} of the DB, and each value is the associated owner's full name. + */ + public Map searchAllSchedulingReports(Session session, final int aPageNumber) { + + Query theQuery = session.createQuery(QUERY_ALL_SCHEDULING_REPORTS_AND_OWNERS); + theQuery.setMaxResults(MAX_JSP_PAGE_SIZE); + theQuery.setFirstResult(MAX_JSP_PAGE_SIZE * (aPageNumber - 1)); + + Map results = new HashMap<>(); + for (Object[] reportData : (List) theQuery.list()) { + DbSchedulingReport dbReport = (DbSchedulingReport) reportData[0]; + String owner = (String) reportData[1]; + results.put(dbReport, owner); + } + return results; + } + + /** + * Returns all data on the scheduling report entries refering to the provided {@link ReportEnum} code.
    + * Returns a {@link Map} whose keys are all the {@link DbSchedulingReport} of the DB, and each value is the associated owner's full name. + */ + public Map searchSchedulingReportByReportCode(Session session, final ReportEnum reportCode, final int aPageNumber) { + Query theQuery = session.createQuery(QUERY_SCHEDULING_REPORTS_BY_TYPE); + theQuery.setMaxResults(MAX_JSP_PAGE_SIZE); + theQuery.setFirstResult(MAX_JSP_PAGE_SIZE * (aPageNumber - 1)); + theQuery.setString(KEY_REPORT_CODE, reportCode.getReportCode()); + + Map results = new HashMap<>(); + for (Object[] reportData : (List) theQuery.list()) { + DbSchedulingReport dbReport = (DbSchedulingReport) reportData[0]; + String owner = (String) reportData[1]; + results.put(dbReport, owner); + } + return results; + } + + /** + * Delete a scheduling report, and all its scheduling values (functional and temporal). + * + * @param schedulingReportId the ID f the scheduled report + * @return the number of lines affected (all criteria values, plus the scheduling itself) + * @throws NotFoundException if Hibernate is unable to perform the operation + */ + public int deleteSchedulingReport(final Long schedulingReportId) throws NotFoundException { + SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); + Session session = sessionFactory.openSession(); + try { + Transaction transaction = session.beginTransaction(); + DbSchedulingReport persistedObj = searchById(session, schedulingReportId); + + log.debug("Find DbSchedulingReport by id " + schedulingReportId); + MngSchedulingCriteriaVal mngSchedulingCriteriaVal = new MngSchedulingCriteriaVal(); + int valuesDeleted = mngSchedulingCriteriaVal.deleteAllSchedulingCriteriaValueBySchedulingReportId(session, schedulingReportId); + delete(session, persistedObj); + transaction.commit(); + return valuesDeleted + 1; + } + catch (HibernateException e) { + throw new NotFoundException("SchedulingReport with id " + schedulingReportId + " not found in DB.", e); + } + finally { + session.close(); + } + } + + @Override + public Class getManagedClass() { + return DbSchedulingReport.class; + } + + /** + * Returns the entry with the provided scheduling_name (if any).
    + * If non exist, returns null + */ + public DbSchedulingReport searchByName(Session session, String planifName) { + return searchBy(session, COLUMN_SCHEDULING_NAME, planifName); + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/database/manager/MngUser.java b/kurt-utility/src/main/java/com/capgemini/reports/database/manager/MngUser.java new file mode 100644 index 0000000..30a1b83 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/database/manager/MngUser.java @@ -0,0 +1,134 @@ +package com.capgemini.reports.database.manager; + +import com.capgemini.framework.common.DateHelper; +import com.capgemini.reports.database.javabean.DbReport; +import com.capgemini.reports.database.javabean.DbUser; +import com.capgemini.reports.database.javabean.DbUser.UserData; +import lombok.extern.slf4j.Slf4j; +import org.hibernate.Query; +import org.hibernate.Session; +import org.hibernate.Transaction; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +/** + * Hibernate manager for DBUser JAVA bean. + **/ +@Slf4j +public class MngUser extends AbstractHibernateManager { + + private static final String KEY_REPORT = "DbReportObject"; + private static final String QUERY_REPORT_OWNERS = + "select T2 from DbReport T0, DbReportOwner T1, DbUser T2 where T0.id = T1.reportId and T1.userId = T2.id and T0.id = :" + KEY_REPORT + + " order by T2.id desc"; + + @Override + public Class getManagedClass() { + return DbUser.class; + } + + /** + * Create new user instance settings its mandatory attributes. + */ + public DbUser insert(Session session, final String aLogin, final String aFirstName, final String aSurname, final String anEmail) { + log.debug("Encountered new user : " + aLogin); + Transaction transaction = session.beginTransaction(); + DbUser theCreatedUser = new DbUser(); + + // Assign default attribute values + theCreatedUser.setLogin(aLogin); + theCreatedUser.setFirstname(aFirstName); + theCreatedUser.setSurname(aSurname); + theCreatedUser.setEmail(anEmail); + theCreatedUser.setLastConnectionDate(DateHelper.getCurrentSqlDate()); + + // Persist object + session.save(theCreatedUser); + transaction.commit(); + return theCreatedUser; + } + + /** + * Search query for retrieving User using its login. + * + * + * @param session + * @param aLogin Searched login value + * @return Found user (or null of not founr) + */ + private DbUser searchByLogin(Session session, final String aLogin) { + return searchBy(session, "login", aLogin); + } + + /** + * Updates a DbUser's data to match the provided UserData (assumed to be up-to-date, freshly provided by the ActiveDirectory). + */ + private void updateUser(Session session, final DbUser dbUser, final UserData user) { + log.debug("Updating user data for " + dbUser.getLogin()); + Transaction transaction = session.beginTransaction(); + dbUser.setEmail(user.getEmail()); + dbUser.setFirstname(user.getFirstName()); + dbUser.setSurname(user.getSurname()); + session.update(dbUser); + transaction.commit(); + } + + /** + * Returns the DbUser from the database.
    + * If the user did not exist, creates the user, then returns it.
    + * If the dbUser did exist, but did not have the same data as the adUser, updates the DbUser to match the adUser, then returns the dbUSer. + */ + public DbUser fetchOrUpdateOrCreateUser(Session session, final UserData adUser) { + // Fetch or Register the requesting user in the DB + MngUser mngUser = new MngUser(); + DbUser dbUser = mngUser.searchByLogin(session, adUser.getLogin()); + if (dbUser == null) { + // User does not already exist, we must create a new one + dbUser = mngUser.insert(session, adUser.getLogin(), adUser.getFirstName(), adUser.getSurname(), adUser.getEmail()); + } + else { + // User has been found, now we need to make sure all its data are up to date + if (!dbUser.sameAs(adUser)) { + mngUser.updateUser(session, dbUser, adUser); + } + } + return dbUser; + } + + /** + * Returns the DbUser(s) from the database.
    + * If any dbUser did not exist, creates that user.
    + * If any dbUser did exist, but did not have the same data as the adUser, updates the DbUser to match the adUser. + */ + public List fetchOrUpdateOrCreateUsers(Session session, final Collection adUsers) { + // Fetch or Register the requesting user in the DB + MngUser mngUser = new MngUser(); + List dbUSers = new ArrayList<>(); + for (UserData adUser : adUsers) { + DbUser dbUser = mngUser.searchByLogin(session, adUser.getLogin()); + if (dbUser == null) { + // User does not already exist, we must create a new one + dbUser = mngUser.insert(session, adUser.getLogin(), adUser.getFirstName(), adUser.getSurname(), adUser.getEmail()); + } + else { + // User has been found, now we need to make sure all its data are up to date + if (!dbUser.sameAs(adUser)) { + mngUser.updateUser(session, dbUser, adUser); + } + } + dbUSers.add(dbUser); + } + return dbUSers; + } + + /** + * Search in database the list of users that requested a specific report to be executed (using its login as search criteria). + */ + public List searchReportOwners(Session session, final DbReport dbReport) { + Query theQuery = session.createQuery(QUERY_REPORT_OWNERS); + theQuery.setEntity(KEY_REPORT, dbReport); + return castAll(theQuery.list()); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/database/stats/GenJspStats.java b/kurt-utility/src/main/java/com/capgemini/reports/database/stats/GenJspStats.java new file mode 100644 index 0000000..6181386 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/database/stats/GenJspStats.java @@ -0,0 +1,291 @@ +package com.capgemini.reports.database.stats; + +import com.capgemini.framework.common.DateHelper; +import com.capgemini.reports.ReportEnum; +import com.capgemini.reports.database.HibernateUtil; +import com.capgemini.reports.database.manager.MngReport; +import com.capgemini.reports.database.manager.MngReport.ReportLaunchByUser; +import org.hibernate.Query; +import org.hibernate.Session; +import org.hibernate.SessionFactory; + +import java.text.ParseException; +import java.util.*; +import java.util.Map.Entry; + +/** + * Class for dynamic content of JSP statistics page. + **/ +public final class GenJspStats { + + private static final String PLACEHOLDER_NUM = "0"; + private static final long MILLIS_IN_S = 1000L; + private static final String START_PERIOD = "startPeriod"; + private static final String END_PERIOD = "endPeriod"; + private static final String TOTAL = "total"; + + /** + * Count exectutions. + */ + private static final String HQL_COUNT_EXECUTIONS_QUERY; + /** + * Count TECHNICAL errors. + */ + private static final String HQL_COUNT_TECHNICAL_ERRORS_QUERY; + /** + * Count FUNCTIONAL errors. + */ + private static final String HQL_COUNT_FUNCTIONAL_ERRORS_QUERY; + /** + * Calc min, avg, and max duration of each report types. + */ + private static final String HQL_MIN_MAX_AVG_DURATION_QUERY; + + static { + String selectCount = "select T0.reportCode, count(DISTINCT T1.reportId) "; + String selectStats = + "select T0.reportCode, min(T0.generationDuration), avg(T0.generationDuration), max(T0.generationDuration) "; + String from = "from DbReport T0, DbReportOwner T1 "; + String whereCoherence = "where T0.id = T1.reportId "; + String andPeriod = "and T1.requestDate between TO_DATE(:" + START_PERIOD + ") and TO_DATE(:" + END_PERIOD + ") + 1 "; + String andSuccess = "and T0.endGenerationDate is not null and T0.state != 'FAILED' "; + String andErrorTypeTech = "and T0.errorType = 'TECHNICAL' "; + String andErrorTypeFunc = "and T0.errorType = 'FUNCTIONAL' "; + String groupBy = "group by T0.reportCode"; + HQL_COUNT_EXECUTIONS_QUERY = selectCount + from + whereCoherence + andPeriod + groupBy; + HQL_COUNT_TECHNICAL_ERRORS_QUERY = selectCount + from + whereCoherence + andPeriod + andErrorTypeTech + groupBy; + HQL_COUNT_FUNCTIONAL_ERRORS_QUERY = selectCount + from + whereCoherence + andPeriod + andErrorTypeFunc + groupBy; + HQL_MIN_MAX_AVG_DURATION_QUERY = selectStats + from + whereCoherence + andPeriod + andSuccess + groupBy; + } + + private GenJspStats() { + // Nothing to do... + } + + /** + * Generate the content of the Javascript array for all statistics. + */ + public static String generateTimingsTableAsJS(final String aStartPeriod, final String aEndPeriod) throws ParseException { + StringBuilder theJsCode = new StringBuilder(); + Collection theReportStatList = getReportStatList(aStartPeriod, aEndPeriod); + + int theLineCount = 0; + for (ReportStatBean currentStat : theReportStatList) { + theJsCode.append(currentStat.toJs("reportStatArray[" + theLineCount + "]")); + theLineCount++; + } + + return theJsCode.toString(); + } + + /** + * Compute statistics from database. + */ + public static Collection getReportStatList(final String startPeriod, final String endPeriod) throws ParseException { + // Compute the limit date in the past for the analyzed interval + Map statMap = initMap(); + Date parsedStartPeriod = DateHelper.parseDate(startPeriod); + Date parsedEndPeriod = DateHelper.parseDate(endPeriod); + SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); + Session session = sessionFactory.openSession(); + try { + countExecutions(parsedStartPeriod, parsedEndPeriod, session, statMap); + countFunctionalErrors(parsedStartPeriod, parsedEndPeriod, session, statMap); + countTechnicalErrors(parsedStartPeriod, parsedEndPeriod, session, statMap); + calcMinMaxAvgDuration(parsedStartPeriod, parsedEndPeriod, session, statMap); + return statMap.values(); + } + finally { + session.close(); + } + } + + private static Map initMap() { + Map statMap = new TreeMap<>(); + for (String reportCode : ReportEnum.getListReportCode()) { + statMap.put(reportCode, new ReportStatBean(reportCode)); + } + return statMap; + } + + private static void countExecutions(final Date startPeriod, final Date endPeriod, final Session hibernateSession, + final Map theStatMap) { + // Fill execution count + Query query = hibernateSession.createQuery(HQL_COUNT_EXECUTIONS_QUERY); + query.setDate(START_PERIOD, startPeriod); + query.setDate(END_PERIOD, endPeriod); + List theResultSet = query.list(); + for (Object[] currentRecord : theResultSet) { + String reportCode = (String) currentRecord[0]; + Long reportCount = (Long) currentRecord[1]; + + ReportStatBean theReportStatBean = theStatMap.get(reportCode); + theReportStatBean.setExecutionCount(reportCount); + } + } + + private static void countFunctionalErrors(final Date aStartPeriod, final Date aEndPeriod, final Session hibernateSession, + final Map theStatMap) { + // Fill functional error count + Query theQuery = hibernateSession.createQuery(HQL_COUNT_FUNCTIONAL_ERRORS_QUERY); + theQuery.setDate(START_PERIOD, aStartPeriod); + theQuery.setDate(END_PERIOD, aEndPeriod); + List theResultSet = theQuery.list(); + for (Object[] currentRecord : theResultSet) { + String theReportCode = (String) currentRecord[0]; + Long theReportCount = (Long) currentRecord[1]; + + ReportStatBean theReportStatBean = theStatMap.get(theReportCode); + theReportStatBean.setFailedFuncCount(theReportCount); + } + } + + private static void countTechnicalErrors(final Date aStartPeriod, final Date aEndPeriod, final Session hibernateSession, + final Map theStatMap) { + // Fill technical error count + Query theQuery = hibernateSession.createQuery(HQL_COUNT_TECHNICAL_ERRORS_QUERY); + theQuery.setDate(START_PERIOD, aStartPeriod); + theQuery.setDate(END_PERIOD, aEndPeriod); + List theResultSet = theQuery.list(); + for (Object[] currentRecord : theResultSet) { + String theReportCode = (String) currentRecord[0]; + Long theReportCount = (Long) currentRecord[1]; + + ReportStatBean theReportStatBean = theStatMap.get(theReportCode); + theReportStatBean.setFailedTechCount(theReportCount); + } + } + + private static void calcMinMaxAvgDuration(final Date startPeriod, final Date endPeriod, final Session hibernateSession, + final Map statMap) { + // Fill min, max and average durations + Query theQuery = hibernateSession.createQuery(HQL_MIN_MAX_AVG_DURATION_QUERY); + theQuery.setDate(START_PERIOD, startPeriod); + theQuery.setDate(END_PERIOD, endPeriod); + List theResultSet = theQuery.list(); + for (Object[] currentRecord : theResultSet) { + String theReportCode = (String) currentRecord[0]; + ReportStatBean theReportStatBean = statMap.get(theReportCode); + + Long theReportMin = (Long) currentRecord[1]; + if (theReportMin != null) { + theReportStatBean.setMinDuration(theReportMin / MILLIS_IN_S); + } + + Double theReportAvg = (Double) currentRecord[2]; + if (theReportAvg != null) { + Long theAvgRepDuration = theReportAvg.longValue(); + theReportStatBean.setAvgDuration(theAvgRepDuration / MILLIS_IN_S); + } + + Long theReportMax = (Long) currentRecord[3]; + if (theReportMax != null) { + theReportStatBean.setMaxDuration(theReportMax / MILLIS_IN_S); + } + } + } + + + private static List generateUserStatBean(Session session, final String startPeriod, final String endPeriod) throws ParseException { + // ref list contains all report + List refListContainsAllReportCode = ReportEnum.getListReportCode(); + + // Get all record + Date parsedStartPeriod = DateHelper.parseDate(startPeriod); + Date parsedEndPeriod = DateHelper.parseDate(endPeriod); + List userReportList = new MngReport().searchUsersReports(session, parsedStartPeriod, parsedEndPeriod); + userReportList.addAll(userReportList.size(), new MngReport().searchAdminSchedulingReports(session, parsedStartPeriod, parsedEndPeriod)); + + Map> mapObjects = new TreeMap<>(); + // objects of period + for (ReportLaunchByUser curReportLaunchByUser : userReportList) { + // current user name + String currentUserName = curReportLaunchByUser.getSurname().concat(" ").concat(curReportLaunchByUser.getFirstName()); + + // if username most exist + if (mapObjects.containsKey(currentUserName)) { + // if you don't have this current reportCode then put it + if (!mapObjects.get(currentUserName).containsKey(curReportLaunchByUser.getReportCode())) { + mapObjects.get(currentUserName).put(curReportLaunchByUser.getReportCode(), curReportLaunchByUser.getReportCount()); + + // Then if total key exist so re-compute + if (mapObjects.get(currentUserName).containsKey(TOTAL)) { + Long curTotal = mapObjects.get(currentUserName).get(TOTAL); + curTotal += curReportLaunchByUser.getReportCount(); + mapObjects.get(currentUserName).put(TOTAL, curTotal); + } + } + } + else { // then create the currentName and put reportCode and reportCount + Map mapDatas = new TreeMap<>(); + mapDatas.put(curReportLaunchByUser.getReportCode(), curReportLaunchByUser.getReportCount()); + mapDatas.put(TOTAL, curReportLaunchByUser.getReportCount()); + mapObjects.put(currentUserName, mapDatas); + } + } + + // Generate object UserStaBean + List usersListStatBean = new ArrayList<>(); + for (Entry> userEntry : mapObjects.entrySet()) { + // temp list for diff + List curListReportCode = new ArrayList<>(); + // create userStatBean + String userName = userEntry.getKey(); + Map datas = userEntry.getValue(); + UserStatBean userStatBean = new UserStatBean(userName); + for (Entry userEntryValues : datas.entrySet()) { + userStatBean.getDatas().put(userEntryValues.getKey(), userEntryValues.getValue().toString()); + curListReportCode.add(userEntryValues.getKey()); + } + // diff + // findAll ref list report + List tempListContainsAllReport = new ArrayList<>(refListContainsAllReportCode); + // diff findAll missing report code + tempListContainsAllReport.removeAll(curListReportCode); + + for (String reportCodeMissing : tempListContainsAllReport) { + userStatBean.getDatas().put(reportCodeMissing, PLACEHOLDER_NUM); + } + // add to list + usersListStatBean.add(userStatBean); + } + + return usersListStatBean; + } + + /** + * Second table implementation for report count per code & user login. + **/ + + public static String generateLaunchCountTableAsJS(final String aStartPeriod, final String aEndPeriod) throws ParseException { + SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); + Session session = sessionFactory.openSession(); + try { + StringBuilder theJsCode = new StringBuilder(); + List users = generateUserStatBean(session, aStartPeriod, aEndPeriod); + int theLineCount = 0; + for (UserStatBean userStatBean : users) { + theJsCode.append(userStatBean.toJs("userStatArray[" + theLineCount + "]")); + theLineCount++; + } + return theJsCode.toString(); + } + finally { + session.close(); + } + } + + /** + * Generate a list of all users stats for csv + */ + public static List generateLaunchCountTableForCsv(final String aStartPeriod, final String aEndPeriod) throws ParseException { + SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); + Session session = sessionFactory.openSession(); + try { + return generateUserStatBean(session, aStartPeriod, aEndPeriod); + } + finally { + session.close(); + } + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/database/stats/ReportStatBean.java b/kurt-utility/src/main/java/com/capgemini/reports/database/stats/ReportStatBean.java new file mode 100644 index 0000000..adc198f --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/database/stats/ReportStatBean.java @@ -0,0 +1,85 @@ +package com.capgemini.reports.database.stats; + +import com.capgemini.framework.common.TimeHelper; +import lombok.Setter; + +/** + * Bean object carrying Statistical information about a report. + */ +@Setter +public class ReportStatBean { + + /** + * HTML entity for blank character. + **/ + private static final String BLANK_CHAR = " "; + private static final String DELIM = "-"; + private static final String ZERO_STRING = "0"; + private final String reportCode; + private Long executionCount; + private Long failedFuncCount; + private Long failedTechCount; + private Long minDuration; + private Long avgDuration; + private Long maxDuration; + + /** + * Makes an ReportStatBean, using its code as a reference. + * @param aReportCode a report code (R' etc.) + * + */ + public ReportStatBean(final String aReportCode) { + this.reportCode = aReportCode; + } + + /** + * Convert the current bean by Javascript code. + * + * @param aJsArray Name of the JAVA script array + * @return The Javascript code + */ + public String toJs(final String aJsArray) { + return aJsArray + " = new Array();\n" + + aJsArray + "['reportCode'] = '" + nullAsBlank(reportCode) + "';\n" + + aJsArray + "['executionCount'] = '" + nullAsBlank(executionCount) + "';\n" + + aJsArray + "['failedFuncCount'] = '" + nullAsBlank(failedFuncCount) + "';\n" + + aJsArray + "['failedTechCount'] = '" + nullAsBlank(failedTechCount) + "';\n" + + aJsArray + "['minDuration'] = '" + TimeHelper.formatDuration(minDuration) + "';\n" + + aJsArray + "['avgDuration'] = '" + TimeHelper.formatDuration(avgDuration) + "';\n" + + aJsArray + "['maxDuration'] = '" + TimeHelper.formatDuration(maxDuration) + "';\n"; + } + + public String toCsv() { + return reportCode + "," + + contentOrZero(executionCount) + "," + + contentOrZero(failedFuncCount) + "," + + contentOrZero(failedTechCount) + "," + + contentOrZero(minDuration) + "," + + contentOrZero(avgDuration) + "," + + contentOrZero(maxDuration); + } + + private String contentOrZero(final Long exec) { + return exec == null ? ZERO_STRING : exec.toString(); + } + + /** + * Display null values with a blank character. + * + * @param value Value which should be converted. + * @return The string value. + */ + private String nullAsBlank(final Object value) { + return value == null ? BLANK_CHAR : value.toString(); + } + + + @Override + public String toString() { + return "ReportStatBean [reportCode=" + reportCode + ", executionCount=" + executionCount + ", failedFuncCount=" + failedFuncCount + + ", failedTechCount=" + failedTechCount + ", minDuration=" + minDuration + ", avgDuration=" + avgDuration + ", maxDuration=" + + maxDuration + "]"; + } + + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/database/stats/UserStatBean.java b/kurt-utility/src/main/java/com/capgemini/reports/database/stats/UserStatBean.java new file mode 100644 index 0000000..b0e91dd --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/database/stats/UserStatBean.java @@ -0,0 +1,69 @@ +package com.capgemini.reports.database.stats; + +import lombok.Getter; +import lombok.Setter; + +import java.util.Map; +import java.util.Map.Entry; +import java.util.TreeMap; + +/** + * Bean object carrying Statistical information about a report. + */ +@Getter +@Setter +public class UserStatBean { + + private static final String TOTAL = "total"; + + /** + * HTML entity for blank character. + **/ + private static final String BLANK_CHAR = " "; + + private String name; + private Map datas = new TreeMap<>(); + + /** + * Make a simple bean containing stats about a user. + * + * @param name the user name + */ + public UserStatBean(final String name) { + this.name = name; + } + + /** + * Convert the current bean by Javascript code. + * + * @param aJsArrayName Name of the JAVA script array + * @return The Javascript code + */ + public String toJs(final String aJsArrayName) { + StringBuilder theJsCodeBuilder = new StringBuilder(aJsArrayName).append(" = new Array();\n"); + theJsCodeBuilder.append(aJsArrayName).append("['name'] = \"").append(nullAsBlank(name)).append("\";\n"); + for (Entry entry : datas.entrySet()) { + if (entry.getKey().equals(TOTAL)) { + theJsCodeBuilder.append(aJsArrayName).append("['Global'] = '").append(nullAsBlank(entry.getValue())).append("';\n"); + } else { + theJsCodeBuilder.append(aJsArrayName).append("['").append(entry.getKey()).append("'] = '").append(nullAsBlank(entry.getValue())).append("';\n"); + } + } + return theJsCodeBuilder.toString(); + } + + /** + * Display null values with a blank character. + * + * @param aValue Value which should be converted. + * @return The string value. + */ + private String nullAsBlank(final Object aValue) { + return aValue == null ? BLANK_CHAR : aValue.toString(); + } + + @Override + public String toString() { + return "UserStatBean [name=" + name + ", datas=" + datas + "]"; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r01report/DataReportPreparatorR01.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r01report/DataReportPreparatorR01.java new file mode 100644 index 0000000..f15dbae --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r01report/DataReportPreparatorR01.java @@ -0,0 +1,110 @@ +package com.capgemini.reports.definition.r01report; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.EmptyNomenclatureException; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcBomObject; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcBomObjectFactory; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcRevisionRule; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcRevisionRuleProperties; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.product.TcProduct; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.product.TcProductRevision; +import com.capgemini.framework.teamcenter.object.runtime.TcBomWindow; +import com.capgemini.framework.teamcenter.object.runtime.TcBomWindowConfiguration; +import com.capgemini.framework.teamcenter.object.runtime.TcRevisionRulesConfiguration; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.bomlineholder.BOMLineHolderFactory; +import com.capgemini.reports.bomlineholder.processor.DefaultAltOrDetBehaviour; +import com.capgemini.reports.definition.r01report.visitors.R01Visitor; +import com.capgemini.reports.exceptions.InvalidUserInputException; +import com.capgemini.reports.exceptions.UserInputErrorEnum; +import com.capgemini.reports.execution.IDataReportPreparator; +import com.capgemini.reports.execution.strategies.IExecutionStrategy; +import com.capgemini.reports.filter.AllIsGoodFilter; +import com.capgemini.reports.printing.PrintParameters; +import com.capgemini.reports.reports.parameters.EffectivityDate; +import com.capgemini.reports.reports.parameters.MonoMulti; +import com.capgemini.reports.teamcenter.resolution.structureservice.IStructureServiceCaller; +import com.capgemini.reports.teamcenter.resolution.structureservice.MultiStructureServiceCaller; +import com.capgemini.reports.teamcenter.resolution.structureservice.TripleStructureServiceCaller; +import com.teamcenter.soa.client.model.ModelObject; +import com.teamcenter.soa.client.model.strong.Form; +import com.teamcenter.soa.client.model.strong.PSBOMView; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +/** + * This class will allow to prepare data and findAll back data for making report R01. + */ +class DataReportPreparatorR01 implements IDataReportPreparator { + private static final long serialVersionUID = -1029419855928264125L; + private static final Logger LOGGER = LoggerFactory.getLogger(DataReportPreparatorR01.class); + + private static final AllIsGoodFilter ACCEPT_ALL = new AllIsGoodFilter(); + + @Override + public String print(TcSession session, ExecutionR01 execution, IExecutionStrategy executionStrategy) throws KurtException { + PrintParameters printParameters = prepareData(session, execution); + executionStrategy.print(printParameters, execution); + return executionStrategy.getReportFileName(execution) + printParameters.getOuputFileExtension(); + } + + private PrintParameters prepareData(final TcSession session, final ExecutionR01 report) throws KurtException { + LOGGER.debug("PrepareData started on: {}", report.getReportIdentifier().getReportTitle()); + + TcBomObject topLineObject= new TcBomObjectFactory(session, report.getGeneric().getItem(session)).create(); + TcProduct productObject = new TcProduct(session, report.getProductUnit().getProduct(session)); + TcProductRevision productObjectRevision = productObject.revisions().get(0); + int unit = report.getProductUnit().getUnit(); + EffectivityDate effectivityDate = report.getEffectivityDate(); + + TcRevisionRuleProperties revisionRuleProperties = new TcRevisionRuleProperties(productObject, unit, effectivityDate.isNow() ? null : effectivityDate.getDateTime()); + TcRevisionRule revisionRule = session.findRevRule(report.getRevisionRule()); + TcRevisionRulesConfiguration revRulesConfiguration = new TcRevisionRulesConfiguration(revisionRule, revisionRuleProperties); + + IStructureServiceCaller service; + if (MonoMulti.MONO.equals(report.getMonoMulti())) { + service = new TripleStructureServiceCaller(session); + } else { + service = new MultiStructureServiceCaller(session); + } + + TcBomWindowConfiguration tcBomWindowConfiguration ; + if (report.isSuperModelBOM()) { + PSBOMView modelBom = productObjectRevision.bomViewRev(); + tcBomWindowConfiguration = new TcBomWindowConfiguration (topLineObject,modelBom,revRulesConfiguration); + } else { + tcBomWindowConfiguration = new TcBomWindowConfiguration(topLineObject, revRulesConfiguration); + } + + try (TcBomWindow bomWindow = session.createBomWindow(tcBomWindowConfiguration)) { + session.setObjectPropPolicy(report.getFullPolicy()); + BOMLineHolder unbuiltTopLine = service.resolve(bomWindow.topLine(), ACCEPT_ALL); + List
    itemRevMaster = unbuiltTopLine.getAllItemRevMasters(); + session.loadProperties(itemRevMaster.toArray(new ModelObject[itemRevMaster.size()])); + + BOMLineHolderFactory.buildTopBom(session, unbuiltTopLine, ACCEPT_ALL); + DefaultAltOrDetBehaviour aBOMLineHolderProcessor = new DefaultAltOrDetBehaviour<>(session, effectivityDate.isNow() ? null : effectivityDate.getDateTime()); + unbuiltTopLine.process(aBOMLineHolderProcessor); + unbuiltTopLine.freeze(); + + R01Visitor visitor = new R01Visitor(); + PrintParameters printParameters = visitor.makeMasterTemplate(report, unbuiltTopLine); + visitor.constructDataMaps(session, printParameters, unbuiltTopLine); + + LOGGER.debug("PrepareData ended on: {}", report.getReportIdentifier().getReportTitle()); + return printParameters; + } catch (EmptyNomenclatureException e) { + switch (report.getGeneric().getType()) { + case GENERIC: + throw new InvalidUserInputException(UserInputErrorEnum.NO_DATA_COULD_BE_EXTRACTED_FOR_GENERIC_PRODUCT_AND_UNIT, e); + case GENERIC_ASSEMB: + throw new InvalidUserInputException(UserInputErrorEnum.NO_DATA_COULD_BE_EXTRACTED_FOR_GENERIC_ASSEMB_PRODUCT_AND_UNIT, e); + default: + throw new KurtException("The TC Nomenclature Resolution returned null", e); + } + } + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r01report/ExecutionR01.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r01report/ExecutionR01.java new file mode 100644 index 0000000..2619ba8 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r01report/ExecutionR01.java @@ -0,0 +1,170 @@ +package com.capgemini.reports.definition.r01report; + +import com.capgemini.framework.common.SettingsHelper; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.reports.JasperTemplate; +import com.capgemini.reports.ReportEnum; +import com.capgemini.reports.ReportLaunchTypeEnum; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.builder.R01Builder; +import com.capgemini.reports.builder.ReportBuilder; +import com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum; +import com.capgemini.reports.database.manager.MngCriteriaVal.CriteriaValue; +import com.capgemini.reports.execution.AbstractExecutionReport; +import com.capgemini.reports.execution.IDataReportPreparator; +import com.capgemini.reports.printing.Printer.PrintFormat; +import com.capgemini.reports.reports.parameters.*; +import com.capgemini.reports.reports.parameters.Generics.GenericType; +import com.capgemini.reports.reports.parameters.checker.*; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; + +import java.util.ArrayList; +import java.util.List; + +/** + * Obtain data for report R01.
    + * Contain {@link IChecker} for a report's construction + */ +@Getter +@EqualsAndHashCode(callSuper = true) +public class ExecutionR01 extends AbstractExecutionReport { + private static final long serialVersionUID = -2173366731814318218L; + + private static final DataReportPreparatorR01 DATA_REPORT_PREPARATOR_R01 = new DataReportPreparatorR01(); + + // Policies parameters + private static final PolicyLocation R01_POLICY_XML_LIGHT = + PolicyLocation.make("R01_policy_light", "/xml/policies/r01report/R01_policy_light.xml"); + private static final PolicyLocation R01_POLICY_XML_FULL = PolicyLocation.make("R01_policy_full", "/xml/policies/r01report/R01_policy_full.xml"); + /** + * Policy for inspecting Alternates and DETs more closely (i.e. looking into their pseudo-folders for alternative parts). + */ + public static final PolicyLocation R01_POLICY_XML_ALT = PolicyLocation.make("R01_policy_alt", "/xml/policies/r01report/R01_policy_alt.xml"); + + + // Launch type parameter + private static final ReportLaunchTypeEnum REPORT_LAUNCH_TYPE = ReportLaunchTypeEnum.getReportLaunchType("common.launch.launchType.REPORT_R01"); + + // Revision rule parameter + private static final String REPORT_REVISION_RULE = + SettingsHelper.getPropertyWithDefaultValue("common.bom.revisionRule.REPORT_R01", DEFAULT_REVISION_RULE); + + // Priority parameter + private static final int REPORT_PRIORITY = SettingsHelper.getPriority(ReportEnum.REPORT_R01); + + // Internal working data + private final Generics generic; + private final MonoMulti monoMulti; + private final ProductUnit productUnit; + private final EffectivityDate effectivityDate; + private final boolean isSuperModelBOM; + + @Setter + private BOMLineHolder topLine; + + /** + * Constructor + * + * @param aProductUnit {@link ProductUnit} - the product and unit + * @param aGeneric le generic {@link Generics} - represent the generic. Can be null if the wanted configuration is only with the Product and the Unit. + * @param aMonoMulti {@link MonoMulti} - represent the type of resolution structure + * @param effectivityDate {@link EffectivityDate} - represent the effectivity date + */ + public ExecutionR01(final ProductUnit aProductUnit, final Generics aGeneric, final MonoMulti aMonoMulti, final EffectivityDate effectivityDate, final boolean isSuperModelBOM) { + super(REPORT_PRIORITY, REPORT_REVISION_RULE, REPORT_LAUNCH_TYPE); + this.productUnit = aProductUnit; + this.generic = aGeneric; + this.monoMulti = aMonoMulti; + this.effectivityDate = effectivityDate; + this.isSuperModelBOM = isSuperModelBOM; + } + + @Override + public List getLaunchData() { + List theCriteria = new ArrayList<>(); + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.PRODUCT, productUnit.getProductID())); + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.UNIT, productUnit.getUnitStr())); + if (generic.getType() == GenericType.GENERIC) { + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.GENERIC, generic.getID())); + } + if (generic.getType() == GenericType.GENERIC_ASSEMB) { + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.GENERIC_ASSEMB, generic.getID())); + } + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.MONO_MULTI, monoMulti.toString())); + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.SUPERMODEL, Boolean.toString(isSuperModelBOM))); + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.EFFECTIVITY_DATE, effectivityDate.formatAsInputCriteria())); + return theCriteria; + } + + @Override + public String getSpecifiedFileName() { + String separator = "-"; + StringBuilder builder = new StringBuilder("R01-"); + if (generic.getType() != GenericType.ONLY_PRODUCT) { + builder.append(generic.getID()).append(separator); + } + builder.append(productUnit.getProductID()).append(separator); + builder.append(productUnit.getUnit()).append(separator); + builder.append(monoMulti.toString()); + return builder.toString(); + } + + @Override + public PrintFormat getPrintingFormat() { + return PrintFormat.XLSX; + } + + @Override + public ReportEnum getReportIdentifier() { + return ReportEnum.REPORT_R01; + } + + @Override + public List getQuickChecks() { + List quickChecks = new ArrayList<>(); + quickChecks.add(new GenericExistenceChecker(generic)); + quickChecks.add(new ProductChecker(productUnit.getProductID())); + quickChecks.add(new ProductUnitChecker(productUnit)); + quickChecks.add(new EffectivityChecker(effectivityDate)); + return quickChecks; + } + + @Override + public List getLongChecks() { + List longChecks = new ArrayList<>(); + longChecks.add(new GenericUnderProductUnitChecker(generic)); + return longChecks; + } + + @Override + public PolicyLocation getPropertyPolicyForLongChecks() { + return R01_POLICY_XML_LIGHT; + } + + @Override + public PolicyLocation getFullPolicy() { + return R01_POLICY_XML_FULL; + } + + @Override + public String getTemplateLocation() { + return JasperTemplate.TEMPLATE_R01.getFilepath(); + } + + @Override + public IDataReportPreparator getDataPreparator() { + return DATA_REPORT_PREPARATOR_R01; + } + + @Override + public AbstractExecutionReport cloneTemplateToExecution() { + return new ExecutionR01(productUnit, generic, monoMulti, effectivityDate, isSuperModelBOM); + } + + @Override + public Class getReportBuilderClass() { + return R01Builder.class; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r01report/visitors/R01Visitor.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r01report/visitors/R01Visitor.java new file mode 100644 index 0000000..6279fd5 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r01report/visitors/R01Visitor.java @@ -0,0 +1,103 @@ +package com.capgemini.reports.definition.r01report.visitors; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.definition.r01report.ExecutionR01; +import com.capgemini.reports.definition.r01report.visitors.bomlineholder.R01BOMLineHolderVisitor; +import com.capgemini.reports.execution.mapconstructor.AbstractStaticTemplateMapConstructor; +import com.capgemini.reports.printing.PrintParameters; +import com.capgemini.reports.reports.IReportVisitor; +import lombok.EqualsAndHashCode; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.NoSuchElementException; + +/** + * Visit a R01 report. + */ +@Slf4j +@EqualsAndHashCode(callSuper = true) +public class R01Visitor extends AbstractStaticTemplateMapConstructor implements IReportVisitor { + + private static final long serialVersionUID = -943826236018829172L; + private static final String NULL = ""; + private static final String EMPTY = ""; + + protected final R01BOMLineHolderVisitor r01BOMLineHolderVisitor = new R01BOMLineHolderVisitor(); + + /** + * Constructor. + */ + public R01Visitor() { + super(); + } + + private static String check(final Object anInput) { + return anInput == null ? NULL : anInput.toString(); + } + + /** + * Translate the specific result of the visitor into something the printer can understand. + */ + private List> translate(final List> visitorMaps) { + // Add empty fields in the first line + Map firstLine = visitorMaps.get(0); + // Empty receptor + firstLine.put(R01VisitorKeys.IDENTIFIANT_RECEPTEUR, EMPTY); + firstLine.put(R01VisitorKeys.REVISION_RECEPTEUR, EMPTY); + firstLine.put(R01VisitorKeys.NOM_RECEPTEUR, EMPTY); + // Empty RF + firstLine.put(R01VisitorKeys.REPERE_FONCTIONNEL, EMPTY); + firstLine.put(R01VisitorKeys.REVISION_REPERE_FONCTIONNEL, EMPTY); + firstLine.put(R01VisitorKeys.IDENTIFIANT_REPERE_FONCTIONNEL, EMPTY); + firstLine.put(R01VisitorKeys.MAQUETTE, EMPTY); + firstLine.put(R01VisitorKeys.TRANSFERT_LIEN_LOGISTIQUE, EMPTY); + firstLine.put(R01VisitorKeys.TRANSFERT_LIEN_MONTAGE, EMPTY); + firstLine.put(R01VisitorKeys.UIN, EMPTY); + firstLine.put(R01VisitorKeys.EQUIVALENT_SNSSIN, EMPTY); + firstLine.put(R01VisitorKeys.RESPONSABLE_REPERE, EMPTY); + firstLine.put(R01VisitorKeys.SUIVI_MONTAGE, EMPTY); + // Empty BOM + firstLine.put(R01VisitorKeys.ALT, EMPTY); + firstLine.put(R01VisitorKeys.SB, EMPTY); + firstLine.put(R01VisitorKeys.QUANTITE_CUMULEE, EMPTY); + firstLine.put(R01VisitorKeys.PANACHE, EMPTY); + firstLine.put(R01VisitorKeys.QUANTITE, EMPTY); + + // Construct the map list expected by the printer + List> printerMaps = new ArrayList<>(); + for (Map visitorMap : visitorMaps) { + Map printerMap = new HashMap<>(); + for (R01VisitorKeys key : R01VisitorKeys.values()) { + printerMap.put(key.toString(), check(visitorMap.get(key))); + } + printerMaps.add(printerMap); + } + + return printerMaps; + } + + @Override + public List> visitReport(final BOMLineHolder holder) { + List> visitorMaps = r01BOMLineHolderVisitor.visitTopReceptorBom(holder); + return translate(visitorMaps); + } + + @Override + public void constructDataMaps(TcSession session, final PrintParameters printParameters, final BOMLineHolder data) throws KurtException { + long start = System.currentTimeMillis(); + if (data == null) { + throw new NoSuchElementException("No Product structure found"); + } + + // Parse all the snecma objects... + List> printerMaps = this.visitReport(data); + printParameters.addReportData(printerMaps); + log.info("Filtering time : {} ms", System.currentTimeMillis() - start); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r01report/visitors/R01VisitorKeys.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r01report/visitors/R01VisitorKeys.java new file mode 100644 index 0000000..50b845a --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r01report/visitors/R01VisitorKeys.java @@ -0,0 +1,49 @@ +package com.capgemini.reports.definition.r01report.visitors; + +/** + * Enumeration of all the columns of the R01 report. + */ +public enum R01VisitorKeys { + IDENTIFIANT_RECEPTEUR, + REVISION_RECEPTEUR, + NOM_RECEPTEUR, + REPERE_FONCTIONNEL, + REVISION_REPERE_FONCTIONNEL, + UIN, + EQUIVALENT_SNSSIN, + RESPONSABLE_REPERE, + SUIVI_MONTAGE, + ALT, + SB, + QUANTITE_CUMULEE, + PANACHE, + QUANTITE, + REF_FABRICANT_REF_SNECMA, + REVISION_REFERENCE, + REFERENCE_CONCEPTEUR, + TYPE_REFERENCE, + NOM_REFERENCE, + DESIGNATION_EN, + REFERENCE_TRANSPOSEE, + RESPONSABLE_CONCEPTION, + ALTERNATIVE, + CLASSEMENT, + SUIVI_UTILISATION, + SUIVI_DUREE_VIE, + MASSE_INDICATIVE, + UNITE_DE_MASSE, + IDENTIFIANT_REPERE_FONCTIONNEL, + MAQUETTE, + TRANSFERT_LIEN_LOGISTIQUE, + TRANSFERT_LIEN_MONTAGE, + STATUT_REFERENCE_ARTICLE, + SUIVI_DEVELOPPEMENT, + TYPE_PRODUIT, + DOCUMENT_CONTROLE, + OBTURATION, + MOT_CLE_EN, + MOT_CLE_FR, + DATE_PEREMPTION, + CR, + CN +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r01report/visitors/bomlineholder/R01AltOrDetBehaviour.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r01report/visitors/bomlineholder/R01AltOrDetBehaviour.java new file mode 100644 index 0000000..9fdae43 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r01report/visitors/bomlineholder/R01AltOrDetBehaviour.java @@ -0,0 +1,61 @@ +package com.capgemini.reports.definition.r01report.visitors.bomlineholder; + +import com.capgemini.reports.bomlineholder.processor.AltOrDetBehaviour; +import com.capgemini.reports.definition.r01report.visitors.R01VisitorKeys; +import com.capgemini.reports.snecmaobjects.part.AlternateRevision; +import com.capgemini.reports.snecmaobjects.part.DETRevision; + +import java.util.Map; + +/** + * This class visits Parts that are below an {@link AlternateRevision} or a {@link DETRevision}.
    + * It puts "Oui" in the ALTERNATIVE field of a map. + */ +public class R01AltOrDetBehaviour implements AltOrDetBehaviour { + private static final long serialVersionUID = -1337127910440186192L; + + private static final String OUI = "Oui"; + private static final String EMPTY_STRING = ""; + + @Override + public boolean shouldVisitPartsInPseudoFolder() { + return true; + } + + @Override + public boolean shouldVisitPartsBelowAlt() { + return true; + } + + @Override + public void treatPartsInPseudoFolder(final Map map) { + treatAnyPartBelowThisAltOrDet(map); + } + + @Override + public void treatAlternateOrDETAsReceptor(final Map map) { + treatAnyPartBelowThisAltOrDet(map); + } + + private void treatAnyPartBelowThisAltOrDet(final Map map) { + // Empty fields + map.put(R01VisitorKeys.REPERE_FONCTIONNEL, EMPTY_STRING); + map.put(R01VisitorKeys.IDENTIFIANT_REPERE_FONCTIONNEL, EMPTY_STRING); + map.put(R01VisitorKeys.REVISION_REPERE_FONCTIONNEL, EMPTY_STRING); + map.put(R01VisitorKeys.MAQUETTE, EMPTY_STRING); + map.put(R01VisitorKeys.UIN, EMPTY_STRING); + map.put(R01VisitorKeys.EQUIVALENT_SNSSIN, EMPTY_STRING); + map.put(R01VisitorKeys.RESPONSABLE_REPERE, EMPTY_STRING); + map.put(R01VisitorKeys.TRANSFERT_LIEN_LOGISTIQUE, EMPTY_STRING); + map.put(R01VisitorKeys.TRANSFERT_LIEN_MONTAGE, EMPTY_STRING); + map.put(R01VisitorKeys.SUIVI_MONTAGE, EMPTY_STRING); + map.put(R01VisitorKeys.ALT, EMPTY_STRING); + map.put(R01VisitorKeys.SB, EMPTY_STRING); + map.put(R01VisitorKeys.QUANTITE_CUMULEE, EMPTY_STRING); + map.put(R01VisitorKeys.PANACHE, EMPTY_STRING); + map.put(R01VisitorKeys.QUANTITE, EMPTY_STRING); + + // Mention that these parts are alternatives to each other + map.put(R01VisitorKeys.ALTERNATIVE, OUI); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r01report/visitors/bomlineholder/R01BOMLineHolderVisitor.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r01report/visitors/bomlineholder/R01BOMLineHolderVisitor.java new file mode 100644 index 0000000..6e830d1 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r01report/visitors/bomlineholder/R01BOMLineHolderVisitor.java @@ -0,0 +1,83 @@ +package com.capgemini.reports.definition.r01report.visitors.bomlineholder; + +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.bomlineholder.visitor.AbstractBOMLineHolderVisitor; +import com.capgemini.reports.definition.r01report.visitors.R01VisitorKeys; +import com.capgemini.reports.definition.r01report.visitors.snecmaobject.R01ComponentVisitor; +import com.capgemini.reports.definition.r01report.visitors.snecmaobject.R01ReceptorVisitor; +import com.capgemini.reports.releasestatus.EffectivityBehaviourHelper; +import lombok.EqualsAndHashCode; +import lombok.extern.slf4j.Slf4j; + +import java.util.Map; + +/** + * Visitor of an expansion of BOMLineHolder for the R01 report. + */ +@Slf4j +@EqualsAndHashCode(callSuper = true) +public class R01BOMLineHolderVisitor extends AbstractBOMLineHolderVisitor { + private static final long serialVersionUID = -2136631482354508026L; + + public R01BOMLineHolderVisitor() { + super(new R01ReceptorVisitor(), new R01ComponentVisitor(), EffectivityBehaviourHelper.visitAnyPart(), + new R01AltOrDetBehaviour(), true, true, true); + } + + @Override + protected Map visitThisReceptor(final BOMLineHolder aBomLine) { + return aBomLine.getSnecmaObject().accept(receptorVisitor); + } + + @Override + protected Map visitThisComponent(final BOMLineHolder aBomLine) { + Map aMap = aBomLine.getSnecmaObject().accept(componentVisitor); + + // Put the BOMLine properties into the map + if ((aBomLine.getSnecmaObject().isGeneric()) || (aBomLine.getSnecmaObject().isPart()) || aBomLine.getSnecmaObject().isSuperModel()) { + aMap.put(R01VisitorKeys.ALT, aBomLine.getBomAlt()); + aMap.put(R01VisitorKeys.SB, aBomLine.getBomSb()); + aMap.put(R01VisitorKeys.QUANTITE_CUMULEE, aBomLine.getBomQtyCumul()); + aMap.put(R01VisitorKeys.PANACHE, aBomLine.getBomPanache()); + aMap.put(R01VisitorKeys.QUANTITE, aBomLine.getBomQty()); + aMap.put(R01VisitorKeys.UIN, aBomLine.getUin()); + } + return aMap; + } + + @Override + protected void visitSpecificFirstLine(final BOMLineHolder aTopBomLine) { + Map theFirstLine = aTopBomLine.getSnecmaObject().accept(getComponentVisitor()); + theReportTable.add(theFirstLine); + } + + @Override + protected void mergeReceptorAndRepereReceptor(final Map aReceptor, final Map aRepereReceptor) { + aReceptor.putAll(aRepereReceptor); + } + + @Override + protected void mergeComponentAndRepereComponent(final Map aComponent, final Map aRepereComponent) { + aComponent.putAll(aRepereComponent); + } + + @Override + protected void mergeRepereReceptorandAdmin(final Map aRepereReceptor, final Map anAdmin) { + aRepereReceptor.putAll(anAdmin); + } + + @Override + protected void mergeRepereComponentandAdmin(final Map aRepereComponent, final Map anAdmin) { + aRepereComponent.putAll(anAdmin); + } + + @Override + protected void addToReport(final Map aReceptor, final Map aComponent) { + // Put the Receptor and Repere Receptor in the Component and modify the Component + // Do not modify the receptor + aComponent.putAll(aReceptor); + + // Add to the R21 report + theReportTable.add(aComponent); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r01report/visitors/snecmaobject/R01ComponentVisitor.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r01report/visitors/snecmaobject/R01ComponentVisitor.java new file mode 100644 index 0000000..48a7f24 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r01report/visitors/snecmaobject/R01ComponentVisitor.java @@ -0,0 +1,393 @@ +package com.capgemini.reports.definition.r01report.visitors.snecmaobject; + +import com.capgemini.framework.common.DoubleFormatter; +import com.capgemini.framework.common.LanguageHelper; +import com.capgemini.framework.teamcenter.object.pom.status.TcReleaseStatus; +import com.capgemini.reports.definition.r01report.visitors.R01VisitorKeys; +import com.capgemini.reports.snecmaobjects.AbstractSnecmaObject; +import com.capgemini.reports.snecmaobjects.admin.RFAdminAGRevision; +import com.capgemini.reports.snecmaobjects.admin.RFAdminAPRevision; +import com.capgemini.reports.snecmaobjects.admin.RFAdminARevision; +import com.capgemini.reports.snecmaobjects.admin.RFAdminRevision; +import com.capgemini.reports.snecmaobjects.descriptif.DescriptifRevision; +import com.capgemini.reports.snecmaobjects.generic.AbstractGenericRevision; +import com.capgemini.reports.snecmaobjects.generic.GenericAssembRevision; +import com.capgemini.reports.snecmaobjects.generic.GenericRevision; +import com.capgemini.reports.snecmaobjects.mockup.MockupRevision; +import com.capgemini.reports.snecmaobjects.part.*; +import com.capgemini.reports.snecmaobjects.product.ProductRevision; +import com.capgemini.reports.snecmaobjects.rf.AbstractRF; +import com.capgemini.reports.snecmaobjects.rf.RFGenericRevision; +import com.capgemini.reports.snecmaobjects.rf.RFPartAssembRevision; +import com.capgemini.reports.snecmaobjects.rf.RFPartRevision; +import com.capgemini.reports.snecmaobjects.supermodel.AbstractSuperModelRevision; +import com.capgemini.reports.snecmaobjects.supermodel.SuperModelRevision; +import com.capgemini.reports.snecmaobjects.visitor.IComponentVisitor; + +import java.util.EnumMap; +import java.util.List; +import java.util.Map; + +/** + * Visit a Component SnecmaObject to make a R01 report. + */ +public class R01ComponentVisitor implements IComponentVisitor> { + private static final long serialVersionUID = -2446473004152109053L; + + private static final int MASS_SIGNIFICANT_DIGITS = 15; + private static final String EMPTY_STRING = ""; + private static final String PART_MAT = "PartMat"; + private static final String SEPARATOR = " / "; + private static final String VALUE_MATIERE = "matière"; + private static final String PRODUIT = "Produit"; + private static final String GENERIQUE_MONTAGE = "Générique Montage"; + private static final String GENERIQUE = "Générique"; + private static final String PARAM_NON = "Non"; + private static final String PARAM_OUI = "Oui"; + private static final String SOLO_SEPARATOR = "/"; + + private static String french(final String string) { + return LanguageHelper.french(string); + } + + @Override + public Map visitComponent(final ProductRevision aProductRev) { + Map theMap = getAbstractSnecmaObjectProperties(aProductRev); + theMap.put(R01VisitorKeys.DESIGNATION_EN, aProductRev.getDesignationEN()); + theMap.put(R01VisitorKeys.TYPE_PRODUIT, aProductRev.getTypeProduit()); + theMap.put(R01VisitorKeys.TYPE_REFERENCE, PRODUIT); + theMap.put(R01VisitorKeys.SUIVI_UTILISATION, PARAM_NON); + theMap.put(R01VisitorKeys.SUIVI_DUREE_VIE, PARAM_NON); + theMap.put(R01VisitorKeys.REFERENCE_CONCEPTEUR, EMPTY_STRING); + theMap.put(R01VisitorKeys.REFERENCE_TRANSPOSEE, EMPTY_STRING); + theMap.put(R01VisitorKeys.RESPONSABLE_CONCEPTION, EMPTY_STRING); + theMap.put(R01VisitorKeys.MASSE_INDICATIVE, EMPTY_STRING); + theMap.put(R01VisitorKeys.UNITE_DE_MASSE, EMPTY_STRING); + theMap.put(R01VisitorKeys.STATUT_REFERENCE_ARTICLE, statutReferenceArticle(aProductRev.getStatusList())); + theMap.put(R01VisitorKeys.CLASSEMENT, "-"); + theMap.put(R01VisitorKeys.ALTERNATIVE, EMPTY_STRING); + theMap.put(R01VisitorKeys.SUIVI_DEVELOPPEMENT, EMPTY_STRING); + theMap.put(R01VisitorKeys.DOCUMENT_CONTROLE, EMPTY_STRING); + theMap.put(R01VisitorKeys.OBTURATION, EMPTY_STRING); + theMap.put(R01VisitorKeys.DATE_PEREMPTION, EMPTY_STRING); + theMap.put(R01VisitorKeys.MOT_CLE_EN, EMPTY_STRING); + theMap.put(R01VisitorKeys.MOT_CLE_FR, EMPTY_STRING); + theMap.put(R01VisitorKeys.CR, EMPTY_STRING); + theMap.put(R01VisitorKeys.CN, EMPTY_STRING); + return theMap; + } + + private String statutReferenceArticle(final List statuses) { + StringBuilder builder = new StringBuilder(); + int size = statuses.size(); + for (int i = 0; i < size; i++) { + builder.append(statuses.get(i).getDisplayableName()); + if (i != size - 1) { + builder.append(", "); + } + } + return builder.toString(); + } + + @Override + public Map visitComponent(final GenericRevision aGenericRev) { + Map theMap = getAbstractSnecmaObjectProperties(aGenericRev); + theMap.put(R01VisitorKeys.TYPE_REFERENCE, GENERIQUE); + putGenericProperties(theMap, aGenericRev); + return theMap; + } + + @Override + public Map visitComponent(final GenericAssembRevision aGenericAssembRev) { + Map theMap = getAbstractSnecmaObjectProperties(aGenericAssembRev); + theMap.put(R01VisitorKeys.TYPE_REFERENCE, GENERIQUE_MONTAGE); + putGenericProperties(theMap, aGenericAssembRev); + return theMap; + } + + @Override + public Map visitComponent(final SuperModelRevision aSuperModelRev) { + Map theMap = getAbstractSnecmaObjectProperties(aSuperModelRev); + theMap.put(R01VisitorKeys.TYPE_REFERENCE, GENERIQUE); + putSuperModelProperties(theMap, aSuperModelRev); + return theMap; + } + + + @Override + public Map visitComponent(final AlternateRevision anAlternateRev) { + Map theMap = getAbstractSnecmaObjectProperties(anAlternateRev); + putPartProperties(theMap, anAlternateRev); + theMap.put(R01VisitorKeys.TYPE_REFERENCE, french(anAlternateRev.getTypeAlt1()) + SEPARATOR + french(anAlternateRev.getTypeAlt2())); + theMap.put(R01VisitorKeys.SUIVI_DEVELOPPEMENT, french(anAlternateRev.getSuiviDeveloppement())); + theMap.put(R01VisitorKeys.DOCUMENT_CONTROLE, french(anAlternateRev.getDocumentControle())); + theMap.put(R01VisitorKeys.OBTURATION, french(anAlternateRev.getObturation())); + theMap.put(R01VisitorKeys.DATE_PEREMPTION, EMPTY_STRING); + return theMap; + } + + @Override + public Map visitComponent(final DETRevision aDetRev) { + Map theMap = getAbstractSnecmaObjectProperties(aDetRev); + putPartProperties(theMap, aDetRev); + theMap.put(R01VisitorKeys.TYPE_REFERENCE, french(aDetRev.getTypeDet1()) + SEPARATOR + french(aDetRev.getTypeDet2())); + theMap.put(R01VisitorKeys.SUIVI_DEVELOPPEMENT, french(aDetRev.getSuiviDeveloppement())); + theMap.put(R01VisitorKeys.DOCUMENT_CONTROLE, french(aDetRev.getDocumentControle())); + theMap.put(R01VisitorKeys.OBTURATION, french(aDetRev.getObturation())); + return theMap; + } + + @Override + public Map visitComponent(final PartAeroRevision aPartAeroRev) { + Map theMap = getAbstractSnecmaObjectProperties(aPartAeroRev); + putPartProperties(theMap, aPartAeroRev); + theMap.put(R01VisitorKeys.TYPE_REFERENCE, french(aPartAeroRev.getTypeAero1()) + SEPARATOR + french(aPartAeroRev.getTypeAero2()) + SEPARATOR + french(aPartAeroRev.getTypeAero3())); + theMap.put(R01VisitorKeys.SUIVI_DEVELOPPEMENT, french(aPartAeroRev.getSuiviDeveloppement())); + theMap.put(R01VisitorKeys.DOCUMENT_CONTROLE, french(aPartAeroRev.getDocumentControle())); + theMap.put(R01VisitorKeys.OBTURATION, french(aPartAeroRev.getObturation())); + return theMap; + } + + @Override + public Map visitComponent(final PartNoAeroRevision aPartNoAeroRev) { + Map theMap = getAbstractSnecmaObjectProperties(aPartNoAeroRev); + putPartProperties(theMap, aPartNoAeroRev); + theMap.put(R01VisitorKeys.TYPE_REFERENCE, french(aPartNoAeroRev.getTypeNoAero())); + theMap.put(R01VisitorKeys.SUIVI_DEVELOPPEMENT, french(aPartNoAeroRev.getSuiviDeveloppement())); + theMap.put(R01VisitorKeys.DOCUMENT_CONTROLE, french(aPartNoAeroRev.getDocumentControle())); + theMap.put(R01VisitorKeys.OBTURATION, EMPTY_STRING); + theMap.put(R01VisitorKeys.DATE_PEREMPTION, EMPTY_STRING); + return theMap; + } + + @Override + public Map visitComponent(final PartAssembRevision aPartAssembRev) { + Map theMap = getAbstractSnecmaObjectProperties(aPartAssembRev); + putPartProperties(theMap, aPartAssembRev); + theMap.put(R01VisitorKeys.TYPE_REFERENCE, french(aPartAssembRev.getTypePartMontage1()) + SEPARATOR + french(aPartAssembRev.getTypePartMontage2())); + theMap.put(R01VisitorKeys.SUIVI_DEVELOPPEMENT, EMPTY_STRING); + theMap.put(R01VisitorKeys.DOCUMENT_CONTROLE, french(aPartAssembRev.getDocumentControle())); + theMap.put(R01VisitorKeys.OBTURATION, EMPTY_STRING); + theMap.put(R01VisitorKeys.DATE_PEREMPTION, EMPTY_STRING); + return theMap; + } + + @Override + public Map visitComponent(final PartMatRevision aPartMatRev) { + Map theMap = getAbstractSnecmaObjectProperties(aPartMatRev); + putPartProperties(theMap, aPartMatRev); + theMap.put(R01VisitorKeys.TYPE_REFERENCE, VALUE_MATIERE); + theMap.put(R01VisitorKeys.CLASSEMENT, aPartMatRev.getClassementMat()); + theMap.put(R01VisitorKeys.MASSE_INDICATIVE, EMPTY_STRING); + theMap.put(R01VisitorKeys.UNITE_DE_MASSE, EMPTY_STRING); + theMap.put(R01VisitorKeys.SUIVI_UTILISATION, PARAM_NON); + theMap.put(R01VisitorKeys.SUIVI_DUREE_VIE, PARAM_NON); + theMap.put(R01VisitorKeys.SUIVI_DEVELOPPEMENT, EMPTY_STRING); + theMap.put(R01VisitorKeys.DOCUMENT_CONTROLE, EMPTY_STRING); + theMap.put(R01VisitorKeys.OBTURATION, EMPTY_STRING); + theMap.put(R01VisitorKeys.DATE_PEREMPTION, EMPTY_STRING); + theMap.put(R01VisitorKeys.MOT_CLE_EN, EMPTY_STRING); + theMap.put(R01VisitorKeys.MOT_CLE_FR, EMPTY_STRING); + return theMap; + } + + @Override + public Map visitComponent(final StandardRevision aStandardRev) { + Map theMap = getAbstractSnecmaObjectProperties(aStandardRev); + putPartProperties(theMap, aStandardRev); + theMap.put(R01VisitorKeys.TYPE_REFERENCE, french(aStandardRev.getTypeStandard())); + theMap.put(R01VisitorKeys.SUIVI_DEVELOPPEMENT, french(aStandardRev.getSuiviDeveloppement())); + theMap.put(R01VisitorKeys.DOCUMENT_CONTROLE, french(aStandardRev.getDocumentControle())); + theMap.put(R01VisitorKeys.OBTURATION, EMPTY_STRING); + return theMap; + } + + /** + * Get Component properties to make a R01 report. + * + * @param anAbstractSnecmaObject AbstractSnecmaObject + * @return theMap Map + */ + private Map getAbstractSnecmaObjectProperties(final AbstractSnecmaObject anAbstractSnecmaObject) { + Map theMap = new EnumMap<>(R01VisitorKeys.class); + theMap.put(R01VisitorKeys.REF_FABRICANT_REF_SNECMA, anAbstractSnecmaObject.getItemId()); + theMap.put(R01VisitorKeys.NOM_REFERENCE, anAbstractSnecmaObject.getName()); + theMap.put(R01VisitorKeys.REVISION_REFERENCE, anAbstractSnecmaObject.getRevisionId()); + theMap.put(R01VisitorKeys.ALTERNATIVE, EMPTY_STRING); + return theMap; + } + + /** + * Put the Generic properties into aMap. + * + * @param aMap Map + * @param anAbstractGenericRevision AbstractGenericRevision + */ + private void putGenericProperties(final Map aMap, final AbstractGenericRevision anAbstractGenericRevision) { + aMap.put(R01VisitorKeys.DESIGNATION_EN, anAbstractGenericRevision.getDesignationEN()); + aMap.put(R01VisitorKeys.RESPONSABLE_CONCEPTION, anAbstractGenericRevision.getResponsableConception()); + aMap.put(R01VisitorKeys.SUIVI_UTILISATION, PARAM_OUI); + aMap.put(R01VisitorKeys.SUIVI_DUREE_VIE, PARAM_NON); + aMap.put(R01VisitorKeys.REFERENCE_CONCEPTEUR, EMPTY_STRING); + aMap.put(R01VisitorKeys.REFERENCE_TRANSPOSEE, EMPTY_STRING); + aMap.put(R01VisitorKeys.MASSE_INDICATIVE, EMPTY_STRING); + aMap.put(R01VisitorKeys.UNITE_DE_MASSE, EMPTY_STRING); + aMap.put(R01VisitorKeys.STATUT_REFERENCE_ARTICLE, statutReferenceArticle(anAbstractGenericRevision.getStatusList())); + aMap.put(R01VisitorKeys.ALTERNATIVE, EMPTY_STRING); + aMap.put(R01VisitorKeys.CLASSEMENT, "-"); + aMap.put(R01VisitorKeys.TYPE_PRODUIT, EMPTY_STRING); + aMap.put(R01VisitorKeys.SUIVI_DEVELOPPEMENT, EMPTY_STRING); + aMap.put(R01VisitorKeys.DOCUMENT_CONTROLE, EMPTY_STRING); + aMap.put(R01VisitorKeys.OBTURATION, EMPTY_STRING); + aMap.put(R01VisitorKeys.DATE_PEREMPTION, EMPTY_STRING); + aMap.put(R01VisitorKeys.MOT_CLE_EN, EMPTY_STRING); + aMap.put(R01VisitorKeys.MOT_CLE_FR, EMPTY_STRING); + aMap.put(R01VisitorKeys.CR, EMPTY_STRING); + aMap.put(R01VisitorKeys.CN, EMPTY_STRING); + } + + + /** + * Put the Super Model properties into aMap. + * + * @param aMap Map + * @param anAbstractSuperModelRevision AbstractSuperModelRevision + */ + private void putSuperModelProperties(final Map aMap, final AbstractSuperModelRevision anAbstractSuperModelRevision) { + aMap.put(R01VisitorKeys.SUIVI_UTILISATION, EMPTY_STRING); + aMap.put(R01VisitorKeys.SUIVI_DUREE_VIE, EMPTY_STRING); + aMap.put(R01VisitorKeys.REFERENCE_CONCEPTEUR, EMPTY_STRING); + aMap.put(R01VisitorKeys.REFERENCE_TRANSPOSEE, EMPTY_STRING); + aMap.put(R01VisitorKeys.MASSE_INDICATIVE, EMPTY_STRING); + aMap.put(R01VisitorKeys.UNITE_DE_MASSE, EMPTY_STRING); + aMap.put(R01VisitorKeys.TYPE_REFERENCE, french(anAbstractSuperModelRevision.getType())); + aMap.put(R01VisitorKeys.STATUT_REFERENCE_ARTICLE, statutReferenceArticle(anAbstractSuperModelRevision.getStatusList())); + aMap.put(R01VisitorKeys.ALTERNATIVE, EMPTY_STRING); + aMap.put(R01VisitorKeys.CLASSEMENT, "-"); + aMap.put(R01VisitorKeys.TYPE_PRODUIT, EMPTY_STRING); + aMap.put(R01VisitorKeys.SUIVI_DEVELOPPEMENT, EMPTY_STRING); + aMap.put(R01VisitorKeys.DOCUMENT_CONTROLE, EMPTY_STRING); + aMap.put(R01VisitorKeys.OBTURATION, EMPTY_STRING); + aMap.put(R01VisitorKeys.DESIGNATION_EN, EMPTY_STRING); + aMap.put(R01VisitorKeys.RESPONSABLE_CONCEPTION, EMPTY_STRING); + aMap.put(R01VisitorKeys.DATE_PEREMPTION, EMPTY_STRING); + aMap.put(R01VisitorKeys.MOT_CLE_EN, EMPTY_STRING); + aMap.put(R01VisitorKeys.MOT_CLE_FR, EMPTY_STRING); + aMap.put(R01VisitorKeys.CR, EMPTY_STRING); + aMap.put(R01VisitorKeys.CN, EMPTY_STRING); + + } + + + /** + * Put the Part properties into aMap. + * + * @param aMap Map + * @param anAbstractPart AbstractPart + */ + private void putPartProperties(final Map aMap, final AbstractPart anAbstractPart) { + aMap.put(R01VisitorKeys.DESIGNATION_EN, anAbstractPart.getDesignationEN()); + aMap.put(R01VisitorKeys.REFERENCE_CONCEPTEUR, anAbstractPart.getRefCompleteConcepteur()); + aMap.put(R01VisitorKeys.REFERENCE_TRANSPOSEE, anAbstractPart.getRefTransposeeSnecma()); + aMap.put(R01VisitorKeys.RESPONSABLE_CONCEPTION, anAbstractPart.getResponsableConception()); + if (!PART_MAT.equals(anAbstractPart.getType())) { + aMap.put(R01VisitorKeys.CLASSEMENT, anAbstractPart.getClassement()); + aMap.put(R01VisitorKeys.SUIVI_UTILISATION, french(anAbstractPart.getSuiviUtilisation())); + aMap.put(R01VisitorKeys.SUIVI_DUREE_VIE, french(anAbstractPart.getSuiviDureeVie())); + aMap.put(R01VisitorKeys.MASSE_INDICATIVE, DoubleFormatter.toSignificantDigits(anAbstractPart.getMass(), MASS_SIGNIFICANT_DIGITS)); + aMap.put(R01VisitorKeys.UNITE_DE_MASSE, anAbstractPart.getMassUnit()); + } + aMap.put(R01VisitorKeys.STATUT_REFERENCE_ARTICLE, statutReferenceArticle(anAbstractPart.getStatusList())); + aMap.put(R01VisitorKeys.TYPE_PRODUIT, anAbstractPart.getTypeProduit()); + aMap.put(R01VisitorKeys.DATE_PEREMPTION, anAbstractPart.getExpirationDate()); + aMap.put(R01VisitorKeys.MOT_CLE_EN, anAbstractPart.getMotClefEN()); + aMap.put(R01VisitorKeys.MOT_CLE_FR, anAbstractPart.getMotClefFR()); + aMap.put(R01VisitorKeys.CR, anAbstractPart.getCRPseudoFolderContentAsString()); + aMap.put(R01VisitorKeys.CN, anAbstractPart.getCNPseudoFolderContentAsString()); + } + + @Override + public Map visitComponent(final RFGenericRevision aRfGenericRev) { + Map theMap = getRfProperties(aRfGenericRev); + theMap.put(R01VisitorKeys.SUIVI_MONTAGE, PARAM_NON); + return theMap; + } + + @Override + public Map visitComponent(final RFPartAssembRevision aRfPartAssembRev) { + Map theMap = new EnumMap<>(R01VisitorKeys.class); + theMap.put(R01VisitorKeys.REPERE_FONCTIONNEL, aRfPartAssembRev.getName()); + theMap.put(R01VisitorKeys.REVISION_REPERE_FONCTIONNEL, aRfPartAssembRev.getRevisionId()); + theMap.put(R01VisitorKeys.IDENTIFIANT_REPERE_FONCTIONNEL, aRfPartAssembRev.getItemId()); + theMap.put(R01VisitorKeys.EQUIVALENT_SNSSIN, EMPTY_STRING); + return theMap; + } + + @Override + public Map visitComponent(final RFPartRevision aRfPartRev) { + return getRfProperties(aRfPartRev); + } + + @Override + public Map visitComponent(final RFAdminRevision aRfAdminRev) { + Map theMap = new EnumMap<>(R01VisitorKeys.class); + theMap.put(R01VisitorKeys.RESPONSABLE_REPERE, aRfAdminRev.getResponsableRepere()); + theMap.put(R01VisitorKeys.MAQUETTE, french(aRfAdminRev.getMaqIntExt())); + return theMap; + } + + @Override + public Map visitComponent(final RFAdminARevision aRfAdminARev) { + Map theMap = new EnumMap<>(R01VisitorKeys.class); + theMap.put(R01VisitorKeys.SUIVI_MONTAGE, french(aRfAdminARev.getSuiviMontage())); + theMap.put(R01VisitorKeys.RESPONSABLE_REPERE, aRfAdminARev.getResponsableRepere()); + theMap.put(R01VisitorKeys.MAQUETTE, french(aRfAdminARev.getMaqIntExt())); + theMap.put(R01VisitorKeys.TRANSFERT_LIEN_LOGISTIQUE, french(aRfAdminARev.getTransfertLienLogisti())); + theMap.put(R01VisitorKeys.TRANSFERT_LIEN_MONTAGE, french(aRfAdminARev.getTransfertLienMontage())); + return theMap; + } + + @Override + public Map visitComponent(final RFAdminAPRevision aRfAdminAPRev) { + Map theMap = new EnumMap<>(R01VisitorKeys.class); + theMap.put(R01VisitorKeys.SUIVI_MONTAGE, french(aRfAdminAPRev.getSuiviMontage())); + theMap.put(R01VisitorKeys.TRANSFERT_LIEN_LOGISTIQUE, french(aRfAdminAPRev.getTransfertLienLogisti())); + theMap.put(R01VisitorKeys.TRANSFERT_LIEN_MONTAGE, french(aRfAdminAPRev.getTransfertLienMontage())); + return theMap; + } + + @Override + public Map visitComponent(final RFAdminAGRevision aRfAdminAGRev) { + Map theMap = new EnumMap<>(R01VisitorKeys.class); + theMap.put(R01VisitorKeys.TRANSFERT_LIEN_LOGISTIQUE, french(aRfAdminAGRev.getTransfertLienLogisti())); + theMap.put(R01VisitorKeys.TRANSFERT_LIEN_MONTAGE, french(aRfAdminAGRev.getTransfertLienMontage())); + return theMap; + } + + /** + * Get the Repere Component properties to make a R01 report. + * + * @param anAbstractRF AbstractRF + * @return theMap Map + */ + private Map getRfProperties(final AbstractRF anAbstractRF) { + Map theMap = new EnumMap<>(R01VisitorKeys.class); + theMap.put(R01VisitorKeys.REPERE_FONCTIONNEL, anAbstractRF.getName()); + theMap.put(R01VisitorKeys.IDENTIFIANT_REPERE_FONCTIONNEL, anAbstractRF.getItemId()); + theMap.put(R01VisitorKeys.REVISION_REPERE_FONCTIONNEL, anAbstractRF.getRevisionId()); + theMap.put(R01VisitorKeys.EQUIVALENT_SNSSIN, anAbstractRF.getEquivalentSnsSin()); + return theMap; + } + + @Override + public Map visitComponent(final MockupRevision aMockupRev) { + // This object is not use in this report + return null; + } + + @Override + public Map visitComponent(final DescriptifRevision aDescriptifRev) { + // This object is not use in this report + return null; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r01report/visitors/snecmaobject/R01ReceptorVisitor.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r01report/visitors/snecmaobject/R01ReceptorVisitor.java new file mode 100644 index 0000000..1800bcd --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r01report/visitors/snecmaobject/R01ReceptorVisitor.java @@ -0,0 +1,164 @@ +package com.capgemini.reports.definition.r01report.visitors.snecmaobject; + +import com.capgemini.reports.definition.r01report.visitors.R01VisitorKeys; +import com.capgemini.reports.snecmaobjects.ISnecmaObject; +import com.capgemini.reports.snecmaobjects.admin.RFAdminAGRevision; +import com.capgemini.reports.snecmaobjects.admin.RFAdminAPRevision; +import com.capgemini.reports.snecmaobjects.admin.RFAdminARevision; +import com.capgemini.reports.snecmaobjects.admin.RFAdminRevision; +import com.capgemini.reports.snecmaobjects.descriptif.DescriptifRevision; +import com.capgemini.reports.snecmaobjects.generic.GenericAssembRevision; +import com.capgemini.reports.snecmaobjects.generic.GenericRevision; +import com.capgemini.reports.snecmaobjects.mockup.MockupRevision; +import com.capgemini.reports.snecmaobjects.part.*; +import com.capgemini.reports.snecmaobjects.product.ProductRevision; +import com.capgemini.reports.snecmaobjects.rf.RFGenericRevision; +import com.capgemini.reports.snecmaobjects.rf.RFPartAssembRevision; +import com.capgemini.reports.snecmaobjects.rf.RFPartRevision; +import com.capgemini.reports.snecmaobjects.supermodel.SuperModelRevision; +import com.capgemini.reports.snecmaobjects.visitor.IReceptorVisitor; + +import java.util.EnumMap; +import java.util.Map; + +/** + * Visit a Receptor SnecmaObject to make a R01 report. + */ +public class R01ReceptorVisitor implements IReceptorVisitor> { + private static final long serialVersionUID = -3978586236500021891L; + + @Override + public Map visitReceptor(final ProductRevision aProductRev) { + return getReceptorProperties(aProductRev); + } + + @Override + public Map visitReceptor(final GenericRevision aGenericRev) { + return getReceptorProperties(aGenericRev); + } + + @Override + public Map visitReceptor(final GenericAssembRevision aGenericAssembRev) { + return getReceptorProperties(aGenericAssembRev); + } + + @Override + public Map visitReceptor(final SuperModelRevision aSuperModelRev) { + return getReceptorProperties(aSuperModelRev); + } + + @Override + public Map visitReceptor(final AlternateRevision anAlternateRev) { + return getReceptorProperties(anAlternateRev); + } + + @Override + public Map visitReceptor(final DETRevision aDetRev) { + return getReceptorProperties(aDetRev); + } + + @Override + public Map visitReceptor(final PartAeroRevision aPartAeroRev) { + return getReceptorProperties(aPartAeroRev); + } + + @Override + public Map visitReceptor(final PartNoAeroRevision aPartNoAeroRev) { + return getReceptorProperties(aPartNoAeroRev); + } + + @Override + public Map visitReceptor(final PartAssembRevision aPartAssembRev) { + return getReceptorProperties(aPartAssembRev); + } + + @Override + public Map visitReceptor(final PartMatRevision aPartMatRev) { + return getReceptorProperties(aPartMatRev); + } + + @Override + public Map visitReceptor(final StandardRevision aStandardRev) { + return getReceptorProperties(aStandardRev); + } + + @Override + public Map visitReceptor(final RFGenericRevision aRfGenericRev) { + // No use in R01 report + return new EnumMap<>(R01VisitorKeys.class); + } + + @Override + public Map visitReceptor(final RFPartAssembRevision aRfPartAssembRev) { + // No use in R01 report + return new EnumMap<>(R01VisitorKeys.class); + } + + @Override + public Map visitReceptor(final RFPartRevision aRfPartRev) { + // No use in R01 report + return new EnumMap<>(R01VisitorKeys.class); + } + + @Override + public Map visitReceptor(final RFAdminRevision aRfAdminRev) { + // No use in R01 report + return new EnumMap<>(R01VisitorKeys.class); + } + + @Override + public Map visitReceptor(final RFAdminARevision aRfAdminARev) { + // No use in R01 report + return new EnumMap<>(R01VisitorKeys.class); + } + + @Override + public Map visitReceptor(final RFAdminAPRevision aRfAdminAPRev) { + // No use in R01 report + return new EnumMap<>(R01VisitorKeys.class); + } + + @Override + public Map visitReceptor(final RFAdminAGRevision aRfAdminAGRev) { + // No use in R01 report + return new EnumMap<>(R01VisitorKeys.class); + } + + /** + * Get the Receptor properties. + */ + private Map getReceptorProperties(final ISnecmaObject iSnecmaObject) { + Map theMap = new EnumMap<>(R01VisitorKeys.class); + theMap.put(R01VisitorKeys.IDENTIFIANT_RECEPTEUR, iSnecmaObject.getItemId()); + theMap.put(R01VisitorKeys.NOM_RECEPTEUR, iSnecmaObject.getName()); + theMap.put(R01VisitorKeys.REVISION_RECEPTEUR, iSnecmaObject.getRevisionId()); + return theMap; + } + + @Override + public Map visitReceptor(final MockupRevision aMockupRev) { + // This object is not use in this report + return null; + } + + @Override + public Map visitReceptor(final DescriptifRevision aDescriptifRev) { + // This object is not use in this report + return null; + } + + @Override + public Map emptyRf() { + Map theMap = new EnumMap<>(R01VisitorKeys.class); + theMap.put(R01VisitorKeys.REPERE_FONCTIONNEL, ""); + theMap.put(R01VisitorKeys.REVISION_REPERE_FONCTIONNEL, ""); + theMap.put(R01VisitorKeys.IDENTIFIANT_REPERE_FONCTIONNEL, ""); + theMap.put(R01VisitorKeys.MAQUETTE, ""); + theMap.put(R01VisitorKeys.TRANSFERT_LIEN_LOGISTIQUE, ""); + theMap.put(R01VisitorKeys.TRANSFERT_LIEN_MONTAGE, ""); + theMap.put(R01VisitorKeys.EQUIVALENT_SNSSIN, ""); + theMap.put(R01VisitorKeys.RESPONSABLE_REPERE, ""); + theMap.put(R01VisitorKeys.SUIVI_MONTAGE, ""); + return theMap; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r03report/DataReportPreparatorR03.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r03report/DataReportPreparatorR03.java new file mode 100644 index 0000000..591b230 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r03report/DataReportPreparatorR03.java @@ -0,0 +1,96 @@ +package com.capgemini.reports.definition.r03report; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.EmptyNomenclatureException; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcBomObject; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcBomObjectFactory; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcRevisionRule; +import com.capgemini.framework.teamcenter.object.runtime.TcBomWindow; +import com.capgemini.framework.teamcenter.object.runtime.TcBomWindowConfiguration; +import com.capgemini.framework.teamcenter.object.runtime.TcRevisionRulesConfiguration; +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.capgemini.framework.teamcenter.queries.saved.modelobject.ItemRevisionQuery; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.bomlineholder.BOMLineHolderFactory; +import com.capgemini.reports.bomlineholder.processor.DefaultAltOrDetBehaviour; +import com.capgemini.reports.definition.r03report.visitors.R03Visitor; +import com.capgemini.reports.exceptions.InvalidUserInputException; +import com.capgemini.reports.exceptions.UserInputErrorEnum; +import com.capgemini.reports.execution.IDataReportPreparator; +import com.capgemini.reports.execution.strategies.IExecutionStrategy; +import com.capgemini.reports.filter.AllIsGoodFilter; +import com.capgemini.reports.printing.PrintParameters; +import com.capgemini.reports.reports.parameters.EffectivityDate; +import com.capgemini.reports.teamcenter.resolution.structureservice.MultiStructureServiceCaller; +import com.teamcenter.soa.client.model.ModelObject; +import com.teamcenter.soa.client.model.strong.Form; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +/** + * This class will allow to prepare data and findAll back data for making report R03. + */ +public class DataReportPreparatorR03 implements IDataReportPreparator { + private static final long serialVersionUID = 8862577856995249621L; + private static final Logger LOGGER = LoggerFactory.getLogger(DataReportPreparatorR03.class); + + private static final AllIsGoodFilter ACCEPT_ALL = new AllIsGoodFilter(); + + @Override + public String print(TcSession session, ExecutionR03 execution, IExecutionStrategy executionStrategy) throws KurtException { + PrintParameters printParameters = prepareData(session, execution); + executionStrategy.print(printParameters, execution); + return executionStrategy.getReportFileName(execution) + printParameters.getOuputFileExtension(); + } + + private PrintParameters prepareData(final TcSession session, final ExecutionR03 report) throws KurtException { + LOGGER.debug("PrepareData started on: {}", report.getReportIdentifier().getReportTitle()); + + List list = new ItemRevisionQuery(session).searchIDAndRevision(report.getPartID(), report.getPartRevisionID()).findAll(); + if (list.isEmpty()) { + throw new InvalidUserInputException(UserInputErrorEnum.OBJECT_DOES_NOT_EXIST); + } + + ItemRevision itemRevision = null; + + for(ItemRevision currentItemRev : list) { + if(SnecmaObjectTypes.isPartRevision(currentItemRev.getTypeObject().getName())){ + itemRevision = currentItemRev; + break; + } + } + + if(itemRevision == null){ + throw new InvalidUserInputException(UserInputErrorEnum.THE_SELECTED_OBJECT_IS_NOT_PERMITTED_ON_THIS_REPORT); + } + + TcRevisionRule revisionRule = session.findRevRule(report.getRevisionRule()); + TcRevisionRulesConfiguration revRulesConfiguration = new TcRevisionRulesConfiguration(revisionRule); + TcBomObject topLineObject = new TcBomObjectFactory(session, itemRevision).create(); + try (TcBomWindow bomWindow = session.createBomWindow(new TcBomWindowConfiguration(topLineObject, revRulesConfiguration))) { + session.setObjectPropPolicy(report.getFullPolicy()); + + BOMLineHolder unbuiltTopLine = new MultiStructureServiceCaller(session).resolve(bomWindow.topLine(), ACCEPT_ALL); + List itemRevMaster = unbuiltTopLine.getAllItemRevMasters(); + session.loadProperties(itemRevMaster.toArray(new ModelObject[itemRevMaster.size()])); + + BOMLineHolderFactory.buildTopBom(session, unbuiltTopLine, ACCEPT_ALL); + DefaultAltOrDetBehaviour altOrDetBehaviour = new DefaultAltOrDetBehaviour(session, new EffectivityDate().getDateTime()); + unbuiltTopLine.process(altOrDetBehaviour); + unbuiltTopLine.freeze(); + + R03Visitor visitor = new R03Visitor(); + PrintParameters printParameters = visitor.makeMasterTemplate(report, unbuiltTopLine); + visitor.constructDataMaps(session, printParameters, unbuiltTopLine); + + LOGGER.debug("PrepareData ended on: {}", report.getReportIdentifier().getReportTitle()); + return printParameters; + } catch (EmptyNomenclatureException e) { + throw new KurtException("The TC Nomenclature Resolution returned null", e); + } + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r03report/ExecutionR03.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r03report/ExecutionR03.java new file mode 100644 index 0000000..139239a --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r03report/ExecutionR03.java @@ -0,0 +1,137 @@ +package com.capgemini.reports.definition.r03report; + +import com.capgemini.framework.common.SettingsHelper; +import com.capgemini.framework.common.TeamcenterDateFormatter; +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.reports.JasperTemplate; +import com.capgemini.reports.ReportEnum; +import com.capgemini.reports.ReportLaunchTypeEnum; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.builder.R03Builder; +import com.capgemini.reports.builder.ReportBuilder; +import com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum; +import com.capgemini.reports.database.manager.MngCriteriaVal.CriteriaValue; +import com.capgemini.reports.execution.AbstractExecutionReport; +import com.capgemini.reports.execution.IDataReportPreparator; +import com.capgemini.reports.printing.Printer.PrintFormat; +import com.capgemini.reports.reports.parameters.IChecker; +import com.capgemini.reports.reports.parameters.checker.ObjectTypeChecker; +import lombok.EqualsAndHashCode; +import lombok.Getter; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; + +/** + * This class controls the execution of the R03 report. + */ +@Getter +@EqualsAndHashCode(callSuper = true) +public class ExecutionR03 extends AbstractExecutionReport { + private static final long serialVersionUID = -1050126556474290283L; + + // Policies parameter + private static final PolicyLocation R03_POLICY_XML_FULL = PolicyLocation.make("R03_policy_full", "/xml/policies/r03report/R03_policy_full.xml"); + private static final PolicyLocation R03_POLICY_XML_LIGHT = PolicyLocation.make("R03_policy_light", "/xml/policies/r03report/R03_policy_light.xml"); + + // Priority parameter + private static final int REPORT_PRIORITY = SettingsHelper.getPriority(ReportEnum.REPORT_R03); + + // Revision rule parameter + private static final String REPORT_REVISION_RULE = SettingsHelper.getPropertyWithDefaultValue("common.bom.revisionRule.REPORT_R03", DEFAULT_REVISION_RULE); + + // Launch type parameter + private static final ReportLaunchTypeEnum REPORT_LAUNCH_TYPE = ReportLaunchTypeEnum.getReportLaunchType("common.launch.launchType.REPORT_R03"); + + // Configuration + private static final String FILE_SEPARATOR = "_"; + private static final String PATTERN_DATE = "dd-MM-yyyy"; + + // Internal working data + private final String partID; + private final String partRevisionID; + + /** + * Executes the Report R03. + * + * @param partId {@link String} - the part Id + * @param partRevisionID {@link String} - the part revision Id + */ + public ExecutionR03(final String partId, final String partRevisionID) { + super(REPORT_PRIORITY, REPORT_REVISION_RULE, REPORT_LAUNCH_TYPE); + this.partID = partId; + this.partRevisionID = partRevisionID; + } + + @Override + public List getLaunchData() { + List theCriteria = new ArrayList<>(); + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.PART_ID, partID)); + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.PART_REVISION, partRevisionID)); + return theCriteria; + } + + @Override + public String getTemplateLocation() { + return JasperTemplate.TEMPLATE_R03.getFilepath(); + } + + @Override + public List getQuickChecks() { + List quickChecks = new ArrayList<>(); + quickChecks.add(new ObjectTypeChecker(partID, SnecmaObjectTypes.ALTERNATE, SnecmaObjectTypes.DET, SnecmaObjectTypes.PART_AERO, + SnecmaObjectTypes.PART_ASSEMB, SnecmaObjectTypes.PART_MAT, SnecmaObjectTypes.PART_NO_AERO, + SnecmaObjectTypes.STANDARD)); + return quickChecks; + } + + @Override + public PolicyLocation getPropertyPolicyForLongChecks() { + return R03_POLICY_XML_LIGHT; + } + + @Override + public PolicyLocation getFullPolicy() { + return R03_POLICY_XML_FULL; + } + + @Override + public List getLongChecks() { + // Empty lists - not used for this report + return new ArrayList<>(); + } + + @Override + public ReportEnum getReportIdentifier() { + return ReportEnum.REPORT_R03; + } + + @Override + public String getSpecifiedFileName() { + // Format file expected : BOMParDATE_ "RéférenceArticle"_"RévisionArticle"_"date_système".pdf + String dateSystem = TeamcenterDateFormatter.formatCalendarToPattern(Calendar.getInstance(), PATTERN_DATE); + return "R03-BOMParDATE_" + partID + FILE_SEPARATOR + partRevisionID + FILE_SEPARATOR + dateSystem; + } + + @Override + public PrintFormat getPrintingFormat() { + return PrintFormat.XLSX; + } + + @Override + public IDataReportPreparator getDataPreparator() { + return new DataReportPreparatorR03(); + } + + @Override + public AbstractExecutionReport cloneTemplateToExecution() { + return new ExecutionR03(partID, partRevisionID); + } + + @Override + public Class getReportBuilderClass() { + return R03Builder.class; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r03report/visitors/R03Visitor.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r03report/visitors/R03Visitor.java new file mode 100644 index 0000000..83d6ff2 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r03report/visitors/R03Visitor.java @@ -0,0 +1,99 @@ +package com.capgemini.reports.definition.r03report.visitors; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.definition.r03report.ExecutionR03; +import com.capgemini.reports.definition.r03report.visitors.bomlineholder.R03BOMLineHolderVisitor; +import com.capgemini.reports.execution.mapconstructor.AbstractStaticTemplateMapConstructor; +import com.capgemini.reports.printing.PrintParameters; +import com.capgemini.reports.reports.IReportVisitor; +import lombok.EqualsAndHashCode; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.NoSuchElementException; + +/** + * Visit a R03 report. + */ +@Slf4j +@EqualsAndHashCode(callSuper = true) +public class R03Visitor extends AbstractStaticTemplateMapConstructor implements IReportVisitor { + private static final long serialVersionUID = -1999990931692459183L; + + private static final String EMPTY = ""; + + protected final R03BOMLineHolderVisitor r03BOMLineHolderVisitor; + + /** + * Constructor. + */ + public R03Visitor() { + super(); + this.r03BOMLineHolderVisitor = new R03BOMLineHolderVisitor(); + } + + private static String check(final Object anInput) { + return anInput == null ? EMPTY : anInput.toString(); + } + + private List> translate(final List> visitorMaps) { + // Add empty fields in the first line + Map firstLine = visitorMaps.get(0); + // Empty receptor + firstLine.put(R03VisitorKeys.IDENTIFIANT_RECEPTEUR, EMPTY); + firstLine.put(R03VisitorKeys.REVISION_RECEPTEUR, EMPTY); + firstLine.put(R03VisitorKeys.NOM_RECEPTEUR, EMPTY); + // Empty RF + firstLine.put(R03VisitorKeys.REPERE_FONCTIONNEL, EMPTY); + firstLine.put(R03VisitorKeys.REVISION_REPERE_FONCTIONNEL, EMPTY); + firstLine.put(R03VisitorKeys.UIN, EMPTY); + firstLine.put(R03VisitorKeys.EQUIVALENT_SNSSIN, EMPTY); + firstLine.put(R03VisitorKeys.RESPONSABLE_REPERE, EMPTY); + // Empty BOM + firstLine.put(R03VisitorKeys.SUIVI_MONTAGE, EMPTY); + firstLine.put(R03VisitorKeys.ALT, EMPTY); + firstLine.put(R03VisitorKeys.SB, EMPTY); + firstLine.put(R03VisitorKeys.QUANTITE_CUMULEE, EMPTY); + firstLine.put(R03VisitorKeys.PANACHE, EMPTY); + firstLine.put(R03VisitorKeys.QUANTITE, EMPTY); + + // Construct the map list expected by the printer + List> printerMaps = new ArrayList<>(); + for (Map visitorMap : visitorMaps) { + Map printerMap = new HashMap<>(); + for (R03VisitorKeys key : R03VisitorKeys.values()) { + printerMap.put(key.toString(), check(visitorMap.get(key))); + } + printerMaps.add(printerMap); + } + + return printerMaps; + } + + @Override + public List> visitReport(final BOMLineHolder holder) { + List> visitorMaps = r03BOMLineHolderVisitor.visitTopReceptorBom(holder); + return translate(visitorMaps); + } + + @Override + public void constructDataMaps(TcSession session, final PrintParameters printParameters, final BOMLineHolder topLine) throws KurtException { + long start = System.currentTimeMillis(); + if (topLine == null) { + + throw new NoSuchElementException("No object structure found"); + } + log.info("constructDataMaps "); + + // Parse all the snecma objects... + List> printerMaps = this.visitReport(topLine); + log.debug("printer map size " + printerMaps.size()); + printParameters.addReportData(printerMaps); + log.info("Filtering time : {} ms", System.currentTimeMillis() - start); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r03report/visitors/R03VisitorKeys.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r03report/visitors/R03VisitorKeys.java new file mode 100644 index 0000000..b6882f9 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r03report/visitors/R03VisitorKeys.java @@ -0,0 +1,35 @@ +package com.capgemini.reports.definition.r03report.visitors; + +/** + * Enumeration of all the columns of the R03 report. + */ +public enum R03VisitorKeys { + IDENTIFIANT_RECEPTEUR, + REVISION_RECEPTEUR, + NOM_RECEPTEUR, + REPERE_FONCTIONNEL, + REVISION_REPERE_FONCTIONNEL, + UIN, + EQUIVALENT_SNSSIN, + RESPONSABLE_REPERE, + SUIVI_MONTAGE, + ALT, + SB, + QUANTITE_CUMULEE, + PANACHE, + QUANTITE, + REF_FABRICANT_REF_SNECMA, + REVISION_REFERENCE, + REFERENCE_CONCEPTEUR, + TYPE_REFERENCE, + NOM_REFERENCE, + DESIGNATION_EN, + REFERENCE_TRANSPOSEE, + RESPONSABLE_CONCEPTION, + ALTERNATIVE, + CLASSEMENT, + SUIVI_UTILISATION, + SUIVI_DUREE_VIE, + MASSE_INDICATIVE, + UNITE_DE_MASSE +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r03report/visitors/bomlineholder/R03AltOrDetBehaviour.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r03report/visitors/bomlineholder/R03AltOrDetBehaviour.java new file mode 100644 index 0000000..a44adc6 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r03report/visitors/bomlineholder/R03AltOrDetBehaviour.java @@ -0,0 +1,57 @@ +package com.capgemini.reports.definition.r03report.visitors.bomlineholder; + +import com.capgemini.reports.bomlineholder.processor.AltOrDetBehaviour; +import com.capgemini.reports.definition.r03report.visitors.R03VisitorKeys; +import com.capgemini.reports.snecmaobjects.part.AlternateRevision; +import com.capgemini.reports.snecmaobjects.part.DETRevision; + +import java.util.Map; + +/** + * This class visits Parts that are below an {@link AlternateRevision} or a {@link DETRevision}.
    + * It puts "Oui" in the ALTERNATIVE field of a map. + */ +public class R03AltOrDetBehaviour implements AltOrDetBehaviour { + private static final long serialVersionUID = -3129556059907841821L; + + private static final String OUI = "Oui"; + private static final String EMPTY_STRING = ""; + + @Override + public boolean shouldVisitPartsInPseudoFolder() { + return true; + } + + @Override + public boolean shouldVisitPartsBelowAlt() { + return true; + } + + @Override + public void treatPartsInPseudoFolder(final Map map) { + treatAnyPartBelowThisAltOrDet(map); + } + + @Override + public void treatAlternateOrDETAsReceptor(final Map map) { + map.put(R03VisitorKeys.ALTERNATIVE, OUI); + } + + private void treatAnyPartBelowThisAltOrDet(final Map map) { + // Empty fields + map.put(R03VisitorKeys.REPERE_FONCTIONNEL, EMPTY_STRING); + map.put(R03VisitorKeys.REVISION_REPERE_FONCTIONNEL, EMPTY_STRING); + map.put(R03VisitorKeys.UIN, EMPTY_STRING); + map.put(R03VisitorKeys.EQUIVALENT_SNSSIN, EMPTY_STRING); + map.put(R03VisitorKeys.RESPONSABLE_REPERE, EMPTY_STRING); + map.put(R03VisitorKeys.SUIVI_MONTAGE, EMPTY_STRING); + map.put(R03VisitorKeys.ALT, EMPTY_STRING); + map.put(R03VisitorKeys.SB, EMPTY_STRING); + map.put(R03VisitorKeys.QUANTITE_CUMULEE, EMPTY_STRING); + map.put(R03VisitorKeys.PANACHE, EMPTY_STRING); + map.put(R03VisitorKeys.QUANTITE, EMPTY_STRING); + + // Mention that these parts are alternatives to each other + map.put(R03VisitorKeys.ALTERNATIVE, OUI); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r03report/visitors/bomlineholder/R03BOMLineHolderVisitor.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r03report/visitors/bomlineholder/R03BOMLineHolderVisitor.java new file mode 100644 index 0000000..7c8066c --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r03report/visitors/bomlineholder/R03BOMLineHolderVisitor.java @@ -0,0 +1,96 @@ +package com.capgemini.reports.definition.r03report.visitors.bomlineholder; + +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.bomlineholder.visitor.AbstractBOMLineHolderVisitor; +import com.capgemini.reports.definition.r03report.visitors.R03VisitorKeys; +import com.capgemini.reports.definition.r03report.visitors.snecmaobject.R03ComponentVisitor; +import com.capgemini.reports.definition.r03report.visitors.snecmaobject.R03ReceptorVisitor; +import com.capgemini.reports.releasestatus.EffectivityBehaviourHelper; +import com.capgemini.reports.snecmaobjects.ISnecmaObject; +import lombok.EqualsAndHashCode; +import lombok.extern.slf4j.Slf4j; + +import java.util.Map; + +/** + * Visitor of an expansion of BOMLineHolder for the R03 report. + */ +@Slf4j +@EqualsAndHashCode(callSuper = true) +public class R03BOMLineHolderVisitor extends AbstractBOMLineHolderVisitor { + private static final long serialVersionUID = -984208349993142537L; + + private static final String EMPTY_STRING = ""; + + /** + * Constructor. + */ + public R03BOMLineHolderVisitor() { + super(new R03ReceptorVisitor(), new R03ComponentVisitor(), EffectivityBehaviourHelper.visitAnyPart(), new R03AltOrDetBehaviour(), false, + false, true); + } + + @Override + protected Map visitThisReceptor(final BOMLineHolder aBomLine) { + return aBomLine.getSnecmaObject().accept(receptorVisitor); + } + + @Override + protected Map visitThisComponent(final BOMLineHolder aBomLine) { + ISnecmaObject snecmaObject = aBomLine.getSnecmaObject(); + Map aMap = snecmaObject.accept(componentVisitor); + // Put the BOMLine properties into the map + if ((snecmaObject.isGeneric()) || (snecmaObject.isPart())) { + aMap.put(R03VisitorKeys.ALT, aBomLine.getBomAlt()); + aMap.put(R03VisitorKeys.SB, aBomLine.getBomSb()); + aMap.put(R03VisitorKeys.QUANTITE_CUMULEE, aBomLine.getBomQtyCumul()); + aMap.put(R03VisitorKeys.PANACHE, aBomLine.getBomPanache()); + aMap.put(R03VisitorKeys.QUANTITE, aBomLine.getBomQty()); + aMap.put(R03VisitorKeys.UIN, aBomLine.getUin()); + } + if (aBomLine.getParentBomLine().getSnecmaObject().isPart() && snecmaObject.isPart()) { + aMap.put(R03VisitorKeys.REPERE_FONCTIONNEL, EMPTY_STRING); + aMap.put(R03VisitorKeys.REVISION_REPERE_FONCTIONNEL, EMPTY_STRING); + aMap.put(R03VisitorKeys.SUIVI_MONTAGE, EMPTY_STRING); + aMap.put(R03VisitorKeys.RESPONSABLE_REPERE, EMPTY_STRING); + aMap.put(R03VisitorKeys.EQUIVALENT_SNSSIN, EMPTY_STRING); + } + return aMap; + } + + @Override + protected void visitSpecificFirstLine(final BOMLineHolder aTopBomLine) { + Map theFirstLine = aTopBomLine.getSnecmaObject().accept(getComponentVisitor()); + theReportTable.add(theFirstLine); + } + + @Override + protected void mergeReceptorAndRepereReceptor(final Map aReceptor, final Map aRepereReceptor) { + // No used for R03 report + } + + @Override + protected void mergeComponentAndRepereComponent(final Map aComponent, final Map aRepereComponent) { + aComponent.putAll(aRepereComponent); + } + + @Override + protected void mergeRepereReceptorandAdmin(final Map aRepereReceptor, final Map anAdmin) { + // No used for R03 report + } + + @Override + protected void mergeRepereComponentandAdmin(final Map aRepereComponent, final Map anAdmin) { + aRepereComponent.putAll(anAdmin); + } + + @Override + protected void addToReport(final Map aReceptor, final Map aComponent) { + // Put the Receptor and Repere Receptor in the Component and modify the Component + // Do not modify the receptor + aComponent.putAll(aReceptor); + + // Add to the R22 report + theReportTable.add(aComponent); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r03report/visitors/snecmaobject/R03ComponentVisitor.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r03report/visitors/snecmaobject/R03ComponentVisitor.java new file mode 100644 index 0000000..abb8d30 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r03report/visitors/snecmaobject/R03ComponentVisitor.java @@ -0,0 +1,217 @@ +package com.capgemini.reports.definition.r03report.visitors.snecmaobject; + +import com.capgemini.framework.common.DoubleFormatter; +import com.capgemini.framework.common.LanguageHelper; +import com.capgemini.reports.definition.r03report.visitors.R03VisitorKeys; +import com.capgemini.reports.snecmaobjects.admin.RFAdminAGRevision; +import com.capgemini.reports.snecmaobjects.admin.RFAdminAPRevision; +import com.capgemini.reports.snecmaobjects.admin.RFAdminARevision; +import com.capgemini.reports.snecmaobjects.admin.RFAdminRevision; +import com.capgemini.reports.snecmaobjects.descriptif.DescriptifRevision; +import com.capgemini.reports.snecmaobjects.generic.GenericAssembRevision; +import com.capgemini.reports.snecmaobjects.generic.GenericRevision; +import com.capgemini.reports.snecmaobjects.mockup.MockupRevision; +import com.capgemini.reports.snecmaobjects.part.*; +import com.capgemini.reports.snecmaobjects.product.ProductRevision; +import com.capgemini.reports.snecmaobjects.rf.RFGenericRevision; +import com.capgemini.reports.snecmaobjects.rf.RFPartAssembRevision; +import com.capgemini.reports.snecmaobjects.rf.RFPartRevision; +import com.capgemini.reports.snecmaobjects.supermodel.SuperModelRevision; +import com.capgemini.reports.snecmaobjects.visitor.IComponentVisitor; + +import java.util.EnumMap; +import java.util.HashMap; +import java.util.Map; + +/** + * Visit a Component SnecmaObject to make a R03 report. + */ +public class R03ComponentVisitor implements IComponentVisitor> { + + private static final long serialVersionUID = -1358969880241440037L; + + private static final int MASS_SIGNIFICANT_DIGITS = 15; + private static final String EMPTY_STRING = ""; + private static final String PART_MAT = "PartMat"; + private static final String SEPARATOR = " / "; + private static final String VALUE_MATIERE = "matière"; + private static final String PARAM_NON = "Non"; + private static final String SOLO_SEPARATOR = "/"; + + /** + * Extracts left side of a string of the form "French text / English text".
    + * Separator slash may have *any* number (0+) of white spaces around them. + */ + private static String french(final String string) { + return LanguageHelper.french(string); + } + + @Override + public Map visitComponent(final ProductRevision aProductRev) { + // No used in R03 report + return new EnumMap<>(R03VisitorKeys.class); + } + + @Override + public Map visitComponent(final GenericRevision aGenericRev) { + // No used in R03 report + return new EnumMap<>(R03VisitorKeys.class); + } + + @Override + public Map visitComponent(SuperModelRevision aSuperModelRev) { + return null; + } + + @Override + public Map visitComponent(final GenericAssembRevision aGenericAssembRev) { + // No used in R03 report + return new EnumMap<>(R03VisitorKeys.class); + } + + @Override + public Map visitComponent(final AlternateRevision anAlternateRev) { + Map theMap = getPartProperties(anAlternateRev); + theMap.put(R03VisitorKeys.TYPE_REFERENCE, french(anAlternateRev.getTypeAlt1()) + SEPARATOR + french(anAlternateRev.getTypeAlt2())); + return theMap; + } + + @Override + public Map visitComponent(final DETRevision aDetRev) { + Map theMap = getPartProperties(aDetRev); + theMap.put(R03VisitorKeys.TYPE_REFERENCE, french(aDetRev.getTypeDet1()) + SEPARATOR + french(aDetRev.getTypeDet2())); + return theMap; + } + + @Override + public Map visitComponent(final PartAeroRevision aPartAeroRev) { + Map theMap = getPartProperties(aPartAeroRev); + theMap.put(R03VisitorKeys.TYPE_REFERENCE, french(aPartAeroRev.getTypeAero1()) + SEPARATOR + french(aPartAeroRev.getTypeAero2()) + SEPARATOR + french(aPartAeroRev.getTypeAero3())); + return theMap; + } + + @Override + public Map visitComponent(final PartNoAeroRevision aPartNoAeroRev) { + Map theMap = getPartProperties(aPartNoAeroRev); + theMap.put(R03VisitorKeys.TYPE_REFERENCE, french(aPartNoAeroRev.getTypeNoAero())); + return theMap; + } + + @Override + public Map visitComponent(final PartAssembRevision aPartAssembRev) { + Map theMap = getPartProperties(aPartAssembRev); + theMap.put(R03VisitorKeys.TYPE_REFERENCE, french(aPartAssembRev.getTypePartMontage1()) + SEPARATOR + french(aPartAssembRev.getTypePartMontage2())); + return theMap; + } + + @Override + public Map visitComponent(final PartMatRevision aPartMatRev) { + Map theMap = getPartProperties(aPartMatRev); + theMap.put(R03VisitorKeys.TYPE_REFERENCE, VALUE_MATIERE); + theMap.put(R03VisitorKeys.CLASSEMENT, aPartMatRev.getClassementMat()); + theMap.put(R03VisitorKeys.SUIVI_UTILISATION, PARAM_NON); + theMap.put(R03VisitorKeys.SUIVI_DUREE_VIE, PARAM_NON); + theMap.put(R03VisitorKeys.MASSE_INDICATIVE, EMPTY_STRING); + theMap.put(R03VisitorKeys.UNITE_DE_MASSE, EMPTY_STRING); + return theMap; + } + + @Override + public Map visitComponent(final StandardRevision aStandardRev) { + Map theMap = getPartProperties(aStandardRev); + theMap.put(R03VisitorKeys.TYPE_REFERENCE, french(aStandardRev.getTypeStandard())); + return theMap; + } + + /** + * Get Component Part properties to make a R03 report. + * + * @param anAbstractPart AbstractPart + * @return theMap Map + */ + private Map getPartProperties(final AbstractPart anAbstractPart) { + Map theMap = new EnumMap<>(R03VisitorKeys.class); + theMap.put(R03VisitorKeys.REF_FABRICANT_REF_SNECMA, anAbstractPart.getItemId()); + theMap.put(R03VisitorKeys.NOM_REFERENCE, anAbstractPart.getName()); + theMap.put(R03VisitorKeys.REVISION_REFERENCE, anAbstractPart.getRevisionId()); + theMap.put(R03VisitorKeys.ALTERNATIVE, EMPTY_STRING); + theMap.put(R03VisitorKeys.DESIGNATION_EN, anAbstractPart.getDesignationEN()); + theMap.put(R03VisitorKeys.REFERENCE_CONCEPTEUR, anAbstractPart.getRefCompleteConcepteur()); + theMap.put(R03VisitorKeys.REFERENCE_TRANSPOSEE, anAbstractPart.getRefTransposeeSnecma()); + theMap.put(R03VisitorKeys.RESPONSABLE_CONCEPTION, anAbstractPart.getResponsableConception()); + if (!PART_MAT.equals(anAbstractPart.getType())) { + theMap.put(R03VisitorKeys.CLASSEMENT, anAbstractPart.getClassement()); + theMap.put(R03VisitorKeys.SUIVI_UTILISATION, french(anAbstractPart.getSuiviUtilisation())); + theMap.put(R03VisitorKeys.SUIVI_DUREE_VIE, french(anAbstractPart.getSuiviDureeVie())); + theMap.put(R03VisitorKeys.MASSE_INDICATIVE, DoubleFormatter.toSignificantDigits(anAbstractPart.getMass(), MASS_SIGNIFICANT_DIGITS)); + theMap.put(R03VisitorKeys.UNITE_DE_MASSE, anAbstractPart.getMassUnit()); + } + return theMap; + } + + @Override + public Map visitComponent(final RFGenericRevision aRfGenericRev) { + return new EnumMap<>(R03VisitorKeys.class); + } + + @Override + public Map visitComponent(final RFPartAssembRevision aRfPartAssembRev) { + Map theMap = new EnumMap<>(R03VisitorKeys.class); + theMap.put(R03VisitorKeys.REPERE_FONCTIONNEL, aRfPartAssembRev.getName()); + theMap.put(R03VisitorKeys.REVISION_REPERE_FONCTIONNEL, aRfPartAssembRev.getRevisionId()); + theMap.put(R03VisitorKeys.EQUIVALENT_SNSSIN, EMPTY_STRING); + return theMap; + } + + @Override + public Map visitComponent(final RFPartRevision aRfPartRev) { + Map theMap = new EnumMap<>(R03VisitorKeys.class); + theMap.put(R03VisitorKeys.REPERE_FONCTIONNEL, aRfPartRev.getName()); + theMap.put(R03VisitorKeys.REVISION_REPERE_FONCTIONNEL, aRfPartRev.getRevisionId()); + theMap.put(R03VisitorKeys.EQUIVALENT_SNSSIN, aRfPartRev.getEquivalentSnsSin()); + return theMap; + } + + @Override + public Map visitComponent(final RFAdminRevision aRfAdminRev) { + Map theMap = new EnumMap<>(R03VisitorKeys.class); + theMap.put(R03VisitorKeys.RESPONSABLE_REPERE, aRfAdminRev.getResponsableRepere()); + return theMap; + } + + @Override + public Map visitComponent(final RFAdminARevision aRfAdminARev) { + Map theMap = new EnumMap<>(R03VisitorKeys.class); + String[] suiviMontage = aRfAdminARev.getSuiviMontage().split(SEPARATOR); + suiviMontage[0].split(SOLO_SEPARATOR); + theMap.put(R03VisitorKeys.SUIVI_MONTAGE, suiviMontage[0]); + theMap.put(R03VisitorKeys.RESPONSABLE_REPERE, aRfAdminARev.getResponsableRepere()); + return theMap; + } + + @Override + public Map visitComponent(final RFAdminAPRevision aRfAdminAPRev) { + Map theMap = new EnumMap<>(R03VisitorKeys.class); + String[] suiviMontage = aRfAdminAPRev.getSuiviMontage().split(SEPARATOR); + suiviMontage[0].split(SOLO_SEPARATOR); + theMap.put(R03VisitorKeys.SUIVI_MONTAGE, suiviMontage[0]); + return theMap; + } + + @Override + public Map visitComponent(final RFAdminAGRevision aRfAdminAGRev) { + return new HashMap<>(); + } + + @Override + public Map visitComponent(final MockupRevision aMockupRev) { + // This object is not use in this report + return null; + } + + @Override + public Map visitComponent(final DescriptifRevision aDescriptifRev) { + // This object is not use in this report + return null; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r03report/visitors/snecmaobject/R03ReceptorVisitor.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r03report/visitors/snecmaobject/R03ReceptorVisitor.java new file mode 100644 index 0000000..e92cf9b --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r03report/visitors/snecmaobject/R03ReceptorVisitor.java @@ -0,0 +1,148 @@ +package com.capgemini.reports.definition.r03report.visitors.snecmaobject; + +import com.capgemini.reports.definition.r03report.visitors.R03VisitorKeys; +import com.capgemini.reports.snecmaobjects.ISnecmaObject; +import com.capgemini.reports.snecmaobjects.admin.RFAdminAGRevision; +import com.capgemini.reports.snecmaobjects.admin.RFAdminAPRevision; +import com.capgemini.reports.snecmaobjects.admin.RFAdminARevision; +import com.capgemini.reports.snecmaobjects.admin.RFAdminRevision; +import com.capgemini.reports.snecmaobjects.descriptif.DescriptifRevision; +import com.capgemini.reports.snecmaobjects.generic.GenericAssembRevision; +import com.capgemini.reports.snecmaobjects.generic.GenericRevision; +import com.capgemini.reports.snecmaobjects.mockup.MockupRevision; +import com.capgemini.reports.snecmaobjects.part.*; +import com.capgemini.reports.snecmaobjects.product.ProductRevision; +import com.capgemini.reports.snecmaobjects.rf.RFGenericRevision; +import com.capgemini.reports.snecmaobjects.rf.RFPartAssembRevision; +import com.capgemini.reports.snecmaobjects.rf.RFPartRevision; +import com.capgemini.reports.snecmaobjects.supermodel.SuperModelRevision; +import com.capgemini.reports.snecmaobjects.visitor.IReceptorVisitor; + +import java.util.EnumMap; +import java.util.Map; + +/** + * Visit a Receptor SnecmaObject to make a R03 report. + */ +public class R03ReceptorVisitor implements IReceptorVisitor> { + + private static final long serialVersionUID = 8706801275271305065L; + + @Override + public Map visitReceptor(final ProductRevision aProductRev) { + return new EnumMap<>(R03VisitorKeys.class); + } + + @Override + public Map visitReceptor(final GenericRevision aGenericRev) { + return new EnumMap<>(R03VisitorKeys.class); + } + + @Override + public Map visitReceptor(final GenericAssembRevision aGenericAssembRev) { + return new EnumMap<>(R03VisitorKeys.class); + } + + @Override + public Map visitReceptor(SuperModelRevision aSuperModelRev) { + return null; + } + + @Override + public Map visitReceptor(final AlternateRevision anAlternateRev) { + return getReceptorProperties(anAlternateRev); + } + + @Override + public Map visitReceptor(final DETRevision aDetRev) { + return getReceptorProperties(aDetRev); + } + + @Override + public Map visitReceptor(final PartAeroRevision aPartAeroRev) { + return getReceptorProperties(aPartAeroRev); + } + + @Override + public Map visitReceptor(final PartNoAeroRevision aPartNoAeroRev) { + return getReceptorProperties(aPartNoAeroRev); + } + + @Override + public Map visitReceptor(final PartAssembRevision aPartAssembRev) { + return getReceptorProperties(aPartAssembRev); + } + + @Override + public Map visitReceptor(final PartMatRevision aPartMatRev) { + return getReceptorProperties(aPartMatRev); + } + + @Override + public Map visitReceptor(final StandardRevision aStandardRev) { + return getReceptorProperties(aStandardRev); + } + + @Override + public Map visitReceptor(final RFGenericRevision aRfGenericRev) { + return new EnumMap<>(R03VisitorKeys.class); + } + + @Override + public Map visitReceptor(final RFPartAssembRevision aRfPartAssembRev) { + return new EnumMap<>(R03VisitorKeys.class); + } + + @Override + public Map visitReceptor(final RFPartRevision aRfPartRev) { + return new EnumMap<>(R03VisitorKeys.class); + } + + @Override + public Map visitReceptor(final RFAdminRevision aRfAdminRev) { + return new EnumMap<>(R03VisitorKeys.class); + } + + @Override + public Map visitReceptor(final RFAdminARevision aRfAdminARev) { + return new EnumMap<>(R03VisitorKeys.class); + } + + @Override + public Map visitReceptor(final RFAdminAPRevision aRfAdminAPRev) { + return new EnumMap<>(R03VisitorKeys.class); + } + + @Override + public Map visitReceptor(final RFAdminAGRevision aRfAdminAGRev) { + return new EnumMap<>(R03VisitorKeys.class); + } + + /** + * Get the Receptor properties. + */ + private Map getReceptorProperties(final ISnecmaObject iSnecmaObject) { + Map theMap = new EnumMap<>(R03VisitorKeys.class); + theMap.put(R03VisitorKeys.IDENTIFIANT_RECEPTEUR, iSnecmaObject.getItemId()); + theMap.put(R03VisitorKeys.NOM_RECEPTEUR, iSnecmaObject.getName()); + theMap.put(R03VisitorKeys.REVISION_RECEPTEUR, iSnecmaObject.getRevisionId()); + return theMap; + } + + @Override + public Map visitReceptor(final MockupRevision aMockupRev) { + // This object is not use in this report + return null; + } + + @Override + public Map visitReceptor(final DescriptifRevision aDescriptifRev) { + // This object is not use in this report + return null; + } + + @Override + public Map emptyRf() { + return new EnumMap<>(R03VisitorKeys.class); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/CRExtractorHelper.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/CRExtractorHelper.java new file mode 100644 index 0000000..b3836ee --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/CRExtractorHelper.java @@ -0,0 +1,58 @@ +package com.capgemini.reports.definition.r07report; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.reports.changeobjects.change.TcChangeNoticeRevision; +import com.capgemini.reports.changeobjects.change.TcChangeRequestRevision; +import com.capgemini.reports.teamcenter.queries.saved.ChangeNoticeR07Query; +import com.capgemini.reports.teamcenter.queries.saved.ChangeRequestR07Query; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +import java.util.ArrayList; +import java.util.List; + +/** + * This class is able to request the ChangeRequests or the ChangeNotices associated to a part or generic. + */ +public class CRExtractorHelper { + + private final TcSession session; + + /** + * Builds an instance of CR helper. + * + * @param session a teamcenter session + */ + public CRExtractorHelper(final TcSession session) { + this.session = session; + } + + /** + * Return map with changeRequest and the list of changeNotice for each changeRequest. + * + * @param itemID ID of a generic or a part. + * @param itemRevisionID Revision of a generic or a part. + * @return map. + */ + public List getCrOnPart(final String itemID, final String itemRevisionID) { + List changeRequestRevs = new ArrayList<>(); + for (ItemRevision changeRequestRev : new ChangeRequestR07Query(session).searchIDAndRevision(itemID, itemRevisionID).findAll()) { + changeRequestRevs.add(new TcChangeRequestRevision(session, changeRequestRev)); + } + return changeRequestRevs; + } + + /** + * Return list of changeNotice which is not associated to a changeRequest but directly to the part or generic. + * + * @param itemID ID of a generic or a part. + * @param itemRevisionID Revision of a generic or a part. + * @return list. + */ + public List getCnOnPart(final String itemID, final String itemRevisionID) { + List changeNoticeRevs = new ArrayList<>(); + for (ItemRevision changeNoticeRev : new ChangeNoticeR07Query(session).searchIDAndRevision(itemID, itemRevisionID).findAll()) { + changeNoticeRevs.add(new TcChangeNoticeRevision(session, changeNoticeRev)); + } + return changeNoticeRevs; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/ExecutionR07.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/ExecutionR07.java new file mode 100644 index 0000000..339e17a --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/ExecutionR07.java @@ -0,0 +1,171 @@ +package com.capgemini.reports.definition.r07report; + +import com.capgemini.framework.common.SettingsHelper; +import com.capgemini.framework.common.StringHelper; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.reports.ReportEnum; +import com.capgemini.reports.ReportLaunchTypeEnum; +import com.capgemini.reports.builder.R07Builder; +import com.capgemini.reports.builder.ReportBuilder; +import com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum; +import com.capgemini.reports.database.manager.MngCriteriaVal.CriteriaValue; +import com.capgemini.reports.definition.r07report.checker.R07ProductUnitChecker; +import com.capgemini.reports.definition.r07report.data.DataReportPreparatorR07; +import com.capgemini.reports.execution.AbstractExecutionReport; +import com.capgemini.reports.execution.IDataReportPreparator; +import com.capgemini.reports.printing.Printer.PrintFormat; +import com.capgemini.reports.reports.parameters.Generics; +import com.capgemini.reports.reports.parameters.Generics.GenericType; +import com.capgemini.reports.reports.parameters.IChecker; +import com.capgemini.reports.reports.parameters.ProductUnit; +import com.capgemini.reports.reports.parameters.checker.GenericExistenceChecker; +import com.capgemini.reports.reports.parameters.checker.ProductChecker; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.Setter; + +import java.util.ArrayList; +import java.util.List; + +/** + * This class controls the execution of a R07 report. + */ +@Setter(value = AccessLevel.PROTECTED) +public class ExecutionR07 extends AbstractExecutionReport { + private static final long serialVersionUID = 584625053050646351L; + + // Policies + private static final PolicyLocation R07_POLICY_XML_FULL = PolicyLocation.make("R07_policy_full", "/xml/policies/r07report/R07_policy_full.xml"); + private static final PolicyLocation R07_POLICY_XML_LIGHT = PolicyLocation.make("R07_policy_light", "/xml/policies/r07report/R07_policy_light.xml"); + // Launch type parameter + private static final ReportLaunchTypeEnum REPORT_LAUNCH_TYPE = ReportLaunchTypeEnum.getReportLaunchType("common.launch.launchType.REPORT_R07"); + // Revision rule parameter + private static final String REPORT_REVISION_RULE = SettingsHelper.getPropertyWithDefaultValue("common.bom.revisionRule.REPORT_R07", DEFAULT_REVISION_RULE); + // Priority parameter + private static final int REPORT_PRIORITY = SettingsHelper.getPriority(ReportEnum.REPORT_R07); + // Report parameters + @Getter + private final Generics genericParam1; + @Getter + private final Generics genericParam2; + + /** + * Constructor. Will compare nomenclature for two generics. + * + * @param genericParam1 the 1st Generic + * @param genericParam2 the 2nd Generic + */ + public ExecutionR07(final Generics genericParam1, final Generics genericParam2) { + super(REPORT_PRIORITY, REPORT_REVISION_RULE, REPORT_LAUNCH_TYPE); + this.genericParam1 = genericParam1; + this.genericParam2 = genericParam2; + } + + @Override + public List getQuickChecks() { + // Sort the quick checks + ArrayList quickChecks = new ArrayList<>(); + quickChecks.add(new GenericExistenceChecker(genericParam1)); // Only 1 Generic because they are the same in the two configurations + quickChecks.add(new ProductChecker(genericParam1.getProductUnit().getProductID())); + quickChecks.add(new R07ProductUnitChecker(genericParam1.getProductUnit(), true)); + quickChecks.add(new R07ProductUnitChecker(genericParam2.getProductUnit(), false)); + return quickChecks; + } + + @Override + public PolicyLocation getPropertyPolicyForLongChecks() { + return R07_POLICY_XML_LIGHT; + } + + @Override + public PolicyLocation getFullPolicy() { + return R07_POLICY_XML_FULL; + } + + @Override + public List getLongChecks() { + return new ArrayList<>(); + } + + @Override + public String getTemplateLocation() { + return "No Template needed for this report! it is automatically generated"; + } + + @Override + public ReportEnum getReportIdentifier() { + return ReportEnum.REPORT_R07; + } + + @Override + public String getSpecifiedFileName() { + return StringHelper.implode("_", "R07", getNameSheet()); + } + + /** + * Returns the spreadsheet's name. + * + * @return the name + */ + String getNameSheet() { + ProductUnit productUnit1 = genericParam1.getProductUnit(); + String productId = productUnit1.getProductID(); + String unit1 = productUnit1.getUnitStr(); + String unit2 = genericParam2.getProductUnit().getUnitStr(); + String name; + switch (genericParam1.getType()) { + case GENERIC: + name = StringHelper.implode("_", genericParam1.getGeneric(), productId, unit1, unit2); + break; + case GENERIC_ASSEMB: + name = StringHelper.implode("_", genericParam1.getGenericAssemb(), productId, unit1, unit2); + break; + case ONLY_PRODUCT: + name = StringHelper.implode("_", productId, unit1, unit2); + break; + default: + name = "R07_UnsupportedGenericType_" + genericParam1.toString() + "_" + genericParam2.toString(); + break; + } + return name; + } + + @Override + public PrintFormat getPrintingFormat() { + return PrintFormat.XLSX; + } + + @Override + public List getLaunchData() { + List theCriteria = new ArrayList<>(); + // The Product is the same for the 2 configurations + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.PRODUCT, genericParam1.getProductUnit().getProductID())); + + // Configuration 1 + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.UNIT_CONFIGURATION_1, genericParam1.getProductUnit().getUnitStr())); + if (GenericType.GENERIC.equals(genericParam1.getType())) { + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.GENERIC, genericParam1.getGeneric())); + } else if (GenericType.GENERIC_ASSEMB.equals(genericParam1.getType())) { + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.GENERIC_ASSEMB, genericParam1.getGenericAssemb())); + } + + // Configuration 2 + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.UNIT_CONFIGURATION_2, genericParam2.getProductUnit().getUnitStr())); + return theCriteria; + } + + @Override + public IDataReportPreparator getDataPreparator() { + return new DataReportPreparatorR07(); + } + + @Override + public AbstractExecutionReport cloneTemplateToExecution() { + return new ExecutionR07(genericParam1, genericParam2); + } + + @Override + public Class getReportBuilderClass() { + return R07Builder.class; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/R07Printer.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/R07Printer.java new file mode 100644 index 0000000..fd314e8 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/R07Printer.java @@ -0,0 +1,327 @@ +package com.capgemini.reports.definition.r07report; + +import com.capgemini.framework.common.LanguageHelper; +import com.capgemini.framework.common.ReportFolderOutputHelper; +import com.capgemini.framework.common.StringHelper; +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.reports.bomlineholder.flattener.line.SnecmaLine; +import com.capgemini.reports.changeobjects.change.TcChangeNoticeRevision; +import com.capgemini.reports.changeobjects.change.TcChangeRequestRevision; +import com.capgemini.reports.definition.r07report.data.DataReportPreparatorR07.ReportDataLineR07; +import com.capgemini.reports.definition.r07report.printing.*; +import com.capgemini.reports.exceptions.FileLoadingException; +import com.capgemini.reports.exceptions.InvalidInputException; +import com.capgemini.reports.exceptions.ReportPrintException; +import com.capgemini.reports.execution.mapconstructor.IMapConstructor; +import com.capgemini.reports.printing.PrintParameters; +import com.capgemini.reports.printing.PrintReportHelper; +import com.capgemini.reports.reports.parameters.Generics; +import com.google.common.collect.SetMultimap; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.Setter; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.*; +import java.util.Map.Entry; + +/** + * Prints a R07 report using data carried in the {@link ExecutionR07}. + */ +@Getter +@Setter(value = AccessLevel.PROTECTED) +public class R07Printer implements IMapConstructor { + + private static final String EMPTY_STRING = ""; + private static final long serialVersionUID = 8191686574681618653L; + private int nbMaxChangeNotice; + private String conf1Name; + private String conf2Name; + + private static String getConfName(final Generics genericParam) throws ReportPrintException { + switch (genericParam.getType()) { + case GENERIC: + return StringHelper.implode(" - ", genericParam.getProductUnit().getProductID(), genericParam.getGeneric(), genericParam.getProductUnit().getUnitStr(), today()); + case GENERIC_ASSEMB: + return StringHelper.implode(" - ", genericParam.getProductUnit().getProductID(), genericParam.getGenericAssemb(), genericParam.getProductUnit().getUnitStr(), today()); + case ONLY_PRODUCT: + return StringHelper.implode(" - ", genericParam.getProductUnit().getProductID(), genericParam.getProductUnit().getUnitStr(), today()); + default: + throw new ReportPrintException("Unsupported Configuration type: " + genericParam.toString()); + } + } + + private static String makeTitleContent(final int confNum, final Generics generics, final int nbConfLine) throws ReportPrintException { + return "Nombre de triplets ou couples dans la configuration " + confNum + " ( " + getConfName(generics) + ") : " + nbConfLine; + } + + private static String today() { + Date dateActual = new Date(); + DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy"); + return dateFormat.format(dateActual); + } + + @Override + public PrintParameters makeMasterTemplate(final ExecutionR07 report, final ReportDataR07 data) throws ReportPrintException, FileLoadingException, + InvalidInputException { + conf1Name = getConfName(report.getGenericParam1()); + conf2Name = getConfName(report.getGenericParam2()); + nbMaxChangeNotice = data.getMaxCN(); + BuilderTemplateR07 templateBuilder = new BuilderTemplateR07(collectParamDifference(), nbMaxChangeNotice, conf1Name, conf2Name, report.getNameSheet()); + String template = templateBuilder.createDynamicTemplate(); + String storageFolder = ReportFolderOutputHelper.getStorageFolderLocation(report.getLaunchType()); + String fileName = report.getFileNameOnDisc(); + return PrintReportHelper.setupPrintParameters(template, storageFolder, fileName, report); + } + + @Override + public void constructDataMaps(final TcSession session, final PrintParameters printParameters, final ReportDataR07 reportData) throws KurtException { + // On recupere toutes les donnees dans la map et apres on etudie chaque map de la liste pour voir les CR et CN + List> lstMapData = new ArrayList<>(); + for (ReportDataLineR07 elem : reportData.getReportDataList()) { + SnecmaLine line = elem.getLine(); + Map structureMap = makeMap(line); // Map representing the structural elements (receptor/repere/component) + SetMultimap bundles = elem.getBundles(); + + // If no CR nor CN were found, add a line anyway + if (bundles.isEmpty()) { + fillerMapDataEffectivity(structureMap, elem.isConf1()); + fillerMapDataDifference(structureMap, elem.isExclusive(), elem.getHasMod()); + fillEmptyCrColumns(structureMap); // Fill unused CR column with blanks + fillEmptyCnColumns(structureMap, 0); // Fill all CN columns with blanks + lstMapData.add(structureMap); + continue; + } + + Set orphans = bundles.removeAll(ReportDataLineR07.FAKE); // Get orphans apart + + /* + * 4 configurations for change objects acting on this component: + * 1) a CR mentions the component, but has zero CNs ------> (put a single line, no CNs on it) + * 2) a CR mentions the component, has some children CNs -> (put a single line, all CNs that also mention the component on the line) + * 3) a CN mentions the component, has a parent CR -------> (DO NOTHING this is handled in 2) because CR<->CN link is reflexive) + * 4) a CN mentions the component, has no parent CR ------> (gather all those CNs -> single line) + */ + + // Put the CR lines with REAL CRs first + for (Entry> entry : bundles.asMap().entrySet()) { + TcChangeRequestRevision changeRequestRevision = entry.getKey(); + // Copy the cnList as we need to remove any eventual null value, but we don't want to update the underlying multimap! + Collection childrenCN = new ArrayList<>(entry.getValue()); + childrenCN.remove(null); + Map mapTemporary = new HashMap<>(structureMap); // Structural map is copied to keep the content the same throughout all the lines + addChangeRequestAndChangeNotice(mapTemporary, changeRequestRevision, childrenCN); + fillerMapDataEffectivity(mapTemporary, elem.isConf1()); + fillerMapDataDifference(mapTemporary, elem.isExclusive(), elem.getHasMod()); + // Now fill with blanks any unused CN columns + fillEmptyCnColumns(mapTemporary, childrenCN.size()); + // finally add the map + lstMapData.add(mapTemporary); + } + + // Finally print the CNs that have no CR parent all in the same line + if (!orphans.isEmpty()) { // SetMultimap.findAll never returns null, but at least an empty map + Map mapTemporary = addChangeNoticeWithoutCR(orphans, structureMap); + fillerMapDataEffectivity(mapTemporary, elem.isConf1()); + fillerMapDataDifference(mapTemporary, elem.isExclusive(), elem.getHasMod()); + lstMapData.add(mapTemporary); + } + } + + // FIX CONFIGURATION WITH NUMBER OF RELATION (recepteur-repere-composant) + Map parameters = new EnumMap<>(EnumChangeR07.class); + parameters.put(EnumChangeR07.TITLE_FIRST_CONFIGURATION, makeTitleContent(1, reportData.getGenericParam1(), reportData.getNumberOfLinesInConf1())); + parameters.put(EnumChangeR07.TITLE_SECOND_CONFIGURATION, makeTitleContent(2, reportData.getGenericParam2(), reportData.getNumberOfLinesInConf2())); + printParameters.addReportParameters(parameters); + if (lstMapData.isEmpty()) { + lstMapData.add(createEmptyMap()); + } + printParameters.addReportData(lstMapData); + } + + private Map createEmptyMap() { + Map mapEmpty = new HashMap<>(); + mapEmpty.put(EnumRecepteurR07.EFFECTIVITE.toString(), EMPTY_STRING); + mapEmpty.put(EnumRecepteurR07.ID_RECEPTEUR.toString(), EMPTY_STRING); + mapEmpty.put(EnumRecepteurR07.REVISION_RECEPTEUR.toString(), EMPTY_STRING); + mapEmpty.put(EnumRecepteurR07.NOM_RECEPTEUR.toString(), EMPTY_STRING); + mapEmpty.put(EnumRepereR07.REPERE_FONCTIONNEL.toString(), EMPTY_STRING); + mapEmpty.put(EnumRepereR07.REVISION_REPERE_FONCTIONNEL.toString(), EMPTY_STRING); + mapEmpty.put(EnumRepereR07.RESPONSABLE_REPERE.toString(), EMPTY_STRING); + mapEmpty.put(EnumRepereR07.SUIVI_MONTAGE.toString(), EMPTY_STRING); + mapEmpty.put(EnumComposantR07.REF_FABRICANT.toString(), EMPTY_STRING); + mapEmpty.put(EnumComposantR07.REVISION_REFERENCE.toString(), EMPTY_STRING); + mapEmpty.put(EnumComposantR07.TYPE_REFERENCE.toString(), EMPTY_STRING); + mapEmpty.put(EnumComposantR07.NOM_REFERENCE.toString(), EMPTY_STRING); + mapEmpty.put(EnumComposantR07.REFERENCE_CONCEPTEUR.toString(), EMPTY_STRING); + mapEmpty.put(EnumComposantR07.REFERENCE_TRANSPOSEE.toString(), EMPTY_STRING); + mapEmpty.put(EnumComposantR07.REFERENCE_ASSOCIEE.toString(), EMPTY_STRING); + mapEmpty.put(EnumComposantR07.RESPONSABLLE_CONCEPTION.toString(), EMPTY_STRING); + mapEmpty.put(EnumComposantR07.ARTICLE_GESTION.toString(), EMPTY_STRING); + mapEmpty.put(EnumComposantR07.CLASSEMENT.toString(), EMPTY_STRING); + mapEmpty.put(EnumComposantR07.SUIVI_UTILISATION.toString(), EMPTY_STRING); + mapEmpty.put(EnumComposantR07.SUIVI_DUREE_VIE.toString(), EMPTY_STRING); + mapEmpty.put(EnumComposantR07.LISTE_FOURNISSEUR.toString(), EMPTY_STRING); + mapEmpty.put(EnumLienNomenclatureR07.ALT.toString(), EMPTY_STRING); + mapEmpty.put(EnumLienNomenclatureR07.SUIVANT_BESOIN.toString(), EMPTY_STRING); + mapEmpty.put(EnumLienNomenclatureR07.QUANTITE_CUMULEE.toString(), EMPTY_STRING); + mapEmpty.put(EnumLienNomenclatureR07.PANACHAGE.toString(), EMPTY_STRING); + mapEmpty.put(EnumLienNomenclatureR07.QUANTITE.toString(), EMPTY_STRING); + mapEmpty.put(EnumChangeR07.ID_CR.toString(), EMPTY_STRING); + mapEmpty.put(EnumChangeR07.REVISION_CR.toString(), EMPTY_STRING); + mapEmpty.put(EnumChangeR07.TYPE_CR.toString(), EMPTY_STRING); + mapEmpty.put(EnumChangeR07.NOM_CR.toString(), EMPTY_STRING); + return mapEmpty; + } + + private void fillEmptyCrColumns(final Map mapTemporary) { + mapTemporary.put(EnumChangeR07.ID_CR.toString(), EMPTY_STRING); + mapTemporary.put(EnumChangeR07.REVISION_CR.toString(), EMPTY_STRING); + mapTemporary.put(EnumChangeR07.TYPE_CR.toString(), EMPTY_STRING); + mapTemporary.put(EnumChangeR07.NOM_CR.toString(), EMPTY_STRING); + } + + /** + * Fills the remaining CN columns with empty cells.
    + * If there are [0..cnMax[ columns, but on this line there are 'n' CNs (n<cnMax) then provide colNum=n=cnList.size().
    + * As a result, all [n..cnMax[ columns will be filled with empty cells + * + * @param mapTemporary the map to fill + * @param colStart the last non-empty CN column + */ + private void fillEmptyCnColumns(final Map mapTemporary, final int colStart) { + for (int colNum = colStart + 1; colNum <= nbMaxChangeNotice; colNum++) { + // For some reason, the printer expects [1..n] instead of [0..n[ + // So here since all [1..n] columns contain some real CNs, we need to fill all ]n..cnMax] columns with blanks ! + mapTemporary.put(EnumChangeR07.ID_CN.toString() + "_" + colNum, EMPTY_STRING); + mapTemporary.put(EnumChangeR07.REVISION_CN.toString() + "_" + colNum, EMPTY_STRING); + mapTemporary.put(EnumChangeR07.TYPE_CN.toString() + "_" + colNum, EMPTY_STRING); + mapTemporary.put(EnumChangeR07.NOM_CN.toString() + "_" + colNum, EMPTY_STRING); + } + } + + private Map makeMap(final SnecmaLine line) { + Map map = new HashMap<>(); + mapReceptor(map, line); + mapRepere(map, line); + mapComponent(map, line); + return map; + } + + private void mapReceptor(final Map map, final SnecmaLine line) { + map.put(EnumRecepteurR07.ID_RECEPTEUR.toString(), line.getIDReceptor()); + map.put(EnumRecepteurR07.REVISION_RECEPTEUR.toString(), line.getRevisionReceptor()); + map.put(EnumRecepteurR07.NOM_RECEPTEUR.toString(), line.getNameReceptor()); + } + + private void mapRepere(final Map map, final SnecmaLine line) { + map.put(EnumRepereR07.REPERE_FONCTIONNEL.toString(), line.getRepereName()); + map.put(EnumRepereR07.REVISION_REPERE_FONCTIONNEL.toString(), line.getRepereRevision()); + map.put(EnumRepereR07.RESPONSABLE_REPERE.toString(), line.getResponsableRepere()); + map.put(EnumRepereR07.SUIVI_MONTAGE.toString(), LanguageHelper.french(line.getSuiviMontage())); // French + } + + private void mapComponent(final Map map, final SnecmaLine line) { + map.put(EnumComposantR07.REF_FABRICANT.toString(), line.getIDComponent()); + map.put(EnumComposantR07.REVISION_REFERENCE.toString(), line.getIDRevisionComponent()); + map.put(EnumComposantR07.TYPE_REFERENCE.toString(), line.getTypeReference()); // French + map.put(EnumComposantR07.NOM_REFERENCE.toString(), line.getNameReference()); + map.put(EnumComposantR07.REFERENCE_CONCEPTEUR.toString(), line.getReferenceConceptor()); + map.put(EnumComposantR07.REFERENCE_TRANSPOSEE.toString(), line.getReferenceTransposed()); + map.put(EnumComposantR07.REFERENCE_ASSOCIEE.toString(), line.getReferenceAssociated()); + map.put(EnumComposantR07.RESPONSABLLE_CONCEPTION.toString(), line.getResponsableConception()); + map.put(EnumComposantR07.ARTICLE_GESTION.toString(), line.getArticleGestion()); + map.put(EnumComposantR07.CLASSEMENT.toString(), line.getClassement()); + map.put(EnumComposantR07.SUIVI_UTILISATION.toString(), LanguageHelper.french(line.getSuiviUtilisation())); // French + map.put(EnumComposantR07.SUIVI_DUREE_VIE.toString(), LanguageHelper.french(line.getSuiviDureeVie())); // French + map.put(EnumComposantR07.LISTE_FOURNISSEUR.toString(), StringHelper.implode(", ", line.getSuppliersList())); + map.put(EnumLienNomenclatureR07.ALT.toString(), line.getALT()); + map.put(EnumLienNomenclatureR07.SUIVANT_BESOIN.toString(), line.getSB()); + map.put(EnumLienNomenclatureR07.QUANTITE_CUMULEE.toString(), line.getQuantiteCumulee()); + map.put(EnumLienNomenclatureR07.PANACHAGE.toString(), LanguageHelper.french(line.getPanachage())); + map.put(EnumLienNomenclatureR07.QUANTITE.toString(), line.getQuantite()); + } + + private Map addChangeNoticeWithoutCR(final Collection changeNoticeList, + final Map structureMap) { + Map mapTemporary = new HashMap<>(structureMap); // Structural map is copied to keep the content the same throughout all the lines + int changeNum = 0; + for (TcChangeNoticeRevision changeNoticeRevision : changeNoticeList) { + addChangeNoticeAtPosition(mapTemporary, changeNoticeRevision, changeNum++); + } + fillEmptyCrColumns(mapTemporary); // Fill unused CR column with blanks + fillEmptyCnColumns(mapTemporary, changeNoticeList.size()); // Fill all remaining CN columns with blanks + return mapTemporary; + } + + private void addChangeRequestAndChangeNotice(final Map map, final TcChangeRequestRevision changeRequesteRevision, + final Collection cnList) { + map.put(EnumChangeR07.ID_CR.toString(), changeRequesteRevision.getItemId()); + map.put(EnumChangeR07.REVISION_CR.toString(), changeRequesteRevision.getRevisionId()); + map.put(EnumChangeR07.TYPE_CR.toString(), LanguageHelper.french(changeRequesteRevision.getTypeModSupportProcess())); + map.put(EnumChangeR07.NOM_CR.toString(), changeRequesteRevision.getChangeName()); + int posCn = 0; + for (TcChangeNoticeRevision changeNoticeRevision : cnList) { + addChangeNoticeAtPosition(map, changeNoticeRevision, posCn++); + } + } + + /** + * Add a CN to the CN columns.
    + * If there are [0..cnMax[ columns, puts the CN in the nth column (n + */ + private void addChangeNoticeAtPosition(final Map mapTemporary, final TcChangeNoticeRevision changeNoticeRevision, + final int changeNum) { + int realPos = changeNum + 1; // For some reason, the printer expects [1..n] instead of [0..n[ + mapTemporary.put(EnumChangeR07.ID_CN.toString() + "_" + realPos, changeNoticeRevision.getItemId()); + mapTemporary.put(EnumChangeR07.REVISION_CN.toString() + "_" + realPos, changeNoticeRevision.getRevisionId()); + mapTemporary.put(EnumChangeR07.TYPE_CN.toString() + "_" + realPos, LanguageHelper.french(changeNoticeRevision.getTypeModification())); + mapTemporary.put(EnumChangeR07.NOM_CN.toString() + "_" + realPos, changeNoticeRevision.getChangeName()); + } + + private void fillerMapDataEffectivity(final Map mapTemporary, final boolean isConf1) { + mapTemporary.put(EnumRecepteurR07.EFFECTIVITE.toString(), isConf1 ? conf1Name : conf2Name); + mapTemporary.put(EnumChangeR07.CONFIGURATION_CONCERNED.toString(), isConf1); + } + + private void fillerMapDataDifference(final Map mapTemporary, final boolean isExclusif, final Map mapMod) { + if (isExclusif) { + mapTemporary.put(EnumMapDelta.ALL_LINE_DIFFERENCE.toString(), true); + } else { + for (Entry elem : mapMod.entrySet()) { + mapTemporary.put(elem.getKey().toString(), elem.getValue()); + } + mapTemporary.put(EnumMapDelta.ALL_LINE_DIFFERENCE.toString(), false); + } + } + + private List collectParamDifference() { + List lstParamDiff = new ArrayList<>(); + lstParamDiff.add(EnumMapDelta.ID_RECEPTEUR_ECART.toString()); + lstParamDiff.add(EnumMapDelta.NOM_RECEPTEUR_ECART.toString()); + lstParamDiff.add(EnumMapDelta.REPERE_FONCTIONNEL_ECART.toString()); + lstParamDiff.add(EnumMapDelta.RESPONSABLE_REPERE_ECART.toString()); + lstParamDiff.add(EnumMapDelta.SUIVI_MONTAGE_ECART.toString()); + lstParamDiff.add(EnumMapDelta.REF_FABRICANT_ECART.toString()); + lstParamDiff.add(EnumMapDelta.TYPE_REFERENCE_ECART.toString()); + lstParamDiff.add(EnumMapDelta.NOM_REFERENCE_ECART.toString()); + lstParamDiff.add(EnumMapDelta.REFERENCE_CONCEPTEUR_ECART.toString()); + lstParamDiff.add(EnumMapDelta.REFERENCE_TRANSPOSEE_ECART.toString()); + lstParamDiff.add(EnumMapDelta.REFERENCE_ASSOCIEE_ECART.toString()); + lstParamDiff.add(EnumMapDelta.RESPONSABLE_CONCEPTION_ECART.toString()); + lstParamDiff.add(EnumMapDelta.ARTICLE_GESTION_ECART.toString()); + lstParamDiff.add(EnumMapDelta.CLASSEMENT_ECART.toString()); + lstParamDiff.add(EnumMapDelta.SUIVI_UTILISATION_ECART.toString()); + lstParamDiff.add(EnumMapDelta.SUIVI_DUREE_VIE_ECART.toString()); + lstParamDiff.add(EnumMapDelta.LISTE_FOURNISSEUR_ECART.toString()); + lstParamDiff.add(EnumMapDelta.ALT_ECART.toString()); + lstParamDiff.add(EnumMapDelta.SUIVI_BESOIN_ECART.toString()); + lstParamDiff.add(EnumMapDelta.QUANTITE_CUMULEE_ECART.toString()); + lstParamDiff.add(EnumMapDelta.PANACHAGE_ECART.toString()); + lstParamDiff.add(EnumMapDelta.QUANTITE_ECART.toString()); + lstParamDiff.add(EnumMapDelta.ALL_LINE_DIFFERENCE.toString()); + return lstParamDiff; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/ReportDataR07.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/ReportDataR07.java new file mode 100644 index 0000000..37e9078 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/ReportDataR07.java @@ -0,0 +1,22 @@ +package com.capgemini.reports.definition.r07report; + +import com.capgemini.reports.definition.r07report.data.DataReportPreparatorR07.ReportDataLineR07; +import com.capgemini.reports.reports.parameters.Generics; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.List; + +/** + * Regroups all the data that is necessary to produce a line in the final report: the written date, the configuration it belongs to, which cells to highlight. + */ +@Getter +@AllArgsConstructor +public class ReportDataR07 { + private final Generics genericParam1; + private final Generics genericParam2; + private final int numberOfLinesInConf1; + private final int numberOfLinesInConf2; + private final int maxCN; + private final List reportDataList; +} \ No newline at end of file diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/checker/R07ProductUnitChecker.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/checker/R07ProductUnitChecker.java new file mode 100644 index 0000000..e8f0898 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/checker/R07ProductUnitChecker.java @@ -0,0 +1,41 @@ +package com.capgemini.reports.definition.r07report.checker; + +import com.capgemini.reports.exceptions.UserInputErrorEnum; +import com.capgemini.reports.reports.parameters.ProductUnit; +import com.capgemini.reports.reports.parameters.checker.ProductUnitChecker; + +/** + * This class checks if a a given Product-Unit is valid for a R07 report. + */ +public class R07ProductUnitChecker extends ProductUnitChecker { + + private final R07Configuration conf; + + /** + * Constructor. + * + * @param productUnit {@link ProductUnit} - the product unit + * @param isConf1 boolean - Is true if it is the configuration 1. Else false. + */ + public R07ProductUnitChecker(final ProductUnit productUnit, final boolean isConf1) { + super(productUnit); + this.conf = isConf1 ? R07Configuration.CONF_1 : R07Configuration.CONF_2; + } + + @Override + protected UserInputErrorEnum getErrorMessage() { + switch (conf) { + case CONF_1: + return UserInputErrorEnum.THE_UNIT_1_IS_NOT_ASSOCIATED_TO_THE_PRODUCT_1; + case CONF_2: + return UserInputErrorEnum.THE_UNIT_2_IS_NOT_ASSOCIATED_TO_THE_PRODUCT_2; + default: + return UserInputErrorEnum.PRODUCT_AND_UNIT_DOES_NOT_EXIST; + } + } + + private enum R07Configuration { + CONF_1, + CONF_2 + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/DataReportPreparatorR07.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/DataReportPreparatorR07.java new file mode 100644 index 0000000..50ed4dd --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/DataReportPreparatorR07.java @@ -0,0 +1,177 @@ +package com.capgemini.reports.definition.r07report.data; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.reports.bomlineholder.flattener.line.SnecmaLine; +import com.capgemini.reports.changeobjects.change.TcChangeNoticeRevision; +import com.capgemini.reports.changeobjects.change.TcChangeRequestRevision; +import com.capgemini.reports.definition.r07report.CRExtractorHelper; +import com.capgemini.reports.definition.r07report.ExecutionR07; +import com.capgemini.reports.definition.r07report.R07Printer; +import com.capgemini.reports.definition.r07report.ReportDataR07; +import com.capgemini.reports.definition.r07report.data.extractor.BomFlattenerR07; +import com.capgemini.reports.definition.r07report.data.extractor.DataExtractorR07; +import com.capgemini.reports.definition.r07report.data.filter.ConfigurationFilterR07; +import com.capgemini.reports.definition.r07report.data.sorter.R07DataSorter; +import com.capgemini.reports.definition.r07report.data.sorter.R07DataSorter.ConfLine; +import com.capgemini.reports.definition.r07report.printing.EnumMapDelta; +import com.capgemini.reports.execution.IDataReportPreparator; +import com.capgemini.reports.execution.strategies.IExecutionStrategy; +import com.capgemini.reports.printing.PrintParameters; +import com.google.common.collect.HashMultimap; +import com.google.common.collect.SetMultimap; +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +/** + * This class will allow to prepare data and findAll back data for making report R07. + */ +public class DataReportPreparatorR07 implements IDataReportPreparator { + private static final long serialVersionUID = 6255355550254874091L; + private static final Logger LOGGER = LoggerFactory.getLogger(DataReportPreparatorR07.class); + + @Override + public String print(TcSession session, ExecutionR07 execution, IExecutionStrategy executionStrategy) throws KurtException { + PrintParameters printParameters = prepareData(session, execution); + executionStrategy.print(printParameters, execution); + return executionStrategy.getReportFileName(execution) + printParameters.getOuputFileExtension(); + } + + private PrintParameters prepareData(final TcSession session, final ExecutionR07 report) throws KurtException { + LOGGER.debug("PrepareData started on: {}", report.getReportIdentifier().getReportTitle()); + + // Extract the Tc data + DataExtractorR07 extractor = new DataExtractorR07(session, report); + extractor.extractData(); + + // Flatten the bomLines to extract all links in a List + BomFlattenerR07 flatConf = new BomFlattenerR07(); + flatConf.visitTopReceptorBom(session, extractor.getTopBomConf1(), extractor.getTopBomConf2()); + + // Define number of triplet for each configuration + int sizeTripletConf1 = flatConf.getConfig1().size(); + int sizeTripletConf2 = flatConf.getConfig2().size(); + + // Filter the data to remove objects that are identical in both configuration. Also isolates exclusive items in each onf. + ConfigurationFilterR07 filter = new ConfigurationFilterR07(); + filter.filter(flatConf); + + // Sort the data according to the original bomLine browsing order + R07DataSorter dataSorter = new R07DataSorter(); + Collection reportLines = dataSorter.sort(filter); + + // Obtain the Change Requests and Change Notices + List dataList = extractCrCn(session, reportLines); + + // Count the maximum number of CNs + int maxCN = countMaxCN(dataList); + ReportDataR07 dataR07 = new ReportDataR07(report.getGenericParam1(), report.getGenericParam2(), sizeTripletConf1, sizeTripletConf2, maxCN, dataList); + R07Printer printer = new R07Printer(); + PrintParameters printParameters = printer.makeMasterTemplate(report, dataR07); + printer.constructDataMaps(session, printParameters, dataR07); + + LOGGER.debug("PrepareData ended on: {}", report.getReportIdentifier().getReportTitle()); + return printParameters; + } + + int countMaxCN(final List dataList) { + int maxCN = 1; // Minimum 1 column + for (ReportDataLineR07 line : dataList) { + // There can be CNs bundled behind a CR. Amongst these lines, the FAKE CR points to the CNs that have no father, so the line length is correct + for (Collection cnInThisLine : line.getBundles().asMap().values()) { + maxCN = Math.max(maxCN, cnInThisLine.size()); + } + } + return maxCN; + } + + List extractCrCn(final TcSession session, final Collection reportLines) { + // Extract CRs and CNs + CRExtractorHelper crExtractor = new CRExtractorHelper(session); + List reportDataList = new ArrayList<>(); + for (ConfLine line : reportLines) { + // Obtain all related CRs and CNs + SnecmaLine snecmaLine = line.getLine(); + String componentId = snecmaLine.getIDComponent(); + String componentRevision = snecmaLine.getIDRevisionComponent(); + List crList = crExtractor.getCrOnPart(componentId, componentRevision); + List cnList = crExtractor.getCnOnPart(componentId, componentRevision); + + // Build map: CR -> CN + SetMultimap bundles = makeBundles(crList, cnList); + reportDataList.add(new ReportDataLineR07(snecmaLine, bundles, line.isConf1(), line.isExclusive(), line.getHasMod())); + } + return reportDataList; + } + + /** + * Remove and group in bundles the CNs that have a common ancestor CR, and leave only the CNs that have no ancestor in the input list. + * + * @param lstCN a {@link List} of {@link TcChangeNoticeRevision}s. Those CNs all mention the part. This list will be altered, only the CNs without a CR 'father' will be left. + * @return a {@link Map} grouping a {@link List} of {@link TcChangeNoticeRevision} sharing a common {@link TcChangeRequestRevision} 'father'. + */ + private SetMultimap makeBundles(final List lstCR, + final List lstCN) { + SetMultimap bundles = HashMultimap.create(); + // Put all the CR first. Link them to their Children CNs IF those children are in the CNlist (they mention the Part in their pseudo-folder 'after') + for (TcChangeRequestRevision changeRequestRevision : lstCR) { + for (TcChangeNoticeRevision child : changeRequestRevision.getChangeNoticesList()) { + if (lstCN.contains(child)) { + bundles.put(changeRequestRevision, child); + } + } + if (!bundles.containsKey(changeRequestRevision)) { + bundles.put(changeRequestRevision, null); + } + } + // Then put all CNs in the map. If they have one or more father CRs, add the CN to the CR's children list. Otherwise, put them in FAKE's list + for (TcChangeNoticeRevision changeNoticeRevision : lstCN) { + if (changeNoticeRevision.getImplementsCR() != null && !changeNoticeRevision.getImplementsCR().isEmpty()) { + for (TcChangeRequestRevision father : changeNoticeRevision.getImplementsCR()) { + bundles.put(father, changeNoticeRevision); + bundles.remove(father, null); // Try to remove a null from the father's sons. May have happened if the father had no known CN. It now has at least one. + } + } else { + bundles.put(ReportDataLineR07.FAKE, changeNoticeRevision); + } + } + return bundles; + } + + /** + * Regroups all the data that is necessary to produce a line in the final report: the written date, the configuration it belongs to, which cells to highlight. + */ + @Getter + @AllArgsConstructor + public static class ReportDataLineR07 { + + /** + * This is a placeholder. + */ + public static final TcChangeRequestRevision FAKE = new TcChangeRequestRevision(null, null) { + private static final long serialVersionUID = -3143088096659343939L; + + }; + + private final SnecmaLine line; + /** + * These CRs keys do not mention the component. However, the CNs in the value List do, and the CR is their 'father'. + */ + private final SetMultimap bundles; + private final boolean conf1; + private final boolean exclusive; + Map hasMod; + + @Override + public String toString() { + return "Data: " + (exclusive ? "E" : "") + (conf1 ? "1" : "2") + line.toString() + " with " + bundles.size() + " CR(s)"; + } + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/TransformerR07.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/TransformerR07.java new file mode 100644 index 0000000..6fdad30 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/TransformerR07.java @@ -0,0 +1,51 @@ +package com.capgemini.reports.definition.r07report.data; + +import com.capgemini.reports.definition.r07report.data.extractor.lines.*; + +/** + * Interface for generating an index with a different algorithm for each line type. + */ +public interface TransformerR07 { + + /** + * Creates an identifier for a {@link R07Quad}. + * + * @param line the line from which to create the Identifier + * @return the {@link String} identifier + */ + String makeIdentifier(final R07Quad line); + + /** + * Creates an identifier for a {@link R07PartRfPart}. + * + * @param line the line from which to create the Identifier + * @return the {@link String} identifier + */ + String makeIdentifier(final R07PartRfPart line); + + + /** + * Creates an identifier for a {@link R07ReceptorLine}. + * + * @param line the line from which to create the Identifier + * @return the {@link String} identifier + */ + String makeIdentifier(final R07ReceptorLine line); + + /** + * Creates an identifier for a {@link R07ProductGeneric}. + * + * @param r07ProductGeneric the line from which to create the Identifier + * @return the {@link String} identifier + */ + String makeIdentifier(final R07ProductGeneric r07ProductGeneric); + + /** + * Creates an identifier for a {@link R07AltPart}. + * + * @param altPart the line from which to create the Identifier + * @return the {@link String} identifier + */ + String makeIdentifier(final R07AltPart altPart); + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/extractor/BomFlattenerR07.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/extractor/BomFlattenerR07.java new file mode 100644 index 0000000..fb0527a --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/extractor/BomFlattenerR07.java @@ -0,0 +1,153 @@ +package com.capgemini.reports.definition.r07report.data.extractor; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.bomlineholder.comparison.AbstractDualBomLineFlattener; +import com.capgemini.reports.bomlineholder.flattener.AbstractBomLineFlattener; +import com.capgemini.reports.bomlineholder.flattener.line.*; +import com.capgemini.reports.definition.r07report.data.TransformerR07; +import com.capgemini.reports.definition.r07report.data.extractor.lines.*; +import com.capgemini.reports.releasestatus.EffectivityBehaviourHelper; +import com.capgemini.reports.snecmaobjects.ISnecmaObject; +import com.capgemini.reports.snecmaobjects.part.AbstractPart; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; + +/** + * This class analyses two {@link BOMLineHolder} and flattens their tree structure into an array of father-son relationships.
    + * The configuration lines are numbered according to the order of the structure, so the structure can be reconstructed after the flattening has been performed. + */ +@Getter +public class BomFlattenerR07 extends AbstractDualBomLineFlattener { + + /** + * Compares two {@link ISnecmaObject} by their Identifiers (Name, or ID). + */ + private static final Comparator ITEM_COMPARATOR = new ItemComparatorR07(); + /** + * Compares to {@link BOMLineHolder}s. Uses the {@link ItemComparatorR07} to compare the {@link ISnecmaObject}s inside. + */ + private static final Comparator BOM_COMPARATOR = new BomComparatorR07(); + + /** + * This counter increments at every new line.
    + * Enables to uniquely identify chronologically every SnecmaLine found on the configuration.
    + * After all the filtering is done, the chronological identifier can be used to mimic the original tree structure of the bom. + */ + private int counter; + + /** + * Builds an {@link AbstractBomLineFlattener} for the R07 report. + */ + public BomFlattenerR07() { + // ***** Spec R07 **** + // - visit only unit-managed parts + // - visit parts in pseudo-folder Alternative + // - Do not retrieve part numbers below RF Generics + // - Do not investigate Parts wwithout a RF above (do not follow Part->Part links + // - Unable to provide the pseudo-folder behaviour yet, will be setup after call to super(...) + // - usual Bom comparator + // - usual item comparator + // - Visit brothers below a parent part BEFORE recursing through the brothers' children + super(EffectivityBehaviourHelper.visitOnlyUnitManagedParts(), true, false, false, null, BOM_COMPARATOR, ITEM_COMPARATOR, true); + this.setPseudoFolderBehaviour(new R07AltOrDetPseudoFolderBehaviour()); + } + + @Override + protected AbstractQuad makeQuad(final TcSession session, final BOMLineHolder receptor, final BOMLineHolder rfReceptor, + final BOMLineHolder component, final BOMLineHolder rfComponent) { + return new R07Quad(session, receptor, rfReceptor, component, rfComponent, counter++); + } + + @Override + protected AbstractTopLine maketopline(final BOMLineHolder aTopBomLine) { + return null; // No need to put the topLine in the report: return null, it will not be put inside the list + } + + @Override + protected AbstractProductGeneric makeProductGeneric(final TcSession session, final BOMLineHolder productReceptor, + final BOMLineHolder genericComponent, final BOMLineHolder rfGenericComponent) { + return new R07ProductGeneric(session, productReceptor, genericComponent, rfGenericComponent, counter++); + } + + @Override + protected AbstractPartNumber makePartNumber(final BOMLineHolder genericReceptor, final BOMLineHolder rfGeneric, + final BOMLineHolder partAero) { + return null; // No need to put part Number in the report: return null, it will not be put inside the list + } + + @Override + protected AbstractPartRfPart makePartRfPart(final TcSession session, final BOMLineHolder partReceptor, final BOMLineHolder rfPartComponent, + final BOMLineHolder partComponent) { + return new R07PartRfPart(session, partReceptor, rfPartComponent, partComponent, counter++); + } + + @Override + protected AbstractReceptorLine makeReceptorLine(final TcSession session, final BOMLineHolder part, final BOMLineHolder rfPart) { + return new R07ReceptorLine(session, part, rfPart, counter++); + } + + @Override + protected AbstractPartPart makePartPart(final BOMLineHolder partReceptor, final BOMLineHolder partComponent) { + return null; // No need to cater for this event in R07, nomenclature should be stopped before: return null, it will not be put inside the list + } + + private static final class ItemComparatorR07 implements Comparator, Serializable { + + private static final long serialVersionUID = 1212463997223603766L; + + @Override + public int compare(final ISnecmaObject obj1, final ISnecmaObject obj2) { + int cmpType = obj1.getType().compareTo(obj2.getType()); + if (cmpType != 0) { + return cmpType; + } + if (obj1.isRF() && obj2.isRF()) { + return obj1.getName().compareTo(obj2.getName()); + } else { + return obj1.getItemId().compareTo(obj2.getItemId()); + } + } + } + + private static final class BomComparatorR07 implements Comparator, Serializable { + + private static final long serialVersionUID = 2176721559188935877L; + + @Override + public int compare(final BOMLineHolder bom1, final BOMLineHolder bom2) { + final int cmp; + if (bom1 == null) { + if (bom2 == null) { + cmp = 0; + } else { + cmp = 1; + } + } else { + if (bom2 == null) { + cmp = -1; + } else { + cmp = ITEM_COMPARATOR.compare(bom1.getSnecmaObject(), bom2.getSnecmaObject()); + } + } + return cmp; + } + } + + @AllArgsConstructor + private class R07AltOrDetPseudoFolderBehaviour implements DealWithAltOrDetPseudoFolder { + @Override + public List> dealWithIt(final BOMLineHolder alt, final AbstractPart partInPseudoFolder) { + List> contents = new ArrayList<>(); + if (alt != null && alt.getSnecmaObject() != null && partInPseudoFolder != null) { + contents.add(new R07AltPart(alt, partInPseudoFolder, counter++)); + } + return contents; + } + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/extractor/DataExtractorR07.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/extractor/DataExtractorR07.java new file mode 100644 index 0000000..95f07c1 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/extractor/DataExtractorR07.java @@ -0,0 +1,130 @@ +package com.capgemini.reports.definition.r07report.data.extractor; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.EmptyNomenclatureException; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.exceptions.NoSuchBomViewException; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcBomObject; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcBomObjectFactory; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcRevisionRule; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcRevisionRuleProperties; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.product.TcProduct; +import com.capgemini.framework.teamcenter.object.runtime.TcBomWindow; +import com.capgemini.framework.teamcenter.object.runtime.TcBomWindowConfiguration; +import com.capgemini.framework.teamcenter.object.runtime.TcRevisionRulesConfiguration; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.bomlineholder.BOMLineHolderFactory; +import com.capgemini.reports.bomlineholder.processor.DefaultAltOrDetBehaviour; +import com.capgemini.reports.definition.r07report.ExecutionR07; +import com.capgemini.reports.exceptions.InvalidInputException; +import com.capgemini.reports.exceptions.InvalidUserInputException; +import com.capgemini.reports.exceptions.MalformedNomenclatureException; +import com.capgemini.reports.exceptions.UserInputErrorEnum; +import com.capgemini.reports.filter.AllIsGoodFilter; +import com.capgemini.reports.reports.parameters.Generics; +import com.capgemini.reports.teamcenter.resolution.structureservice.MultiStructureServiceCaller; +import com.teamcenter.soa.client.model.ModelObject; +import com.teamcenter.soa.client.model.strong.Form; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; + +import java.util.List; + +/** + * Extracts both raw nemenclature from Teamcenter, puts the result into the ExecutionR07. + */ +@Slf4j +public class DataExtractorR07 { + + private static final AllIsGoodFilter ACCEPT_ALL = new AllIsGoodFilter(); + private final TcSession session; + private final ExecutionR07 report; + + // Data gathered + @Getter + private BOMLineHolder topBomConf1; + @Getter + private BOMLineHolder topBomConf2; + + /** + * Creates a {@link DataExtractorR07} object. + * + * @param session the Tc session + * @param report the report holding the necessary bom data + */ + public DataExtractorR07(final TcSession session, final ExecutionR07 report) { + this.session = session; + this.report = report; + } + + /** + * Extracts the two configurations to be compared in the R07 report. + * + * @throws InvalidInputException if the parameters are incorrect + * @throws EmptyNomenclatureException if the nomeclature is empty + * @throws NoSuchBomViewException if the bomview could not be found + * @throws MalformedNomenclatureException if the nomeclature cannot be formed + */ + public void extractData() throws KurtException { + log.debug("PrepareData started on: " + report.getReportIdentifier().getReportTitle()); + long start = System.currentTimeMillis(); + + // Setup the policy + session.setObjectPropPolicy(report.getFullPolicy()); + + String revisionRule = report.getRevisionRule(); + + log.debug("Check the data structures using revision rule {}.", revisionRule); + Generics genericParam1 = report.getGenericParam1(); + Generics genericParam2 = report.getGenericParam2(); + + log.debug("Resolve Configuration 1"); + topBomConf1 = resolveTopBom(genericParam1); + + log.debug("Resolve Configuration 2"); + topBomConf2 = resolveTopBom(genericParam2); + + log.debug("Data gathering time : {} ms", System.currentTimeMillis() - start); + } + + private BOMLineHolder resolveTopBom(final Generics generic) throws KurtException { + TcBomObject topLineObject = new TcBomObjectFactory(session, generic.getItem(session)).create(); + TcProduct productObject = new TcProduct(session, generic.getProductUnit().getProduct(session)); + int unit = generic.getProductUnit().getUnit(); + + TcRevisionRuleProperties revisionRuleProperties = new TcRevisionRuleProperties(productObject, unit); + + TcRevisionRule revisionRule = session.findRevRule(report.getRevisionRule()); + TcRevisionRulesConfiguration revRulesConfiguration = new TcRevisionRulesConfiguration(revisionRule, revisionRuleProperties); + + // Perform the job + log.debug("Data configured, now starting nomenclature resolution"); + try (TcBomWindow bomWindow = session.createBomWindow(new TcBomWindowConfiguration(topLineObject, revRulesConfiguration))) { + session.setObjectPropPolicy(report.getFullPolicy()); + + BOMLineHolder unbuiltTopLine = new MultiStructureServiceCaller(session).resolve(bomWindow.topLine(), ACCEPT_ALL); + List itemRevMaster = unbuiltTopLine.getAllItemRevMasters(); + session.loadProperties(itemRevMaster.toArray(new ModelObject[itemRevMaster.size()])); + + log.debug("Building the Snecma Objects"); + BOMLineHolderFactory.buildTopBom(session, unbuiltTopLine, ACCEPT_ALL); + + log.debug("Loading the correct revisions of all Items in the pseudo-folders of Alt And DET parts"); + DefaultAltOrDetBehaviour altOrDetBehaviour = new DefaultAltOrDetBehaviour<>(session, null); + unbuiltTopLine.process(altOrDetBehaviour); + + log.debug("All required data was loaded, freezing the BomLineHolder..."); + unbuiltTopLine.freeze(); + return unbuiltTopLine; + } catch (EmptyNomenclatureException e) { + switch (generic.getType()) { + case GENERIC: + throw new InvalidUserInputException(UserInputErrorEnum.NO_DATA_COULD_BE_EXTRACTED_FOR_GENERIC_PRODUCT_AND_UNIT, e); + case GENERIC_ASSEMB: + throw new InvalidUserInputException(UserInputErrorEnum.NO_DATA_COULD_BE_EXTRACTED_FOR_GENERIC_ASSEMB_PRODUCT_AND_UNIT, e); + default: + throw e; + } + } + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/extractor/lines/ComparableLine.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/extractor/lines/ComparableLine.java new file mode 100644 index 0000000..390e089 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/extractor/lines/ComparableLine.java @@ -0,0 +1,57 @@ +package com.capgemini.reports.definition.r07report.data.extractor.lines; + + +/** + * Interface used in the R07 for comparing lines to each other. + */ +public interface ComparableLine { + /** + * Compares a line to any other {@link ComparableLine}. + * + * @param other the other line + * @return the difference + */ + int compareLineContent(final ComparableLine other); + + /** + * Compares a line a to a {@link R07Quad}. + * + * @param other the other line + * @return the difference + */ + int compareContent(final R07Quad other); + + /** + * Compares a line a to a {@link R07PartRfPart}. + * + * @param other the other line + * @return the difference + */ + int compareContent(final R07PartRfPart other); + + /** + * Compares a line a to a {@link R07ReceptorLine}. + * + * @param other the other line + * @return the difference + */ + int compareContent(final R07ReceptorLine other); + + /** + * Compares a line a to a {@link R07ProductGeneric}. + * + * @param other the other line + * @return the difference + */ + int compareContent(final R07ProductGeneric other); + + /** + * Compares a line a to a {@link R07AltPart}. + * + * @param other the other line + * @return the difference + */ + int compareContent(final R07AltPart other); + + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/extractor/lines/R07AltPart.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/extractor/lines/R07AltPart.java new file mode 100644 index 0000000..534634f --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/extractor/lines/R07AltPart.java @@ -0,0 +1,74 @@ +package com.capgemini.reports.definition.r07report.data.extractor.lines; + +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.bomlineholder.flattener.line.AbstractAltPart; +import com.capgemini.reports.definition.r07report.data.TransformerR07; +import com.capgemini.reports.definition.r07report.data.filter.comparators.AbstractBomLineComparator; +import com.capgemini.reports.definition.r07report.data.filter.comparators.AbstractItemComparator; +import com.capgemini.reports.exceptions.NotSupportedException; +import com.capgemini.reports.snecmaobjects.part.AbstractPart; +import lombok.extern.slf4j.Slf4j; + +/** + * Represents The link between an Alt and a Part in its pseudo-folder. + */ +@Slf4j +public class R07AltPart extends AbstractAltPart implements ComparableLine { + + /** + * builds the link between an Altenrate and a Part in its pseudo-folder. + * + * @param alt the Alternate + * @param child the child part + * @param counter the position of this line in the nomenclature. + */ + public R07AltPart(final BOMLineHolder alt, final AbstractPart child, final int counter) { + super(alt, child, counter); + } + + @Override + public String transform(final TransformerR07 transformer) { + return transformer.makeIdentifier(this); + } + + @Override + public int compareLineContent(final ComparableLine other) { + return other.compareContent(this); + } + + @Override + public int compareContent(final R07AltPart other) { + try { + int cmp = AbstractBomLineComparator.compareReceptors(this.getAltBL(), other.getAltBL()); + if (cmp != 0) { + return cmp; + } + cmp = AbstractItemComparator.compareComponents(this.getChild(), other.getChild()); + return cmp; + } catch (NotSupportedException e) { + log.info("Failed object comparison", e); + return 1; + } + } + + @Override + public int compareContent(final R07Quad other) { + return 1; + } + + @Override + public int compareContent(final R07ReceptorLine other) { + return 1; + } + + @Override + public int compareContent(final R07ProductGeneric other) { + return 1; + } + + @Override + public int compareContent(final R07PartRfPart other) { + return 1; + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/extractor/lines/R07PartRfPart.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/extractor/lines/R07PartRfPart.java new file mode 100644 index 0000000..c5f71a5 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/extractor/lines/R07PartRfPart.java @@ -0,0 +1,78 @@ +package com.capgemini.reports.definition.r07report.data.extractor.lines; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.bomlineholder.flattener.line.AbstractPartRfPart; +import com.capgemini.reports.definition.r07report.data.TransformerR07; +import com.capgemini.reports.definition.r07report.data.filter.comparators.AbstractBomLineComparator; +import com.capgemini.reports.definition.r07report.data.filter.comparators.rf.RfComparator; +import com.capgemini.reports.exceptions.NotSupportedException; +import lombok.extern.slf4j.Slf4j; + +/** + * Represents a classical 'triplet' between a Part, a Rf Part and a Part. + */ +@Slf4j +public class R07PartRfPart extends AbstractPartRfPart implements ComparableLine { + + + /** + * Builds a classical 'triplet' between a Part, a Rf Part and a Part. + * + * @param partReceptor a {@link BOMLineHolder} + * @param rfPartComponent a {@link BOMLineHolder} + * @param partComponent a {@link BOMLineHolder} + * @param counter the position of the line in the nomenclature. + */ + public R07PartRfPart(final TcSession session, final BOMLineHolder partReceptor, final BOMLineHolder rfPartComponent, final BOMLineHolder partComponent, + final int counter) { + super(session, partReceptor, rfPartComponent, partComponent, counter); + } + + @Override + public String transform(final TransformerR07 transformer) { + return transformer.makeIdentifier(this); + } + + @Override + public int compareLineContent(final ComparableLine other) { + return other.compareContent(this); + } + + @Override + public int compareContent(final R07PartRfPart other) { + try { + int cmp = AbstractBomLineComparator.compareReceptors(this.getPartReceptorBL(), other.getPartReceptorBL()); + if (cmp == 0) { + cmp = RfComparator.compareRf(this.getRfPartComponentBL(), other.getRfPartComponentBL()); + if (cmp == 0) { + cmp = AbstractBomLineComparator.compareComponents(this.getPartComponentBL(), other.getPartComponentBL()); + } + } + return cmp; + } catch (NotSupportedException e) { + log.warn("Failed object comparison", e); + return 1; + } + } + + @Override + public int compareContent(final R07Quad other) { + return 1; + } + + @Override + public int compareContent(final R07ReceptorLine other) { + return 1; + } + + @Override + public int compareContent(final R07ProductGeneric other) { + return 1; + } + + @Override + public int compareContent(final R07AltPart other) { + return 1; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/extractor/lines/R07ProductGeneric.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/extractor/lines/R07ProductGeneric.java new file mode 100644 index 0000000..eaf7487 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/extractor/lines/R07ProductGeneric.java @@ -0,0 +1,77 @@ +package com.capgemini.reports.definition.r07report.data.extractor.lines; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.bomlineholder.flattener.line.AbstractProductGeneric; +import com.capgemini.reports.definition.r07report.data.TransformerR07; +import com.capgemini.reports.definition.r07report.data.filter.comparators.AbstractBomLineComparator; +import com.capgemini.reports.definition.r07report.data.filter.comparators.rf.RfComparator; +import com.capgemini.reports.exceptions.NotSupportedException; +import lombok.extern.slf4j.Slf4j; + +/** + * Represents a Product - Generic line for R07 report. + */ +@Slf4j +public class R07ProductGeneric extends AbstractProductGeneric implements ComparableLine { + + /** + * Builds a Product - Generic line for the R07 report. + * + * @param productReceptor a {@link BOMLineHolder} + * @param genericComponent a {@link BOMLineHolder} + * @param rfGenericComponent a {@link BOMLineHolder} + * @param counter the position of this line in the Bom. + */ + public R07ProductGeneric(final TcSession session, final BOMLineHolder productReceptor, final BOMLineHolder genericComponent, final BOMLineHolder rfGenericComponent, + final int counter) { + super(session, productReceptor, genericComponent, rfGenericComponent, counter); + } + + @Override + public String transform(final TransformerR07 transformer) { + return transformer.makeIdentifier(this); + } + + @Override + public int compareLineContent(final ComparableLine other) { + return other.compareContent(this); + } + + @Override + public int compareContent(final R07PartRfPart other) { + return 1; + } + + @Override + public int compareContent(final R07Quad other) { + return 1; + } + + @Override + public int compareContent(final R07ReceptorLine other) { + return 1; + } + + @Override + public int compareContent(final R07ProductGeneric other) { + try { + int cmp = AbstractBomLineComparator.compareReceptors(this.getProductReceptorBL(), other.getProductReceptorBL()); + if (cmp == 0) { + cmp = RfComparator.compareRf(this.getRfGenericComponentBL(), other.getRfGenericComponentBL()); + if (cmp == 0) { + cmp = AbstractBomLineComparator.compareComponents(this.getGenericComponentBL(), other.getGenericComponentBL()); + } + } + return cmp; + } catch (NotSupportedException e) { + log.warn("Failed object comparison", e); + return 1; + } + } + + @Override + public int compareContent(final R07AltPart other) { + return 1; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/extractor/lines/R07Quad.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/extractor/lines/R07Quad.java new file mode 100644 index 0000000..8053f8e --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/extractor/lines/R07Quad.java @@ -0,0 +1,80 @@ +package com.capgemini.reports.definition.r07report.data.extractor.lines; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.bomlineholder.flattener.line.AbstractQuad; +import com.capgemini.reports.definition.r07report.data.TransformerR07; +import com.capgemini.reports.definition.r07report.data.filter.comparators.AbstractBomLineComparator; +import com.capgemini.reports.definition.r07report.data.filter.comparators.rf.RfComparator; +import com.capgemini.reports.exceptions.NotSupportedException; +import lombok.extern.slf4j.Slf4j; + +/** + * Represents a {@link AbstractQuad} line, with receptor and component, both having their own repere.
    + * Receptors and components can be Parts or Generics.
    + * For the R07, the Quad accepts a TransformerR07 which will generate a custom Id for it, for sorting purposes. + */ +@Slf4j +public class R07Quad extends AbstractQuad implements ComparableLine { + + /** + * Builds a 'quad' object, using receptor, its repere, a component, and its repere. + * + * @param recepteurBL a {@link BOMLineHolder} + * @param repereRecepteurBL a {@link BOMLineHolder} + * @param composantBL a {@link BOMLineHolder} + * @param repereComposantBL a {@link BOMLineHolder} + * @param counter the position of this line in the Bom + */ + public R07Quad(final TcSession session, final BOMLineHolder recepteurBL, final BOMLineHolder repereRecepteurBL, final BOMLineHolder composantBL, + final BOMLineHolder repereComposantBL, final int counter) { + super(session, recepteurBL, repereRecepteurBL, composantBL, repereComposantBL, counter); + } + + @Override + public String transform(final TransformerR07 transformer) { + return transformer.makeIdentifier(this); + } + + @Override + public int compareLineContent(final ComparableLine other) { + return other.compareContent(this); + } + + @Override + public int compareContent(final R07Quad other) { + try { + int cmp = AbstractBomLineComparator.compareReceptors(this.getRecepteurBL(), other.getRecepteurBL()); + if (cmp == 0) { + cmp = RfComparator.compareRf(this.getRepereComposantBL(), other.getRepereComposantBL()); + if (cmp == 0) { + cmp = AbstractBomLineComparator.compareComponents(this.getComposantBL(), other.getComposantBL()); + } + } + return cmp; + } catch (NotSupportedException e) { + log.warn("Failed object comparison", e); + return 1; + } + } + + @Override + public int compareContent(final R07PartRfPart other) { + return 1; + } + + @Override + public int compareContent(final R07ReceptorLine other) { + return 1; + } + + @Override + public int compareContent(final R07ProductGeneric other) { + return 1; + } + + @Override + public int compareContent(final R07AltPart other) { + return 1; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/extractor/lines/R07ReceptorLine.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/extractor/lines/R07ReceptorLine.java new file mode 100644 index 0000000..29fce52 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/extractor/lines/R07ReceptorLine.java @@ -0,0 +1,60 @@ +package com.capgemini.reports.definition.r07report.data.extractor.lines; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.bomlineholder.flattener.line.AbstractReceptorLine; +import com.capgemini.reports.definition.r07report.data.TransformerR07; +import com.capgemini.reports.definition.r07report.data.filter.comparators.AbstractBomLineComparator; + +/** + * Represents a Receptor whose Repere does ot have a Component. + */ +public class R07ReceptorLine extends AbstractReceptorLine implements ComparableLine { + + + /** + * Builds a Receptor whose Repere does ot have a Component. + * + * @param recepteurBL the bom line holder of the receptor + * @param repereRecepteurBL the bom line holder of the repere + * @param counter the position of the line in the nomenclature + */ + public R07ReceptorLine(final TcSession session, final BOMLineHolder recepteurBL, final BOMLineHolder repereRecepteurBL, final int counter) { + super(session, recepteurBL, repereRecepteurBL, counter); + } + + @Override + public String transform(final TransformerR07 transformer) { + return transformer.makeIdentifier(this); + } + + @Override + public int compareLineContent(final ComparableLine other) { + return other.compareContent(this); + } + + @Override + public int compareContent(final R07Quad other) { + return 1; + } + + @Override + public int compareContent(final R07PartRfPart other) { + return 1; + } + + @Override + public int compareContent(final R07ReceptorLine other) { + return AbstractBomLineComparator.compareReceptors(this.getRecepteurBL(), other.getRecepteurBL()); + } + + @Override + public int compareContent(final R07ProductGeneric other) { + return 1; + } + + @Override + public int compareContent(final R07AltPart other) { + return 1; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/ConfigurationFilterR07.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/ConfigurationFilterR07.java new file mode 100644 index 0000000..8766402 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/ConfigurationFilterR07.java @@ -0,0 +1,302 @@ +package com.capgemini.reports.definition.r07report.data.filter; + +import com.capgemini.reports.bomlineholder.flattener.line.SnecmaLine; +import com.capgemini.reports.definition.r07report.data.TransformerR07; +import com.capgemini.reports.definition.r07report.data.extractor.BomFlattenerR07; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.*; + +/** + * This class filters two configurations, then extracts the differences. + *
      + *
    • All lines that are identical on both sides are lost
    • + *
    • All lines that boast the same structure (same receptor, repere, component for example) but have a difference in their content, are stored side by side in a {@link List} of {@link Diff} named {@link ConfigurationFilterR07#propDiff propDiff}.
    • + *
    • All lines that are exclusive to either configuration are kept in a separate {@link List} of {@link SnecmaLine}s named {@link ConfigurationFilterR07#exclusiveConf1 exclusiveConf1} and {@link ConfigurationFilterR07#exclusiveConf2 exclusiveConf2}.
    • + *
    + */ +@Getter +public class ConfigurationFilterR07 { + + /** + * Provides capabilities for comparing structure (receptor/repere) between two {@link SnecmaLine}s. + */ + private static final Comparator> STRUCTURAL_COMPARATOR = new StructuralComparator(); + /** + * Provides capabilities for comparing full-depth content between two {@link SnecmaLine}s. + */ + private static final Comparator> CONTENT_COMPARATOR = new ContentComparator(); + /** + * List of differences detected in properties' contents between two objects of the same structure. + */ + private final List propDiff = new ArrayList<>(); + /** + * Pairs exclusively present in Conf1. + */ + private final List> exclusiveConf1 = new ArrayList<>(); + /** + * Pairs exclusively present in Conf2. + */ + private final List> exclusiveConf2 = new ArrayList<>(); + /** + * Number of exact matches in both configurations: same structure, same data content. + */ + private int cloneNum; + + /** + * The main method of the class: performs a Filtering on two configurations.
    + * Leaves this instance in a state where it holds: + *
      + *
    • A {@link List} of {@link Diff} between data pairs conf1-conf2
    • + *
    • Two {@link List}s of exclusive content
    • + *
    • and the number of clones found in both configurations
    • + *
    + *
    + * Note: the input {@link BomFlattenerR07}'s contents will be cleared in the process! + * + * @param conf the configuration holder + */ + public void filter(final BomFlattenerR07 conf) { + List similarBuckets = filterExclusiveContent(conf.getConfig1(), conf.getConfig2()); + for (R07Bucket bucket : similarBuckets) { + bucket.filterSimilarContent(); + } + } + + /** + * Detect exclusive items of each conf, stores them appart, and removes them from their respective conf. + * + * @return a series of data buckets, each holding two sets of objects from either conf, which belong share the same structure + */ + private List filterExclusiveContent(final List> conf1, + final List> conf2) { + List similarBuckets = new ArrayList<>(); + + // Sort both configurations in place, according to the comparator. + // Note several elements may be 'equal' regarding to the comparator: they will keep their respective order + // Sorting several times using increasingly restrictive comparators is not so expensive, because each pass uses the pre-optimised result of the previous pass + Collections.sort(conf1, STRUCTURAL_COMPARATOR); + Collections.sort(conf2, STRUCTURAL_COMPARATOR); + R07Bucket currentBucket = null; + Iterator> iteratorConf1 = conf1.iterator(); + Iterator> iteratorConf2 = conf2.iterator(); + SnecmaLine lowestConf1 = iteratorConf1.next(); + SnecmaLine lowestConf2 = iteratorConf2.next(); + iteratorConf1.remove(); + iteratorConf2.remove(); + boolean keepOn = true; + // Now iterate from 'lowest' member of either conf to 'highest' member of either conf + while (keepOn) { + int compare = STRUCTURAL_COMPARATOR.compare(lowestConf1, lowestConf2); + if (compare == 0) { + // Same structure on both stacks! + if (currentBucket == null) { + currentBucket = new R07Bucket(lowestConf1); // Start new bucket + } else { + // Packet already existing, does it have the same value? + if (currentBucket.compareTo(lowestConf1) != 0) { + similarBuckets.add(currentBucket); // different value detected, let's register the old bucket... + currentBucket = new R07Bucket(lowestConf1); // ...and start a new one + } + } + + // The current bucket has the correct ref value, we just need to add the new data pair in it + currentBucket.add(lowestConf1, lowestConf2); + if (iteratorConf1.hasNext() && iteratorConf2.hasNext()) { + // Prepare next run + lowestConf1 = iteratorConf1.next(); + lowestConf2 = iteratorConf2.next(); + iteratorConf1.remove(); + iteratorConf2.remove(); + } else { + keepOn = false; // End of the while + } + } else { + // Stream of similar-valued object has stopped. Time to register the bucket content (if any) + if (currentBucket != null && !currentBucket.isEmpty()) { + similarBuckets.add(currentBucket); + } + currentBucket = null; + if (compare < 0) { // Stack 1 is strictly lower than stack 2 + exclusiveConf1.add(lowestConf1); // Any encountered value is removed from the conf1 and added to the 'exclusive conf 1' list + if (iteratorConf1.hasNext()) { + // Prepare next run + lowestConf1 = iteratorConf1.next(); + iteratorConf1.remove(); + } else { + keepOn = false; // End of the while loop + } + } else { // Stack 2 is strictly lower than stack 1 + exclusiveConf2.add(lowestConf2); // Any encountered value is removed from the conf2 and added to the 'exclusive conf 2' list + if (iteratorConf2.hasNext()) { + // Prepare next run + lowestConf2 = iteratorConf2.next(); + iteratorConf2.remove(); + } else { + keepOn = false; // End of the while loop + } + } + } + } + // Cleanup: active bucket may need to be added to the list if not empty + if (currentBucket != null && !currentBucket.isEmpty()) { + similarBuckets.add(currentBucket); + } + // Cleanup: Any remaining item between index and the end of its stack is exclusive to that stack + while (!conf1.isEmpty()) { + exclusiveConf1.add(conf1.remove(0)); + } + while (!conf2.isEmpty()) { + exclusiveConf2.add(conf2.remove(0)); + } + return similarBuckets; + } + + /** + * Holds twoLines of either configuration, which are the same, but have a content difference between them. + */ + @AllArgsConstructor + @Getter + public static class Diff { + + private final SnecmaLine first; + private final SnecmaLine second; + + @Override + public String toString() { + return "Diff{" + first.toString() + " != " + second.toString() + "}"; + } + } + + /** + * 'Bucket' class to store 'similar' (According to the BOM_COMPARATOR) objects from both configurations.
    + * Objects that are 'identical' according to the CONTENT_COMPARATOR can then be identified and removed. + */ + @AllArgsConstructor + @Getter + private class R07Bucket { + + /** + * Reference line. Defines the Structure signature of this bucket uniquely. + */ + private final SnecmaLine ref; + /** + * Contains all the SnecmaLine from conf1 that have the same Structure as the REF. + */ + private final List> first = new ArrayList<>(); + /** + * Contains all the SnecmaLine from conf2 that have the same Structure as the REF. + */ + private final List> second = new ArrayList<>(); + + /** + * Compares this bucket's ref to the line. + * + * @param line the line + * @return the result + */ + public int compareTo(final SnecmaLine line) { + return ref.compareTo(line); + } + + /** + * Bucket empty? + * + * @return true if it is empty + */ + public boolean isEmpty() { + return first.isEmpty() && second.isEmpty(); + } + + /** + * Adds a pair to the bucket. Added objects MUST be 'similar' to the bucket's content. + * + * @param conf1 the object from conf1 + * @param conf2 the object from conf2 + */ + public void add(final SnecmaLine conf1, final SnecmaLine conf2) { + first.add(conf1); + second.add(conf2); + } + + /** + * This method: + *
      + *
    1. Removes 'identical' (same content) pairs found in both configurations.
    2. + *
    3. Bundles 'similar' (same structure) but not 'identical' objects from either confs together
    4. + *
    5. Remaining 'surplus' objects from a conf (that therefore cannot be appaired to an object from the other conf) are sent to an 'exclusive' list.
    6. + *
    + */ + void filterSimilarContent() { + removeIdenticalPairs(); + // All exact pairs from this bucket have been found and matched together (they will not show up in the report + bundleSimilarPairs(); + // Any remaining item in the larger list of the two will be shown as an exclusive member of its conf + exclusiveConf1.addAll(first); + exclusiveConf2.addAll(second); + } + + /** + * Finds and removes all identical pairs from this bucket (they will not show up in the report). + */ + private void removeIdenticalPairs() { + Iterator> conf1Iterator = first.iterator(); + while (conf1Iterator.hasNext()) { + SnecmaLine line1 = conf1Iterator.next(); + Iterator> conf2Iterator = second.iterator(); + while (conf2Iterator.hasNext()) { + SnecmaLine line2 = conf2Iterator.next(); + if (CONTENT_COMPARATOR.compare(line1, line2) == 0) { // Exact same content detected, from two lines in the same bucket so same structure) + cloneNum++; + // This pair will never make it to the report + conf1Iterator.remove(); + conf2Iterator.remove(); + break; + } + } + } + } + + /** + * Bundles together any two line from either configuration.
    + * At this point these lines all have a difference otherwise they would have been removed by the previous step {@link R07Bucket#removeIdenticalPairs()}.
    + * In priority, lines from either configuration that have the same Part number will be paired. This is not required, but is nice. + */ + private void bundleSimilarPairs() { + // First pair lines that have the same Part ID. If several can be found, the 1st one is chosen (arbitrary) + Iterator> conf1Iterator = first.iterator(); + while (conf1Iterator.hasNext()) { + SnecmaLine line1 = conf1Iterator.next(); + Iterator> conf2Iterator = second.iterator(); + while (conf2Iterator.hasNext()) { + SnecmaLine line2 = conf2Iterator.next(); + if (line1.getIDComponent().compareTo(line2.getIDComponent()) == 0) { + // This pair will be shown as a content diff between the two configurations + propDiff.add(new Diff(line1, line2)); + conf1Iterator.remove(); + conf2Iterator.remove(); + break; // Find another couple + } + } + } + + // Any remaining item in the bucket will be paired arbitrarily until one conf is emptied + conf1Iterator = first.iterator(); + Iterator> conf2Iterator = second.iterator(); + while (conf1Iterator.hasNext() && conf2Iterator.hasNext()) { + SnecmaLine line1 = conf1Iterator.next(); + SnecmaLine line2 = conf2Iterator.next(); + // This pair will be shown as a content diff between the two configurations + propDiff.add(new Diff(line1, line2)); + conf1Iterator.remove(); + conf2Iterator.remove(); + } + } + + @Override + public String toString() { + return "Pack<" + first.toString() + " vs " + second.toString() + ">"; + } + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/ContentComparator.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/ContentComparator.java new file mode 100644 index 0000000..12c8462 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/ContentComparator.java @@ -0,0 +1,25 @@ +package com.capgemini.reports.definition.r07report.data.filter; + +import com.capgemini.reports.bomlineholder.flattener.line.SnecmaLine; +import com.capgemini.reports.definition.r07report.data.TransformerR07; +import com.capgemini.reports.definition.r07report.data.extractor.lines.ComparableLine; +import lombok.extern.slf4j.Slf4j; + +import java.util.Comparator; + +/** + * Provides capabilities for comparing full-depth content between two {@link SnecmaLine}s. + */ +@Slf4j +public class ContentComparator implements Comparator> { + @Override + public int compare(final SnecmaLine line1, final SnecmaLine line2) { + if (line1 instanceof ComparableLine && line2 instanceof ComparableLine) { + return ((ComparableLine) line1).compareLineContent((ComparableLine) line2); + } else { + log.warn("A SnecmaLine of unsupported Type was found in the R07 during comparison: {} vs. {}", line1.getClass().getName(), line2 + .getClass().getName()); + return 1; + } + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/StructuralComparator.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/StructuralComparator.java new file mode 100644 index 0000000..8c8e78a --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/StructuralComparator.java @@ -0,0 +1,31 @@ +package com.capgemini.reports.definition.r07report.data.filter; + +import com.capgemini.reports.bomlineholder.flattener.line.SnecmaLine; +import com.capgemini.reports.definition.r07report.data.TransformerR07; +import com.capgemini.reports.definition.r07report.data.filter.identifiers.ReceptorIdExtractor; +import com.capgemini.reports.definition.r07report.data.filter.identifiers.RepereIdExtractor; + +import java.util.Comparator; + +/** + * Provides capabilities for comparing structure (receptor ID/repere NAME) between two {@link SnecmaLine}s. + */ +public class StructuralComparator implements Comparator> { + + private static final TransformerR07 RECEPTOR_ID_EXTRACTOR = new ReceptorIdExtractor(); + private static final TransformerR07 REPERE_ID_EXTRACTOR = new RepereIdExtractor(); + + @Override + public int compare(final SnecmaLine line1, final SnecmaLine line2) { + String receptorId1 = line1.transform(RECEPTOR_ID_EXTRACTOR); + String receptorId2 = line2.transform(RECEPTOR_ID_EXTRACTOR); + int diff = receptorId1.compareTo(receptorId2); + if (diff != 0) { + return diff; // Structural difference: Receptor mismatch + } + String repereId1 = line1.transform(REPERE_ID_EXTRACTOR); + String repereId2 = line2.transform(REPERE_ID_EXTRACTOR); + diff = repereId1.compareTo(repereId2); + return diff; // last possible structural difference: Repere mismatch + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/AbstractBomLineComparator.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/AbstractBomLineComparator.java new file mode 100644 index 0000000..70f7176 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/AbstractBomLineComparator.java @@ -0,0 +1,73 @@ +package com.capgemini.reports.definition.r07report.data.filter.comparators; + +import com.capgemini.framework.common.StringHelper; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.definition.r07report.data.filter.comparators.generics.GenericBLComparator; +import com.capgemini.reports.definition.r07report.data.filter.comparators.part.PartBLComparator; +import com.capgemini.reports.exceptions.NotSupportedException; +import com.capgemini.reports.snecmaobjects.ISnecmaObject; + +import java.io.Serializable; +import java.util.Comparator; + +/** + * Helper class to comapre two {@link BOMLineHolder}s content. + */ +public abstract class AbstractBomLineComparator implements Comparator, Serializable { + private static final long serialVersionUID = 3764547367272622769L; + + private static int mySafeCmp(final String str1, final String str2) { + if (str1 == null) { + return str2 == null ? 0 : 1; + } else if (str2 == null) { + return -1; + } else { + return str1.compareTo(str2); + } + } + + /** + * Compares two Receptors together. Only their item ID and Name are compared. + * + * @param thisBL this object + * @param otherBL an other object + * @return the diff + */ + public static int compareReceptors(final BOMLineHolder thisBL, final BOMLineHolder otherBL) { + ISnecmaObject thisReceptor = thisBL.getSnecmaObject(); + ISnecmaObject otherReceptor = otherBL.getSnecmaObject(); + return AbstractItemComparator.compareReceptors(thisReceptor, otherReceptor); + } + + /** + * Compares two components's contents. The components can be any Part or any Generic. + * + * @param thisBL this object + * @param otherBL an other object + * @return the diff + * @throws NotSupportedException if the objects are of the wrong type + */ + public static int compareComponents(final BOMLineHolder thisBL, final BOMLineHolder otherBL) throws NotSupportedException { + ISnecmaObject thisComponent = thisBL.getSnecmaObject(); + ISnecmaObject otherComponent = otherBL.getSnecmaObject(); + String thisType = thisComponent.getType(); + String otherType = otherComponent.getType(); + int cmp = thisType.compareTo(otherType); + if (cmp != 0) { + return cmp; + } + if (thisComponent.isGeneric()) { + return GenericBLComparator.compareGenerics(thisBL, otherBL); + } + if (thisComponent.isPart()) { + return PartBLComparator.compareParts(thisBL, otherBL); + } else { + throw new NotSupportedException( + StringHelper.concat("Unsupported Component type: ", thisComponent.getItemId(), " of type ", thisType).toString()); + } + } + + protected int safeCmp(final String str1, final String str2) { + return mySafeCmp(str1, str2); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/AbstractItemComparator.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/AbstractItemComparator.java new file mode 100644 index 0000000..e804d29 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/AbstractItemComparator.java @@ -0,0 +1,80 @@ +package com.capgemini.reports.definition.r07report.data.filter.comparators; + +import com.capgemini.framework.common.StringHelper; +import com.capgemini.reports.definition.r07report.data.filter.comparators.generics.GenericComparator; +import com.capgemini.reports.definition.r07report.data.filter.comparators.part.PartComparator; +import com.capgemini.reports.exceptions.NotSupportedException; +import com.capgemini.reports.snecmaobjects.ISnecmaObject; + +import java.io.Serializable; +import java.util.Comparator; + +/** + * Helper class to comapre two {@link ISnecmaObject}s content. + */ +public abstract class AbstractItemComparator implements Comparator, Serializable { + private static final long serialVersionUID = -8787518342193550661L; + + private static int mySafeCmp(final String str1, final String str2) { + if (str1 == null) { + return str2 == null ? 0 : 1; + } else if (str2 == null) { + return -1; + } else { + return str1.compareTo(str2); + } + } + + /** + * Compares two Receptors together. Only their item ID and Name are compared. + * + * @param thisObj this object + * @param otherObj an other object + * @return the diff + */ + static int compareReceptors(final ISnecmaObject thisObj, final ISnecmaObject otherObj) { + String thisType = thisObj.getType(); + String otherType = otherObj.getType(); + int cmp = thisType.compareTo(otherType); + if (cmp != 0) { + return cmp; + } + // Compare basic data + cmp = mySafeCmp(thisObj.getItemId(), otherObj.getItemId()); + if (cmp != 0) { + return cmp; + } + cmp = mySafeCmp(thisObj.getName(), otherObj.getName()); + return cmp; + } + + /** + * Compares two components's contents. The components can be any Part or any Generic. + * + * @param thisComponent this object + * @param otherComponent an other object + * @return the diff + * @throws NotSupportedException if objects are of the wrong type + */ + public static int compareComponents(final ISnecmaObject thisComponent, final ISnecmaObject otherComponent) throws NotSupportedException { + String thisType = thisComponent.getType(); + String otherType = otherComponent.getType(); + int cmp = thisType.compareTo(otherType); + if (cmp != 0) { + return cmp; + } + if (thisComponent.isGeneric()) { + return GenericComparator.compareGenerics(thisComponent, otherComponent); + } + if (thisComponent.isPart()) { + return PartComparator.compareParts(thisComponent, otherComponent); + } else { + throw new NotSupportedException( + StringHelper.concat("Unsupported Component type: ", thisComponent.getItemId(), " of type ", thisType).toString()); + } + } + + protected int safeCmp(final String str1, final String str2) { + return mySafeCmp(str1, str2); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/generics/GenericBLComparator.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/generics/GenericBLComparator.java new file mode 100644 index 0000000..66eb860 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/generics/GenericBLComparator.java @@ -0,0 +1,58 @@ +package com.capgemini.reports.definition.r07report.data.filter.comparators.generics; + +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.definition.r07report.data.filter.comparators.AbstractBomLineComparator; +import com.capgemini.reports.exceptions.NotSupportedException; + +/** + * Compares two Generics / Generics Assembs' {@link BOMLineHolder}s to each other. + */ +public class GenericBLComparator extends AbstractBomLineComparator { + private static final long serialVersionUID = -1959398094059231129L; + + /** + * Compares a two Generic/Generic Assemb contents. + * + * @param thisGen this object + * @param otherGen an other object + * @return the difference + * @throws NotSupportedException if either bomline does not hold a Generic / Generic Assemb + */ + public static int compareGenerics(final BOMLineHolder thisGen, final BOMLineHolder otherGen) throws NotSupportedException { + String thisType = thisGen.getSnecmaObject().getType(); + String otherType = otherGen.getSnecmaObject().getType(); + int cmp = thisType.compareTo(otherType); + if (cmp != 0) { + return cmp; + } + if (SnecmaObjectTypes.GENERIC_REVISION.equals(thisType) || SnecmaObjectTypes.GENERIC_ASSEMB_REVISION.equals(thisType)) { + return new GenericBLComparator().compare(thisGen, otherGen); + } else { + throw new NotSupportedException("Unsupported Generic type: " + thisGen.getSnecmaObject().getItemId() + " of type " + thisType); + } + } + + @Override + public int compare(final BOMLineHolder thisGenericBL, final BOMLineHolder otherGenericBL) { + // Compare BOM data + int cmp = safeCmp(thisGenericBL.getBomQty(), otherGenericBL.getBomQty()); + if (cmp == 0) { + cmp = safeCmp(thisGenericBL.getBomAlt(), otherGenericBL.getBomAlt()); + } + if (cmp == 0) { + cmp = safeCmp(thisGenericBL.getBomSb(), otherGenericBL.getBomSb()); + } + if (cmp == 0) { + cmp = safeCmp(thisGenericBL.getBomQtyCumul(), otherGenericBL.getBomQtyCumul()); + } + if (cmp == 0) { + cmp = safeCmp(thisGenericBL.getBomPanache(), otherGenericBL.getBomPanache()); + } + if (cmp == 0) { + // Compare Generic data + cmp = new GenericComparator().compare(thisGenericBL.getSnecmaObject(), otherGenericBL.getSnecmaObject()); + } + return cmp; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/generics/GenericComparator.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/generics/GenericComparator.java new file mode 100644 index 0000000..fe76287 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/generics/GenericComparator.java @@ -0,0 +1,55 @@ +package com.capgemini.reports.definition.r07report.data.filter.comparators.generics; + +import com.capgemini.framework.common.StringHelper; +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.capgemini.reports.definition.r07report.data.filter.comparators.AbstractItemComparator; +import com.capgemini.reports.exceptions.NotSupportedException; +import com.capgemini.reports.snecmaobjects.ISnecmaObject; +import com.capgemini.reports.snecmaobjects.generic.AbstractGenericRevision; + +/** + * Compares two Generic's contents. + */ +public class GenericComparator extends AbstractItemComparator { + private static final long serialVersionUID = -1959398094059231129L; + + /** + * Compares two Generic's contents. + * + * @param thisGen this object + * @param otherGen an other object + * @return the diff + * @throws NotSupportedException if objects are not Generics + */ + public static int compareGenerics(final ISnecmaObject thisGen, final ISnecmaObject otherGen) throws NotSupportedException { + String thisType = thisGen.getType(); + String otherType = otherGen.getType(); + int cmp = thisType.compareTo(otherType); + if (cmp != 0) { + return cmp; + } + if (SnecmaObjectTypes.GENERIC_REVISION.equals(thisType) || SnecmaObjectTypes.GENERIC_ASSEMB_REVISION.equals(thisType)) { + return new GenericComparator().compare(thisGen, otherGen); + } else { + throw new NotSupportedException(StringHelper.concat("Unsupported Generic type: ", thisGen.getItemId(), " of type ", thisType).toString()); + } + } + + @Override + public int compare(final ISnecmaObject thisItem, final ISnecmaObject otherItem) { + // Compare Generic data + AbstractGenericRevision thisGeneric = (AbstractGenericRevision) thisItem; + AbstractGenericRevision otherGeneric = (AbstractGenericRevision) otherItem; + int cmp = thisGeneric.getItemId().compareTo(otherGeneric.getItemId()); + if (cmp == 0) { + cmp = safeCmp(thisGeneric.getName(), otherGeneric.getName()); + if (cmp == 0) { + cmp = safeCmp(thisGeneric.getDesignationEN(), otherGeneric.getDesignationEN()); + if (cmp == 0) { + cmp = safeCmp(thisGeneric.getResponsableConception(), otherGeneric.getResponsableConception()); + } + } + } + return cmp; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/AlternateBLComparator.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/AlternateBLComparator.java new file mode 100644 index 0000000..96ab087 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/AlternateBLComparator.java @@ -0,0 +1,21 @@ +package com.capgemini.reports.definition.r07report.data.filter.comparators.part; + +import com.capgemini.reports.bomlineholder.BOMLineHolder; + +/** + * Compares Alternates' {@link BOMLineHolder}s. + */ +public class AlternateBLComparator extends PartBLComparator { + + private static final long serialVersionUID = 4589727916093844161L; + + @Override + public int compare(final BOMLineHolder thisPartBL, final BOMLineHolder otherPartBL) { + int cmp = super.compare(thisPartBL, otherPartBL); + if (cmp != 0) { + return cmp; + } + return new AlternateComparator().compare(thisPartBL.getSnecmaObject(), otherPartBL.getSnecmaObject()); + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/AlternateComparator.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/AlternateComparator.java new file mode 100644 index 0000000..74dfe70 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/AlternateComparator.java @@ -0,0 +1,28 @@ +package com.capgemini.reports.definition.r07report.data.filter.comparators.part; + +import com.capgemini.reports.snecmaobjects.ISnecmaObject; +import com.capgemini.reports.snecmaobjects.part.AlternateRevision; + +/** + * Compares two {@link AlternateRevision}'s contents. + */ +public class AlternateComparator extends PartComparator { + private static final long serialVersionUID = 4589727916093844161L; + + @Override + public int compare(final ISnecmaObject thisPart, final ISnecmaObject otherPart) { + int cmp = super.compare(thisPart, otherPart); + if (cmp != 0) { + return cmp; + } + AlternateRevision thisAlt = (AlternateRevision) thisPart; + AlternateRevision otherAlt = (AlternateRevision) otherPart; + cmp = thisAlt.getTypeAlt1().compareTo(otherAlt.getTypeAlt1()); + if (cmp != 0) { + return cmp; + } + cmp = thisAlt.getTypeAlt2().compareTo(otherAlt.getTypeAlt2()); + return cmp; + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/DetBLComparator.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/DetBLComparator.java new file mode 100644 index 0000000..0f8bd1d --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/DetBLComparator.java @@ -0,0 +1,21 @@ +package com.capgemini.reports.definition.r07report.data.filter.comparators.part; + +import com.capgemini.reports.bomlineholder.BOMLineHolder; + +/** + * Compares DETs' {@link BOMLineHolder}s. + */ +public class DetBLComparator extends PartBLComparator { + + private static final long serialVersionUID = 7467086955431692767L; + + @Override + public int compare(final BOMLineHolder thisPartBL, final BOMLineHolder otherPartBL) { + int cmp = super.compare(thisPartBL, otherPartBL); + if (cmp != 0) { + return cmp; + } + return new DetComparator().compare(thisPartBL.getSnecmaObject(), otherPartBL.getSnecmaObject()); + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/DetComparator.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/DetComparator.java new file mode 100644 index 0000000..5a9669c --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/DetComparator.java @@ -0,0 +1,29 @@ +package com.capgemini.reports.definition.r07report.data.filter.comparators.part; + +import com.capgemini.reports.snecmaobjects.ISnecmaObject; +import com.capgemini.reports.snecmaobjects.part.DETRevision; + +/** + * Compares two {@link DETRevision}'s contents. + */ +public class DetComparator extends PartComparator { + + private static final long serialVersionUID = 3412387355420636670L; + + @Override + public int compare(final ISnecmaObject thisPart, final ISnecmaObject otherPart) { + int cmp = super.compare(thisPart, otherPart); + if (cmp != 0) { + return cmp; + } + DETRevision thisDET = (DETRevision) thisPart; + DETRevision otherDET = (DETRevision) otherPart; + cmp = thisDET.getTypeDet1().compareTo(otherDET.getTypeDet1()); + if (cmp != 0) { + return cmp; + } + cmp = thisDET.getTypeDet2().compareTo(otherDET.getTypeDet2()); + return cmp; + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/PartAeroBLComparator.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/PartAeroBLComparator.java new file mode 100644 index 0000000..89f9198 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/PartAeroBLComparator.java @@ -0,0 +1,21 @@ +package com.capgemini.reports.definition.r07report.data.filter.comparators.part; + +import com.capgemini.reports.bomlineholder.BOMLineHolder; + +/** + * Compares two PartAeros' {@link BOMLineHolder}. + */ +public class PartAeroBLComparator extends PartBLComparator { + private static final long serialVersionUID = 4353837710227367827L; + + @Override + public int compare(final BOMLineHolder thisPartBL, final BOMLineHolder otherPartBL) { + int cmp = super.compare(thisPartBL, otherPartBL); + if (cmp != 0) { + return cmp; + } + return new PartAeroComparator().compare(thisPartBL.getSnecmaObject(), otherPartBL.getSnecmaObject()); + + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/PartAeroComparator.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/PartAeroComparator.java new file mode 100644 index 0000000..06fec66 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/PartAeroComparator.java @@ -0,0 +1,28 @@ +package com.capgemini.reports.definition.r07report.data.filter.comparators.part; + +import com.capgemini.reports.snecmaobjects.ISnecmaObject; +import com.capgemini.reports.snecmaobjects.part.PartAeroRevision; + +/** + * Compares two {@link PartAeroRevision}'s contents. + */ +public class PartAeroComparator extends PartComparator { + private static final long serialVersionUID = 5813446144969040585L; + + @Override + public int compare(final ISnecmaObject thisPart, final ISnecmaObject otherPart) { + int cmp = super.compare(thisPart, otherPart); + if (cmp == 0) { + PartAeroRevision thisPartAero = (PartAeroRevision) thisPart; + PartAeroRevision otherPartAero = (PartAeroRevision) otherPart; + cmp = thisPartAero.getTypeAero1().compareTo(otherPartAero.getTypeAero1()); + if (cmp == 0) { + cmp = thisPartAero.getTypeAero2().compareTo(otherPartAero.getTypeAero2()); + if (cmp == 0) { + cmp = thisPartAero.getTypeAero3().compareTo(otherPartAero.getTypeAero3()); + } + } + } + return cmp; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/PartAssembBLComparator.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/PartAssembBLComparator.java new file mode 100644 index 0000000..520f29b --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/PartAssembBLComparator.java @@ -0,0 +1,20 @@ +package com.capgemini.reports.definition.r07report.data.filter.comparators.part; + +import com.capgemini.reports.bomlineholder.BOMLineHolder; + +/** + * Compares two PartAssembs' {@link BOMLineHolder}s. + */ +public class PartAssembBLComparator extends PartBLComparator { + private static final long serialVersionUID = -8453498458441935461L; + + @Override + public int compare(final BOMLineHolder thisPartBL, final BOMLineHolder otherPartBL) { + int cmp = super.compare(thisPartBL, otherPartBL); + if (cmp != 0) { + return cmp; + } + return new PartAssembComparator().compare(thisPartBL.getSnecmaObject(), otherPartBL.getSnecmaObject()); + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/PartAssembComparator.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/PartAssembComparator.java new file mode 100644 index 0000000..3df81b4 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/PartAssembComparator.java @@ -0,0 +1,28 @@ +package com.capgemini.reports.definition.r07report.data.filter.comparators.part; + +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.snecmaobjects.ISnecmaObject; +import com.capgemini.reports.snecmaobjects.part.PartAssembRevision; + +/** + * Compares two {@link PartAssembRevision}'s {@link BOMLineHolder}s. + */ +public class PartAssembComparator extends PartComparator { + private static final long serialVersionUID = 3276642480323176366L; + + @Override + public int compare(final ISnecmaObject thisParL, final ISnecmaObject otherPart) { + int cmp = super.compare(thisParL, otherPart); + if (cmp != 0) { + return cmp; + } + PartAssembRevision thisPartAssemb = (PartAssembRevision) thisParL; + PartAssembRevision otherPartAssemb = (PartAssembRevision) otherPart; + cmp = thisPartAssemb.getTypePartMontage1().compareTo(otherPartAssemb.getTypePartMontage1()); + if (cmp != 0) { + return cmp; + } + cmp = thisPartAssemb.getTypePartMontage2().compareTo(otherPartAssemb.getTypePartMontage2()); + return cmp; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/PartBLComparator.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/PartBLComparator.java new file mode 100644 index 0000000..ff83262 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/PartBLComparator.java @@ -0,0 +1,74 @@ +package com.capgemini.reports.definition.r07report.data.filter.comparators.part; + +import com.capgemini.framework.common.StringHelper; +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.definition.r07report.data.filter.comparators.AbstractBomLineComparator; +import com.capgemini.reports.exceptions.NotSupportedException; + +/** + * Compares two Parts' {@link BOMLineHolder}s, for any type of Part. + */ +public class PartBLComparator extends AbstractBomLineComparator { + private static final long serialVersionUID = 1847560066180416682L; + + /** + * Compare two part bomlines together. + * + * @param part this object + * @param other an other object + * @return the diff + * @throws NotSupportedException if objects are of the wrong type + */ + public static int compareParts(final BOMLineHolder part, final BOMLineHolder other) throws NotSupportedException { + String thisType = part.getSnecmaObject().getType(); + String otherType = other.getSnecmaObject().getType(); + int cmp = thisType.compareTo(otherType); + if (cmp != 0) { + return cmp; + } + // Same types + if (SnecmaObjectTypes.ALTERNATE_REVISION.equals(thisType)) { + cmp = new AlternateBLComparator().compare(part, other); + } else if (SnecmaObjectTypes.DET_REVISION.equals(thisType)) { + cmp = new DetBLComparator().compare(part, other); + } else if (SnecmaObjectTypes.PART_AERO_REVISION.equals(thisType)) { + cmp = new PartAeroBLComparator().compare(part, other); + } else if (SnecmaObjectTypes.PART_NO_AERO_REVISION.equals(thisType)) { + cmp = new PartNoAeroBLComparator().compare(part, other); + } else if (SnecmaObjectTypes.PART_ASSEMB_REVISION.equals(thisType)) { + cmp = new PartAssembBLComparator().compare(part, other); + } else if (SnecmaObjectTypes.PART_MAT_REVISION.equals(thisType)) { + cmp = new PartMatBLComparator().compare(part, other); + } else if (SnecmaObjectTypes.STANDARD_REVISION.equals(thisType)) { + cmp = new StandardBLComparator().compare(part, other); + } else { + throw new NotSupportedException( + StringHelper.concat("Unsupported Part type: ", part.getSnecmaObject().getItemId(), " of type ", thisType).toString()); + } + return cmp; + } + + @Override + public int compare(final BOMLineHolder thisPartBL, final BOMLineHolder otherPartBL) { + // Compare BOM data + int cmp = safeCmp(thisPartBL.getBomQty(), otherPartBL.getBomQty()); + if (cmp == 0) { + cmp = safeCmp(thisPartBL.getBomAlt(), otherPartBL.getBomAlt()); + } + if (cmp == 0) { + cmp = safeCmp(thisPartBL.getBomSb(), otherPartBL.getBomSb()); + } + if (cmp == 0) { + cmp = safeCmp(thisPartBL.getBomQtyCumul(), otherPartBL.getBomQtyCumul()); + } + if (cmp == 0) { + cmp = safeCmp(thisPartBL.getBomPanache(), otherPartBL.getBomPanache()); + } + if (cmp == 0) { + return new PartComparator().compare(thisPartBL.getSnecmaObject(), otherPartBL.getSnecmaObject()); + } + return cmp; + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/PartComparator.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/PartComparator.java new file mode 100644 index 0000000..b0ff0aa --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/PartComparator.java @@ -0,0 +1,89 @@ +package com.capgemini.reports.definition.r07report.data.filter.comparators.part; + +import com.capgemini.framework.common.StringHelper; +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.definition.r07report.data.filter.comparators.AbstractItemComparator; +import com.capgemini.reports.exceptions.NotSupportedException; +import com.capgemini.reports.snecmaobjects.ISnecmaObject; +import com.capgemini.reports.snecmaobjects.part.AbstractPart; + +/** + * Compares two {@link AbstractPart}'s {@link BOMLineHolder}s. + */ +public class PartComparator extends AbstractItemComparator { + private static final long serialVersionUID = 8767701166124425908L; + + /** + * Compares two Part's contents. + * + * @param part this object + * @param other an other object + * @return the diff + * @throws NotSupportedException when one of the input is not a Part + */ + public static int compareParts(final ISnecmaObject part, final ISnecmaObject other) throws NotSupportedException { + String thisType = part.getType(); + String otherType = other.getType(); + int cmp = thisType.compareTo(otherType); + if (cmp == 0) { + if (SnecmaObjectTypes.ALTERNATE_REVISION.equals(thisType)) { + cmp = new AlternateComparator().compare(part, other); + } else if (SnecmaObjectTypes.DET_REVISION.equals(thisType)) { + cmp = new DetComparator().compare(part, other); + } else if (SnecmaObjectTypes.PART_AERO_REVISION.equals(thisType)) { + cmp = new PartAeroComparator().compare(part, other); + } else if (SnecmaObjectTypes.PART_NO_AERO_REVISION.equals(thisType)) { + cmp = new PartNoAeroComparator().compare(part, other); + } else if (SnecmaObjectTypes.PART_ASSEMB_REVISION.equals(thisType)) { + cmp = new PartAssembComparator().compare(part, other); + } else if (SnecmaObjectTypes.PART_MAT_REVISION.equals(thisType)) { + cmp = new PartMatComparator().compare(part, other); + } else if (SnecmaObjectTypes.STANDARD_REVISION.equals(thisType)) { + cmp = new StandardComparator().compare(part, other); + } else { + throw new NotSupportedException(StringHelper.concat("Unsupported Part type: ", part.getItemId(), " of type ", thisType).toString()); + } + } + return cmp; + } + + @Override + public int compare(final ISnecmaObject thisObj, final ISnecmaObject otherObj) { + AbstractPart thisPart = (AbstractPart) thisObj; + AbstractPart otherPart = (AbstractPart) otherObj; + // Compare part data + int cmp = thisPart.getItemId().compareTo(otherPart.getItemId()); + if (cmp == 0) { + cmp = safeCmp(thisPart.getName(), otherPart.getName()); + } + if (cmp == 0) { + cmp = safeCmp(thisPart.getDesignationEN(), otherPart.getDesignationEN()); + } + if (cmp == 0) { + cmp = safeCmp(thisPart.getRefCompleteConcepteur(), otherPart.getRefCompleteConcepteur()); + } + if (cmp == 0) { + cmp = safeCmp(thisPart.getRefTransposeeSnecma(), otherPart.getRefTransposeeSnecma()); + } + if (cmp == 0) { + cmp = safeCmp(thisPart.getResponsableConception(), otherPart.getResponsableConception()); + } + if (cmp == 0) { + cmp = safeCmp(thisPart.getClassement(), otherPart.getClassement()); + } + if (cmp == 0) { + cmp = safeCmp(thisPart.getSuiviUtilisation(), otherPart.getSuiviUtilisation()); + } + if (cmp == 0) { + cmp = safeCmp(thisPart.getSuiviDureeVie(), otherPart.getSuiviDureeVie()); + } + if (cmp == 0) { + cmp = Double.compare(thisPart.getMass(), otherPart.getMass()); + } + if (cmp == 0) { + cmp = safeCmp(thisPart.getMassUnit(), otherPart.getMassUnit()); + } + return cmp; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/PartMatBLComparator.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/PartMatBLComparator.java new file mode 100644 index 0000000..016c0d4 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/PartMatBLComparator.java @@ -0,0 +1,20 @@ +package com.capgemini.reports.definition.r07report.data.filter.comparators.part; + +import com.capgemini.reports.bomlineholder.BOMLineHolder; + +/** + * Compares two PartMats' {@link BOMLineHolder}s. + */ +public class PartMatBLComparator extends PartBLComparator { + private static final long serialVersionUID = -2934813561955929208L; + + @Override + public int compare(final BOMLineHolder thisPartBL, final BOMLineHolder otherPartBL) { + int cmp = super.compare(thisPartBL, otherPartBL); + if (cmp != 0) { + return cmp; + } + return new PartMatComparator().compare(thisPartBL.getSnecmaObject(), otherPartBL.getSnecmaObject()); + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/PartMatComparator.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/PartMatComparator.java new file mode 100644 index 0000000..f615e32 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/PartMatComparator.java @@ -0,0 +1,25 @@ +package com.capgemini.reports.definition.r07report.data.filter.comparators.part; + +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.snecmaobjects.ISnecmaObject; +import com.capgemini.reports.snecmaobjects.part.PartMatRevision; + +/** + * Compares two {@link PartMatRevision}'s {@link BOMLineHolder}s. + */ +public class PartMatComparator extends PartComparator { + private static final long serialVersionUID = 4148977376229148277L; + + @Override + public int compare(final ISnecmaObject thisPart, final ISnecmaObject otherPart) { + int cmp = super.compare(thisPart, otherPart); + if (cmp != 0) { + return cmp; + } + PartMatRevision thisPartMat = (PartMatRevision) thisPart; + PartMatRevision otherPartMat = (PartMatRevision) otherPart; + cmp = thisPartMat.getClassementMat().compareTo(otherPartMat.getClassementMat()); + return cmp; + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/PartNoAeroBLComparator.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/PartNoAeroBLComparator.java new file mode 100644 index 0000000..3594143 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/PartNoAeroBLComparator.java @@ -0,0 +1,20 @@ +package com.capgemini.reports.definition.r07report.data.filter.comparators.part; + +import com.capgemini.reports.bomlineholder.BOMLineHolder; + +/** + * Compares two PartNoAeros' {@link BOMLineHolder}s. + */ +public class PartNoAeroBLComparator extends PartBLComparator { + private static final long serialVersionUID = 5954871414512808855L; + + @Override + public int compare(final BOMLineHolder thisPartBL, final BOMLineHolder otherPartBL) { + int cmp = super.compare(thisPartBL, otherPartBL); + if (cmp != 0) { + return cmp; + } + return new PartNoAeroComparator().compare(thisPartBL.getSnecmaObject(), otherPartBL.getSnecmaObject()); + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/PartNoAeroComparator.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/PartNoAeroComparator.java new file mode 100644 index 0000000..da9a475 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/PartNoAeroComparator.java @@ -0,0 +1,24 @@ +package com.capgemini.reports.definition.r07report.data.filter.comparators.part; + +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.snecmaobjects.ISnecmaObject; +import com.capgemini.reports.snecmaobjects.part.PartNoAeroRevision; + +/** + * Compares two {@link PartNoAeroRevision}'s {@link BOMLineHolder}s. + */ +public class PartNoAeroComparator extends PartComparator { + private static final long serialVersionUID = -1728487703112167469L; + + @Override + public int compare(final ISnecmaObject thisPart, final ISnecmaObject otherPart) { + int cmp = super.compare(thisPart, otherPart); + if (cmp != 0) { + return cmp; + } + PartNoAeroRevision thisPartNoAero = (PartNoAeroRevision) thisPart; + PartNoAeroRevision otherPartNoAero = (PartNoAeroRevision) otherPart; + cmp = thisPartNoAero.getTypeNoAero().compareTo(otherPartNoAero.getTypeNoAero()); + return cmp; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/StandardBLComparator.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/StandardBLComparator.java new file mode 100644 index 0000000..5daae9a --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/StandardBLComparator.java @@ -0,0 +1,20 @@ +package com.capgemini.reports.definition.r07report.data.filter.comparators.part; + +import com.capgemini.reports.bomlineholder.BOMLineHolder; + +/** + * Compares two Standards' {@link BOMLineHolder}s. + */ +public class StandardBLComparator extends PartBLComparator { + private static final long serialVersionUID = 7862979771467078306L; + + @Override + public int compare(final BOMLineHolder thisPartBL, final BOMLineHolder otherPartBL) { + int cmp = super.compare(thisPartBL, otherPartBL); + if (cmp != 0) { + return cmp; + } + return new StandardComparator().compare(thisPartBL.getSnecmaObject(), otherPartBL.getSnecmaObject()); + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/StandardComparator.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/StandardComparator.java new file mode 100644 index 0000000..6162ed4 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/part/StandardComparator.java @@ -0,0 +1,24 @@ +package com.capgemini.reports.definition.r07report.data.filter.comparators.part; + +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.snecmaobjects.ISnecmaObject; +import com.capgemini.reports.snecmaobjects.part.StandardRevision; + +/** + * Compares two {@link StandardRevision}'s {@link BOMLineHolder}s. + */ +public class StandardComparator extends PartComparator { + private static final long serialVersionUID = -3007235542630939436L; + + @Override + public int compare(final ISnecmaObject thisPart, final ISnecmaObject otherPart) { + int cmp = super.compare(thisPart, otherPart); + if (cmp != 0) { + return cmp; + } + StandardRevision thisStandard = (StandardRevision) thisPart; + StandardRevision otherStandard = (StandardRevision) otherPart; + cmp = thisStandard.getTypeStandard().compareTo(otherStandard.getTypeStandard()); + return cmp; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/rf/RfComparator.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/rf/RfComparator.java new file mode 100644 index 0000000..4cf3f46 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/rf/RfComparator.java @@ -0,0 +1,49 @@ +package com.capgemini.reports.definition.r07report.data.filter.comparators.rf; + +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.bomlineholder.BOMLineHolderHelper; +import com.capgemini.reports.definition.r07report.data.filter.comparators.AbstractBomLineComparator; +import com.capgemini.reports.exceptions.InvalidInputException; +import com.capgemini.reports.exceptions.NotFoundException; +import com.capgemini.reports.exceptions.NotSupportedException; +import com.capgemini.reports.snecmaobjects.admin.RFAdminRevision; +import lombok.extern.slf4j.Slf4j; + +/** + * Compares two RFs' {@link BOMLineHolder}s together. + */ +@Slf4j +public abstract class RfComparator extends AbstractBomLineComparator { + private static final long serialVersionUID = -1907326362935233365L; + + /** + * Compares two RFs of any subtype. + */ + public static int compareRf(final BOMLineHolder thisRf, final BOMLineHolder otherRf) throws NotSupportedException { + String thisType = thisRf.getSnecmaObject().getType(); + String otherType = otherRf.getSnecmaObject().getType(); + int cmp = thisType.compareTo(otherType); + if (cmp == 0) { + if (SnecmaObjectTypes.RF_GENERIC_REVISION.equals(thisType)) { + cmp = new RfGenericComparator().compare(thisRf, otherRf); + } else if (SnecmaObjectTypes.RF_PART_REVISION.equals(thisType)) { + cmp = new RfPartComparator().compare(thisRf, otherRf); + } else if (SnecmaObjectTypes.RF_PART_ASSEMB_REVISION.equals(thisType)) { + cmp = new RfPartAssembComparator().compare(thisRf, otherRf); + } else { + throw new NotSupportedException("Unsupported RF type: " + thisRf.getSnecmaObject().getItemId() + " of type " + thisType); + } + } + return cmp; + } + + RFAdminRevision findRfAdmin(final BOMLineHolder aRF) { + try { + return BOMLineHolderHelper.findRfAdmin(aRF); + } catch (NotFoundException | InvalidInputException nfe) { + log.warn("No RF Admin AP found below: " + aRF.getSnecmaObject().getName(), nfe); + return null; + } + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/rf/RfGenericComparator.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/rf/RfGenericComparator.java new file mode 100644 index 0000000..b0ada5d --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/rf/RfGenericComparator.java @@ -0,0 +1,37 @@ +package com.capgemini.reports.definition.r07report.data.filter.comparators.rf; + +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.snecmaobjects.admin.RFAdminRevision; +import lombok.extern.slf4j.Slf4j; + +/** + * Compares two RF Generics together. + */ +@Slf4j +public class RfGenericComparator extends RfComparator { + + private static final long serialVersionUID = 8420569609216039442L; + + RfGenericComparator() { + } + + @Override + public int compare(final BOMLineHolder thisRfBL, final BOMLineHolder otherRfBL) { + // Bowse children for RF Admin + RFAdminRevision thisRfAdmin = findRfAdmin(thisRfBL); + RFAdminRevision otherRfAdmin = findRfAdmin(otherRfBL); + if (thisRfAdmin == null || otherRfAdmin == null) { + if (thisRfAdmin == null && otherRfAdmin == null) { + log.warn("No RF Admin found below both compared RF Generics: " + thisRfBL.getSnecmaObject().getName() + " / " + + otherRfBL.getSnecmaObject().getName()); + // No difference, then! + return 0; + } else { + log.warn("No RF Admin found below one of the compared RF Generics: " + thisRfBL.getSnecmaObject().getName() + " / " + + otherRfBL.getSnecmaObject().getName()); + return 1; // Diff found + } + } + return safeCmp(thisRfAdmin.getResponsableRepere(), otherRfAdmin.getResponsableRepere()); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/rf/RfPartAssembComparator.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/rf/RfPartAssembComparator.java new file mode 100644 index 0000000..d719b20 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/rf/RfPartAssembComparator.java @@ -0,0 +1,68 @@ +package com.capgemini.reports.definition.r07report.data.filter.comparators.rf; + +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.bomlineholder.BOMLineHolderHelper; +import com.capgemini.reports.exceptions.InvalidInputException; +import com.capgemini.reports.exceptions.NotFoundException; +import com.capgemini.reports.snecmaobjects.admin.RFAdminARevision; +import com.capgemini.reports.snecmaobjects.rf.AbstractRF; +import lombok.extern.slf4j.Slf4j; + +/** + * Compares two RFPartAssembs together. + */ +@Slf4j +public class RfPartAssembComparator extends RfComparator { + + private static final long serialVersionUID = -9166209208947984853L; + + RfPartAssembComparator() { + } + + @Override + public int compare(final BOMLineHolder thisRfBL, final BOMLineHolder otherRfBL) { + // Compare part data + AbstractRF thisRf = (AbstractRF) thisRfBL.getSnecmaObject(); + AbstractRF otherRf = (AbstractRF) otherRfBL.getSnecmaObject(); + int cmp = thisRf.getName().compareTo(otherRf.getName()); + if (cmp != 0) { + return cmp; + } + + // Bowse children for RF Admin A + return compareRfAdminA(thisRfBL, otherRfBL); + } + + private int compareRfAdminA(final BOMLineHolder thisRfBL, final BOMLineHolder otherRfBL) { + // Bowse children for RF Admin A + RFAdminARevision thisRfAdminAP = getRfAdminA(thisRfBL); + RFAdminARevision otherRfAdminAP = getRfAdminA(otherRfBL); + + if (thisRfAdminAP == null || otherRfAdminAP == null) { + if (thisRfAdminAP == null && otherRfAdminAP == null) { + log.warn("No RF Admin AP found below both compared RF Parts: " + thisRfBL.getSnecmaObject().getName() + " / " + + otherRfBL.getSnecmaObject().getName()); + // No difference, then! + return 0; + } else { + log.warn("No RF Admin AP found below one of the compared RF Parts: " + thisRfBL.getSnecmaObject().getName() + " / " + + otherRfBL.getSnecmaObject().getName()); + return 1; // Diff found + } + } + int cmp = safeCmp(thisRfAdminAP.getSuiviMontage(), otherRfAdminAP.getSuiviMontage()); + if (cmp == 0) { + cmp = safeCmp(thisRfAdminAP.getResponsableRepere(), otherRfAdminAP.getResponsableRepere()); + } + return cmp; + } + + private RFAdminARevision getRfAdminA(final BOMLineHolder thisRfBL) { + try { + return BOMLineHolderHelper.findRfAdminA(thisRfBL); + } catch (NotFoundException | InvalidInputException nfe) { + log.warn("No RF Admin AP found below: " + thisRfBL.getSnecmaObject().getName(), nfe); + return null; + } + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/rf/RfPartComparator.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/rf/RfPartComparator.java new file mode 100644 index 0000000..3e38b03 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/comparators/rf/RfPartComparator.java @@ -0,0 +1,91 @@ +package com.capgemini.reports.definition.r07report.data.filter.comparators.rf; + +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.bomlineholder.BOMLineHolderHelper; +import com.capgemini.reports.exceptions.InvalidInputException; +import com.capgemini.reports.exceptions.NotFoundException; +import com.capgemini.reports.snecmaobjects.admin.RFAdminAPRevision; +import com.capgemini.reports.snecmaobjects.admin.RFAdminRevision; +import com.capgemini.reports.snecmaobjects.rf.AbstractRF; +import lombok.extern.slf4j.Slf4j; + +/** + * Comapres two RF Parts together. + */ +@Slf4j +public class RfPartComparator extends RfComparator { + private static final long serialVersionUID = -185746619920561652L; + + RfPartComparator() { + } + + @Override + public int compare(final BOMLineHolder thisRfBL, final BOMLineHolder otherRfBL) { + // Compare part data + AbstractRF thisRf = (AbstractRF) thisRfBL.getSnecmaObject(); + AbstractRF otherRf = (AbstractRF) otherRfBL.getSnecmaObject(); + int cmp = thisRf.getName().compareTo(otherRf.getName()); + if (cmp != 0) { + return cmp; + } + cmp = safeCmp(thisRf.getEquivalentSnsSin(), otherRf.getEquivalentSnsSin()); + if (cmp != 0) { + return cmp; + } + // Bowse children for RF Admin + cmp = compareRfAdmin(thisRfBL, otherRfBL); + if (cmp != 0) { + return cmp; + } + // Bowse children for RF Admin AP + cmp = compareRfAdminAP(thisRfBL, otherRfBL); + return cmp; + } + + private int compareRfAdmin(final BOMLineHolder thisRfBL, final BOMLineHolder otherRfBL) { + // Bowse children for RF Admin + RFAdminRevision thisRfAdmin = findRfAdmin(thisRfBL); + RFAdminRevision otherRfAdmin = findRfAdmin(otherRfBL); + if (thisRfAdmin == null || otherRfAdmin == null) { + if (thisRfAdmin == null && otherRfAdmin == null) { + log.warn("No RF Admin found below both compared RF Generics: " + thisRfBL.getSnecmaObject().getName() + " / " + + otherRfBL.getSnecmaObject().getName()); + // No difference, then! + return 0; + } else { + log.warn("No RF Admin found below one of the compared RF Generics: " + thisRfBL.getSnecmaObject().getName() + " / " + + otherRfBL.getSnecmaObject().getName()); + return 1; // Diff found + } + } + return safeCmp(thisRfAdmin.getResponsableRepere(), otherRfAdmin.getResponsableRepere()); + } + + private int compareRfAdminAP(final BOMLineHolder thisRfBL, final BOMLineHolder otherRfBL) { + // Bowse children for RF Admin + RFAdminAPRevision thisRfAdminAP = findRfAdminAP(thisRfBL); + RFAdminAPRevision otherRfAdminAP = findRfAdminAP(otherRfBL); + + if (thisRfAdminAP == null || otherRfAdminAP == null) { + if (thisRfAdminAP == null && otherRfAdminAP == null) { + log.warn("No RF Admin AP found below both compared RF Parts: " + thisRfBL.getSnecmaObject().getName() + " / " + + otherRfBL.getSnecmaObject().getName()); + return 0; + } else { + log.warn("No RF Admin AP found below one of the compared RF Parts: " + thisRfBL.getSnecmaObject().getName() + " / " + + otherRfBL.getSnecmaObject().getName()); + return 1; + } + } + return safeCmp(thisRfAdminAP.getSuiviMontage(), otherRfAdminAP.getSuiviMontage()); + } + + private RFAdminAPRevision findRfAdminAP(final BOMLineHolder aRF) { + try { + return BOMLineHolderHelper.findRfAdminAP(aRF); + } catch (NotFoundException | InvalidInputException nfe) { + log.warn("No RF Admin AP found below: " + aRF.getSnecmaObject().getName(), nfe); + return null; + } + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/identifiers/ReceptorIdExtractor.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/identifiers/ReceptorIdExtractor.java new file mode 100644 index 0000000..6a0119b --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/identifiers/ReceptorIdExtractor.java @@ -0,0 +1,35 @@ +package com.capgemini.reports.definition.r07report.data.filter.identifiers; + +import com.capgemini.reports.definition.r07report.data.TransformerR07; +import com.capgemini.reports.definition.r07report.data.extractor.lines.*; + +/** + * Extracts a receptor's identifier: its Id. + */ +public class ReceptorIdExtractor implements TransformerR07 { + + @Override + public String makeIdentifier(final R07Quad line) { + return line.getRecepteur().getItemId(); + } + + @Override + public String makeIdentifier(final R07PartRfPart line) { + return line.getPartReceptor().getItemId(); + } + + @Override + public String makeIdentifier(final R07ReceptorLine line) { + return line.getRecepteur().getItemId(); + } + + @Override + public String makeIdentifier(final R07ProductGeneric line) { + return line.getProductReceptor().getItemId(); + } + + @Override + public String makeIdentifier(final R07AltPart altPart) { + return altPart.getAltBL().getSnecmaObject().getItemId(); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/identifiers/RepereIdExtractor.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/identifiers/RepereIdExtractor.java new file mode 100644 index 0000000..cde514d --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/filter/identifiers/RepereIdExtractor.java @@ -0,0 +1,36 @@ +package com.capgemini.reports.definition.r07report.data.filter.identifiers; + +import com.capgemini.reports.definition.r07report.data.TransformerR07; +import com.capgemini.reports.definition.r07report.data.extractor.lines.*; + +/** + * Extracts a Repere's identifier: its NAME. + */ +public class RepereIdExtractor implements TransformerR07 { + + @Override + public String makeIdentifier(final R07Quad line) { + return line.getRepereComposant().getName(); + } + + @Override + public String makeIdentifier(final R07PartRfPart line) { + return line.getRfPartComponent().getName(); + } + + @Override + public String makeIdentifier(final R07ReceptorLine line) { + return line.getRepere().getName(); + } + + @Override + public String makeIdentifier(final R07ProductGeneric line) { + return line.getRfGenericComponent().getItemId(); + } + + @Override + public String makeIdentifier(final R07AltPart altPart) { + return ""; + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/sorter/R07DataSorter.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/sorter/R07DataSorter.java new file mode 100644 index 0000000..0a0c8f0 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/data/sorter/R07DataSorter.java @@ -0,0 +1,133 @@ +package com.capgemini.reports.definition.r07report.data.sorter; + +import com.capgemini.reports.bomlineholder.flattener.line.SnecmaLine; +import com.capgemini.reports.definition.r07report.data.TransformerR07; +import com.capgemini.reports.definition.r07report.data.filter.ConfigurationFilterR07; +import com.capgemini.reports.definition.r07report.data.filter.ConfigurationFilterR07.Diff; +import com.capgemini.reports.definition.r07report.printing.EnumMapDelta; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.*; + +/** + * Sorts the various differences spotted between the two configuration: puts the lines in the original nomenclature's order. + */ +public class R07DataSorter { + + private static final boolean CONF1 = true; + private static final boolean CONF2 = false; + private static final boolean EXCLU = true; + private static final boolean BOTH_CONF = false; + + /** + * Returns true when there is a diff between the two objects. + */ + private static > Boolean safeDiff(final T obj1, final T obj2) { + if (obj1 == null && obj2 == null) { + return false; + } + if (obj1 != null && obj2 != null) { + return obj1.compareTo(obj2) != 0; + } + return true; + } + + /** + * Main method of the class: sorts the filter's unique diff content back into the original nombenclature's order. + * + * @param filter the filter containging the diff data + * @return a collection of {@link ConfLine}s + */ + public List sort(final ConfigurationFilterR07 filter) { + List list = new ArrayList<>(); + for (SnecmaLine line : filter.getExclusiveConf1()) { + list.add(new ConfLine(line, line.getLineNumber(), CONF1, EXCLU, null)); + } + for (SnecmaLine line : filter.getExclusiveConf2()) { + list.add(new ConfLine(line, line.getLineNumber(), CONF2, EXCLU, null)); + } + for (Diff diff : filter.getPropDiff()) { + SnecmaLine conf1 = diff.getFirst(); + SnecmaLine conf2 = diff.getSecond(); + + // Create the line comparison map to know which cells to highlight in yellow + Map delta = new EnumMap<>(EnumMapDelta.class); + delta.put(EnumMapDelta.ALT_ECART, safeDiff(conf1.getALT(), conf2.getALT())); + delta.put(EnumMapDelta.ARTICLE_GESTION_ECART, safeDiff(conf1.getArticleGestion(), conf2.getArticleGestion())); + delta.put(EnumMapDelta.CLASSEMENT_ECART, safeDiff(conf1.getClassement(), conf2.getClassement())); + delta.put(EnumMapDelta.ID_RECEPTEUR_ECART, safeDiff(conf1.getIDReceptor(), conf2.getIDReceptor())); + delta.put(EnumMapDelta.LISTE_FOURNISSEUR_ECART, compareArray(conf1.getSuppliersList(), conf2.getSuppliersList())); + delta.put(EnumMapDelta.NOM_RECEPTEUR_ECART, safeDiff(conf1.getNameReceptor(), conf2.getNameReceptor())); + delta.put(EnumMapDelta.NOM_REFERENCE_ECART, safeDiff(conf1.getNameReference(), conf2.getNameReference())); + delta.put(EnumMapDelta.PANACHAGE_ECART, safeDiff(conf1.getPanachage(), conf2.getPanachage())); + delta.put(EnumMapDelta.QUANTITE_CUMULEE_ECART, safeDiff(conf1.getQuantiteCumulee(), conf2.getQuantiteCumulee())); + delta.put(EnumMapDelta.QUANTITE_ECART, safeDiff(conf1.getQuantite(), conf2.getQuantite())); + delta.put(EnumMapDelta.REF_FABRICANT_ECART, safeDiff(conf1.getIDComponent(), conf2.getIDComponent())); + delta.put(EnumMapDelta.REFERENCE_ASSOCIEE_ECART, safeDiff(conf1.getReferenceAssociated(), conf2.getReferenceAssociated())); + delta.put(EnumMapDelta.REFERENCE_CONCEPTEUR_ECART, safeDiff(conf1.getReferenceConceptor(), conf2.getReferenceConceptor())); + delta.put(EnumMapDelta.REFERENCE_TRANSPOSEE_ECART, safeDiff(conf1.getReferenceTransposed(), conf2.getReferenceTransposed())); + delta.put(EnumMapDelta.REPERE_FONCTIONNEL_ECART, safeDiff(conf1.getRepereName(), conf2.getRepereName())); + delta.put(EnumMapDelta.RESPONSABLE_REPERE_ECART, safeDiff(conf1.getResponsableRepere(), conf2.getResponsableRepere())); + delta.put(EnumMapDelta.RESPONSABLE_CONCEPTION_ECART, safeDiff(conf1.getResponsableConception(), conf2.getResponsableConception())); + delta.put(EnumMapDelta.SUIVI_BESOIN_ECART, safeDiff(conf1.getSB(), conf2.getSB())); + delta.put(EnumMapDelta.SUIVI_DUREE_VIE_ECART, safeDiff(conf1.getSuiviDureeVie(), conf2.getSuiviDureeVie())); + delta.put(EnumMapDelta.SUIVI_MONTAGE_ECART, safeDiff(conf1.getSuiviMontage(), conf2.getSuiviMontage())); + delta.put(EnumMapDelta.SUIVI_UTILISATION_ECART, safeDiff(conf1.getSuiviUtilisation(), conf2.getSuiviUtilisation())); + delta.put(EnumMapDelta.TYPE_REFERENCE_ECART, safeDiff(conf1.getTypeReference(), conf2.getTypeReference())); + + // Both have the same line number: they will appear side-by-side in the report! + int lineNumber = Math.min(conf1.getLineNumber(), conf2.getLineNumber()); + list.add(new ConfLine(conf1, lineNumber, CONF1, BOTH_CONF, delta)); + list.add(new ConfLine(conf2, lineNumber, CONF2, BOTH_CONF, delta)); + } + + // Do the sorting now + Collections.sort(list, new Comparator() { + + @Override + public int compare(final ConfLine line1, final ConfLine line2) { + return line1.getNum() - line2.getNum(); + } + + }); + return list; + } + + /** + * Compares two lists, returns true if there is a DIFFERENCE. + */ + private boolean compareArray(final String[] conf1, final String[] conf2) { + boolean result = false; + if (conf1.length != conf2.length) { + result = true; + } else { + for (int i = 0; i < conf1.length; i++) { + if (conf1[i] != null && conf2[i] != null) { + return conf1[i].compareTo(conf2[i]) != 0; + } else if (conf1[i] != null || conf2[i] != null) { + return true; + } + } + } + return result; + } + + /** + * Regroups all the data regarding the comparison between two. + */ + @AllArgsConstructor + @Getter + public static class ConfLine { + private final SnecmaLine line; + int num; + boolean conf1; + boolean exclusive; + Map hasMod; + + @Override + public String toString() { + return String.format("%03d", num) + (exclusive ? " EXCLU " : " CONF ") + (conf1 ? "1 " : "2 ") + line.toString(); + } + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/printing/BuilderTemplateR07.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/printing/BuilderTemplateR07.java new file mode 100644 index 0000000..bdefec4 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/printing/BuilderTemplateR07.java @@ -0,0 +1,339 @@ +package com.capgemini.reports.definition.r07report.printing; + +import com.capgemini.reports.exceptions.FileLoadingException; +import com.capgemini.reports.exceptions.InvalidInputException; +import com.capgemini.reports.templates.Alignment; +import com.capgemini.reports.templates.CellFormat; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Class which allow to build a dynamic template thanks to DynamicTemplateBuilder class. + */ +@Slf4j +@Getter +public class BuilderTemplateR07 { + private static final int COL_WIDTH_NOM_CN = 125; + private static final int COL_WIDTH_TYPE_CN = 110; + private static final int COL_WIDTH_REVISION_CN = 80; + private static final int COL_WIDTH_ID_CN = 80; + private static final int COL_WIDTH_NOM_CR = 125; + private static final int COL_WIDTH_TYPE_CR = 110; + private static final int COL_WIDTH_REVISION_CR = 100; + private static final int COL_WIDTH_ID_CR = 100; + private static final int COL_WIDTH_QUANTITE = 90; + private static final int COL_WIDTH_PANACHAGE = 80; + private static final int COL_WIDTH_QUANTITE_CUMULEE = 80; + private static final int COL_WIDTH_SUIVANT_BESOIN = 80; + private static final int COL_WIDTH_ALT = 40; + private static final int COL_WIDTH_LISTE_FOURNISSEUR = 90; + private static final int COL_WIDTH_SUIVI_DUREE_DE_VIE = 75; + private static final int COL_WIDTH_SUIVI_UTILISATION = 75; + private static final int COL_WIDTH_CLASSEMENT = 70; + private static final int COL_WIDTH_ARTICLE_GESTION = 90; + private static final int COL_WIDTH_RESPONSABLE_CONCEPTION = 80; + private static final int COL_WIDTH_REFERENCE_ASSOCIEE = 80; + private static final int COL_WIDTH_REFERENCE_TRANSPOSEE = 80; + private static final int COL_WIDTH_REFERENCE_CONCEPTEUR = 140; + private static final int COL_WIDTH_NOM_REFERENCE = 100; + private static final int COL_WIDTH_TYPE_REFERENCE = 134; + private static final int COL_WIDTH_REVISION_REFERENCE = 60; + private static final int COL_WIDTH_REF_FABRICANT = 90; + private static final int COL_WIDTH_SUIVI_MONTAGE = 90; + private static final int COL_WIDTH_RESPONSABLE_REPERE = 80; + private static final int COL_WIDTH_REVISION_REPERE_FONCTIONNEL = 100; + private static final int COL_WIDTH_REPERE_FONCTIONNEL = 90; + private static final int COL_WIDTH_NOM_RECEPTEUR = 140; + private static final int COL_WIDTH_REVISION_RECEPTEUR = 70; + private static final int COL_WIDTH_ID_RECEPTEUR = 80; + private static final int COL_WIDTH_EFFECTIVITY = 170; + + private static final Map MAP_VALUE_WIDTH_COLUMN = getWidthColumn(); + private static final boolean DYNAMIC_HEADER_EXCEPT_EFFECTIVIY = false; + private static final boolean STRETCH_OVER_FLOW = true; + + private final List listParam; + private final Integer numberMaxOfChangeNotice; + private final List headerColumnName; + private final String confTitle1; + private final String confTitle2; + private final String nameSheetTemplate; + + /** + * Builds a template for R07 using pre-computed values: number of CNs, etc. + * + * @param aListParam a List of differences + * @param nbMaxCN the max number of CNs encountered + * @param conf1name the name of conf 1 + * @param conf2name the name of conf 2 + * @param nameSheet the sheet name + */ + public BuilderTemplateR07(final List aListParam, final Integer nbMaxCN, final String conf1name, final String conf2name, + final String nameSheet) { + listParam = aListParam; + numberMaxOfChangeNotice = nbMaxCN; + headerColumnName = getHeaderWithoutChangeColumn(); + confTitle1 = conf1name; + confTitle2 = conf2name; + nameSheetTemplate = nameSheet; + } + + private static List getHeaderFieldWithoutChangeColumn() { + List headers = new ArrayList<>(); + headers.add(EnumRecepteurR07.EFFECTIVITE.toString()); + headers.add(EnumRecepteurR07.ID_RECEPTEUR.toString()); + headers.add(EnumRecepteurR07.REVISION_RECEPTEUR.toString()); + headers.add(EnumRecepteurR07.NOM_RECEPTEUR.toString()); + headers.add(EnumRepereR07.REPERE_FONCTIONNEL.toString()); + headers.add(EnumRepereR07.REVISION_REPERE_FONCTIONNEL.toString()); + headers.add(EnumRepereR07.RESPONSABLE_REPERE.toString()); + headers.add(EnumRepereR07.SUIVI_MONTAGE.toString()); + headers.add(EnumComposantR07.REF_FABRICANT.toString()); + headers.add(EnumComposantR07.REVISION_REFERENCE.toString()); + headers.add(EnumComposantR07.TYPE_REFERENCE.toString()); + headers.add(EnumComposantR07.NOM_REFERENCE.toString()); + headers.add(EnumComposantR07.REFERENCE_CONCEPTEUR.toString()); + headers.add(EnumComposantR07.REFERENCE_TRANSPOSEE.toString()); + headers.add(EnumComposantR07.REFERENCE_ASSOCIEE.toString()); + headers.add(EnumComposantR07.RESPONSABLLE_CONCEPTION.toString()); + headers.add(EnumComposantR07.ARTICLE_GESTION.toString()); + headers.add(EnumComposantR07.CLASSEMENT.toString()); + headers.add(EnumComposantR07.SUIVI_UTILISATION.toString()); + headers.add(EnumComposantR07.SUIVI_DUREE_VIE.toString()); + headers.add(EnumComposantR07.LISTE_FOURNISSEUR.toString()); + headers.add(EnumLienNomenclatureR07.ALT.toString()); + headers.add(EnumLienNomenclatureR07.SUIVANT_BESOIN.toString()); + headers.add(EnumLienNomenclatureR07.QUANTITE_CUMULEE.toString()); + headers.add(EnumLienNomenclatureR07.PANACHAGE.toString()); + headers.add(EnumLienNomenclatureR07.QUANTITE.toString()); + headers.add(EnumChangeR07.ID_CR.toString()); + headers.add(EnumChangeR07.REVISION_CR.toString()); + headers.add(EnumChangeR07.TYPE_CR.toString()); + headers.add(EnumChangeR07.NOM_CR.toString()); + return headers; + } + + private static Map getWidthColumn() { + Map mapWidthColumn = new HashMap<>(); + mapWidthColumn.put(EnumRecepteurR07.EFFECTIVITE.toString(), COL_WIDTH_EFFECTIVITY); + mapWidthColumn.put(EnumRecepteurR07.ID_RECEPTEUR.toString(), COL_WIDTH_ID_RECEPTEUR); + mapWidthColumn.put(EnumRecepteurR07.REVISION_RECEPTEUR.toString(), COL_WIDTH_REVISION_RECEPTEUR); + mapWidthColumn.put(EnumRecepteurR07.NOM_RECEPTEUR.toString(), COL_WIDTH_NOM_RECEPTEUR); + mapWidthColumn.put(EnumRepereR07.REPERE_FONCTIONNEL.toString(), COL_WIDTH_REPERE_FONCTIONNEL); + mapWidthColumn.put(EnumRepereR07.REVISION_REPERE_FONCTIONNEL.toString(), COL_WIDTH_REVISION_REPERE_FONCTIONNEL); + mapWidthColumn.put(EnumRepereR07.RESPONSABLE_REPERE.toString(), COL_WIDTH_RESPONSABLE_REPERE); + mapWidthColumn.put(EnumRepereR07.SUIVI_MONTAGE.toString(), COL_WIDTH_SUIVI_MONTAGE); + mapWidthColumn.put(EnumComposantR07.REF_FABRICANT.toString(), COL_WIDTH_REF_FABRICANT); + mapWidthColumn.put(EnumComposantR07.REVISION_REFERENCE.toString(), COL_WIDTH_REVISION_REFERENCE); + mapWidthColumn.put(EnumComposantR07.TYPE_REFERENCE.toString(), COL_WIDTH_TYPE_REFERENCE); + mapWidthColumn.put(EnumComposantR07.NOM_REFERENCE.toString(), COL_WIDTH_NOM_REFERENCE); + mapWidthColumn.put(EnumComposantR07.REFERENCE_CONCEPTEUR.toString(), COL_WIDTH_REFERENCE_CONCEPTEUR); + mapWidthColumn.put(EnumComposantR07.REFERENCE_TRANSPOSEE.toString(), COL_WIDTH_REFERENCE_TRANSPOSEE); + mapWidthColumn.put(EnumComposantR07.REFERENCE_ASSOCIEE.toString(), COL_WIDTH_REFERENCE_ASSOCIEE); + mapWidthColumn.put(EnumComposantR07.RESPONSABLLE_CONCEPTION.toString(), COL_WIDTH_RESPONSABLE_CONCEPTION); + mapWidthColumn.put(EnumComposantR07.ARTICLE_GESTION.toString(), COL_WIDTH_ARTICLE_GESTION); + mapWidthColumn.put(EnumComposantR07.CLASSEMENT.toString(), COL_WIDTH_CLASSEMENT); + mapWidthColumn.put(EnumComposantR07.SUIVI_UTILISATION.toString(), COL_WIDTH_SUIVI_UTILISATION); + mapWidthColumn.put(EnumComposantR07.SUIVI_DUREE_VIE.toString(), COL_WIDTH_SUIVI_DUREE_DE_VIE); + mapWidthColumn.put(EnumComposantR07.LISTE_FOURNISSEUR.toString(), COL_WIDTH_LISTE_FOURNISSEUR); + mapWidthColumn.put(EnumLienNomenclatureR07.ALT.toString(), COL_WIDTH_ALT); + mapWidthColumn.put(EnumLienNomenclatureR07.SUIVANT_BESOIN.toString(), COL_WIDTH_SUIVANT_BESOIN); + mapWidthColumn.put(EnumLienNomenclatureR07.QUANTITE_CUMULEE.toString(), COL_WIDTH_QUANTITE_CUMULEE); + mapWidthColumn.put(EnumLienNomenclatureR07.PANACHAGE.toString(), COL_WIDTH_PANACHAGE); + mapWidthColumn.put(EnumLienNomenclatureR07.QUANTITE.toString(), COL_WIDTH_QUANTITE); + mapWidthColumn.put(EnumChangeR07.ID_CR.toString(), COL_WIDTH_ID_CR); + mapWidthColumn.put(EnumChangeR07.REVISION_CR.toString(), COL_WIDTH_REVISION_CR); + mapWidthColumn.put(EnumChangeR07.TYPE_CR.toString(), COL_WIDTH_TYPE_CR); + mapWidthColumn.put(EnumChangeR07.NOM_CR.toString(), COL_WIDTH_NOM_CR); + return mapWidthColumn; + } + + /** + * Creates the template. + * + * @return the template file content (.jrxml) + * @throws InvalidInputException if a dynamic table could not be created because of invalid grid size (rows/columns) + * @throws FileLoadingException if unable to load a template file + */ + public String createDynamicTemplate() throws InvalidInputException, FileLoadingException { + List contentCellColumn = createListContentCell(); + List lstWidth = createListWidth(finalWidth(), finalTotalHeader()); + String configurationLine = getBackLineConfiguration(); + Map mapStyle = defineStyleReport(); + DynamicGridTemplateR07 template = new DynamicGridTemplateR07(lstWidth, contentCellColumn, null, listStretchOverFlow(headerColumnName), + listParam, configurationLine, mapStyle, nameSheetTemplate); + template.addHeaderLine(30, headerColumnName, listDynamicHeader(headerColumnName), + new CellFormat().setAlignment(Alignment.CENTER).setBold(true), null); + template.ignorePagination(); + return template.generateCode(); + } + + private List listStretchOverFlow(final List lstHeaderFinal) { + List lstDynamic = new ArrayList<>(); + for (int i = 0; i < lstHeaderFinal.size(); i++) { + lstDynamic.add(STRETCH_OVER_FLOW); + } + return lstDynamic; + } + + private Map defineStyleReport() { + Map mapStyle = new HashMap<>(); + mapStyle.put(EnumRecepteurR07.EFFECTIVITE.toString(), "style_static"); + mapStyle.put(EnumRecepteurR07.ID_RECEPTEUR.toString(), "style_ID_RECEPTEUR"); + mapStyle.put(EnumRecepteurR07.REVISION_RECEPTEUR.toString(), "style_static"); + mapStyle.put(EnumRecepteurR07.NOM_RECEPTEUR.toString(), "style_NOM_RECEPTEUR"); + mapStyle.put(EnumRepereR07.REPERE_FONCTIONNEL.toString(), "style_REPERE_FONCTIONNEL"); + mapStyle.put(EnumRepereR07.REVISION_REPERE_FONCTIONNEL.toString(), "style_static"); + mapStyle.put(EnumRepereR07.RESPONSABLE_REPERE.toString(), "style_RESPONSABLE_REPERE"); + mapStyle.put(EnumRepereR07.SUIVI_MONTAGE.toString(), "style_SUIVI_MONTAGE"); + mapStyle.put(EnumComposantR07.REF_FABRICANT.toString(), "style_REF_FABRICANT"); + mapStyle.put(EnumComposantR07.REVISION_REFERENCE.toString(), "style_static"); + mapStyle.put(EnumComposantR07.TYPE_REFERENCE.toString(), "style_TYPE_REFERENCE"); + mapStyle.put(EnumComposantR07.NOM_REFERENCE.toString(), "style_NOM_REFERENCE"); + mapStyle.put(EnumComposantR07.REFERENCE_CONCEPTEUR.toString(), "style_REFERENCE_CONCEPTEUR"); + mapStyle.put(EnumComposantR07.REFERENCE_TRANSPOSEE.toString(), "style_REFERENCE_TRANSPOSEE"); + mapStyle.put(EnumComposantR07.REFERENCE_ASSOCIEE.toString(), "style_REFERENCE_ASSOCIEE"); + mapStyle.put(EnumComposantR07.RESPONSABLLE_CONCEPTION.toString(), "style_RESPONSABLLE_CONCEPTION"); + mapStyle.put(EnumComposantR07.ARTICLE_GESTION.toString(), "style_ARTICLE_GESTION"); + mapStyle.put(EnumComposantR07.CLASSEMENT.toString(), "style_CLASSEMENT"); + mapStyle.put(EnumComposantR07.SUIVI_UTILISATION.toString(), "style_SUIVI_UTILISATION"); + mapStyle.put(EnumComposantR07.SUIVI_DUREE_VIE.toString(), "style_SUIVI_DUREE_VIE"); + mapStyle.put(EnumComposantR07.LISTE_FOURNISSEUR.toString(), "style_LISTE_FOURNISSEUR"); + mapStyle.put(EnumLienNomenclatureR07.ALT.toString(), "style_ALT"); + mapStyle.put(EnumLienNomenclatureR07.SUIVANT_BESOIN.toString(), "style_SUIVI_BESOIN"); + mapStyle.put(EnumLienNomenclatureR07.QUANTITE_CUMULEE.toString(), "style_QUANTITE_CUMULEE"); + mapStyle.put(EnumLienNomenclatureR07.PANACHAGE.toString(), "style_PANACHAGE"); + mapStyle.put(EnumLienNomenclatureR07.QUANTITE.toString(), "style_QUANTITE"); + mapStyle.put(EnumChangeR07.ID_CR.toString(), "style_static"); + mapStyle.put(EnumChangeR07.REVISION_CR.toString(), "style_static"); + mapStyle.put(EnumChangeR07.TYPE_CR.toString(), "style_static"); + mapStyle.put(EnumChangeR07.NOM_CR.toString(), "style_static"); + for (int i = 0; i < numberMaxOfChangeNotice; i++) { + mapStyle.put(EnumChangeR07.ID_CN.toString() + "_" + (i + 1), "style_static"); + mapStyle.put(EnumChangeR07.REVISION_CN.toString() + "_" + (i + 1), "style_static"); + mapStyle.put(EnumChangeR07.TYPE_CN.toString() + "_" + (i + 1), "style_static"); + mapStyle.put(EnumChangeR07.NOM_CN.toString() + "_" + (i + 1), "style_static"); + } + return mapStyle; + } + + private List createListContentCell() { + List contentCellColumn = getHeaderFieldWithoutChangeColumn(); + List lstColumnChangeNotice = createColumnFieldChangeNotice(); + for (String aLstColumnChangeNotice : lstColumnChangeNotice) { + contentCellColumn.add(aLstColumnChangeNotice); + } + return contentCellColumn; + } + + private List createColumnFieldChangeNotice() { + List lstColumnChangeNotice = new ArrayList<>(); + for (int i = 0; i < numberMaxOfChangeNotice; i++) { + lstColumnChangeNotice.add(EnumChangeR07.ID_CN.toString() + "_" + (i + 1)); + lstColumnChangeNotice.add(EnumChangeR07.REVISION_CN.toString() + "_" + (i + 1)); + lstColumnChangeNotice.add(EnumChangeR07.TYPE_CN.toString() + "_" + (i + 1)); + lstColumnChangeNotice.add(EnumChangeR07.NOM_CN.toString() + "_" + (i + 1)); + } + return lstColumnChangeNotice; + } + + private List listDynamicHeader(final List lstHeaderFinal) { + List lstDynamic = new ArrayList<>(); + for (int i = 0; i < lstHeaderFinal.size(); i++) { + lstDynamic.add(DYNAMIC_HEADER_EXCEPT_EFFECTIVIY); + } + return lstDynamic; + } + + private String getBackLineConfiguration() { + return EnumChangeR07.CONFIGURATION_CONCERNED.toString(); + } + + private List getHeaderWithoutChangeColumn() { + List lstHeader = new ArrayList<>(); + lstHeader.add("Effectivité"); + lstHeader.add("Identifiant récepteur"); + lstHeader.add("Révision récepteur"); + lstHeader.add("Nom récepteur"); + lstHeader.add("Repère fonctionnel"); + lstHeader.add("Révision repère fonctionnel"); + lstHeader.add("Responsable repère"); + lstHeader.add("Suivi montage"); + lstHeader.add("Ref. Fabricant / Ref. Snecma"); + lstHeader.add("Révision référence"); + lstHeader.add("Type référence"); + lstHeader.add("Nom référence"); + lstHeader.add("Référence concepteur"); + lstHeader.add("Référence transposée"); + lstHeader.add("Référence associée"); + lstHeader.add("Responsable conception"); + lstHeader.add("Article de gestion"); + lstHeader.add("Classement"); + lstHeader.add("Suivi utilisation"); + lstHeader.add("Suivi durée de vie"); + lstHeader.add("Liste fournisseur(s) validé(s)"); + lstHeader.add("ALT"); + lstHeader.add("SB (Suivant Besoin)"); + lstHeader.add("Quantité cumulée"); + lstHeader.add("Panachage"); + lstHeader.add("Quantité"); + lstHeader.add("Identifiant ChangeRequest"); + lstHeader.add("Révision ChangeRequest"); + lstHeader.add("Type ChangeRequest"); + lstHeader.add("Nom ChangeRequest"); + List lstHeadChange = createColumnChangeNotice(); + for (int i = 0; i < numberMaxOfChangeNotice; i++) { + for (String aLstHeadChange : lstHeadChange) { + lstHeader.add(aLstHeadChange); + } + } + return lstHeader; + } + + private List createColumnChangeNotice() { + List lstColumnChangeNotice = new ArrayList<>(); + lstColumnChangeNotice.add("Identifiant ChangeNotice"); + lstColumnChangeNotice.add("Révision ChangeNotice"); + lstColumnChangeNotice.add("Type ChangeNotice"); + lstColumnChangeNotice.add("Nom ChangeNotice"); + return lstColumnChangeNotice; + } + + private List finalTotalHeader() { + List lstHeader = getHeaderFieldWithoutChangeColumn(); + List lstColumnChangeNotice = createColumnFieldChangeNotice(); + for (String aLstColumnChangeNotice : lstColumnChangeNotice) { + lstHeader.add(aLstColumnChangeNotice); + } + return lstHeader; + } + + private Map finalWidth() { + Map mapWidthColumn = MAP_VALUE_WIDTH_COLUMN; + for (int i = 0; i < numberMaxOfChangeNotice; i++) { + mapWidthColumn.put(EnumChangeR07.ID_CN.toString() + "_" + (i + 1), COL_WIDTH_ID_CN); + mapWidthColumn.put(EnumChangeR07.REVISION_CN.toString() + "_" + (i + 1), COL_WIDTH_REVISION_CN); + mapWidthColumn.put(EnumChangeR07.TYPE_CN.toString() + "_" + (i + 1), COL_WIDTH_TYPE_CN); + mapWidthColumn.put(EnumChangeR07.NOM_CN.toString() + "_" + (i + 1), COL_WIDTH_NOM_CN); + } + return mapWidthColumn; + } + + private List createListWidth(final Map mapWidth, final List headers) { + List lstWidth = new ArrayList<>(); + for (String header : headers) { + for (String valKey : mapWidth.keySet()) { + if (valKey.equals(header)) { + lstWidth.add(mapWidth.get(header)); + break; + } + } + } + return lstWidth; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/printing/DynamicGridTemplateR07.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/printing/DynamicGridTemplateR07.java new file mode 100644 index 0000000..c8874f8 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/printing/DynamicGridTemplateR07.java @@ -0,0 +1,250 @@ +package com.capgemini.reports.definition.r07report.printing; + +import com.capgemini.framework.common.ResourceHelper; +import com.capgemini.reports.exceptions.FileLoadingException; +import com.capgemini.reports.exceptions.InvalidInputException; +import com.capgemini.reports.templates.CellFormat; +import com.capgemini.reports.templates.Column; +import com.capgemini.reports.templates.DynamicGridTemplateBuilder; + +import java.util.List; +import java.util.Map; + +/** + * Create a dynamic template for the report 07. + */ +public class DynamicGridTemplateR07 extends DynamicGridTemplateBuilder { + private static final int CENTENT_HEIGHT_PX = 13; + private static final int TITLE_HEIGHT_PX = 45; + private static final String BLACK = "#000000\""; + private static final String FORECOLOR = " forecolor=\""; + private static final String BACKCOLOR_WHITE = " backcolor = \"#FFFFFF\" "; + private static final String BACKCOLOR_YELLOW = " backcolor = \"#FFFF00\" "; + private static final String EMPTY_STRING = ""; + private static final String COULEUR_CONFIGURATION_2 = "#FF0000"; + private static final String COULEUR_CONFIGURATION_1 = "#0000FF"; + private static final String TITLE_FIRST_CONFIGURATION = "TITLE_FIRST_CONFIGURATION"; + private static final String TITLE_SECOND_CONFIGURATION = "TITLE_SECOND_CONFIGURATION"; + private final List find; + private final String config; + private final List sizeColumn; + private final Map mapStyle; + private final String nameSheet; + + /** + * Builds a template for the R07 report. + * + * @param widths the column widths + * @param contentKeys the KEYs to the cell's content + * @param formats the cell formats + * @param stretchWithOverFlow stretch with overflow? + * @param findDifference a list of differences found + * @param configNum the number iterated through the conf + * @param aMapStyle a Style map + * @param nameSheetTemplate a spreadsheet template name + * @throws FileLoadingException if unable to load template file + * @throws InvalidInputException if inputs are incorrect (non-matching List sizes) + */ + public DynamicGridTemplateR07(final List widths, final List contentKeys, final List formats, + final List stretchWithOverFlow, final List findDifference, final String configNum, + final Map aMapStyle, final String nameSheetTemplate) throws FileLoadingException, InvalidInputException { + super(widths, contentKeys, formats, stretchWithOverFlow, CENTENT_HEIGHT_PX); + this.sizeColumn = widths; + this.find = findDifference; + this.config = configNum; + this.mapStyle = aMapStyle; + this.heigthTitle = TITLE_HEIGHT_PX; + this.listElementTitle.add(TITLE_FIRST_CONFIGURATION); + this.listElementTitle.add(TITLE_SECOND_CONFIGURATION); + this.nameSheet = nameSheetTemplate; + this.setTemplateContent(ResourceHelper.getResourceContent("/Jasper/template/template_R07.jrxml")); + } + + private StringBuilder getFieldOption() { + StringBuilder stringBuilder = new StringBuilder(200); + for (String aFind : find) { + stringBuilder.append("\n "); + } + stringBuilder.append("\n "); + return stringBuilder; + } + + @Override + public String generateCode() { + defineColumnStyle(); + makeAligment(); + nameSheetDeclaration = nameSheet; + propertyDeclaration = makePropertyDeclaration(); + fieldsDeclaration = getFieldOption(); + contentStyle = makeStyle(this.columns); + parametersDeclaration = makeParamTitle(); + titleDeclaration = makeTitle(); + + super.setTagValue(TITLE, titleDeclaration.toString()); + super.setTagValue(TITLE_HEIGHT, String.valueOf(heigthTitle)); + super.setTagValue(NAME_SHEET, nameSheetDeclaration); + super.setTagValue(PROPERTY, propertyDeclaration.toString()); + super.setTagValue(STYLE, contentStyle.toString()); + return super.generateCode(); + } + + private StringBuilder makePropertyDeclaration() { + return new StringBuilder("\n"); + } + + private StringBuilder makeParamTitle() { + StringBuilder stringBuilder = new StringBuilder(); + for (String aListElementTitle : listElementTitle) { + stringBuilder.append(BEGIN_PARAM).append(aListElementTitle).append(END_PARAM); + + } + return stringBuilder; + } + + private StringBuilder makeTitle() { + StringBuilder stringBuilder = new StringBuilder(); + int sizeTitle = 0; + int yPos = 0; + int xPos = 0; + int size = 0; + for (int i = 0; i < 4; i++) { + sizeTitle += sizeColumn.get(i); + } + for (String aListElementTitle : listElementTitle) { + stringBuilder.append("\n \n").append(BEGIN_VARIABLE_PARAM_DATA).append(aListElementTitle) + .append("}]]>\n \n"); + xPos = sizeTitle; + for (int i = 4; i < sizeColumn.size(); i++) { + stringBuilder.append("\n \n\"").append(EMPTY_STRING) + .append("\"\n"); + xPos += sizeColumn.get(i); + } + yPos += 15; + } + for (Integer aSizeColumn : sizeColumn) { + stringBuilder.append(" \n \n\"").append(EMPTY_STRING).append("\"\n"); + size += aSizeColumn; + } + return stringBuilder; + } + + private StringBuilder makeStyle(final List column) { + StringBuilder stringBuilder = new StringBuilder(); + boolean findStyleStatic = false; + int staticStyleFind = 0; + for (int i = 0; i < column.size(); i++) { + if ("style_static".equals(column.get(i).getField().getNameStyle())) { + staticStyleFind++; + if (!findStyleStatic) { + stringBuilder.append(BEGIN_STYLE).append(column.get(i).getField().getNameStyle()).append('\"').append(END_STYLE).append('\n') + .append(BEGIN_CONDITIONAL_STYLE).append(BEGIN_CONDITIONAL_EXPRESSION).append(BEGIN_VARIABLE_DATA_FALSE_BOOLEAN) + .append(find.get(find.size() - 1)).append('}').append(MULTIPLE_CONDITIONAL_INCLUSIF) + .append(BEGIN_VARIABLE_FUNCTION_FALSE_BOOLEAN).append(config).append("}]]>").append(END_CONDITIONAL_EXPRESSION) + .append(BEGIN_STYLE_MODE).append("\"Opaque\"").append(BACKCOLOR_WHITE).append(FORECOLOR + COULEUR_CONFIGURATION_2 + '\"') + .append(END_STYLE).append(BEGIN_BOX).append(TOP_PEN).append(LINE_WIDTH).append("0.5\"").append(LINE_COLOR).append(BLACK) + .append(END).append(LEFT_PEN).append(LINE_WIDTH).append("0.5\"").append(LINE_COLOR).append(BLACK).append(END) + .append(BOTTOM_PEN).append(LINE_WIDTH).append("0.5\"").append(LINE_COLOR).append(BLACK).append(END).append(RIGHT_PEN) + .append(LINE_WIDTH).append("0.5\"").append(LINE_COLOR).append(BLACK).append(END).append(END_BOX).append(END_STYLE_MODE) + .append(END_CONDITIONAL_STYLE).append(BEGIN_CONDITIONAL_STYLE).append(BEGIN_CONDITIONAL_EXPRESSION) + .append(BEGIN_VARIABLE_DATA_FALSE_BOOLEAN).append(find.get(find.size() - 1)).append('}') + .append(MULTIPLE_CONDITIONAL_INCLUSIF).append(BEGIN_VARIABLE_FUNCTION).append(config).append("}]]>") + .append(END_CONDITIONAL_EXPRESSION).append(BEGIN_STYLE_MODE).append("\"Opaque\"").append(BACKCOLOR_WHITE) + .append(FORECOLOR + COULEUR_CONFIGURATION_1 + "\"").append(END_STYLE).append(BEGIN_BOX).append(TOP_PEN).append(LINE_WIDTH) + .append("0.5\"").append(LINE_COLOR).append(BLACK).append(END).append(LEFT_PEN).append(LINE_WIDTH).append("0.5\"") + .append(LINE_COLOR).append(BLACK).append(END).append(BOTTOM_PEN).append(LINE_WIDTH).append("0.5\"").append(LINE_COLOR) + .append(BLACK).append(END).append(RIGHT_PEN).append(LINE_WIDTH).append("0.5\"").append(LINE_COLOR).append(BLACK) + .append(END).append(END_BOX).append(END_STYLE_MODE).append(END_CONDITIONAL_STYLE).append(BEGIN_CONDITIONAL_STYLE) + .append(BEGIN_CONDITIONAL_EXPRESSION).append(BEGIN_VARIABLE_DATA).append(find.get(find.size() - 1)).append('}') + .append(MULTIPLE_CONDITIONAL_INCLUSIF).append(BEGIN_VARIABLE_FUNCTION_FALSE_BOOLEAN).append(config).append("}]]>") + .append(END_CONDITIONAL_EXPRESSION).append(BEGIN_STYLE_MODE).append("\"Opaque\"").append(BACKCOLOR_YELLOW) + .append(FORECOLOR + COULEUR_CONFIGURATION_2 + "\"").append(END_STYLE).append(BEGIN_BOX).append(TOP_PEN).append(LINE_WIDTH) + .append("0.5\"").append(LINE_COLOR).append(BLACK).append(END).append(LEFT_PEN).append(LINE_WIDTH).append("0.5\"") + .append(LINE_COLOR).append(BLACK).append(END).append(BOTTOM_PEN).append(LINE_WIDTH).append("0.5\"").append(LINE_COLOR) + .append(BLACK).append(END).append(RIGHT_PEN).append(LINE_WIDTH).append("0.5\"").append(LINE_COLOR).append(BLACK) + .append(END).append(END_BOX).append(END_STYLE_MODE).append(END_CONDITIONAL_STYLE).append(BEGIN_CONDITIONAL_STYLE) + .append(BEGIN_CONDITIONAL_EXPRESSION).append(BEGIN_VARIABLE_DATA).append(find.get(find.size() - 1)).append('}') + .append(MULTIPLE_CONDITIONAL_INCLUSIF).append(BEGIN_VARIABLE_FUNCTION).append(config).append("}]]>") + .append(END_CONDITIONAL_EXPRESSION).append(BEGIN_STYLE_MODE).append("\"Opaque\"").append(BACKCOLOR_YELLOW) + .append(FORECOLOR).append(COULEUR_CONFIGURATION_1).append('\"').append(END_STYLE).append(BEGIN_BOX).append(TOP_PEN) + .append(LINE_WIDTH).append("0.5\"").append(LINE_COLOR).append(BLACK).append(END).append(LEFT_PEN).append(LINE_WIDTH) + .append("0.5\"").append(LINE_COLOR).append(BLACK).append(END).append(BOTTOM_PEN).append(LINE_WIDTH).append("0.5\"") + .append(LINE_COLOR).append(BLACK).append(END).append(RIGHT_PEN).append(LINE_WIDTH).append("0.5\"").append(LINE_COLOR) + .append(BLACK).append(END).append(END_BOX).append(END_STYLE_MODE).append(END_CONDITIONAL_STYLE).append(END_STYLE_FIRST); + findStyleStatic = true; + } + } else { + stringBuilder.append(BEGIN_STYLE).append(column.get(i).getField().getNameStyle()).append('\"').append(END_STYLE).append('\n') + .append(BEGIN_CONDITIONAL_STYLE).append(BEGIN_CONDITIONAL_EXPRESSION).append(BEGIN_VARIABLE_DATA_FALSE_BOOLEAN_CONDITION) + .append(find.get(find.size() - 1)).append('}').append(MULTIPLE_CONDITIONAL_INCLUSIF) + .append(BEGIN_VARIABLE_FUNCTION_FALSE_BOOLEAN).append(find.get(i - staticStyleFind)).append("}) ") + .append(MULTIPLE_CONDITIONAL_INCLUSIF).append(BEGIN_VARIABLE_FUNCTION_FALSE_BOOLEAN).append(config).append("}]]>") + .append(END_CONDITIONAL_EXPRESSION).append(BEGIN_STYLE_MODE).append("\"Opaque\"").append(BACKCOLOR_WHITE) + .append(FORECOLOR + COULEUR_CONFIGURATION_2 + "\"").append(END_STYLE).append(BEGIN_BOX).append(TOP_PEN).append(LINE_WIDTH) + .append("0.5\"").append(LINE_COLOR).append(BLACK).append(END).append(LEFT_PEN).append(LINE_WIDTH).append("0.5\"") + .append(LINE_COLOR).append(BLACK).append(END).append(BOTTOM_PEN).append(LINE_WIDTH).append("0.5\"").append(LINE_COLOR) + .append(BLACK).append(END).append(RIGHT_PEN).append(LINE_WIDTH).append("0.5\"").append(LINE_COLOR).append(BLACK).append(END) + .append(END_BOX).append(END_STYLE_MODE).append(END_CONDITIONAL_STYLE).append(BEGIN_CONDITIONAL_STYLE) + .append(BEGIN_CONDITIONAL_EXPRESSION).append(BEGIN_VARIABLE_DATA_FALSE_BOOLEAN_CONDITION).append(find.get(find.size() - 1)) + .append('}').append(MULTIPLE_CONDITIONAL_INCLUSIF).append(BEGIN_VARIABLE_FUNCTION_FALSE_BOOLEAN) + .append(find.get(i - staticStyleFind)).append("}) ").append(MULTIPLE_CONDITIONAL_INCLUSIF).append(BEGIN_VARIABLE_FUNCTION) + .append(config).append("}]]>").append(END_CONDITIONAL_EXPRESSION).append(BEGIN_STYLE_MODE).append("\"Opaque\"") + .append(BACKCOLOR_WHITE).append(FORECOLOR + COULEUR_CONFIGURATION_1 + '\"').append(END_STYLE).append(BEGIN_BOX) + .append(TOP_PEN).append(LINE_WIDTH).append("0.5\"").append(LINE_COLOR).append(BLACK).append(END).append(LEFT_PEN) + .append(LINE_WIDTH).append("0.5\"").append(LINE_COLOR).append(BLACK).append(END).append(BOTTOM_PEN).append(LINE_WIDTH) + .append("0.5\"").append(LINE_COLOR).append(BLACK).append(END).append(RIGHT_PEN).append(LINE_WIDTH).append("0.5\"") + .append(LINE_COLOR).append(BLACK).append(END).append(END_BOX).append(END_STYLE_MODE).append(END_CONDITIONAL_STYLE) + .append(BEGIN_CONDITIONAL_STYLE).append(BEGIN_CONDITIONAL_EXPRESSION).append(BEGIN_VARIABLE_DATA_CONDITION) + .append(find.get(find.size() - 1)).append('}').append(MULTIPLE_CONDITIONAL_EXCLUSIF).append(BEGIN_VARIABLE_FUNCTION) + .append(find.get(i - staticStyleFind)).append("}) ").append(MULTIPLE_CONDITIONAL_INCLUSIF) + .append(BEGIN_VARIABLE_FUNCTION_FALSE_BOOLEAN).append(config).append("}]]>").append(END_CONDITIONAL_EXPRESSION) + .append(BEGIN_STYLE_MODE).append("\"Opaque\"").append(BACKCOLOR_YELLOW).append(FORECOLOR + COULEUR_CONFIGURATION_2 + '\"') + .append(END_STYLE).append(BEGIN_BOX).append(TOP_PEN).append(LINE_WIDTH).append("0.5\"").append(LINE_COLOR).append(BLACK) + .append(END).append(LEFT_PEN).append(LINE_WIDTH).append("0.5\"").append(LINE_COLOR).append(BLACK).append(END) + .append(BOTTOM_PEN).append(LINE_WIDTH).append("0.5\"").append(LINE_COLOR).append(BLACK).append(END).append(RIGHT_PEN) + .append(LINE_WIDTH).append("0.5\"").append(LINE_COLOR).append(BLACK).append(END).append(END_BOX).append(END_STYLE_MODE) + .append(END_CONDITIONAL_STYLE).append(BEGIN_CONDITIONAL_STYLE).append(BEGIN_CONDITIONAL_EXPRESSION) + .append(BEGIN_VARIABLE_DATA_CONDITION).append(find.get(find.size() - 1)).append('}').append(MULTIPLE_CONDITIONAL_EXCLUSIF) + .append(BEGIN_VARIABLE_FUNCTION).append(find.get(i - staticStyleFind)).append("}) ").append(MULTIPLE_CONDITIONAL_INCLUSIF) + .append(BEGIN_VARIABLE_FUNCTION).append(config).append("}]]>").append(END_CONDITIONAL_EXPRESSION).append(BEGIN_STYLE_MODE) + .append("\"Opaque\"").append(BACKCOLOR_YELLOW).append(FORECOLOR + COULEUR_CONFIGURATION_1 + '\"').append(END_STYLE) + .append(BEGIN_BOX).append(TOP_PEN).append(LINE_WIDTH).append("0.5\"").append(LINE_COLOR).append(BLACK).append(END) + .append(LEFT_PEN).append(LINE_WIDTH).append("0.5\"").append(LINE_COLOR).append(BLACK).append(END).append(BOTTOM_PEN) + .append(LINE_WIDTH).append("0.5\"").append(LINE_COLOR).append(BLACK).append(END).append(RIGHT_PEN).append(LINE_WIDTH) + .append("0.5\"").append(LINE_COLOR).append(BLACK).append(END).append(END_BOX).append(END_STYLE_MODE) + .append(END_CONDITIONAL_STYLE).append(END_STYLE_FIRST); + } + } + + return stringBuilder; + + } + + private void makeAligment() { + for (Column column : this.columns) { + column.getHeaders().get(0).getFormat().setAlignment("Middle\""); + } + } + + /** + * Allow to associate a style with a column : every column has his own style(except effectivity , revision , CR and CN). + */ + private void defineColumnStyle() { + for (Column column : this.columns) { + if (mapStyle.containsKey(column.getField().getContent())) { + column.getField().setNameStyle(mapStyle.get(column.getField().getContent())); + } else { + column.getField().setNameStyle(null); + } + for (int i = 0; i < column.getHeaders().size(); i++) { + if (mapStyle.containsKey(column.getHeaders().get(i).getContent())) { + column.getHeaders().get(i).setNameStyle(mapStyle.get(column.getHeaders().get(i).getContent())); + } else { + column.getHeaders().get(i).setNameStyle(null); + } + } + } + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/printing/EnumChangeR07.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/printing/EnumChangeR07.java new file mode 100644 index 0000000..6cd9aa4 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/printing/EnumChangeR07.java @@ -0,0 +1,18 @@ +package com.capgemini.reports.definition.r07report.printing; + +/** + * Enum listing all the keys related to ChangeRequests and ChangeNotices in the R07. + */ +public enum EnumChangeR07 { + ID_CR, + REVISION_CR, + TYPE_CR, + NOM_CR, + CONFIGURATION_CONCERNED, + TITLE_FIRST_CONFIGURATION, + TITLE_SECOND_CONFIGURATION, + ID_CN, + REVISION_CN, + TYPE_CN, + NOM_CN +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/printing/EnumComposantR07.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/printing/EnumComposantR07.java new file mode 100644 index 0000000..fed6d61 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/printing/EnumComposantR07.java @@ -0,0 +1,20 @@ +package com.capgemini.reports.definition.r07report.printing; + +/** + * Enum listing all the keys related to Components in the R07. + */ +public enum EnumComposantR07 { + REF_FABRICANT, + REVISION_REFERENCE, + TYPE_REFERENCE, + NOM_REFERENCE, + REFERENCE_CONCEPTEUR, + REFERENCE_TRANSPOSEE, + REFERENCE_ASSOCIEE, + RESPONSABLLE_CONCEPTION, + ARTICLE_GESTION, + CLASSEMENT, + SUIVI_UTILISATION, + SUIVI_DUREE_VIE, + LISTE_FOURNISSEUR +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/printing/EnumLienNomenclatureR07.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/printing/EnumLienNomenclatureR07.java new file mode 100644 index 0000000..de8887e --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/printing/EnumLienNomenclatureR07.java @@ -0,0 +1,12 @@ +package com.capgemini.reports.definition.r07report.printing; + +/** + * Enum listing all the keys related to Bom data in the R07. + */ +public enum EnumLienNomenclatureR07 { + ALT, + SUIVANT_BESOIN, + QUANTITE_CUMULEE, + PANACHAGE, + QUANTITE +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/printing/EnumMapDelta.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/printing/EnumMapDelta.java new file mode 100644 index 0000000..fb8b727 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/printing/EnumMapDelta.java @@ -0,0 +1,30 @@ +package com.capgemini.reports.definition.r07report.printing; + +/** + * Enum listing all the keys that mark if a column has a diff between conf1 and conf2, in the R07. + */ +public enum EnumMapDelta { + REF_FABRICANT_ECART, + TYPE_REFERENCE_ECART, + NOM_REFERENCE_ECART, + REFERENCE_CONCEPTEUR_ECART, + REFERENCE_TRANSPOSEE_ECART, + REFERENCE_ASSOCIEE_ECART, + RESPONSABLE_CONCEPTION_ECART, + ARTICLE_GESTION_ECART, + CLASSEMENT_ECART, + SUIVI_UTILISATION_ECART, + SUIVI_DUREE_VIE_ECART, + LISTE_FOURNISSEUR_ECART, + ALT_ECART, + SUIVI_BESOIN_ECART, + QUANTITE_CUMULEE_ECART, + PANACHAGE_ECART, + QUANTITE_ECART, + ID_RECEPTEUR_ECART, + NOM_RECEPTEUR_ECART, + REPERE_FONCTIONNEL_ECART, + RESPONSABLE_REPERE_ECART, + SUIVI_MONTAGE_ECART, + ALL_LINE_DIFFERENCE +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/printing/EnumRecepteurR07.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/printing/EnumRecepteurR07.java new file mode 100644 index 0000000..ed9850a --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/printing/EnumRecepteurR07.java @@ -0,0 +1,11 @@ +package com.capgemini.reports.definition.r07report.printing; + +/** + * Enum listing all the keys related to Receptors in the R07. + */ +public enum EnumRecepteurR07 { + EFFECTIVITE, + ID_RECEPTEUR, + REVISION_RECEPTEUR, + NOM_RECEPTEUR +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/printing/EnumRepereR07.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/printing/EnumRepereR07.java new file mode 100644 index 0000000..46d0e90 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r07report/printing/EnumRepereR07.java @@ -0,0 +1,11 @@ +package com.capgemini.reports.definition.r07report.printing; + +/** + * Enum listing all the keys related to Repere data in the R07. + */ +public enum EnumRepereR07 { + REPERE_FONCTIONNEL, + REVISION_REPERE_FONCTIONNEL, + RESPONSABLE_REPERE, + SUIVI_MONTAGE +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r10report/DataReportPreparatorR10.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r10report/DataReportPreparatorR10.java new file mode 100644 index 0000000..4675aee --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r10report/DataReportPreparatorR10.java @@ -0,0 +1,127 @@ +package com.capgemini.reports.definition.r10report; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.EmptyNomenclatureException; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.exceptions.NoSuchBomViewException; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcBomObject; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcBomObjectFactory; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcRevisionRule; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcRevisionRuleProperties; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.product.TcProduct; +import com.capgemini.framework.teamcenter.object.runtime.TcBomWindow; +import com.capgemini.framework.teamcenter.object.runtime.TcBomWindowConfiguration; +import com.capgemini.framework.teamcenter.object.runtime.TcRevisionRulesConfiguration; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.bomlineholder.BOMLineHolderFactory; +import com.capgemini.reports.definition.r10report.ExecutionR10.ReportDataR10; +import com.capgemini.reports.exceptions.InvalidInputException; +import com.capgemini.reports.exceptions.InvalidUserInputException; +import com.capgemini.reports.exceptions.MalformedNomenclatureException; +import com.capgemini.reports.exceptions.UserInputErrorEnum; +import com.capgemini.reports.execution.IDataReportPreparator; +import com.capgemini.reports.execution.strategies.IExecutionStrategy; +import com.capgemini.reports.filter.AllIsGoodFilter; +import com.capgemini.reports.filter.FilterExcludeByType; +import com.capgemini.reports.printing.PrintParameters; +import com.capgemini.reports.reports.parameters.EffectivityDate; +import com.capgemini.reports.reports.parameters.MonoMulti; +import com.capgemini.reports.teamcenter.resolution.structureservice.IStructureServiceCaller; +import com.capgemini.reports.teamcenter.resolution.structureservice.MultiStructureServiceCaller; +import com.capgemini.reports.teamcenter.resolution.structureservice.TripleStructureServiceCaller; +import com.teamcenter.soa.client.model.ModelObject; +import com.teamcenter.soa.client.model.strong.BOMLine; +import com.teamcenter.soa.client.model.strong.Form; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +/** + * This class will allow to prepare data and findAll back data for making report R10. + */ +public class DataReportPreparatorR10 implements IDataReportPreparator { + private static final long serialVersionUID = 9204365823895275478L; + private static final Logger LOGGER = LoggerFactory.getLogger(DataReportPreparatorR10.class); + + private static final FilterExcludeByType FILTER_MOCKUP_GEOMETRY = new FilterExcludeByType("Mockup Revision", "Geometry Revision"); // Mockup Revision and Geometry Revision can be found in a BOM, but are not needed + + @Override + public String print(TcSession session, ExecutionR10 execution, IExecutionStrategy executionStrategy) throws KurtException { + PrintParameters printParameters = prepareData(session, execution); + executionStrategy.print(printParameters, execution); + return executionStrategy.getReportFileName(execution) + printParameters.getOuputFileExtension(); + } + + private PrintParameters prepareData(final TcSession session, final ExecutionR10 report) throws KurtException { + LOGGER.debug("PrepareData started on: {}", report.getReportIdentifier().getReportTitle()); + + TcBomObject topLineObject = new TcBomObjectFactory(session, report.getGenerics().getItem(session)).create(); + TcProduct productObject = new TcProduct(session, report.getGenerics().getProductUnit().getProduct(session)); + int unit = report.getGenerics().getProductUnit().getUnit(); + EffectivityDate effectivityDate = report.getEffectivityDate(); + + TcRevisionRuleProperties revisionRuleProperties = new TcRevisionRuleProperties(productObject, unit, effectivityDate.isNow() ? null : effectivityDate.getDateTime()); + + TcRevisionRule revisionRule = session.findRevRule(report.getRevisionRule()); + TcRevisionRulesConfiguration revRulesConfiguration = new TcRevisionRulesConfiguration(revisionRule, revisionRuleProperties); + + try (TcBomWindow bomWindow = session.createBomWindow(new TcBomWindowConfiguration(topLineObject, revRulesConfiguration))) { + session.setObjectPropPolicy(report.getFullPolicy()); + + // Explode the structure + BOMLineHolder unbuiltTopLine = explode(session, bomWindow.topLine(), report); + + List itemRevMaster = unbuiltTopLine.getAllItemRevMasters(); + session.loadProperties(itemRevMaster.toArray(new ModelObject[itemRevMaster.size()])); + + // build the BomLine + BOMLineHolderFactory.buildTopBom(session, unbuiltTopLine, FILTER_MOCKUP_GEOMETRY); + + // Freeze after processing + unbuiltTopLine.freeze(); + ReportDataR10 dataR10 = new ReportDataR10(unbuiltTopLine); + + R10Printer printer = new R10Printer(report.getEffectivityDate().isNow() ? null : report.getEffectivityDate().getDateTime()); + PrintParameters printParameters = printer.makeMasterTemplate(report, dataR10); + printer.constructDataMaps(session, printParameters, dataR10); + + LOGGER.debug("PrepareData ended on: {}", report.getReportIdentifier().getReportTitle()); + return printParameters; + } catch (EmptyNomenclatureException e) { + switch (report.getGenerics().getType()) { + case GENERIC: + throw new InvalidUserInputException(UserInputErrorEnum.NO_DATA_COULD_BE_EXTRACTED_FOR_GENERIC_PRODUCT_AND_UNIT, e); + case GENERIC_ASSEMB: + throw new InvalidUserInputException(UserInputErrorEnum.NO_DATA_COULD_BE_EXTRACTED_FOR_GENERIC_ASSEMB_PRODUCT_AND_UNIT, e); + default: + throw new KurtException("The TC Nomenclature Resolution returned null", e); + } + } + } + + private BOMLineHolder explode(final TcSession session, final BOMLine topBomLine, final ExecutionR10 report) + throws InvalidInputException, MalformedNomenclatureException { + IStructureServiceCaller service; + if (MonoMulti.MONO.equals(report.getMonoMulti())) { + service = new TripleStructureServiceCaller(session); + } else { + service = new MultiStructureServiceCaller(session); + } + + try { + return service.resolve(topBomLine, new AllIsGoodFilter()); + } catch (EmptyNomenclatureException e) { + switch (report.getGenerics().getType()) { + case GENERIC: + throw new InvalidUserInputException(UserInputErrorEnum.NO_DATA_COULD_BE_EXTRACTED_FOR_GENERIC_PRODUCT_AND_UNIT, e); + case GENERIC_ASSEMB: + throw new InvalidUserInputException(UserInputErrorEnum.NO_DATA_COULD_BE_EXTRACTED_FOR_GENERIC_ASSEMB_PRODUCT_AND_UNIT, e); + default: + throw new InvalidInputException("The TC Nomenclature Resolution returned null", e); + } + } catch (NoSuchBomViewException e) { + throw new InvalidInputException("No such Bom View", e); + } + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r10report/DocumentExtractor.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r10report/DocumentExtractor.java new file mode 100644 index 0000000..3c1c9bb --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r10report/DocumentExtractor.java @@ -0,0 +1,257 @@ +package com.capgemini.reports.definition.r10report; + +import com.capgemini.framework.common.LanguageHelper; +import com.capgemini.framework.common.StringHelper; +import com.capgemini.framework.common.TeamcenterDateFormatter; +import com.capgemini.framework.teamcenter.object.pom.status.TcReleaseStatus; +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.capgemini.framework.teamcenter.resolution.filtering.TcTypeInclusionFilter; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.bomlineholder.BOMLineHolderHelper; +import com.capgemini.reports.definition.r10report.lines.*; +import com.capgemini.reports.documentationobjects.*; +import com.capgemini.reports.exceptions.InvalidInputException; +import com.capgemini.reports.exceptions.MalformedNomenclatureException; +import com.capgemini.reports.exceptions.NotFoundException; +import com.capgemini.reports.releasestatus.DefaultRevisionSelector; +import com.capgemini.reports.snecmaobjects.ISnecmaObject; +import com.capgemini.reports.snecmaobjects.descriptif.DescriptifRevision; +import com.capgemini.reports.snecmaobjects.part.AbstractPart; +import com.capgemini.reports.snecmaobjects.product.ProductRevision; +import lombok.extern.slf4j.Slf4j; + +import java.util.*; + +import static com.capgemini.framework.teamcenter.object.pom.status.StatusEnum.FROZEN; +import static com.capgemini.framework.teamcenter.object.pom.status.StatusEnum.PUBLISHED; +import static com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes.*; + +/** + * Extracts documents' Revision from their Master, stores their status in a Map. + */ +@Slf4j +public class DocumentExtractor implements IDocVisitor> { + + private static final String TYPE_DEFINITION_DOCUMENTS = "Definition documents"; + private static final String TYPE_REFERENCE_DOCUMENTS = "Reference documents"; + private final Calendar effectivityDate; + private final Map docCache; + + public DocumentExtractor(final Calendar effectivityDate, final Map docCache) { + this.effectivityDate = effectivityDate; + this.docCache = docCache; + } + + private static List> noDocuments() { + List> list = new ArrayList<>(); + Map emptyDoc = new EnumMap<>(R10Keys.class); + emptyDoc.put(R10Keys.DOC_CREATION_DATE, StringHelper.EMPTY); + emptyDoc.put(R10Keys.DOC_ID, StringHelper.EMPTY); + emptyDoc.put(R10Keys.DOC_INDEX, StringHelper.EMPTY); + emptyDoc.put(R10Keys.DOC_LINK_TYPE, StringHelper.EMPTY); + emptyDoc.put(R10Keys.DOC_NAME, StringHelper.EMPTY); + emptyDoc.put(R10Keys.DOC_NAME_ENG, StringHelper.EMPTY); + emptyDoc.put(R10Keys.DOC_REVISION, StringHelper.EMPTY); + emptyDoc.put(R10Keys.DOC_STATUS, StringHelper.EMPTY); + emptyDoc.put(R10Keys.DOC_TYPE, StringHelper.EMPTY); + list.add(emptyDoc); + return list; + } + + /** + * Extract the content of each Document of a {@link R10ProductGeneric}. + * + * @param r10ProductGeneric the product/Generic line (the Generic holds the Documents) + * @return a {@link List} of {@link Map}s + * @throws MalformedNomenclatureException if nomenclature is not well-defined + * @throws NotFoundException if no descriptif is found below the RfGeneric of the Generic + * @throws InvalidInputException if generic bomLine is null + */ + public List> extract(final R10ProductGeneric r10ProductGeneric) throws MalformedNomenclatureException, NotFoundException, InvalidInputException { + // For generics, a Descriptif can be found as a bom Child, which owns some pseudo-folders containing the documents + BOMLineHolder genericComponent = r10ProductGeneric.getGenericComponentBL(); + return extractDocsFromGeneric(genericComponent); + } + + /** + * Extract the content of each Document of a {@link R10PartRfPart}. + * + * @param partRfPart the Part/Rf Part/Part (the Part component holds the documents) + * @return a {@link List} of {@link Map}s + */ + public List> extract(final R10PartRfPart partRfPart) { + // For Parts, the documents can be found directly in their pseudo-fodlers + BOMLineHolder component = partRfPart.getPartComponentBL(); + AbstractPart part = (AbstractPart) component.getSnecmaObject(); + return extractDocsFromPart(part); + } + + /** + * Extract the content of each Document of a {@link R10Quad}. + */ + public List> extract(final R10Quad quad) throws InvalidInputException, MalformedNomenclatureException, NotFoundException { + ISnecmaObject component = quad.getComposant(); + if (component.isPart()) { + AbstractPart part = (AbstractPart) component; + return extractDocsFromPart(part); + } else { + BOMLineHolder genericComponent = quad.getComposantBL(); + return extractDocsFromGeneric(genericComponent); + } + } + + /** + * Extract the content of each Document of a {@link R10ReceptorLine}. + */ + public List> extract(final R10ReceptorLine receptorLine) throws InvalidInputException, MalformedNomenclatureException, NotFoundException { + ISnecmaObject receptor = receptorLine.getRecepteur(); + if (receptor.isGeneric()) { + return extractDocsFromGeneric(receptorLine.getRecepteurBL()); + } else { + return noDocuments(); + } + } + + /** + * Extract the content of each Document of a {@link R10TopLine}. + */ + public List> extract(final R10TopLine r10TopLine) throws InvalidInputException, MalformedNomenclatureException, NotFoundException { + ISnecmaObject topComponent = r10TopLine.getBomLineObject(); + if (topComponent.isGeneric()) { + return extractDocsFromGeneric(r10TopLine.getBomLine()); + } else if (topComponent.isProduct()) { + return extractDocsFromProduct((ProductRevision) topComponent); + } else { + log.warn("Unknown behaviour when top object is neither a Generic nor a Product, but is a :" + topComponent.getType()); + return noDocuments(); + } + } + + /** + * Extract the content of each Document of a {@link R10Quad}. + * + * @param r10AltPart The Alt/PArt (the part holds the Documents) + * @return a {@link List} of {@link Map}s + */ + public List> extract(final R10AltPart r10AltPart) { + AbstractPart component = r10AltPart.getChild(); + return extractDocsFromPart(component); + } + + private List> extractDocsFromGeneric(final BOMLineHolder gen) + throws InvalidInputException, MalformedNomenclatureException, NotFoundException { + // For generics, a Descriptif can be found as a bom Child, which owns some pseudo-folders containing the documents + BOMLineHolder rfGeneric = BOMLineHolderHelper.findRfGenericBL(gen); + BOMLineHolder descriptifBL = BOMLineHolderHelper.findFirst(rfGeneric, SnecmaObjectTypes.DESCRIPTIF_REVISION); + DescriptifRevision descriptif = (DescriptifRevision) descriptifBL.getSnecmaObject(); + + // Extract the documents from the Descriptif + List docs = new ArrayList<>(); + docs.addAll(descriptif.getReferenceDocumentsOfTypes( + new TcTypeInclusionFilter(DOC_NORM, DOC_NORM_STANDARD), + new DefaultRevisionSelector(effectivityDate, FROZEN, PUBLISHED), docCache)); + docs.addAll(descriptif.getDefinitionDocumentsOfTypes(new TcTypeInclusionFilter(DOC_TECHNIC_REVISION), docCache)); + return extractDocContent(docs); + } + + private List> extractDocsFromPart(final AbstractPart part) { + List docs = new ArrayList<>(); + docs.addAll(part.getReferenceDocumentsOfTypes( + new TcTypeInclusionFilter(DOC_NORM, DOC_NORM_STANDARD), + new DefaultRevisionSelector(effectivityDate, FROZEN, PUBLISHED), docCache)); + docs.addAll(part.getDefinitionDocumentsOfTypes(new TcTypeInclusionFilter(DOC_TECHNIC_REVISION), docCache)); + docs.addAll(part.getRepresentedDocumentsOfTypes(new TcTypeInclusionFilter(DOC_DRAWING_REVISION), docCache)); + return extractDocContent(docs); + } + + /* ************** This Applies the Visitor on each documents. ******************/ + + private List> extractDocsFromProduct(final ProductRevision product) { + List docs = new ArrayList<>(product.getDefinitionDocumentsOfTypes( + new TcTypeInclusionFilter(DOC_TECHNIC_REVISION), docCache)); + return extractDocContent(docs); + } + + /* ************** This section defines the Visitor behaviour on each documents. ******************/ + + private List> extractDocContent(final List docs) { + if (docs.isEmpty()) { + return noDocuments(); + } + List> docContentList = new ArrayList<>(); + for (AbstractDoc doc : docs) { + docContentList.add(doc.accept(this)); + } + return docContentList; + } + + @Override + public Map visit(final DocDrawing doc) { + Map map = new EnumMap<>(R10Keys.class); + map.put(R10Keys.DOC_LINK_TYPE, TYPE_DEFINITION_DOCUMENTS); + map.put(R10Keys.DOC_ID, doc.getDocId()); + map.put(R10Keys.DOC_REVISION, doc.getRevision()); + map.put(R10Keys.DOC_INDEX, doc.getIndicePlan()); + map.put(R10Keys.DOC_TYPE, "Représentation 2D"); // Devrait être "Représentation 2D / Drawing" mais on demande la partie FR... + map.put(R10Keys.DOC_NAME, doc.getName()); + map.put(R10Keys.DOC_NAME_ENG, doc.getDesignationEn()); + List status = doc.getStatus(); + map.put(R10Keys.DOC_STATUS, status.isEmpty() ? "" : status.get(0).getDisplayableName()); + map.put(R10Keys.DOC_CREATION_DATE, TeamcenterDateFormatter.formatCalendarToFrench(doc.getDateCreation())); + return map; + } + + @Override + public Map visit(final DocGeometry doc) { + return null; // not used in R10 + } + + @Override + public Map visit(final DocNorm doc) { + Map map = new EnumMap<>(R10Keys.class); + map.put(R10Keys.DOC_LINK_TYPE, TYPE_REFERENCE_DOCUMENTS); + map.put(R10Keys.DOC_ID, doc.getDocId()); + map.put(R10Keys.DOC_REVISION, doc.getRevision()); + map.put(R10Keys.DOC_INDEX, "-"); + map.put(R10Keys.DOC_TYPE, LanguageHelper.french(doc.getTypeDocNorm())); + map.put(R10Keys.DOC_NAME, doc.getItemName()); + map.put(R10Keys.DOC_NAME_ENG, doc.getDesignationEn()); + List status = doc.getStatus(); + map.put(R10Keys.DOC_STATUS, status.isEmpty() ? "" : status.get(0).getDisplayableName()); + map.put(R10Keys.DOC_CREATION_DATE, TeamcenterDateFormatter.formatCalendarToFrench(doc.getDateCreation())); + return map; + } + + @Override + public Map visit(final DocNormStandard doc) { + Map map = new EnumMap<>(R10Keys.class); + map.put(R10Keys.DOC_LINK_TYPE, TYPE_REFERENCE_DOCUMENTS); + map.put(R10Keys.DOC_ID, doc.getDocId()); + map.put(R10Keys.DOC_REVISION, doc.getRevision()); + map.put(R10Keys.DOC_INDEX, "-"); + map.put(R10Keys.DOC_TYPE, "Norme pour acticles standards"); // Specification says to put "Norme pour acticles standards / Norm for Standard ItemsStringHelper.EMPTY, but also says to extract the french part ^^ + map.put(R10Keys.DOC_NAME, doc.getItemName()); + map.put(R10Keys.DOC_NAME_ENG, doc.getDesignationEn()); + List status = doc.getStatus(); + map.put(R10Keys.DOC_STATUS, status.isEmpty() ? "" : status.get(0).getDisplayableName()); + map.put(R10Keys.DOC_CREATION_DATE, TeamcenterDateFormatter.formatCalendarToFrench(doc.getDateCreation())); + return map; + } + + @Override + public Map visit(final DocTechnic doc) { + String docId = (doc.getIdOrigine() == null || doc.getIdOrigine().isEmpty()) ? doc.getDocId() : doc.getIdOrigine(); + Map map = new EnumMap<>(R10Keys.class); + map.put(R10Keys.DOC_LINK_TYPE, TYPE_DEFINITION_DOCUMENTS); + map.put(R10Keys.DOC_ID, docId); + map.put(R10Keys.DOC_REVISION, doc.getRevision()); + map.put(R10Keys.DOC_INDEX, doc.getIndice()); + map.put(R10Keys.DOC_TYPE, LanguageHelper.french(doc.getTypeDocTechnic1()) + " / " + LanguageHelper.french(doc.getTypeDocTechnic2())); + map.put(R10Keys.DOC_NAME, doc.getName()); + map.put(R10Keys.DOC_NAME_ENG, doc.getDesignationEn()); + List status = doc.getStatus(); + map.put(R10Keys.DOC_STATUS, status.isEmpty() ? "" : status.get(0).getDisplayableName()); + map.put(R10Keys.DOC_CREATION_DATE, TeamcenterDateFormatter.formatCalendarToFrench(doc.getDateCreation())); + return map; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r10report/ExecutionR10.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r10report/ExecutionR10.java new file mode 100644 index 0000000..6d927e8 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r10report/ExecutionR10.java @@ -0,0 +1,168 @@ +package com.capgemini.reports.definition.r10report; + +import com.capgemini.framework.common.SettingsHelper; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.reports.JasperTemplate; +import com.capgemini.reports.ReportEnum; +import com.capgemini.reports.ReportLaunchTypeEnum; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.builder.R10Builder; +import com.capgemini.reports.builder.ReportBuilder; +import com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum; +import com.capgemini.reports.database.manager.MngCriteriaVal.CriteriaValue; +import com.capgemini.reports.definition.r10report.ExecutionR10.ReportDataR10; +import com.capgemini.reports.execution.AbstractExecutionReport; +import com.capgemini.reports.execution.IDataReportPreparator; +import com.capgemini.reports.printing.Printer.PrintFormat; +import com.capgemini.reports.reports.parameters.EffectivityDate; +import com.capgemini.reports.reports.parameters.Generics; +import com.capgemini.reports.reports.parameters.Generics.GenericType; +import com.capgemini.reports.reports.parameters.IChecker; +import com.capgemini.reports.reports.parameters.MonoMulti; +import com.capgemini.reports.reports.parameters.checker.*; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.ArrayList; +import java.util.List; + +/** + * Class responsible for executing a R10 report. + */ +@Getter +public class ExecutionR10 extends AbstractExecutionReport { + + private static final String SEPARATOR = "-"; + + private static final long serialVersionUID = 5053661528356709081L; + + // Policies parameters + private static final PolicyLocation R10_POLICY_XML_LIGHT = PolicyLocation.make("R10_policy_light", "/xml/policies/r10report/R10_policy_light.xml"); + private static final PolicyLocation R10_POLICY_XML_FULL = PolicyLocation.make("R10_policy_full", "/xml/policies/r10report/R10_policy_full.xml"); + + // Launch type parameter + private static final ReportLaunchTypeEnum REPORT_LAUNCH_TYPE = ReportLaunchTypeEnum.getReportLaunchType("common.launch.launchType.REPORT_R10"); + + // Revision rule parameter + private static final String REPORT_REVISION_RULE = SettingsHelper.getPropertyWithDefaultValue("common.bom.revisionRule.REPORT_R10", DEFAULT_REVISION_RULE); + + // Priority parameter + private static final int REPORT_PRIORITY = SettingsHelper.getPriority(ReportEnum.REPORT_R10); + + private final Generics generics; + private final MonoMulti monoMulti; + private final EffectivityDate effectivityDate; + + /** + * Usual constructor. + * + * @param generics the {@link Generics} + * @param monoMulti the level of explosion + * @param effectivityDate the effectivity + */ + public ExecutionR10(final Generics generics, final MonoMulti monoMulti, final EffectivityDate effectivityDate) { + super(REPORT_PRIORITY, REPORT_REVISION_RULE, REPORT_LAUNCH_TYPE); + this.generics = generics; + this.monoMulti = monoMulti; + this.effectivityDate = effectivityDate; + } + + @Override + public List getQuickChecks() { + List quickChecks = new ArrayList<>(); + quickChecks.add(new GenericExistenceChecker(generics)); + quickChecks.add(new ProductChecker(generics.getProductUnit().getProductID())); + quickChecks.add(new ProductUnitChecker(generics.getProductUnit())); + quickChecks.add(new EffectivityChecker(effectivityDate)); + return quickChecks; + } + + @Override + public PolicyLocation getPropertyPolicyForLongChecks() { + return R10_POLICY_XML_LIGHT; + } + + @Override + public PolicyLocation getFullPolicy() { + return R10_POLICY_XML_FULL; + } + + @Override + public List getLongChecks() { + List longChecks = new ArrayList<>(); + longChecks.add(new GenericUnderProductUnitChecker(generics)); + return longChecks; + } + + @Override + public String getTemplateLocation() { + return JasperTemplate.TEMPLATE_R10.getFilepath(); + } + + @Override + public ReportEnum getReportIdentifier() { + return ReportEnum.REPORT_R10; + } + + @Override + public String getSpecifiedFileName() { + StringBuilder builder = new StringBuilder("R10-"); + if (generics.getType() == GenericType.GENERIC) { + builder.append(generics.getID()).append(SEPARATOR); + } else if (generics.getType() == GenericType.GENERIC_ASSEMB) { + builder.append(generics.getID()).append(SEPARATOR); + } + builder.append(generics.getProductUnit().getProductID()).append(SEPARATOR); + builder.append(generics.getProductUnit().getUnitStr()).append(SEPARATOR); + builder.append((MonoMulti.MONO.equals(monoMulti)) ? "Mono" : "Multi").append(SEPARATOR); + return builder.toString(); + } + + @Override + public PrintFormat getPrintingFormat() { + return PrintFormat.XLSX; + } + + @Override + public List getLaunchData() { + List theCriteria = new ArrayList<>(); + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.PRODUCT, generics.getProductUnit().getProductID())); + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.UNIT, generics.getProductUnit().getUnitStr())); + if (generics.getType() == GenericType.GENERIC) { + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.GENERIC, generics.getID())); + } + if (generics.getType() == GenericType.GENERIC_ASSEMB) { + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.GENERIC_ASSEMB, generics.getID())); + } + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.MONO_MULTI, monoMulti.toString())); + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.EFFECTIVITY_DATE, effectivityDate.formatAsInputCriteria())); + return theCriteria; + } + + @Override + public IDataReportPreparator getDataPreparator() { + return new DataReportPreparatorR10(); + } + + @Override + public AbstractExecutionReport cloneTemplateToExecution() { + return new ExecutionR10(generics, monoMulti, effectivityDate); + } + + @Override + public Class getReportBuilderClass() { + return R10Builder.class; + } + + /** + * Stores all data obtained from TC. + */ + @AllArgsConstructor + static class ReportDataR10 { + private final BOMLineHolder config; + + public BOMLineHolder getConfig() { + return config; + } + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r10report/R10BomLineFlattener.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r10report/R10BomLineFlattener.java new file mode 100644 index 0000000..c133b34 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r10report/R10BomLineFlattener.java @@ -0,0 +1,88 @@ +package com.capgemini.reports.definition.r10report; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.bomlineholder.flattener.AbstractBomLineFlattener; +import com.capgemini.reports.bomlineholder.flattener.line.*; +import com.capgemini.reports.definition.r10report.lines.*; +import com.capgemini.reports.releasestatus.EffectivityBehaviourHelper; +import com.capgemini.reports.snecmaobjects.part.AbstractPart; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +/** + * Flattens a bomLine. + */ +public class R10BomLineFlattener extends AbstractBomLineFlattener>, DocumentExtractor> { + + private static final boolean VISIT_PART_BELOW_PART = false; + private static final boolean RETRIEVE_PART_NUMBER_UNDER_RF_GENERIC = false; + private static final boolean VISIT_PARTS_IN_PSEUDO_FOLDER = true; + private static final boolean GENERATE_BROTHER_LINES_BEFORE_RECURSION = false; + private final TcSession session; + private int counter; + + /** + * Usual constructor. + */ + R10BomLineFlattener(final TcSession session) { + super(EffectivityBehaviourHelper.visitOnlyUnitManagedParts(), VISIT_PARTS_IN_PSEUDO_FOLDER, RETRIEVE_PART_NUMBER_UNDER_RF_GENERIC, + VISIT_PART_BELOW_PART, null, GENERATE_BROTHER_LINES_BEFORE_RECURSION); + this.session = session; + this.setPseudoFolderBehaviour(new R10PseudoFolderBrowser()); + } + + @Override + protected AbstractQuad>, DocumentExtractor> makeQuad(final BOMLineHolder receptor, final BOMLineHolder rfReceptor, + final BOMLineHolder component, final BOMLineHolder rfComponent) { + return new R10Quad(session, receptor, rfReceptor, component, rfComponent, counter++); + } + + @Override + protected AbstractTopLine>, DocumentExtractor> makeTopline(final BOMLineHolder aTopBomLine) { + return new R10TopLine(aTopBomLine, counter++); // Nothing to do for this report: top line is ignored + } + + @Override + protected AbstractPartNumber>, DocumentExtractor> makePartNumber(final BOMLineHolder genericReceptor, + final BOMLineHolder rfGeneric, final BOMLineHolder partAero) { + return null; // Nothing to do for this report: part number is ignored + } + + @Override + protected AbstractPartRfPart>, DocumentExtractor> makePartRfPart(final BOMLineHolder partReceptor, + final BOMLineHolder rfPartComponent, final BOMLineHolder partComponent) { + return new R10PartRfPart(session, partReceptor, rfPartComponent, partComponent, counter++); + } + + @Override + protected AbstractPartPart>, DocumentExtractor> makePartPart(final BOMLineHolder partReceptor, + final BOMLineHolder partComponent) { + return null; // Nothing to do for this report: top line is ignored + } + + @Override + protected AbstractReceptorLine>, DocumentExtractor> makeReceptorLine(final BOMLineHolder part, + final BOMLineHolder rfPart) { + return null; // Nothing to do for this report: When there is no Component, there is no line + } + + @Override + protected AbstractProductGeneric>, DocumentExtractor> makeProductGeneric(final BOMLineHolder productReceptor, + final BOMLineHolder genericComponent, final BOMLineHolder rfGenericComponent) { + return new R10ProductGeneric(session, productReceptor, genericComponent, rfGenericComponent, counter++); + } + + private class R10PseudoFolderBrowser implements AbstractBomLineFlattener.DealWithAltOrDetPseudoFolder>, DocumentExtractor> { + + @Override + public Collection>, DocumentExtractor>> dealWithIt(final BOMLineHolder alt, final AbstractPart partInPseudoFolder) { + Collection>, DocumentExtractor>> list = new ArrayList<>(); + list.add(new R10AltPart(alt, partInPseudoFolder, counter++)); + return list; + } + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r10report/R10Keys.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r10report/R10Keys.java new file mode 100644 index 0000000..60fded3 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r10report/R10Keys.java @@ -0,0 +1,33 @@ +package com.capgemini.reports.definition.r10report; + +/** + * Key attributes to the Jasper report content. + */ +public enum R10Keys { + RECEPTOR_ID, + RECEPTOR_REVISION, + RECEPTOR_NAME, + REPERE_NAME, + REPERE_REVISION, + RESPONSABLE_REPERE, + QUANTITY, + COMPONENT_ID, + COMPONENT_REVISION, + COMPONENT_TYPE, + COMPONENT_NAME, + COMPONENT_REF_TRANSPOSED, + COMPONENT_DESIGN_MANAGER, + COMPONENT_NAME_ENG, + COMPONENT_CLASSEMENT, + COMPONENT_MASS, + COMPONENT_MASS_UNIT, + DOC_LINK_TYPE, + DOC_ID, + DOC_REVISION, + DOC_INDEX, + DOC_TYPE, + DOC_NAME, + DOC_NAME_ENG, + DOC_STATUS, + DOC_CREATION_DATE +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r10report/R10Printer.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r10report/R10Printer.java new file mode 100644 index 0000000..42076f6 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r10report/R10Printer.java @@ -0,0 +1,105 @@ +package com.capgemini.reports.definition.r10report; + +import com.capgemini.framework.common.DoubleFormatter; +import com.capgemini.framework.common.StringHelper; +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.reports.bomlineholder.flattener.line.SnecmaLine; +import com.capgemini.reports.definition.r10report.ExecutionR10.ReportDataR10; +import com.capgemini.reports.documentationobjects.AbstractDoc; +import com.capgemini.reports.execution.mapconstructor.AbstractStaticTemplateMapConstructor; +import com.capgemini.reports.printing.PrintParameters; +import lombok.extern.slf4j.Slf4j; + +import java.util.*; + +/** + * Extracts the relevant data obtained from TC into the expected List of Maps for Jasper. + */ +@Slf4j +public class R10Printer extends AbstractStaticTemplateMapConstructor { + private static final long serialVersionUID = 2418903684813779698L; + + private static final int SIGNIFICANT_DIGITS = 6; + private static final Map EMPTY_BOM_MAP = new EnumMap<>(R10Keys.class); + + static { + EMPTY_BOM_MAP.put(R10Keys.COMPONENT_CLASSEMENT, ""); + EMPTY_BOM_MAP.put(R10Keys.COMPONENT_DESIGN_MANAGER, ""); + EMPTY_BOM_MAP.put(R10Keys.COMPONENT_ID, ""); + EMPTY_BOM_MAP.put(R10Keys.COMPONENT_MASS, ""); + EMPTY_BOM_MAP.put(R10Keys.COMPONENT_MASS_UNIT, ""); + EMPTY_BOM_MAP.put(R10Keys.COMPONENT_NAME, ""); + EMPTY_BOM_MAP.put(R10Keys.COMPONENT_NAME_ENG, ""); + EMPTY_BOM_MAP.put(R10Keys.COMPONENT_REF_TRANSPOSED, ""); + EMPTY_BOM_MAP.put(R10Keys.COMPONENT_REVISION, ""); + EMPTY_BOM_MAP.put(R10Keys.COMPONENT_TYPE, ""); + EMPTY_BOM_MAP.put(R10Keys.QUANTITY, ""); + EMPTY_BOM_MAP.put(R10Keys.RECEPTOR_ID, ""); + EMPTY_BOM_MAP.put(R10Keys.RECEPTOR_NAME, ""); + EMPTY_BOM_MAP.put(R10Keys.RECEPTOR_REVISION, ""); + EMPTY_BOM_MAP.put(R10Keys.REPERE_NAME, ""); + EMPTY_BOM_MAP.put(R10Keys.REPERE_REVISION, ""); + EMPTY_BOM_MAP.put(R10Keys.RESPONSABLE_REPERE, ""); + } + + private final Calendar effectivityDate; + + public R10Printer(final Calendar effectivityDate) { + this.effectivityDate = effectivityDate; + } + + @Override + public void constructDataMaps(final TcSession session, final PrintParameters printParameters, final ReportDataR10 reportData) throws KurtException { + log.info("Browsing the Snecma Objects"); + R10BomLineFlattener flattener = new R10BomLineFlattener(session); + flattener.visitTopReceptorBom(session, reportData.getConfig()); + + // Degroup with doc data + log.info("Regrouping conf elements with their documents"); + List> result = new ArrayList<>(); + Map docCache = new HashMap<>(); + for (SnecmaLine>, DocumentExtractor> elem : flattener.getConfig()) { + Map bomMap = generateCommonBomMap(elem); + List> docMaps = elem.transform(new DocumentExtractor(effectivityDate, docCache)); + // Put the bom info in the 1st line, leave the rest blank + Iterator> docIterator = docMaps.iterator(); + docIterator.next().putAll(bomMap); + // Put empty fields in the rest + while (docIterator.hasNext()) { + docIterator.next().putAll(EMPTY_BOM_MAP); + } + result.addAll(docMaps); + } + log.info("{} Lines generated for {} parts.", result.size(), flattener.getConfig().size()); + printParameters.addReportDataFromEnum(result); + } + + private Map generateCommonBomMap(final SnecmaLine>, DocumentExtractor> line) { + String massStr; + if (line.getMass() == null) { + massStr = StringHelper.EMPTY; // when no mass is set (ex: receptor without component) print nothing + } else { + massStr = DoubleFormatter.toSignificantDigits(line.getMass(), SIGNIFICANT_DIGITS); + } + Map map = new EnumMap<>(R10Keys.class); + map.put(R10Keys.RECEPTOR_ID, line.getIDReceptor()); + map.put(R10Keys.RECEPTOR_NAME, line.getNameReceptor()); + map.put(R10Keys.RECEPTOR_REVISION, line.getRevisionReceptor()); + map.put(R10Keys.REPERE_NAME, line.getRepereName()); + map.put(R10Keys.REPERE_REVISION, line.getRepereRevision()); + map.put(R10Keys.RESPONSABLE_REPERE, line.getResponsableRepere()); + map.put(R10Keys.COMPONENT_ID, line.getIDComponent()); + map.put(R10Keys.COMPONENT_REVISION, line.getIDRevisionComponent()); + map.put(R10Keys.COMPONENT_NAME, line.getNameReference()); + map.put(R10Keys.COMPONENT_NAME_ENG, line.getDesignationENG()); + map.put(R10Keys.COMPONENT_TYPE, line.getTypeReference()); + map.put(R10Keys.COMPONENT_REF_TRANSPOSED, line.getReferenceTransposed()); + map.put(R10Keys.COMPONENT_DESIGN_MANAGER, line.getResponsableConception()); + map.put(R10Keys.COMPONENT_CLASSEMENT, line.getClassement()); + map.put(R10Keys.COMPONENT_MASS, massStr); + map.put(R10Keys.COMPONENT_MASS_UNIT, line.getMassUnit()); + map.put(R10Keys.QUANTITY, line.getQuantite()); + return map; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r10report/lines/R10AltPart.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r10report/lines/R10AltPart.java new file mode 100644 index 0000000..4381c62 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r10report/lines/R10AltPart.java @@ -0,0 +1,35 @@ +package com.capgemini.reports.definition.r10report.lines; + +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.bomlineholder.flattener.line.AbstractAltPart; +import com.capgemini.reports.definition.r10report.DocumentExtractor; +import com.capgemini.reports.definition.r10report.R10Keys; +import com.capgemini.reports.snecmaobjects.part.AbstractPart; +import lombok.Getter; + +import java.util.List; +import java.util.Map; + +/** + * Represents The link between an Alt and a Part in its pseudo-folder. + */ +@Getter +public class R10AltPart extends AbstractAltPart>, DocumentExtractor> { + + /** + * builds the link between an Altenrate and a Part in its pseudo-folder. + * + * @param alt the Alternate + * @param child the child part + * @param counter the position of this line in the nomenclature. + */ + public R10AltPart(final BOMLineHolder alt, final AbstractPart child, final int counter) { + super(alt, child, counter); + } + + @Override + public List> transform(final DocumentExtractor extractor) { + return extractor.extract(this); + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r10report/lines/R10PartRfPart.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r10report/lines/R10PartRfPart.java new file mode 100644 index 0000000..8878bdc --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r10report/lines/R10PartRfPart.java @@ -0,0 +1,36 @@ +package com.capgemini.reports.definition.r10report.lines; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.bomlineholder.flattener.line.AbstractPartRfPart; +import com.capgemini.reports.definition.r10report.DocumentExtractor; +import com.capgemini.reports.definition.r10report.R10Keys; +import lombok.Getter; + +import java.util.List; +import java.util.Map; + +/** + * Represents a classical 'triplet' between a Part, a Rf Part and a Part. + */ +@Getter +public class R10PartRfPart extends AbstractPartRfPart>, DocumentExtractor> { + + /** + * Builds a classical 'triplet' between a Part, a Rf Part and a Part. + * + * @param partReceptor the {@link BOMLineHolder} Part receptor + * @param rfPartComponent the {@link BOMLineHolder} RF Part receptor + * @param partComponent the {@link BOMLineHolder} APrt component + * @param counter the position of the line in the nomenclature. + */ + public R10PartRfPart(final TcSession session, final BOMLineHolder partReceptor, final BOMLineHolder rfPartComponent, final BOMLineHolder partComponent, + final int counter) { + super(session, partReceptor, rfPartComponent, partComponent, counter); + } + + @Override + public List> transform(final DocumentExtractor extractor) { + return extractor.extract(this); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r10report/lines/R10ProductGeneric.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r10report/lines/R10ProductGeneric.java new file mode 100644 index 0000000..768d48b --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r10report/lines/R10ProductGeneric.java @@ -0,0 +1,62 @@ +package com.capgemini.reports.definition.r10report.lines; + +import com.capgemini.framework.common.StringHelper; +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.bomlineholder.flattener.line.AbstractProductGeneric; +import com.capgemini.reports.definition.r10report.DocumentExtractor; +import com.capgemini.reports.definition.r10report.R10Keys; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.EnumMap; +import java.util.List; +import java.util.Map; + +/** + * Represents a Product - Generic line for R07 report. + */ +@Slf4j +public class R10ProductGeneric extends AbstractProductGeneric>, DocumentExtractor> { + + /** + * Builds a Product - Generic line for the R07 report. + * + * @param productReceptor the {@link BOMLineHolder} product (receptor) + * @param genericComponent the {@link BOMLineHolder} generic (component) + * @param rfGenericComponent the {@link BOMLineHolder} RfGeneric + * @param counter the line num + */ + public R10ProductGeneric(final TcSession session, final BOMLineHolder productReceptor, final BOMLineHolder genericComponent, final BOMLineHolder rfGenericComponent, + final int counter) { + super(session, productReceptor, genericComponent, rfGenericComponent, counter); + } + + @Override + public List> transform(final DocumentExtractor extractor) { + try { + return extractor.extract(this); + } catch (KurtException e) { + log.error("Unable to obtain the list of documents for " + getLineId(), e); + // Make the line still appear by placing an entry in the list. However all fields will be empty. + Map mapWithEmptyStrings = new EnumMap<>(R10Keys.class); + for (R10Keys key : R10Keys.values()) { + mapWithEmptyStrings.put(key, StringHelper.EMPTY); + } + List> listWithOneMapWithEmptyString = new ArrayList<>(); + listWithOneMapWithEmptyString.add(mapWithEmptyStrings); + return listWithOneMapWithEmptyString; + } + } + + @Override + public Double getMass() { + return 0d; + } + + @Override + public String getMassUnit() { + return "Kg"; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r10report/lines/R10Quad.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r10report/lines/R10Quad.java new file mode 100644 index 0000000..78592b2 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r10report/lines/R10Quad.java @@ -0,0 +1,88 @@ +package com.capgemini.reports.definition.r10report.lines; + +import com.capgemini.framework.common.StringHelper; +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.bomlineholder.flattener.line.AbstractQuad; +import com.capgemini.reports.definition.r10report.DocumentExtractor; +import com.capgemini.reports.definition.r10report.R10Keys; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.EnumMap; +import java.util.List; +import java.util.Map; + +/** + * Represents a {@link AbstractQuad} line, with receptor and component, both having their own repere.
    + * Receptors and components can be Parts or Generics.
    + * For the R07, the Quad accepts a TransformerR07 which will generate a custom Id for it, for sorting purposes. + */ +@Slf4j +@Getter +public class R10Quad extends AbstractQuad>, DocumentExtractor> { + + + /** + * Builds a 'quad' object, using receptor, its repere, a component, and its repere. + * + * @param recepteurBL the {@link BOMLineHolder} receptor + * @param repereRecepteurBL the {@link BOMLineHolder} repere of the receptor + * @param composantBL the {@link BOMLineHolder} composant + * @param repereComposantBL the {@link BOMLineHolder} repere of the composant + * @param counter the position of this line in the Bom + */ + public R10Quad(final TcSession session, final BOMLineHolder recepteurBL, final BOMLineHolder repereRecepteurBL, final BOMLineHolder composantBL, + final BOMLineHolder repereComposantBL, final int counter) { + super(session, recepteurBL, repereRecepteurBL, composantBL, repereComposantBL, counter); + } + + @Override + public List> transform(final DocumentExtractor extractor) { + try { + return extractor.extract(this); + } catch (KurtException e) { + log.error("Unable to obtain the list of documents for this Quadline: " + getLineId(), e); + // Make the line still appear by placing an entry in the list. However all fields will be empty. + Map mapWithEmptyStrings = new EnumMap<>(R10Keys.class); + for (R10Keys key : R10Keys.values()) { + mapWithEmptyStrings.put(key, StringHelper.EMPTY); + } + List> listWithOneMapWithEmptyString = new ArrayList<>(); + listWithOneMapWithEmptyString.add(mapWithEmptyStrings); + return listWithOneMapWithEmptyString; + } + + } + + @Override + public String getClassement() { + if (getComposant().isGeneric() || getComposant().isProduct()) { + return "-"; + } else { + return super.getClassement(); + } + } + + @Override + public Double getMass() { + if (getComposant().isGeneric()) { + return 0d; + } else { + return super.getMass(); + } + } + + @Override + public String getMassUnit() { + if (getComposant().isGeneric() || SnecmaObjectTypes.PART_MAT_REVISION.equals(getComposant().getType())) { + return "Kg"; + } else { + return super.getMassUnit(); + } + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r10report/lines/R10ReceptorLine.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r10report/lines/R10ReceptorLine.java new file mode 100644 index 0000000..26608ee --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r10report/lines/R10ReceptorLine.java @@ -0,0 +1,46 @@ +package com.capgemini.reports.definition.r10report.lines; + +import com.capgemini.framework.common.StringHelper; +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.bomlineholder.flattener.line.AbstractReceptorLine; +import com.capgemini.reports.definition.r10report.DocumentExtractor; +import com.capgemini.reports.definition.r10report.R10Keys; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.EnumMap; +import java.util.List; +import java.util.Map; + +/** + * Represents a Receptor whose Repere does ot have a Component. + */ +@Slf4j +public class R10ReceptorLine extends AbstractReceptorLine>, DocumentExtractor> { + + /** + * Builds a Receptor whose Repere does not have a Component. + */ + public R10ReceptorLine(final TcSession session, final BOMLineHolder recepteurBL, final BOMLineHolder repereRecepteurBL, final int counter) { + super(session, recepteurBL, repereRecepteurBL, counter); + } + + @Override + public List> transform(final DocumentExtractor extractor) { + try { + return extractor.extract(this); + } catch (KurtException e) { + log.error("Unable to obtain the list of documents for this TopLine: " + getLineId(), e); + // Make the line still appear by placing an entry in the list. However all fields will be empty. + Map mapWithEmptyStrings = new EnumMap<>(R10Keys.class); + for (R10Keys key : R10Keys.values()) { + mapWithEmptyStrings.put(key, StringHelper.EMPTY); + } + List> listWithOneMapWithEmptyString = new ArrayList<>(); + listWithOneMapWithEmptyString.add(mapWithEmptyStrings); + return listWithOneMapWithEmptyString; + } + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r10report/lines/R10TopLine.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r10report/lines/R10TopLine.java new file mode 100644 index 0000000..9738dc1 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r10report/lines/R10TopLine.java @@ -0,0 +1,85 @@ +package com.capgemini.reports.definition.r10report.lines; + +import com.capgemini.framework.common.StringHelper; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.bomlineholder.flattener.line.AbstractTopLine; +import com.capgemini.reports.definition.r10report.DocumentExtractor; +import com.capgemini.reports.definition.r10report.R10Keys; +import com.capgemini.reports.snecmaobjects.generic.AbstractGenericRevision; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.EnumMap; +import java.util.List; +import java.util.Map; + +/** + * Represents a TopLine of nemenclature (i.e. Product or Generic) for R07. + */ +@Slf4j +public class R10TopLine extends AbstractTopLine>, DocumentExtractor> { + + /** + * Simple constructor. + * + * @param topBomLine the original topLine {@link BOMLineHolder} + * @param lineNum the line number (normally zero for a TopLine!) + */ + public R10TopLine(final BOMLineHolder topBomLine, final int lineNum) { + super(topBomLine, lineNum); + } + + @Override + public List> transform(final DocumentExtractor transformer) { + try { + return transformer.extract(this); + } catch (KurtException e) { + log.error("Unable to obtain the list of documents for this TopLine: " + getLineId(), e); + // Make the line still appear by placing an entry in the list. However all fields will be empty. + Map mapWithEmptyStrings = new EnumMap<>(R10Keys.class); + for (R10Keys key : R10Keys.values()) { + mapWithEmptyStrings.put(key, StringHelper.EMPTY); + } + List> listWithOneMapWithEmptyString = new ArrayList<>(); + listWithOneMapWithEmptyString.add(mapWithEmptyStrings); + return listWithOneMapWithEmptyString; + } + } + + @Override + public String getResponsableConception() { + if (getBomLineObject().isGeneric()) { + return ((AbstractGenericRevision) getBomLineObject()).getResponsableConception(); + } else { + return StringHelper.EMPTY; + } + } + + @Override + public String getClassement() { + if (getBomLineObject().isGeneric() || getBomLineObject().isProduct()) { + return "-"; + } else { + return super.getClassement(); + } + } + + @Override + public Double getMass() { + if (getBomLineObject().isGeneric()) { + return 0d; + } else { + return super.getMass(); + } + } + + @Override + public String getMassUnit() { + if (getBomLineObject().isGeneric()) { + return "Kg"; + } else { + return super.getMassUnit(); + } + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r11report/DataReportPreparatorR11.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r11report/DataReportPreparatorR11.java new file mode 100644 index 0000000..799d313 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r11report/DataReportPreparatorR11.java @@ -0,0 +1,106 @@ +package com.capgemini.reports.definition.r11report; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.EmptyNomenclatureException; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcBomObject; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcBomObjectFactory; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcRevisionRule; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcRevisionRuleProperties; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.product.TcProduct; +import com.capgemini.framework.teamcenter.object.runtime.TcBomWindow; +import com.capgemini.framework.teamcenter.object.runtime.TcBomWindowConfiguration; +import com.capgemini.framework.teamcenter.object.runtime.TcRevisionRulesConfiguration; +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.bomlineholder.BOMLineHolderFactory; +import com.capgemini.reports.definition.r11report.data.extractor.FilterByTypeObject; +import com.capgemini.reports.exceptions.InvalidUserInputException; +import com.capgemini.reports.exceptions.UserInputErrorEnum; +import com.capgemini.reports.execution.IDataReportPreparator; +import com.capgemini.reports.execution.strategies.IExecutionStrategy; +import com.capgemini.reports.filter.AllIsGoodFilter; +import com.capgemini.reports.printing.PrintParameters; +import com.capgemini.reports.reports.parameters.EffectivityDate; +import com.capgemini.reports.reports.parameters.Generics; +import com.capgemini.reports.reports.parameters.MonoMulti; +import com.capgemini.reports.teamcenter.resolution.structureservice.IStructureServiceCaller; +import com.capgemini.reports.teamcenter.resolution.structureservice.MultiStructureServiceCaller; +import com.capgemini.reports.teamcenter.resolution.structureservice.TripleStructureServiceCaller; +import com.teamcenter.soa.client.model.ModelObject; +import com.teamcenter.soa.client.model.strong.Form; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + + +/** + * Class which prepare data for the reports. + */ +public class DataReportPreparatorR11 implements IDataReportPreparator { + private static final long serialVersionUID = 6949217671922185431L; + private static final Logger LOGGER = LoggerFactory.getLogger(DataReportPreparatorR11.class); + + @Override + public String print(TcSession session, ExecutionR11 execution, IExecutionStrategy executionStrategy) throws KurtException { + PrintParameters printParameters = prepareData(session, execution); + executionStrategy.print(printParameters, execution); + return executionStrategy.getReportFileName(execution) + printParameters.getOuputFileExtension(); + } + + private PrintParameters prepareData(final TcSession session, final ExecutionR11 report) throws KurtException { + LOGGER.debug("PrepareData started on: {}", report.getReportIdentifier().getReportTitle()); + + // Setup the policy + session.setObjectPropPolicy(report.getFullPolicy()); + + Generics generic = report.getGeneric(); + TcBomObject topLineObject = new TcBomObjectFactory(session, report.getGeneric().getItem(session)).create(); + TcProduct productObject = new TcProduct(session, generic.getProductUnit().getProduct(session)); + int unit = generic.getProductUnit().getUnit(); + EffectivityDate effectivityDate = report.getEffectivity(); + + TcRevisionRuleProperties revisionRuleProperties = new TcRevisionRuleProperties(productObject, unit, effectivityDate.isNow() ? null : effectivityDate.getDateTime()); + + TcRevisionRule revisionRule = session.findRevRule(report.getRevisionRule()); + TcRevisionRulesConfiguration revRulesConfiguration = new TcRevisionRulesConfiguration(revisionRule, revisionRuleProperties); + + IStructureServiceCaller service; + if (MonoMulti.MONO.equals(report.getMonoMulti())) { + service = new TripleStructureServiceCaller(session); + } else { + service = new MultiStructureServiceCaller(session); + } + + try (TcBomWindow bomWindow = session.createBomWindow(new TcBomWindowConfiguration(topLineObject, revRulesConfiguration))) { + session.setObjectPropPolicy(report.getFullPolicy()); + + BOMLineHolder unbuiltTopLine = service.resolve(bomWindow.topLine(), new AllIsGoodFilter()); + List itemRevMaster = unbuiltTopLine.getAllItemRevMasters(); + session.loadProperties(itemRevMaster.toArray(new ModelObject[itemRevMaster.size()])); + + BOMLineHolderFactory.buildTopBom(session, unbuiltTopLine, new FilterByTypeObject(SnecmaObjectTypes.ALTERNATE_REVISION, + SnecmaObjectTypes.DET_REVISION, SnecmaObjectTypes.RF_PART_REVISION, SnecmaObjectTypes.PART_AERO_REVISION, + SnecmaObjectTypes.PART_MAT_REVISION, SnecmaObjectTypes.PART_NO_AERO_REVISION, SnecmaObjectTypes.GENERIC_REVISION, + SnecmaObjectTypes.RF_GENERIC_REVISION, SnecmaObjectTypes.STANDARD_REVISION, SnecmaObjectTypes.MOCKUP_REVISION, + SnecmaObjectTypes.RF_ADMIN_AG_REVISION, SnecmaObjectTypes.RF_ADMIN_AP_REVISION, SnecmaObjectTypes.RF_ADMIN_REVISION)); + + + R11Printer printer = new R11Printer(); + PrintParameters printParameters = printer.makeMasterTemplate(report, unbuiltTopLine); + printer.constructDataMaps(session, printParameters, unbuiltTopLine); + + return printParameters; + } catch (EmptyNomenclatureException e) { + switch (generic.getType()) { + case GENERIC: + throw new InvalidUserInputException(UserInputErrorEnum.NO_DATA_COULD_BE_EXTRACTED_FOR_GENERIC_PRODUCT_AND_UNIT, e); + case GENERIC_ASSEMB: + throw new InvalidUserInputException(UserInputErrorEnum.NO_DATA_COULD_BE_EXTRACTED_FOR_GENERIC_ASSEMB_PRODUCT_AND_UNIT, e); + default: + throw new KurtException("The TC Nomenclature Resolution returned null", e); + } + } + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r11report/ExecutionR11.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r11report/ExecutionR11.java new file mode 100644 index 0000000..8baff2c --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r11report/ExecutionR11.java @@ -0,0 +1,154 @@ +package com.capgemini.reports.definition.r11report; + +import com.capgemini.framework.common.SettingsHelper; +import com.capgemini.framework.common.TeamcenterDateFormatter; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.reports.JasperTemplate; +import com.capgemini.reports.ReportEnum; +import com.capgemini.reports.ReportLaunchTypeEnum; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.builder.R11Builder; +import com.capgemini.reports.builder.ReportBuilder; +import com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum; +import com.capgemini.reports.database.manager.MngCriteriaVal.CriteriaValue; +import com.capgemini.reports.definition.r11report.checker.R11GenericExistenceChecker; +import com.capgemini.reports.execution.AbstractExecutionReport; +import com.capgemini.reports.execution.IDataReportPreparator; +import com.capgemini.reports.printing.Printer.PrintFormat; +import com.capgemini.reports.reports.parameters.*; +import com.capgemini.reports.reports.parameters.Generics.GenericType; +import com.capgemini.reports.reports.parameters.checker.EffectivityChecker; +import com.capgemini.reports.reports.parameters.checker.ProductChecker; +import com.capgemini.reports.reports.parameters.checker.ProductUnitChecker; +import lombok.EqualsAndHashCode; +import lombok.Getter; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; + +/** + * Class which manage the execution of a R11 report. + */ +@Getter +@EqualsAndHashCode(callSuper = true) +public class ExecutionR11 extends AbstractExecutionReport { + private static final long serialVersionUID = 2431051269754641192L; + + private static final String SEPARATOR = "-"; + private static final String MODEL_DATE = "dd-MM-yyyy"; + // Policies parameters + private static final PolicyLocation R11_POLICY_XML_LIGHT = PolicyLocation.make("R11_policy_light", "/xml/policies/r11report/R11_policy_light.xml"); + private static final PolicyLocation R11_POLICY_XML_FULL = PolicyLocation.make("R11_policy_full", "/xml/policies/r11report/R11_policy_full.xml"); + // Launch type parameter + private static final ReportLaunchTypeEnum REPORT_LAUNCH_TYPE = ReportLaunchTypeEnum.getReportLaunchType("common.launch.launchType.REPORT_R11"); + // Revision rule parameter + private static final String REPORT_REVISION_RULE = SettingsHelper.getPropertyWithDefaultValue("common.bom.revisionRule.REPORT_R11", DEFAULT_REVISION_RULE); + // Priority parameter + private static final int REPORT_PRIORITY = SettingsHelper.getPriority(ReportEnum.REPORT_R11); + private final Generics generic; + private final MonoMulti monoMulti; + private final EffectivityDate effectivity; + + /** + * Constructor. + * + * @param generic {@link Generics} - the generic configuration with his product unit + * @param aMonoMulti {@link MonoMulti} - the level of the resolution structure + * @param anEffectivity {@link EffectivityDate} - the effectivity date + */ + public ExecutionR11(final Generics generic, final MonoMulti aMonoMulti, final EffectivityDate anEffectivity) { + super(REPORT_PRIORITY, REPORT_REVISION_RULE, REPORT_LAUNCH_TYPE); + this.generic = generic; + this.monoMulti = aMonoMulti; + this.effectivity = anEffectivity; + } + + @Override + public List getQuickChecks() { + List quickChecks = new ArrayList<>(); + ProductUnit productUnit = generic.getProductUnit(); + quickChecks.add(new ProductChecker(productUnit.getProductID())); + quickChecks.add(new ProductUnitChecker(productUnit)); + quickChecks.add(new R11GenericExistenceChecker(generic)); + quickChecks.add(new EffectivityChecker(effectivity)); + return quickChecks; + } + + @Override + public PolicyLocation getPropertyPolicyForLongChecks() { + return R11_POLICY_XML_LIGHT; + } + + @Override + public PolicyLocation getFullPolicy() { + return R11_POLICY_XML_FULL; + } + + @Override + public List getLongChecks() { + return new ArrayList<>(); + } + + @Override + public String getTemplateLocation() { + return JasperTemplate.TEMPLATE_R11.getFilepath(); + } + + @Override + public ReportEnum getReportIdentifier() { + return ReportEnum.REPORT_R11; + } + + @Override + public String getSpecifiedFileName() { + String dateSystem = TeamcenterDateFormatter.formatCalendarToPattern(Calendar.getInstance(), MODEL_DATE); + StringBuilder builder = new StringBuilder("R11-"); + if (generic.getType() == GenericType.GENERIC) { + builder.append(generic.getID()).append(SEPARATOR); + } else if (generic.getType() == GenericType.GENERIC_ASSEMB) { + builder.append(generic.getID()).append(SEPARATOR); + } + builder.append(generic.getProductUnit().getProductID()).append(SEPARATOR); + builder.append(generic.getProductUnit().getUnitStr()).append(SEPARATOR); + builder.append((MonoMulti.MONO.equals(monoMulti)) ? "Mono" : "Multi").append(SEPARATOR); + builder.append(effectivity.getDateTime() != null ? effectivity.formatAsInputCriteria() : dateSystem); + return builder.toString(); + } + + @Override + public PrintFormat getPrintingFormat() { + return PrintFormat.XLSX; + } + + @Override + public List getLaunchData() { + List theCriteria = new ArrayList<>(); + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.PRODUCT, generic.getProductUnit().getProductID())); + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.UNIT, generic.getProductUnit().getUnitStr())); + if (generic.getType() == GenericType.GENERIC) { + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.GENERIC, generic.getID())); + } + if (generic.getType() == GenericType.GENERIC_ASSEMB) { + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.GENERIC_ASSEMB, generic.getID())); + } + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.MONO_MULTI, monoMulti.toString())); + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.EFFECTIVITY_DATE, effectivity.formatAsInputCriteria())); + return theCriteria; + } + + @Override + public IDataReportPreparator getDataPreparator() { + return new DataReportPreparatorR11(); + } + + @Override + public AbstractExecutionReport cloneTemplateToExecution() { + return new ExecutionR11(generic, monoMulti, effectivity); + } + + @Override + public Class getReportBuilderClass() { + return R11Builder.class; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r11report/R11Keys.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r11report/R11Keys.java new file mode 100644 index 0000000..d02ac22 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r11report/R11Keys.java @@ -0,0 +1,36 @@ +package com.capgemini.reports.definition.r11report; + +/** + * Enum class for the report R11. + */ +public enum R11Keys { + IDENTIFIANT_RECEPTEUR, + REVISION_RECEPTEUR, + NOM_RECEPTEUR, + REPERE_FONCTIONNEL, + REVISION_REPERE_FONCTIONNEL, + RESPONSABLE_REPERE, + MAQUETTE_INTERNE_EXTERNE, + STATUT_MISE_EN_MAQUETTE, + REF_FRABRICANT_REF_SNECMA, + REVISION_REFERENCE, + NOM_REFERENCE, + TYPE_OBJET, + DESIGNATION_ANGLAISE, + CONTROLE_COHERENCE, + STATUT_PART_P, + STATUT_PART_S, + STATUT_PART_K, + STATUT_PART_R, + STATUT_PART_M, + STATUT_PART_C, + STATUT_PART_I, + NOMBRE_REPERE_FONCTIONNEL_METTRE_EN_MAQUETTE, + NOMBRE_REPERE_FONCTIONNEL_MAQUETTE, + MISE_EN_MAQUETTE_POURCENTAGE, + NOMBRE_REPERE_FONCTIONNEL_INCOHERENT, + REPERE_FONCTIONNEL_MAQUETTE_INCOHERENTE_POURCENTAGE, + NOMBRE_REPERE_FONCTIONNEL_MISE_EN_MAQUETTE_COHERENTE, + POURCENTAGE_MAQUETTE_COHERENTE, + A_METTRE_EN_MAQUETTE +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r11report/R11Printer.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r11report/R11Printer.java new file mode 100644 index 0000000..1e61313 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r11report/R11Printer.java @@ -0,0 +1,236 @@ +package com.capgemini.reports.definition.r11report; + +import com.capgemini.framework.common.LanguageHelper; +import com.capgemini.framework.common.ReportFolderOutputHelper; +import com.capgemini.framework.common.ResourceHelper; +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.object.pom.status.StatusEnum; +import com.capgemini.framework.teamcenter.object.pom.status.TcEffectivity; +import com.capgemini.framework.teamcenter.object.pom.status.TcReleaseStatus; +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.definition.r11report.data.extractor.BomLineBrowserR11; +import com.capgemini.reports.definition.r11report.data.extractor.R11ReceptorRepere; +import com.capgemini.reports.exceptions.FileLoadingException; +import com.capgemini.reports.exceptions.InvalidInputException; +import com.capgemini.reports.exceptions.ReportPrintException; +import com.capgemini.reports.execution.mapconstructor.IMapConstructor; +import com.capgemini.reports.filter.AllIsGoodFilter; +import com.capgemini.reports.printing.PrintParameters; +import com.capgemini.reports.printing.PrintReportHelper; +import com.capgemini.reports.snecmaobjects.ISnecmaObject; +import com.capgemini.reports.snecmaobjects.admin.RFAdminRevision; +import com.capgemini.reports.snecmaobjects.generic.GenericRevision; +import com.capgemini.reports.snecmaobjects.mockup.MockupRevision; +import com.capgemini.reports.snecmaobjects.part.AbstractPart; +import com.capgemini.reports.snecmaobjects.rf.AbstractRF; + +import java.util.*; + +/** + * Printer for the report R11. Put in the map all data to send to the template jasper. + */ +public class R11Printer implements IMapConstructor { + private static final long serialVersionUID = -8731017017029400269L; + + private static final int PERCENT = 100; + private static final String COMA = ", "; + private static final String EMPTY = ""; + private static final String NON = "Non"; + private static final String OUI = "Oui"; + + private int nbRepereFonctionnelMettreEnMaquette; + private int nbRepereMisEnMaquette; + private int nbRepereFonctionnelAvecIncoherence; + private int nbRepereFonctionnelAvecCoherence; + + @Override + public void constructDataMaps(final TcSession session, final PrintParameters printParameters, final BOMLineHolder topLine) throws KurtException { + BomLineBrowserR11 bomLineBrowserR11 = new BomLineBrowserR11(); + bomLineBrowserR11.setFilterNomenclature(new AllIsGoodFilter()); + bomLineBrowserR11.visitTopReceptorBom(session, topLine); + List> lstMapData = new ArrayList<>(); + Map parameters = new EnumMap<>(R11Keys.class); + treatementReceptor(bomLineBrowserR11.getConfig(), lstMapData); + printParameters.addReportData(lstMapData); + parameters.put(R11Keys.NOMBRE_REPERE_FONCTIONNEL_METTRE_EN_MAQUETTE, nbRepereFonctionnelMettreEnMaquette); + parameters.put(R11Keys.NOMBRE_REPERE_FONCTIONNEL_INCOHERENT, nbRepereFonctionnelAvecIncoherence); + parameters.put(R11Keys.NOMBRE_REPERE_FONCTIONNEL_MAQUETTE, nbRepereMisEnMaquette); + parameters.put(R11Keys.NOMBRE_REPERE_FONCTIONNEL_MISE_EN_MAQUETTE_COHERENTE, nbRepereFonctionnelAvecCoherence); + String ratioMiseEnMaquette = safeDiv(nbRepereMisEnMaquette, nbRepereFonctionnelMettreEnMaquette); + String ratioMaquettesIncoherentes = safeDiv(nbRepereFonctionnelAvecIncoherence, nbRepereMisEnMaquette); + String ratioMaquettesCoherentes = safeDiv(nbRepereFonctionnelAvecCoherence, nbRepereFonctionnelMettreEnMaquette); + parameters.put(R11Keys.MISE_EN_MAQUETTE_POURCENTAGE, ratioMiseEnMaquette); + parameters.put(R11Keys.REPERE_FONCTIONNEL_MAQUETTE_INCOHERENTE_POURCENTAGE, ratioMaquettesIncoherentes); + parameters.put(R11Keys.POURCENTAGE_MAQUETTE_COHERENTE, ratioMaquettesCoherentes); + printParameters.addReportParameters(parameters); + } + + private String safeDiv(final int num, final int denom) { + if (denom == 0) { + return "0 %"; + } else { + return ((PERCENT * num) / denom) + " %"; + } + } + + private void treatementReceptor(final List lstReceptorRepere, final List> lstMapData) { + for (R11ReceptorRepere element : lstReceptorRepere) { + Map mapLine = new HashMap<>(); + mapLine.put(R11Keys.IDENTIFIANT_RECEPTEUR.toString(), element.getIDReceptor()); + mapLine.put(R11Keys.NOM_RECEPTEUR.toString(), element.getNameReceptor()); + mapLine.put(R11Keys.REVISION_RECEPTEUR.toString(), element.getRevisionReceptor()); + mapLine.put(R11Keys.REPERE_FONCTIONNEL.toString(), element.getRepereName()); + mapLine.put(R11Keys.REVISION_REPERE_FONCTIONNEL.toString(), element.getRepereRevision()); + mapLine.put(R11Keys.RESPONSABLE_REPERE.toString(), element.getResponsableRepere()); + mapLine.put(R11Keys.MAQUETTE_INTERNE_EXTERNE.toString(), element.getMaquetteInterneExterne()); + extratorDataRepere(element, mapLine); + lstMapData.add(mapLine); + } + } + + private void extratorDataRepere(final R11ReceptorRepere receptorRepere, final Map mapLine) { + BOMLineHolder bomLineRepere = receptorRepere.getRepereFonctionnel(); + if (bomLineRepere.getObjectType().equals(SnecmaObjectTypes.RF_GENERIC_REVISION)) { + getRepereGeneric(bomLineRepere, mapLine); + } else { + getReperePart(bomLineRepere, mapLine); + } + defineComponent((AbstractRF) bomLineRepere.getSnecmaObject(), mapLine, bomLineRepere); + } + + private void getReperePart(final BOMLineHolder bomLineRepere, final Map mapLine) { + StringBuilder iDComponent = new StringBuilder(); + int nbPartBrowsed = 0; + int nbPart = retrieveNbPart(bomLineRepere.getBomChilds()); + for (BOMLineHolder child : bomLineRepere.getBomChilds()) { + final ISnecmaObject snecmaObject = child.getSnecmaObject(); + if (snecmaObject.isPart()) { + nbPartBrowsed++; + iDComponent.append(snecmaObject.getItemId()); + if (nbPartBrowsed < nbPart) { + iDComponent.append(COMA); + } + mapLine.put(R11Keys.REVISION_REFERENCE.toString(), snecmaObject.getRevisionId()); + mapLine.put(R11Keys.NOM_REFERENCE.toString(), snecmaObject.getName()); + mapLine.put(R11Keys.DESIGNATION_ANGLAISE.toString(), ((AbstractPart) snecmaObject).getDesignationEN()); + mapLine.put(R11Keys.TYPE_OBJET.toString(), LanguageHelper.getNameTypeWithoutRevision(snecmaObject.getType())); + } + } + mapLine.put(R11Keys.REF_FRABRICANT_REF_SNECMA.toString(), iDComponent.toString()); + } + + private int retrieveNbPart(final List bomChildMap) { + int nbPart = 0; + for (BOMLineHolder bomLineHolder : bomChildMap) { + if (bomLineHolder.getSnecmaObject().isPart()) { + nbPart++; + } + } + return nbPart; + } + + private void getRepereGeneric(final BOMLineHolder bomLineRepere, final Map mapLine) { + final GenericRevision snecmaObject = (GenericRevision) bomLineRepere.getParentBomLine().getSnecmaObject(); + mapLine.put(R11Keys.TYPE_OBJET.toString(), LanguageHelper.getNameTypeWithoutRevision(bomLineRepere.getParentBomLine().getObjectType())); + mapLine.put(R11Keys.REF_FRABRICANT_REF_SNECMA.toString(), snecmaObject.getItemId()); + mapLine.put(R11Keys.REVISION_REFERENCE.toString(), snecmaObject.getRevisionId()); + mapLine.put(R11Keys.NOM_REFERENCE.toString(), snecmaObject.getName()); + mapLine.put(R11Keys.DESIGNATION_ANGLAISE.toString(), snecmaObject.getDesignationEN()); + } + + private void defineComponent(final AbstractRF rf, final Map mapLine, final BOMLineHolder bomLineRepere) { + boolean isFindDMUStatut = false; + boolean isFindDataMockUp = false; + for (TcReleaseStatus status : rf.getStatusList()) { + if (status.getStatusEnum() == StatusEnum.DMU_READY) { + isFindDMUStatut = true; + } + } + for (int nbChild = 0; nbChild < bomLineRepere.getBomChilds().size(); nbChild++) { + if (bomLineRepere.getBomChilds().get(nbChild).getObjectType().equals(SnecmaObjectTypes.RF_ADMIN_REVISION)) { + RFAdminRevision rfAdmin = (RFAdminRevision) bomLineRepere.getBomChilds().get(nbChild).getSnecmaObject(); + if (LanguageHelper.french(rfAdmin.getEnveloppeCinematique()).equals(OUI) + || LanguageHelper.french(rfAdmin.getEnveloppeMaintenance()).equals(OUI) + || LanguageHelper.french(rfAdmin.getEnveloppeMontage()).equals(OUI) + || LanguageHelper.french(rfAdmin.getGeometriePieceRigide()).equals(OUI) + || LanguageHelper.french(rfAdmin.getGeometrieSimplifiee()).equals(OUI) + || LanguageHelper.french(rfAdmin.getTraceAxiale()).equals(OUI) + || LanguageHelper.french(rfAdmin.getInterfaceRfAdmin()).equals(OUI)) { + isFindDataMockUp = true; + } + } + } + mapLine.put(R11Keys.STATUT_MISE_EN_MAQUETTE.toString(), isFindDataMockUp && isFindDMUStatut ? OUI : NON); + mapLine.put(R11Keys.A_METTRE_EN_MAQUETTE.toString(), isFindDataMockUp ? OUI : NON); + nbRepereFonctionnelMettreEnMaquette = isFindDataMockUp ? nbRepereFonctionnelMettreEnMaquette + 1 : nbRepereFonctionnelMettreEnMaquette; + nbRepereMisEnMaquette = isFindDataMockUp && isFindDMUStatut ? nbRepereMisEnMaquette + 1 : nbRepereMisEnMaquette; + MockupRevision mockUpObject = null; + for (BOMLineHolder bomLineChild : bomLineRepere.getBomChilds()) { + if (bomLineChild.getObjectType().equals(SnecmaObjectTypes.MOCKUP_REVISION)) { + mockUpObject = (MockupRevision) bomLineChild.getSnecmaObject(); + mapLine.put(R11Keys.CONTROLE_COHERENCE.toString(), mockUpObject.getCoherenceControl()); + } + } + if (mockUpObject == null) { + mapLine.put(R11Keys.CONTROLE_COHERENCE.toString(), EMPTY); + mapLine.put(R11Keys.STATUT_PART_C.toString(), NON); + mapLine.put(R11Keys.STATUT_PART_S.toString(), NON); + mapLine.put(R11Keys.STATUT_PART_R.toString(), NON); + mapLine.put(R11Keys.STATUT_PART_M.toString(), NON); + mapLine.put(R11Keys.STATUT_PART_K.toString(), NON); + mapLine.put(R11Keys.STATUT_PART_I.toString(), NON); + mapLine.put(R11Keys.STATUT_PART_P.toString(), NON); + nbRepereFonctionnelAvecCoherence = + isFindDataMockUp && isFindDMUStatut ? nbRepereFonctionnelAvecCoherence + 1 : nbRepereFonctionnelAvecCoherence; + + } else { + mapLine.put(R11Keys.CONTROLE_COHERENCE.toString(), mockUpObject.getCoherenceControl()); + boolean isDMUPartK = false; + boolean isDMUPartP = false; + boolean isDMUPartS = false; + boolean isDMUPartR = false; + boolean isDMUPartC = false; + boolean isDMUPartI = false; + boolean isDMUPartM = false; + for (TcReleaseStatus status : mockUpObject.getStatusList()) { + isDMUPartC |= defineIsFindStatutMockup(status, StatusEnum.DMU_KO_PART_C); + isDMUPartK |= defineIsFindStatutMockup(status, StatusEnum.DMU_KO_PART_K); + isDMUPartP |= defineIsFindStatutMockup(status, StatusEnum.DMU_KO_PART_P); + isDMUPartI |= defineIsFindStatutMockup(status, StatusEnum.DMU_KO_PART_I); + isDMUPartR |= defineIsFindStatutMockup(status, StatusEnum.DMU_KO_PART_R); + isDMUPartM |= defineIsFindStatutMockup(status, StatusEnum.DMU_KO_PART_M); + isDMUPartS |= defineIsFindStatutMockup(status, StatusEnum.DMU_KO_PART_S); + } + mapLine.put(R11Keys.STATUT_PART_C.toString(), isDMUPartC ? OUI : NON); + mapLine.put(R11Keys.STATUT_PART_S.toString(), isDMUPartS ? OUI : NON); + mapLine.put(R11Keys.STATUT_PART_R.toString(), isDMUPartR ? OUI : NON); + mapLine.put(R11Keys.STATUT_PART_M.toString(), isDMUPartM ? OUI : NON); + mapLine.put(R11Keys.STATUT_PART_K.toString(), isDMUPartK ? OUI : NON); + mapLine.put(R11Keys.STATUT_PART_I.toString(), isDMUPartI ? OUI : NON); + mapLine.put(R11Keys.STATUT_PART_P.toString(), isDMUPartP ? OUI : NON); + + nbRepereFonctionnelAvecIncoherence = isDMUPartC || isDMUPartI || isDMUPartK || isDMUPartM || isDMUPartP || isDMUPartS || isDMUPartR + ? nbRepereFonctionnelAvecIncoherence + 1 + : nbRepereFonctionnelAvecIncoherence; + nbRepereFonctionnelAvecCoherence = !isDMUPartC && !isDMUPartI && !isDMUPartK & !isDMUPartM && !isDMUPartP && !isDMUPartS && !isDMUPartR + && isFindDataMockUp && isFindDMUStatut ? nbRepereFonctionnelAvecCoherence + 1 : nbRepereFonctionnelAvecCoherence; + } + } + + private boolean defineIsFindStatutMockup(final TcReleaseStatus status, final StatusEnum dmuStatus) { + TcEffectivity effectivity = status.getEffectivity(); + String dateRange = effectivity == null ? null : effectivity.dateRange(); + return (dateRange == null || dateRange.isEmpty()) && status.getStatusEnum() == dmuStatus; + } + + @Override + public PrintParameters makeMasterTemplate(final ExecutionR11 report, final BOMLineHolder optionalData) + throws ReportPrintException, FileLoadingException, InvalidInputException { + String storageFolder = ReportFolderOutputHelper.getStorageFolderLocation(report.getLaunchType()); + String fileName = report.getFileNameOnDisc(); + return PrintReportHelper.setupPrintParameters(ResourceHelper.getResourceContent(report.getTemplateLocation()), storageFolder, fileName, + report); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r11report/checker/R11GenericExistenceChecker.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r11report/checker/R11GenericExistenceChecker.java new file mode 100644 index 0000000..473caa5 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r11report/checker/R11GenericExistenceChecker.java @@ -0,0 +1,41 @@ +package com.capgemini.reports.definition.r11report.checker; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.queries.saved.modelobject.ItemQuery; +import com.capgemini.reports.exceptions.InvalidUserInputException; +import com.capgemini.reports.exceptions.UserInputErrorEnum; +import com.capgemini.reports.reports.parameters.Generics; +import com.capgemini.reports.reports.parameters.checker.GenericExistenceChecker; +import com.teamcenter.soa.client.model.strong.Item; + +import java.util.List; + +/** + * This class checks if a Generics (which represents a Generic and/or GenericAssemb) exists within the TC database for a R11 report. + */ +public class R11GenericExistenceChecker extends GenericExistenceChecker { + + /** + * Constructor. + * + * @param generics {@link Generics} - the generic + */ + public R11GenericExistenceChecker(final Generics generics) { + super(generics); + } + + // generic assemb not allowed! + @Override + protected void genericExists(final TcSession session) throws InvalidUserInputException { + List list = new ItemQuery(session).searchID(super.generics.getGeneric()).searchGeneric().findAll(); + List listGenericAssemb = new ItemQuery(session).searchID(generics.getGeneric()).searchGenericAssemb().findAll(); + + if (list == null || list.isEmpty()) { + if (!(listGenericAssemb == null || listGenericAssemb.isEmpty())) { + throw new InvalidUserInputException(UserInputErrorEnum.THE_GENERIC_MUST_BELONG_TO_THE_TECHNICAL_VIEW); + } else { + throw new InvalidUserInputException(getTechnicalErrorMsg()); + } + } + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r11report/data/extractor/BomLineBrowserR11.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r11report/data/extractor/BomLineBrowserR11.java new file mode 100644 index 0000000..dc6776b --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r11report/data/extractor/BomLineBrowserR11.java @@ -0,0 +1,36 @@ +package com.capgemini.reports.definition.r11report.data.extractor; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.bomlineholder.flattener.AbstractRepereFlattener; +import com.capgemini.reports.releasestatus.EffectivityBehaviourHelper; +import com.capgemini.reports.snecmaobjects.part.DETRevision; + +import javax.enterprise.inject.Alternative; + +/** + * This class is specific of the report R11.
    + * Inherits {@link AbstractRepereFlattener}, he gets only receptor and repere.
    + * For the report 11, the explosion of nomenclature is deepth-first, we don't need to findAll {@link Alternative} and {@link DETRevision}, to findAll the part number and only the effectivity by unit. + */ +public class BomLineBrowserR11 extends AbstractRepereFlattener { + private static final boolean VISIT_PART_BELOW_PART = false; + private static final boolean RETRIEVE_PART_NUMBER_UNDER_RF_GENERIC = false; + private static final boolean VISIT_PARTS_IN_PSEUDO_FOLDER = false; + private static final boolean DEEPLY_EXPLOSION = true; + + /** + * Constructor. + */ + public BomLineBrowserR11() { + super(EffectivityBehaviourHelper.visitOnlyUnitManagedParts(), VISIT_PARTS_IN_PSEUDO_FOLDER, RETRIEVE_PART_NUMBER_UNDER_RF_GENERIC, + VISIT_PART_BELOW_PART, DEEPLY_EXPLOSION); + } + + @Override + public R11ReceptorRepere makeRepairReceptorLine(final TcSession session, final BOMLineHolder bomLineReceptor, final BOMLineHolder bomLineRepair) { + return new R11ReceptorRepere(session, bomLineReceptor, bomLineRepair); + + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r11report/data/extractor/FilterByTypeObject.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r11report/data/extractor/FilterByTypeObject.java new file mode 100644 index 0000000..8884b7f --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r11report/data/extractor/FilterByTypeObject.java @@ -0,0 +1,32 @@ +package com.capgemini.reports.definition.r11report.data.extractor; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.resolution.filtering.TcTypeInclusionFilter; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.filter.IFilterExplosionNomenclature; +import com.capgemini.reports.snecmaobjects.ISnecmaObject; + +/** + * Class which allow to filter some objects which is defined in lstTypeObject. + */ +public class FilterByTypeObject extends TcTypeInclusionFilter implements IFilterExplosionNomenclature { + + /** + * Builds a Filter instance, that will ALLOW any object of the provided type. + * + * @param lstTypeObject the object types to be included + */ + public FilterByTypeObject(final String... lstTypeObject) { + super(lstTypeObject); + } + + @Override + public boolean isExcluded(TcSession session, final BOMLineHolder objectToFind) { + return super.isExcluded(objectToFind.getObjectType()); + } + + @Override + public boolean isExcluded(final ISnecmaObject object) { + return super.isExcluded(object.getType()); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r11report/data/extractor/R11ReceptorRepere.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r11report/data/extractor/R11ReceptorRepere.java new file mode 100644 index 0000000..2865725 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r11report/data/extractor/R11ReceptorRepere.java @@ -0,0 +1,52 @@ +package com.capgemini.reports.definition.r11report.data.extractor; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.bomlineholder.flattener.line.AbstractReceptorRepere; +import com.capgemini.reports.bomlineholder.flattener.line.SnecmaLine; + +/** + * Class which inherits of {@link AbstractReceptorRepere}.Just need only receptor and rf. + */ +public class R11ReceptorRepere extends AbstractReceptorRepere { + + private static final String EMPTY = ""; + + /** + * Constructor. + * + * @param bomLineReceptor the {@link BOMLineHolder} of a receptor + * @param bomLineRepere the {@link BOMLineHolder} of a repere + */ + R11ReceptorRepere(final TcSession session, final BOMLineHolder bomLineReceptor, final BOMLineHolder bomLineRepere) { + super(session, bomLineReceptor, bomLineRepere); + } + + @Override + public String getLineId() { + return EMPTY; + } + + @Override + public int getLineNumber() { + // nothing to do + return 0; + } + + @Override + public Void transform(final Void transformer) { + // nothing to do because it's all voids + return null; + } + + @Override + public int compareTo(final SnecmaLine line) { + // nothing to do + return 0; + } + + @Override + public String getDesignationENG() { + return EMPTY; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r13report/R13Keys.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r13report/R13Keys.java new file mode 100644 index 0000000..e32425c --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r13report/R13Keys.java @@ -0,0 +1,58 @@ +package com.capgemini.reports.definition.r13report; + +/** + * Enumeration of the columns of the R13 report. + */ +public enum R13Keys { + ATTACHE_PILOTE, + NOM_PILOTE, + STATUT_PILOTE, + ITEM_ID, + ITEM_REVISION, + DATE_CREATION, + DESIGNATION, + LIGNE_PRODUIT, + TYPE, + STATUT, + DATE_STATUT, + NOM_TEMPLATE_WKF, + ATTACHE_PILOTE_WKF, + NOM_PILOTE_WKF, + STATUT_PILOTE_WKF, + NOM_TACHE, + ATTACHE_ACTEUR_TACHE, + NOM_ACTEUR_TACHE, + STATUT_ACTEUR_TACHE, + DATE_CIBLE, + AVANCE_RETARD; + + /** + * Enumeration of the specific columns for a R13 report with CR objects. + */ + public enum CR { + ID_PROBLEM_REPORT, + REVISION_PROBLEM_REPORT, + EFFECTIVITES, + MODULES, + ATTACHE_PILOTE_CN, + NOM_PILOTE_CN, + STATUT_PILOTE_CN, + ITEM_ID_CN, + ITEM_REVISION_CN, + DATE_CREATION_CN, + LIGNE_PRODUIT_CN, + DESIGNATION_CN, + TYPE_CN, + STATUT_CN, + DATE_STATUT_CN, + PARTS_CHANGE_NOTICE, + PARTS_CHANGE_REQUEST + } + + /** + * Enumeration of the specific columns for a R13 report with FPP objects. + */ + public enum FPP { + PARTS_FPP + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r13report/datapreparator/AbstractDataReportPreparatorR13.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r13report/datapreparator/AbstractDataReportPreparatorR13.java new file mode 100644 index 0000000..89af286 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r13report/datapreparator/AbstractDataReportPreparatorR13.java @@ -0,0 +1,84 @@ +package com.capgemini.reports.definition.r13report.datapreparator; + +import com.capgemini.framework.common.DateHelper; +import com.capgemini.framework.common.TeamcenterDateFormatter; +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.queries.saved.AbstractReplicatedQuery; +import com.capgemini.reports.definition.r13report.execution.AbstractExecutionR13; +import com.capgemini.reports.execution.IDataReportPreparator; +import com.capgemini.reports.execution.strategies.IExecutionStrategy; +import com.capgemini.reports.printing.PrintParameters; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import com.teamcenter.soa.client.model.strong.ReleaseStatus; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * This class will allow to prepare common data for the R13 report. + * + * @param the daughter class: CR or FPP + */ +public abstract class AbstractDataReportPreparatorR13 implements IDataReportPreparator { + private static final long serialVersionUID = -3275014753104915202L; + private static final Logger LOGGER = LoggerFactory.getLogger(AbstractDataReportPreparatorR13.class); + + @Override + public String print(TcSession session, T execution, IExecutionStrategy executionStrategy) throws KurtException { + PrintParameters printParameters = prepareData(session, execution); + executionStrategy.print(printParameters, execution); + return executionStrategy.getReportFileName(execution) + printParameters.getOuputFileExtension(); + } + + /** + * Method will allow to prepare data in common between report R13CR and R13FPP. + * + * @param session , the session of TC + * @param report the execution report + * @return a List of the Objects which will make up the report's content + */ + private PrintParameters prepareData(final TcSession session, final T report) throws KurtException { + LOGGER.debug("PrepareData started on: {}", report.getReportIdentifier().getReportTitle()); + session.setObjectPropPolicy(report.getFullPolicy()); + return buildValidatedChangeObjects(session, report); + } + + void addParamPeriod(final AbstractReplicatedQuery query, final T report) { + if (report.getStartDate() != null) { + query.addAfterDate(report.getStartDate().getFormattedDateForTcRequest()); + } + if (report.getFinalDate() != null) { + query.addBeforeDate(TeamcenterDateFormatter.translateDateFormatForRequest(DateHelper.getDatePlusOneWithReferenceCalendar(report.getFinalDate().getDateTime()))); + } + } + + /** + * Detects invalid status. + */ + boolean isStatusValid(final TcSession session, final ItemRevision itemRev) { + session.loadProperties(itemRev, "release_status_list"); + ReleaseStatus[] releaseStatuses = itemRev.get_release_status_list(); + session.loadProperties(releaseStatuses); + for (ReleaseStatus status : releaseStatuses) { + if (!validateStatusByName(status.get_name())) { + return false; + } + } + return true; // By default, if no status exist then the PR must be in the report + } + + /** + * Excludes specific statuses. + * + * @param statusName the input status name + * @return true if the status name is valid, false if it should be discarded + */ + protected abstract boolean validateStatusByName(final String statusName); + + /** + * Specific validation tests of an item, for each version of the R13. + */ + protected abstract boolean specificValidation(final TcSession session, final ItemRevision itemRev); + + protected abstract PrintParameters buildValidatedChangeObjects(final TcSession session, T report) throws KurtException; +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r13report/datapreparator/DataReportPreparatorR13CR.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r13report/datapreparator/DataReportPreparatorR13CR.java new file mode 100644 index 0000000..3e8cdae --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r13report/datapreparator/DataReportPreparatorR13CR.java @@ -0,0 +1,86 @@ +package com.capgemini.reports.definition.r13report.datapreparator; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.queries.saved.AbstractReplicatedQuery; +import com.capgemini.framework.teamcenter.resolution.filtering.TcTypeExclusionFilter; +import com.capgemini.reports.ItemRevisionComparator; +import com.capgemini.reports.changeobjects.change.TcChangeRequestRevision; +import com.capgemini.reports.definition.r13report.execution.ExecutionR13CR; +import com.capgemini.reports.definition.r13report.printer.R13PrinterCR; +import com.capgemini.reports.execution.IDataReportPreparator; +import com.capgemini.reports.printing.PrintParameters; +import com.capgemini.reports.teamcenter.queries.saved.ChangeRequestWithSeqQuery; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * This class will allow to prepare data and findAll back data for making report R13CR. + */ +@Slf4j +public class DataReportPreparatorR13CR extends AbstractDataReportPreparatorR13 implements IDataReportPreparator { + private static final long serialVersionUID = 811112181278567085L; + + // Configuration + private static final String FINISHED = "Finished"; + private static final String CANCELLED = "Cancelled"; + private static final String SB_DISTRIBUTED = "SB distributed"; + + private static final String CR_DEPRECIE_REVISION = "CR Déprécié Revision"; + private static final String PV4_CR_DEPREC_REVISION = "PV4_CR_DEPRECRevision"; + + private static final TcTypeExclusionFilter FILTER_EXCLUDE_FINISHED_CANCELLED_DISTRIBUTED = new TcTypeExclusionFilter(FINISHED, CANCELLED, SB_DISTRIBUTED); + private static final TcTypeExclusionFilter FILTER_EXCLUDE_CR_DEPREC = new TcTypeExclusionFilter(CR_DEPRECIE_REVISION, PV4_CR_DEPREC_REVISION); + + @Override + protected boolean validateStatusByName(final String statusName) { + return FILTER_EXCLUDE_FINISHED_CANCELLED_DISTRIBUTED.isIncluded(statusName); + } + + @Override + protected boolean specificValidation(final TcSession session, final ItemRevision itemRev) { + // Filter out deprecated CRs + return FILTER_EXCLUDE_CR_DEPREC.isIncluded(itemRev.getTypeObject().getName()); + } + + @Override + protected PrintParameters buildValidatedChangeObjects(final TcSession session, ExecutionR13CR report) throws KurtException { + AbstractReplicatedQuery query = new ChangeRequestWithSeqQuery(session); + addParamPeriod(query, report); + List data = new ArrayList<>(); + for (ItemRevision itemRev : validateChangeObjects(query.searchAllObjects().findAll(), session)) { + data.add(new TcChangeRequestRevision(session, itemRev)); + } + + R13PrinterCR printer = new R13PrinterCR(); + PrintParameters printParameters = printer.makeMasterTemplate(report, data); + printer.constructDataMaps(session, printParameters, data); + + return printParameters; + } + + private List validateChangeObjects(final List objects, final TcSession session) { + List validatedObjects = new ArrayList<>(); + Collections.sort(objects, new ItemRevisionComparator()); + for (ItemRevision itemRev : objects) { + if (itemRev == null) { + continue; + } + // Common treatment on status + if (!isStatusValid(session, itemRev)) { + continue; + } + // Specific treatment if required (FPP) + if (!specificValidation(session, itemRev)) { + continue; + } + validatedObjects.add(itemRev); + } + + return validatedObjects; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r13report/datapreparator/DataReportPreparatorR13FPP.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r13report/datapreparator/DataReportPreparatorR13FPP.java new file mode 100644 index 0000000..9ee9a42 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r13report/datapreparator/DataReportPreparatorR13FPP.java @@ -0,0 +1,105 @@ +package com.capgemini.reports.definition.r13report.datapreparator; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.queries.saved.AbstractReplicatedQuery; +import com.capgemini.framework.teamcenter.resolution.filtering.TcTypeExclusionFilter; +import com.capgemini.reports.ItemRevisionComparator; +import com.capgemini.reports.changeobjects.change.FPPRevision; +import com.capgemini.reports.definition.r13report.execution.ExecutionR13FPP; +import com.capgemini.reports.definition.r13report.printer.R13PrinterFPP; +import com.capgemini.reports.execution.IDataReportPreparator; +import com.capgemini.reports.printing.PrintParameters; +import com.capgemini.reports.teamcenter.queries.saved.FppWithSeqQuery; +import com.capgemini.reports.teamcenter.queries.saved.WorkflowOnChangeQuery; +import com.capgemini.reports.workflows.Task.TaskState; +import com.teamcenter.soa.client.model.strong.EPMTask; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * This class will allow to prepare data and findAll back data for making report R13FPP. + */ +public class DataReportPreparatorR13FPP extends AbstractDataReportPreparatorR13 implements IDataReportPreparator { + private static final long serialVersionUID = -5070390508126458855L; + + // Configuration + private static final String PB_REPORT_APPROVED = "Pb Report Approved"; + private static final String REFUSED = "Refused"; + private static final String CANCELLED = "Cancelled"; + + @Override + protected boolean validateStatusByName(final String statusName) { + return new TcTypeExclusionFilter(PB_REPORT_APPROVED, REFUSED, CANCELLED).isIncluded(statusName); + } + + @Override + protected boolean specificValidation(final TcSession session, final ItemRevision itemRev) { + String itemID = itemRev.get_item_id(); + String revisionID = itemRev.get_item_revision_id(); + List wkfList = new WorkflowOnChangeQuery(session).searchIDAndRevision(itemID, revisionID) + .searchSequenceId(String.valueOf(itemRev.get_sequence_id())).findAll(); + + // 1st case : wkf list is empty, it must appear in the report + if (wkfList.isEmpty()) { + return true; // Keep this CR + } + + // Remove finished wkf + List wkfToRemove = new ArrayList<>(); + for (EPMTask wkf : wkfList) { + if (TaskState.COMPLETED.matches(wkf.get_state())) { + wkfToRemove.add(wkf); + } + } + wkfList.removeAll(wkfToRemove); + + // 2rd case : all the wkf are finished + if (wkfList.isEmpty()) { + return false; // Discard this CR + } + + // 3rd case : at least 1 wkf is active + return true; // Keep this CR + } + + @Override + protected PrintParameters buildValidatedChangeObjects(final TcSession session, final ExecutionR13FPP report) throws KurtException { + AbstractReplicatedQuery query = new FppWithSeqQuery(session); + addParamPeriod(query, report); + List data = new ArrayList<>(); + for (ItemRevision itemRev : validateChangeObjects(query.searchAllObjects().findAll(), session)) { + data.add(new FPPRevision(session, itemRev)); + } + + R13PrinterFPP printer = new R13PrinterFPP(); + PrintParameters printParameters = printer.makeMasterTemplate(report, data); + printer.constructDataMaps(session, printParameters, data); + + return printParameters; + } + + private List validateChangeObjects(final List objects, final TcSession session) { + List validatedObjects = new ArrayList<>(); + Collections.sort(objects, new ItemRevisionComparator()); + for (ItemRevision itemRev : objects) { + if (itemRev == null) { + continue; + } + // Common treatment on status + if (!isStatusValid(session, itemRev)) { + continue; + } + // Specific treatment if required (FPP) + if (!specificValidation(session, itemRev)) { + continue; + } + validatedObjects.add(itemRev); + } + + return validatedObjects; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r13report/execution/AbstractExecutionR13.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r13report/execution/AbstractExecutionR13.java new file mode 100644 index 0000000..2002b8c --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r13report/execution/AbstractExecutionR13.java @@ -0,0 +1,115 @@ +package com.capgemini.reports.definition.r13report.execution; + +import com.capgemini.framework.common.SettingsHelper; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.reports.ReportEnum; +import com.capgemini.reports.ReportLaunchTypeEnum; +import com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum; +import com.capgemini.reports.database.manager.MngCriteriaVal.CriteriaValue; +import com.capgemini.reports.execution.AbstractExecutionReport; +import com.capgemini.reports.printing.Printer.PrintFormat; +import com.capgemini.reports.reports.parameters.EffectivityDate; +import com.capgemini.reports.reports.parameters.IChecker; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; + +/** + * This class controls the execution of a R13 report. + * + * @param generic object for a report + * @param the objects sent by the data preparator to the Printer (FPP or ChangeRequest) + */ +@Getter +@Slf4j +@EqualsAndHashCode(callSuper = true) +public abstract class AbstractExecutionR13, U> extends AbstractExecutionReport> { + + // Policies + protected static final PolicyLocation R13_POLICY_XML_FULL = PolicyLocation.make("R13_policy_full", "/xml/policies/r13report/R13_policy_full.xml"); + protected static final PolicyLocation R13_POLICY_XML_LIGHT = PolicyLocation.make("R13_policy_light", "/xml/policies/r13report/R13_policy_light.xml"); + private static final long serialVersionUID = 7486257915745387797L; + // Priority parameter + private static final int REPORT_PRIORITY = SettingsHelper.getPriority(ReportEnum.REPORT_R13); + // Revision rule parameter + private static final String REPORT_REVISION_RULE = SettingsHelper.getPropertyWithDefaultValue("common.bom.revisionRule.REPORT_R13", DEFAULT_REVISION_RULE); + // Launch type parameter + private static final ReportLaunchTypeEnum REPORT_LAUNCH_TYPE = ReportLaunchTypeEnum.getReportLaunchType("common.launch.launchType.REPORT_R13"); + // Raw input parameters + protected final String typeObject; + protected final EffectivityDate finalDate; + protected final EffectivityDate startDate; + + /** + * Constructor. + * + * @param typeObject String - the type of the Object + * @param finalDate {@link Calendar} - the final date + * @param startDate {@link Calendar} - the previous date + */ + AbstractExecutionR13(final String typeObject, final EffectivityDate finalDate, final EffectivityDate startDate) { + super(REPORT_PRIORITY, REPORT_REVISION_RULE, REPORT_LAUNCH_TYPE); + this.typeObject = typeObject; + this.finalDate = finalDate; + this.startDate = startDate; + } + + @Override + public List getLaunchData() { + List theCriteria = new ArrayList<>(); + String prevValue = (startDate == null) ? "" : startDate.formatAsInputCriteria(); + String finalValue = finalDate.formatAsInputCriteria(); + log.info("R13 input:" + typeObject + "\t" + prevValue + "\t" + finalValue); + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.TYPE_OBJET, typeObject)); + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.DATE_DEBUT, prevValue)); + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.DATE_FIN, finalValue)); + return theCriteria; + } + + @Override + public List getQuickChecks() { + return new ArrayList<>(); + } + + @Override + public PolicyLocation getPropertyPolicyForLongChecks() { + return R13_POLICY_XML_LIGHT; + } + + @Override + public PolicyLocation getFullPolicy() { + return R13_POLICY_XML_FULL; + } + + @Override + public List getLongChecks() { + return new ArrayList<>(); + } + + @Override + public ReportEnum getReportIdentifier() { + return ReportEnum.REPORT_R13; + } + + @Override + public String getSpecifiedFileName() { + String separator = "_"; + StringBuilder builder = new StringBuilder("R13_").append(typeObject).append(separator); + if (startDate != null) { + builder.append(startDate.getFormattedDateForFrenchUser()).append(separator).append(finalDate.getFormattedDateForFrenchUser()); + } else { + builder.append("NoPrevDate").append(separator).append("NoFinalDate"); + } + + return builder.toString(); + } + + @Override + public PrintFormat getPrintingFormat() { + return PrintFormat.XLSX; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r13report/execution/ExecutionR13CR.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r13report/execution/ExecutionR13CR.java new file mode 100644 index 0000000..b04c358 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r13report/execution/ExecutionR13CR.java @@ -0,0 +1,52 @@ +package com.capgemini.reports.definition.r13report.execution; + +import com.capgemini.reports.JasperTemplate; +import com.capgemini.reports.builder.R13CrBuilder; +import com.capgemini.reports.builder.ReportBuilder; +import com.capgemini.reports.changeobjects.change.TcChangeRequestRevision; +import com.capgemini.reports.definition.r13report.datapreparator.DataReportPreparatorR13CR; +import com.capgemini.reports.execution.AbstractExecutionReport; +import com.capgemini.reports.execution.IDataReportPreparator; +import com.capgemini.reports.reports.parameters.EffectivityDate; +import lombok.EqualsAndHashCode; +import lombok.Getter; + +/** + * This class controls the execution of a R13 report with CR objects. + */ +@Getter +@EqualsAndHashCode(callSuper = true) +public class ExecutionR13CR extends AbstractExecutionR13 { + + private static final long serialVersionUID = 2186783921659331654L; + + /** + * Constructor. + * + * @param finalDate {@link EffectivityDate} -the final date + * @param beginDate {@link EffectivityDate} -the previous date + */ + public ExecutionR13CR(final EffectivityDate finalDate, final EffectivityDate beginDate) { + super("CR", finalDate, beginDate); + } + + @Override + public String getTemplateLocation() { + return JasperTemplate.TEMPLATE_R13_CR.getFilepath(); + } + + @Override + public IDataReportPreparator getDataPreparator() { + return new DataReportPreparatorR13CR(); + } + + @Override + public AbstractExecutionReport cloneTemplateToExecution() { + return new ExecutionR13CR(finalDate, startDate); + } + + @Override + public Class getReportBuilderClass() { + return R13CrBuilder.class; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r13report/execution/ExecutionR13FPP.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r13report/execution/ExecutionR13FPP.java new file mode 100644 index 0000000..d3d4906 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r13report/execution/ExecutionR13FPP.java @@ -0,0 +1,50 @@ +package com.capgemini.reports.definition.r13report.execution; + +import com.capgemini.reports.JasperTemplate; +import com.capgemini.reports.builder.R13FppBuilder; +import com.capgemini.reports.builder.ReportBuilder; +import com.capgemini.reports.changeobjects.change.FPPRevision; +import com.capgemini.reports.definition.r13report.datapreparator.DataReportPreparatorR13FPP; +import com.capgemini.reports.execution.AbstractExecutionReport; +import com.capgemini.reports.execution.IDataReportPreparator; +import com.capgemini.reports.reports.parameters.EffectivityDate; +import lombok.Getter; + +/** + * This class controls the execution of a R13 report with FPP objects. + */ +@Getter +public class ExecutionR13FPP extends AbstractExecutionR13 { + + private static final long serialVersionUID = 3645528867618039977L; + + /** + * Constructor. + * + * @param finalDate {@link EffectivityDate} -the final date + * @param previousDate {@link EffectivityDate} -the previous date + */ + public ExecutionR13FPP(final EffectivityDate finalDate, final EffectivityDate previousDate) { + super("FPP", finalDate, previousDate); + } + + @Override + public String getTemplateLocation() { + return JasperTemplate.TEMPLATE_R13_FPP.getFilepath(); + } + + @Override + public IDataReportPreparator getDataPreparator() { + return new DataReportPreparatorR13FPP(); + } + + @Override + public AbstractExecutionReport cloneTemplateToExecution() { + return new ExecutionR13FPP(finalDate, startDate); + } + + @Override + public Class getReportBuilderClass() { + return R13FppBuilder.class; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r13report/printer/AbstractR13Printer.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r13report/printer/AbstractR13Printer.java new file mode 100644 index 0000000..a3b6535 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r13report/printer/AbstractR13Printer.java @@ -0,0 +1,372 @@ +package com.capgemini.reports.definition.r13report.printer; + +import com.capgemini.framework.common.StringHelper; +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.object.pom.status.TcReleaseStatus; +import com.capgemini.reports.changeobjects.change.AbstractChangeObject; +import com.capgemini.reports.changeobjects.change.TcChangeNoticeRevision; +import com.capgemini.reports.definition.r13report.R13Keys; +import com.capgemini.reports.definition.r13report.execution.AbstractExecutionR13; +import com.capgemini.reports.execution.mapconstructor.AbstractStaticTemplateMapConstructor; +import com.capgemini.reports.printing.PrintParameters; +import com.capgemini.reports.reports.parameters.EffectivityDate; +import com.capgemini.reports.users.SnecmaPerson; +import com.capgemini.reports.users.SnecmaUser; +import com.capgemini.reports.workflows.Task; +import com.google.common.base.Joiner; +import lombok.EqualsAndHashCode; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.EnumMap; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +/** + * Printer of a R13 Report. + * + * @param {@link AbstractExecutionR13} - the abstract execution report + * @param The change objects required to make a reprot line (FPP or ChangeRequest) + */ +@Slf4j +@EqualsAndHashCode(callSuper = true) +public abstract class AbstractR13Printer, U extends AbstractChangeObject> + extends AbstractStaticTemplateMapConstructor> { + + private static final long serialVersionUID = 1510278082994267162L; + + private static final long MILLISECONDS_IN_SECONDS = 1000; + private static final long SECONDS_IN_MINUTES = 60; + private static final long MINUTES_IN_HOURS = 60; + private static final long HOURS_IN_DAY = 24; + private static final long MILLIS_PER_DAY = HOURS_IN_DAY * MINUTES_IN_HOURS * SECONDS_IN_MINUTES * MILLISECONDS_IN_SECONDS; + + private static final String INACTIF = "Inactif"; + private static final String ACTIF = "Actif"; + private static final String EMPTY_STRING = ""; + + @Override + public void constructDataMaps(TcSession session, final PrintParameters printParameters, final List changeList) throws KurtException { + long start = System.currentTimeMillis(); + List> reportLines = new ArrayList<>(); + for (U rootChangeObject : changeList) { + Map typeObjectParam = generateChangeObjectParameters(rootChangeObject); + Map> expandedChangeObject = getChangeObjectData(rootChangeObject, typeObjectParam); + for (Entry> entry : expandedChangeObject.entrySet()) { + AbstractChangeObject changeObject = entry.getKey(); + Map prefix = entry.getValue(); + try { + reportLines.addAll(discoverWorkflows(changeObject, prefix)); + } + catch (KurtException e) { + throw new KurtException("Erreur sur la MOD " + changeObject.getItemId(), e); + } + } + } + if (reportLines.isEmpty()) { + reportLines.add(putEmptyLine()); + } + printParameters.addReportData(reportLines); + printParameters.addReportParameters(new EnumMap<>(R13Keys.class)); + log.trace("Execution time : {} ms for {}", System.currentTimeMillis() - start, "data filtering"); + } + + /** + * Creates a map of one or several {@link AbstractChangeObject} to data relative to said change object.
    + * The change objects are related to the provided change object as follows: + *
      + *
    • In the case of a FPP report, the only key is the FPP passed as parameter
    • + *
    • In the case of a CR report, the first key is the CR passed as parameter, the rest are the CNs that depend on the CR. As the order is important, the return type must be a {@link LinkedHashMap} and not a simple {@link Map}/li> + *
    + * The provided prefix is used on each line, it may NOT be modified. + * + * @param data the change object to represent + * @param typeObjectParam prefix (DO NOT MODIFY) + * @return a + */ + protected abstract Map> getChangeObjectData(final U data, + final Map typeObjectParam); + + private Map generateChangeObjectParameters(final U change) { + // Users parameters + Map mapPrinter = makeUserParameters(change); + + // Object parameters + mapPrinter.put(R13Keys.ITEM_ID.toString(), change.getItemId()); + mapPrinter.put(R13Keys.ITEM_REVISION.toString(), change.getRevisionId()); + mapPrinter.put(R13Keys.DATE_CREATION.toString(), new EffectivityDate(change.getDateCreation()).getFormattedDateForFrenchUser()); + mapPrinter.put(R13Keys.DESIGNATION.toString(), change.getChangeName()); + String concatenatedLigneProduit = Joiner.on(StringHelper.LINE_FEED).join(change.getLignesProduit()); // Line jump within the cell + mapPrinter.put(R13Keys.LIGNE_PRODUIT.toString(), concatenatedLigneProduit); + + // Validated status of object parameters + mapPrinter.putAll(makeReleaseStatusParameters(change)); + return mapPrinter; + } + + /** + * These properties are present on both CR and FPP. + */ + Map makeUserParameters(final AbstractChangeObject change) { + final Map param = new HashMap<>(); + SnecmaUser user = change.getUser(); + SnecmaPerson person = user.getPerson(); + String codeCourrier = person.getCodeCourrier(); + if (change instanceof TcChangeNoticeRevision) { + param.put(R13Keys.CR.ATTACHE_PILOTE_CN.toString(), (codeCourrier == null || codeCourrier.isEmpty()) ? EMPTY_STRING : codeCourrier); + param.put(R13Keys.CR.NOM_PILOTE_CN.toString(), person.getPersonName()); + param.put(R13Keys.CR.STATUT_PILOTE_CN.toString(), userStatus(user)); + } else { + param.put(R13Keys.ATTACHE_PILOTE.toString(), (codeCourrier == null || codeCourrier.isEmpty()) ? EMPTY_STRING : codeCourrier); + param.put(R13Keys.NOM_PILOTE.toString(), person.getPersonName()); + param.put(R13Keys.STATUT_PILOTE.toString(), userStatus(user)); + } + return param; + } + + Map makeReleaseStatusParameters(final AbstractChangeObject change) { + TcReleaseStatus validatedStatus = findLastValidatedStatus(change); + boolean isCN = change instanceof TcChangeNoticeRevision; + String valueStatus; + String valueDate; + if (validatedStatus == null) { + valueStatus = EMPTY_STRING; + valueDate = EMPTY_STRING; + } else { + valueStatus = validatedStatus.getDisplayableName(); + valueDate = new EffectivityDate(validatedStatus.dateReleased()).getFormattedDateForFrenchUser(); + } + String keyStatus = (isCN ? R13Keys.CR.STATUT_CN : R13Keys.STATUT).toString(); + String keyDate = (isCN ? R13Keys.CR.DATE_STATUT_CN : R13Keys.DATE_STATUT).toString(); + Map param = new HashMap<>(); + param.put(keyStatus, valueStatus); + param.put(keyDate, valueDate); + return param; + } + + /** + * Returns the last validated status. If no (valid) status, returns null. + */ + private TcReleaseStatus findLastValidatedStatus(final AbstractChangeObject change) { + TcReleaseStatus selectedStatus = null; + for (TcReleaseStatus status : change.getReleaseStatusContainingMaturity()) { + if (isValid(status, change) && (selectedStatus == null || status.dateReleased().after(selectedStatus.dateReleased()))) { + selectedStatus = status; + } + } + return selectedStatus; + } + + /** + * Validates a status of a change. + * + * @param status the TcReleaseStatus of the change + * @param change the change + * @return true if the status of the change is valid (should be kept) or false if the status ishould be ignored. + */ + protected abstract boolean isValid(final TcReleaseStatus status, final AbstractChangeObject change); + + /** + * Returns a description of the status of all Workflows found to be associated with the provided change item. The provided prefix will be added to each line, unmodified. + * + * @param change the {@link AbstractChangeObject} + * @param prefix the first few columns, pre-calculated + * @return aLine for each task of each workflow (each line contains the provided prefix) + */ + private List> discoverWorkflows(final AbstractChangeObject change, final Map prefix) throws KurtException { + List wkfList = change.getWkfList(); + List> result = new ArrayList<>(); + if (wkfList == null || wkfList.isEmpty()) { + result.add(makeEmptyWkfAndTask(prefix)); + } else { + boolean allWorkflowsAreCompleted = true; + for (Task wkf : wkfList) { + if (wkf.isRunning()) { // Remove workflows when not currently running (aborted, skipped, failed, pending, etc.) + allWorkflowsAreCompleted = false; + Map wkfParam = new HashMap<>(prefix); // Copy input prefix + + // Workflow parameters + wkfParam.put(R13Keys.NOM_TEMPLATE_WKF.toString(), wkf.getName()); + + // Users parameters associated to WKF + SnecmaUser wkfResponsibleUser = wkf.getResponsibleUser() ; + SnecmaPerson wkfResponsiblePerson = wkfResponsibleUser.getPerson(); + String codeCourrier = wkfResponsiblePerson.getCodeCourrier(); + wkfParam.put(R13Keys.ATTACHE_PILOTE_WKF.toString(), (codeCourrier == null || codeCourrier.isEmpty()) ? EMPTY_STRING : codeCourrier); + wkfParam.put(R13Keys.NOM_PILOTE_WKF.toString(), wkfResponsiblePerson.getPersonName()); + wkfParam.put(R13Keys.STATUT_PILOTE_WKF.toString(), userStatus(wkfResponsibleUser)); + + // Active task parameters + result.addAll(discoverActiveTasks(wkf, change, wkfParam)); + } + } + if (allWorkflowsAreCompleted) { + result.add(makeEmptyWkfAndTask(prefix)); + } + } + return result; + } + + /** + * Returns a line for each Active Task of the Workflow. The provided prefix will be added to each line, unmodified. + * + * @param change the change item + * @param prefix the first few columns, pre-calculated + * @return a Line for each active task of the Workflow (each containing the provided prefix) + */ + private List> discoverActiveTasks(final Task rootTask, final AbstractChangeObject change, final Map prefix) throws KurtException { + List activeMotherTasks = rootTask.getActiveChildTasks(); + List> result = new ArrayList<>(); + if (activeMotherTasks == null || activeMotherTasks.isEmpty()) { + // Prepare a line containing the prefix, and "" everywhere else + HashMap copy = new HashMap<>(prefix); + addEmptyTask(copy); + result.add(copy); + } else { + for (Task activeMotherTask : activeMotherTasks) { + // Level 0: task representing the whole "Workflow" + // Level 1: 'Mother' tasks --> obtain name & due date here + // Level 2: 'Daughter' tasks --> These are the 'ACTIVE' tasks, obtain users here + + // Here, we always are on the mother task's level + Map line = new HashMap<>(prefix); // Copy prefix without modify it + + // Warning : if a CR has a CN and both of them have workflows, the CR will have its own workflow and the CN's + if (activeMotherTask.isInTargetAttachments(change)) { + // Task name + line.put(R13Keys.NOM_TACHE.toString(), activeMotherTask.getName()); + + // Due date + Calendar parentDueDate = activeMotherTask.getDueDate(); + if (parentDueDate == null) { + line.put(R13Keys.DATE_CIBLE.toString(), EMPTY_STRING); + line.put(R13Keys.AVANCE_RETARD.toString(), EMPTY_STRING); + } else { + line.put(R13Keys.DATE_CIBLE.toString(), new EffectivityDate(parentDueDate).getFormattedDateForFrenchUser()); + line.put(R13Keys.AVANCE_RETARD.toString(), compareWithDateSystem(parentDueDate)); + } + + // The users are found on the daughter task if it exists + SnecmaUser motherOwner = activeMotherTask.getResponsibleUser(); + List activeChildTasks = activeMotherTask.getActiveChildTasks(); + if (!activeChildTasks.isEmpty()) { + for (Task childTask : activeChildTasks) { + // Add a line for each users (they, however, are found on the daughter task...) + result.addAll(discoverUserTasks(childTask, line, motherOwner)); + } + } else { + // Add a line for each users (they, however, are found on the daughter task...) + result.addAll(discoverUserTasks(activeMotherTask, line, motherOwner)); + } + } + } + } + return result; + } + + private List> discoverUserTasks(final Task childTask, final Map taskParam, SnecmaUser motherOwner) { + List validSignoffsValues = childTask.getPendingSignoffsUser(); // Only users that have not yet validated their task + List> result = new ArrayList<>(); + if (!validSignoffsValues.isEmpty()) { + for (SnecmaUser signoffUser : validSignoffsValues) { + Map personParam = new HashMap<>(taskParam); // Defensive copy of prefix + + // Person parameters + SnecmaPerson signoffPerson = signoffUser.getPerson(); + String codeCourrier = signoffPerson.getCodeCourrier(); + personParam.put(R13Keys.ATTACHE_ACTEUR_TACHE.toString(), + (codeCourrier == null || codeCourrier.isEmpty()) ? EMPTY_STRING : codeCourrier); + personParam.put(R13Keys.NOM_ACTEUR_TACHE.toString(), signoffPerson.getPersonName()); + personParam.put(R13Keys.STATUT_ACTEUR_TACHE.toString(), userStatus(signoffUser)); + + // Add to results list + result.add(personParam); + } + } else { + // Default behavior when no users are active on the daughter task + Map personParam = new HashMap<>(taskParam); // Defensive copy of prefix + SnecmaPerson responsibleUser = motherOwner.getPerson(); + String codeCourrier = responsibleUser.getCodeCourrier(); + personParam.put(R13Keys.ATTACHE_ACTEUR_TACHE.toString(), (codeCourrier == null || codeCourrier.isEmpty()) ? EMPTY_STRING : codeCourrier); + personParam.put(R13Keys.NOM_ACTEUR_TACHE.toString(), responsibleUser.getPersonName()); + personParam.put(R13Keys.STATUT_ACTEUR_TACHE.toString(), userStatus(motherOwner)); + result.add(personParam); + } + return result; + } + + String compareWithDateSystem(final Calendar dueDate) { + long epochToDueDate = daysSinceEpoch(dueDate); + long epochToToday = daysSinceEpoch(Calendar.getInstance()); + long diff = epochToDueDate - epochToToday; + return String.valueOf(diff); + } + + /** + * Returns the number of days elapsed since {@link Calendar}'s Epoch (Jan, 1st 1970) until the beggining of the provided Calendar's day : midnight 00:00:000).
    + * Ex: + *
      + *
    • if Calendar is Jan, 1st 1970, 00h:00m:00s:000): 000000000 ms
    • + *
    • if Calendar is Jan, 1st 1970, 00h:00m:00s:125): 000000125 ms
    • + *
    • if Calendar is Jan, 1st 1970, 00h:00m:05s:125): 000005125 ms
    • + *
    • if Calendar is Jan, 1st 1970, 00h:01m:05s:125): 000065125 ms
    • + *
    • if Calendar is Jan, 1st 1970, 01h:00m:05s:125): 003605125 ms
    • + *
    • if Calendar is Jan, 3rd 1970, 00h:00m:00s:000): 259200000 ms
    • + *
    • if Calendar is Jan, 3rd 1970, 00h:00m:05s:125): 259205125 ms
    • + *
    + * + * @param dueDate the Date to calculate + * @return the number of milliseconds elapsed since {@link Calendar}'s Epoch (Jan, 1st 1970) until the beggining of the provided Calendar's day : midnight 00:00:000) + */ + private long daysSinceEpoch(final Calendar dueDate) { + return dueDate.getTimeInMillis() / MILLIS_PER_DAY; // TRUNCATE to remove any trace of time spend past midnight + } + + private Map makeEmptyWkfAndTask(final Map param) { + param.put(R13Keys.NOM_TEMPLATE_WKF.toString(), EMPTY_STRING); + param.put(R13Keys.ATTACHE_PILOTE_WKF.toString(), EMPTY_STRING); + param.put(R13Keys.NOM_PILOTE_WKF.toString(), EMPTY_STRING); + param.put(R13Keys.STATUT_PILOTE_WKF.toString(), EMPTY_STRING); + addEmptyTask(param); + return param; + } + + private void addEmptyTask(final Map taskParam) { + taskParam.put(R13Keys.NOM_TACHE.toString(), EMPTY_STRING); + taskParam.put(R13Keys.ATTACHE_ACTEUR_TACHE.toString(), EMPTY_STRING); + taskParam.put(R13Keys.NOM_ACTEUR_TACHE.toString(), EMPTY_STRING); + taskParam.put(R13Keys.STATUT_ACTEUR_TACHE.toString(), EMPTY_STRING); + taskParam.put(R13Keys.DATE_CIBLE.toString(), EMPTY_STRING); + taskParam.put(R13Keys.AVANCE_RETARD.toString(), EMPTY_STRING); + } + + private Map putEmptyLine() { + Map mapPrinter = makeEmptyWkfAndTask(new HashMap()); + mapPrinter.put(R13Keys.ATTACHE_PILOTE.toString(), EMPTY_STRING); + mapPrinter.put(R13Keys.NOM_PILOTE.toString(), EMPTY_STRING); + mapPrinter.put(R13Keys.STATUT_PILOTE.toString(), EMPTY_STRING); + mapPrinter.put(R13Keys.ITEM_ID.toString(), EMPTY_STRING); + mapPrinter.put(R13Keys.ITEM_REVISION.toString(), EMPTY_STRING); + mapPrinter.put(R13Keys.DATE_CREATION.toString(), EMPTY_STRING); + mapPrinter.put(R13Keys.DESIGNATION.toString(), EMPTY_STRING); + mapPrinter.put(R13Keys.LIGNE_PRODUIT.toString(), EMPTY_STRING); + mapPrinter.put(R13Keys.TYPE.toString(), EMPTY_STRING); + mapPrinter.put(R13Keys.STATUT.toString(), EMPTY_STRING); + mapPrinter.put(R13Keys.DATE_STATUT.toString(), EMPTY_STRING); + mapPrinter.put(R13Keys.CR.PARTS_CHANGE_REQUEST.toString(), EMPTY_STRING); + mapPrinter.put(R13Keys.FPP.PARTS_FPP.toString(), EMPTY_STRING); + specificTreatmentEmptyLines(mapPrinter); + return mapPrinter; + } + + private String userStatus(final SnecmaUser user) { + return (user.isActive()) ? ACTIF : INACTIF; + } + + protected abstract void specificTreatmentEmptyLines(final Map mapPrinter); +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r13report/printer/R13PrinterCR.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r13report/printer/R13PrinterCR.java new file mode 100644 index 0000000..879f8c5 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r13report/printer/R13PrinterCR.java @@ -0,0 +1,246 @@ +package com.capgemini.reports.definition.r13report.printer; + +import com.capgemini.framework.common.LanguageHelper; +import com.capgemini.framework.common.StringHelper; +import com.capgemini.framework.teamcenter.object.pom.status.StatusEnum; +import com.capgemini.framework.teamcenter.object.pom.status.TcEffectivity; +import com.capgemini.framework.teamcenter.object.pom.status.TcReleaseStatus; +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.capgemini.framework.teamcenter.resolution.filtering.TcTypeExclusionFilter; +import com.capgemini.reports.changeobjects.change.AbstractChangeObject; +import com.capgemini.reports.changeobjects.change.FPPRevision; +import com.capgemini.reports.changeobjects.change.TcChangeNoticeRevision; +import com.capgemini.reports.changeobjects.change.TcChangeRequestRevision; +import com.capgemini.reports.definition.r13report.R13Keys; +import com.capgemini.reports.definition.r13report.execution.ExecutionR13CR; +import com.capgemini.reports.execution.mapconstructor.IMapConstructor; +import com.capgemini.reports.reports.parameters.EffectivityDate; +import com.capgemini.reports.snecmaobjects.generic.AbstractGeneric; +import com.google.common.base.Joiner; +import lombok.EqualsAndHashCode; + +import java.util.*; + +import static com.capgemini.reports.changeobjects.change.AbstractChangeObject.getItemIdFromModelObjectSetToString; + +/** + * Printer of a R13 Report for CR objects. + */ +@EqualsAndHashCode(callSuper = true) +public class R13PrinterCR extends AbstractR13Printer implements IMapConstructor> { + private static final long serialVersionUID = 7886687130935534458L; + + private static final String CN_DEPRECIE_REVISION = "CN Déprécié Revision"; + private static final String PV4_CN_DEPREC_REVISION = "PV4_CN_DEPRECRevision"; + private static final String EMPTY_STRING = ""; + private static final String SAUT_LIGNE = "\n"; + private static final String COMMA = " , "; + + @Override + protected LinkedHashMap> getChangeObjectData(final TcChangeRequestRevision change, final Map typeObjectParam) { + Map prefix = new HashMap<>(typeObjectParam); + + // Add FPP cell (optional) + decoratePrefixWithFpp(change, prefix); + + // CR properties + prefix.put(R13Keys.TYPE.toString(), LanguageHelper.french(change.getTypeModSupportProcess())); + prefix.put(R13Keys.CR.EFFECTIVITES.toString(), getEffectivityValue(change)); + prefix.put(R13Keys.CR.PARTS_CHANGE_REQUEST.toString(),getItemIdFromModelObjectSetToString(change.getPartsFromApresPseudoFolder(null))); + + // Discover CNs (1 CN -> 1 additional line) and extract their prefixes + return discoverCN(change, prefix); + } + + private void decoratePrefixWithFpp(final TcChangeRequestRevision change, final Map param) { + List fppList = change.getFppList(); + if (fppList == null || fppList.isEmpty()) { + emptyFPP(param); // No FPP, empty cell + } + else { + StringBuilder builderId = new StringBuilder(); + StringBuilder builderRev = new StringBuilder(); + boolean firstPass = true; + for (FPPRevision fpp : fppList) { + if (firstPass) { + builderId.append(fpp.getItemId()); + builderRev.append(fpp.getRevisionId()); + firstPass = false; + } + else { + builderId.append(SAUT_LIGNE).append(fpp.getItemId()); // If several FPPs are found, add them all in the same cell with a new line + builderRev.append(SAUT_LIGNE).append(fpp.getRevisionId()); + } + } + param.put(R13Keys.CR.ID_PROBLEM_REPORT.toString(), builderId.toString()); + param.put(R13Keys.CR.REVISION_PROBLEM_REPORT.toString(), builderRev.toString()); + } + } + + /** + * Concatenates all effectivities of the ChangeRequest in a String. + * + * @param change the change + * @return a String containing all effectivities, comma-separated + */ + private String getEffectivityValue(final TcChangeRequestRevision change) { + StringBuilder builder = new StringBuilder(); + List statuses = change.getReleaseStatusContainingEffectivity(); + if (statuses != null && !statuses.isEmpty()) { + boolean firstPass = true; + for (TcReleaseStatus status : statuses) { + // Must check because only the TcEffectivity are wanted (and not Set_Effectivity, Old effectivity, Interface todo) + if (SnecmaObjectTypes.EFFECTIVITY.equals(status.getStatusEnum().getIdentifier())) { + for (TcEffectivity effectivity : status.getEffectivities()) { + if (firstPass) { + firstPass = false; + } + else { + builder.append(COMMA); + } + effectivitySentence(builder, effectivity); + } + } + } + } + return builder.toString(); + } + + /** + * Appends the {@link TcEffectivity} description to the {@link StringBuilder}. + */ + private void effectivitySentence(final StringBuilder builder, final TcEffectivity effectivityBuilt) { + String articleFinalId = effectivityBuilt.endItemId(); + builder.append(articleFinalId).append('['); + String unitRange = effectivityBuilt.unitRange(); + if (unitRange.isEmpty()) { + builder.append(effectivityBuilt.dateRange()); + } + else { + builder.append(unitRange); + } + builder.append(']'); + } + + /** + * Complete the CN columns + * @param change + * @param fppCrPrefix + * @return LinkedHashMap> + */ + private LinkedHashMap> discoverCN(final TcChangeRequestRevision change, + final Map fppCrPrefix) { + LinkedHashMap> result = new LinkedHashMap<>(); + // Put a line with the CR alone + Map emptyCnData = makeEmptyCN(fppCrPrefix); + // Override module with CR modules + Set crModuleValues = getModuleValues(change); + emptyCnData.put(R13Keys.CR.MODULES.toString(), StringHelper.implodeList(COMMA, crModuleValues)); + result.put(change, emptyCnData); + + // Now put an extra line for every CN found + for (TcChangeNoticeRevision changeNotice : change.getChangeNoticesList(new TcTypeExclusionFilter(CN_DEPRECIE_REVISION, PV4_CN_DEPREC_REVISION), StatusEnum.forbid(StatusEnum.FINISHED, StatusEnum.CANCELLED))) { + Map cnParam = new HashMap<>(fppCrPrefix); // Copy prefix without modifying it + + // Users parameters of the CN + cnParam.putAll(makeUserParameters(changeNotice)); + + // ChangeNotice parameters + Set cnModuleValues = getModuleValues(changeNotice); + cnParam.put(R13Keys.CR.MODULES.toString(), StringHelper.implodeList(COMMA, cnModuleValues)); + cnParam.put(R13Keys.CR.ITEM_ID_CN.toString(), changeNotice.getItemId()); + cnParam.put(R13Keys.CR.ITEM_REVISION_CN.toString(), changeNotice.getRevisionId()); + cnParam.put(R13Keys.CR.DATE_CREATION_CN.toString(), new EffectivityDate(changeNotice.getDateCreation()).getFormattedDateForFrenchUser()); + cnParam.put(R13Keys.CR.LIGNE_PRODUIT_CN.toString(), Joiner.on(StringHelper.LINE_FEED).join(changeNotice.getLignesProduit())); + cnParam.put(R13Keys.CR.DESIGNATION_CN.toString(), changeNotice.getChangeName()); + cnParam.put(R13Keys.CR.TYPE_CN.toString(), LanguageHelper.french(changeNotice.getTypeModification())); + cnParam.put(R13Keys.CR.PARTS_CHANGE_NOTICE.toString(), getItemIdFromModelObjectSetToString(changeNotice.getPartsFromApresPseudoFolder(null))); + // Validated status of object parameters + cnParam.putAll(makeReleaseStatusParameters(changeNotice)); + + // Register this ChangeNotice for further processing (wkf, tasks etc.) + result.put(changeNotice, cnParam); + } + return result; + } + + /** + * Complete CN columns with empty strings + * @param param + * @return Map + */ + private Map makeEmptyCN(final Map param) { + Map result = new HashMap<>(param); + result.put(R13Keys.CR.ATTACHE_PILOTE_CN.toString(), EMPTY_STRING); + result.put(R13Keys.CR.NOM_PILOTE_CN.toString(), EMPTY_STRING); + result.put(R13Keys.CR.STATUT_PILOTE_CN.toString(), EMPTY_STRING); + result.put(R13Keys.CR.MODULES.toString(), EMPTY_STRING); + result.put(R13Keys.CR.ITEM_ID_CN.toString(), EMPTY_STRING); + result.put(R13Keys.CR.ITEM_REVISION_CN.toString(), EMPTY_STRING); + result.put(R13Keys.CR.DATE_CREATION_CN.toString(), EMPTY_STRING); + result.put(R13Keys.CR.LIGNE_PRODUIT_CN.toString(), EMPTY_STRING); + result.put(R13Keys.CR.DESIGNATION_CN.toString(), EMPTY_STRING); + result.put(R13Keys.CR.TYPE_CN.toString(), EMPTY_STRING); + result.put(R13Keys.CR.STATUT_CN.toString(), EMPTY_STRING); + result.put(R13Keys.CR.DATE_STATUT_CN.toString(), EMPTY_STRING); + result.put(R13Keys.CR.PARTS_CHANGE_NOTICE.toString(), EMPTY_STRING); + return result; + } + + /** + * Compiles the content required for the 'Module' column. + * + * @param changeRequest the {@link TcChangeRequestRevision} of the line + * @return the module column's content + */ + private Set getModuleValues(final TcChangeRequestRevision changeRequest) { + Set moduleNames = new TreeSet<>(); + // Obtain modules in gens with or without rupture of the CR + for (AbstractGeneric gen : changeRequest.getListOfGenericRevWithOrWithoutRupture()) { + moduleNames.add(getModuleName(gen)); + } + // Append all Generics in gens with/without rupture of all child CNs + for (TcChangeNoticeRevision cn : changeRequest.getChangeNoticesList(new TcTypeExclusionFilter(CN_DEPRECIE_REVISION, PV4_CN_DEPREC_REVISION), StatusEnum.forbid(StatusEnum.FINISHED, StatusEnum.CANCELLED))) { + moduleNames.addAll(getModuleValues(cn)); + } + return moduleNames; + } + + /** + * Compiles the content required for the 'Module' column. + * + * @param changeNotice the {@link TcChangeRequestRevision} of the line + * @return the module column's content + */ + private Set getModuleValues(final TcChangeNoticeRevision changeNotice) { + Set moduleNames = new TreeSet<>(); + for (AbstractGeneric gen : changeNotice.getListOfGenericRevWithOrWithoutRupture()) { + String moduleName = getModuleName(gen); + moduleNames.add(moduleName); + } + return moduleNames; + } + + private String getModuleName(final AbstractGeneric gen) { + return gen.getItemId(); + } + + @Override + protected boolean isValid(final TcReleaseStatus status, final AbstractChangeObject change) { + // If change is neither a CR nor a CN, it is not valid + return (change instanceof TcChangeRequestRevision) || (change instanceof TcChangeNoticeRevision); + } + + @Override + protected void specificTreatmentEmptyLines(final Map mapPrinter) { + emptyFPP(mapPrinter); + mapPrinter.put(R13Keys.CR.EFFECTIVITES.toString(), EMPTY_STRING); + mapPrinter.putAll(makeEmptyCN(mapPrinter)); // replace all entries back into the input map + } + + private void emptyFPP(final Map mapPrinter) { + mapPrinter.put(R13Keys.CR.ID_PROBLEM_REPORT.toString(), EMPTY_STRING); + mapPrinter.put(R13Keys.CR.REVISION_PROBLEM_REPORT.toString(), EMPTY_STRING); + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r13report/printer/R13PrinterFPP.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r13report/printer/R13PrinterFPP.java new file mode 100644 index 0000000..c761002 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r13report/printer/R13PrinterFPP.java @@ -0,0 +1,53 @@ +package com.capgemini.reports.definition.r13report.printer; + +import com.capgemini.framework.common.LanguageHelper; +import com.capgemini.framework.teamcenter.object.pom.status.StatusEnum; +import com.capgemini.framework.teamcenter.object.pom.status.TcReleaseStatus; +import com.capgemini.reports.changeobjects.change.AbstractChangeObject; +import com.capgemini.reports.changeobjects.change.FPPRevision; +import com.capgemini.reports.definition.r13report.R13Keys; +import com.capgemini.reports.definition.r13report.execution.ExecutionR13FPP; +import com.capgemini.reports.execution.mapconstructor.IMapConstructor; +import lombok.EqualsAndHashCode; + +import java.util.*; + +import static com.capgemini.reports.changeobjects.change.AbstractChangeObject.getItemIdFromModelObjectSetToString; + +/** + * Printer of a R13 Report for FPP objects. + */ +@EqualsAndHashCode(callSuper = true) +public class R13PrinterFPP extends AbstractR13Printer implements IMapConstructor> { + private static final long serialVersionUID = 6460682170787086789L; + + @Override + protected Map> getChangeObjectData(final FPPRevision fpp, final Map typeObjectParam) { + // copyParameters + Map prefixCopy = new HashMap<>(typeObjectParam); + + // Add specific FPP parameters + prefixCopy.put(R13Keys.TYPE.toString(), LanguageHelper.french(fpp.getOrigineDemande())); + prefixCopy.put(R13Keys.FPP.PARTS_FPP.toString(), getItemIdFromModelObjectSetToString(fpp.getPartsOfSubModifications())); + + Map> result = new LinkedHashMap<>(); + result.put(fpp, prefixCopy); // Only ever one object here (the original FPP) + + // Workflow and active task parameters + return result; + } + + @Override + protected boolean isValid(final TcReleaseStatus status, final AbstractChangeObject change) { + boolean validStatus = false; + if (status.getStatusEnum() == StatusEnum.J0) { + validStatus = true; + } + return validStatus; + } + + @Override + protected void specificTreatmentEmptyLines(final Map mapPrinter) { + // No sepcific treatment + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/AbstractDataReportPreparatorR15R16R17.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/AbstractDataReportPreparatorR15R16R17.java new file mode 100644 index 0000000..2f9b592 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/AbstractDataReportPreparatorR15R16R17.java @@ -0,0 +1,206 @@ +package com.capgemini.reports.definition.r15r16r17reports; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.object.pom.status.StatusEnum; +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.capgemini.framework.teamcenter.queries.saved.modelobject.ItemRevisionQuery; +import com.capgemini.reports.documentationobjects.DocNorm; +import com.capgemini.reports.documentationobjects.DocNormStandard; +import com.capgemini.reports.documentationobjects.DocTechnic; +import com.capgemini.reports.execution.IDataReportPreparator; +import com.capgemini.reports.releasestatus.RevisionStatusAndDate; +import com.capgemini.reports.snecmaobjects.part.AbstractPart; +import com.capgemini.reports.teamcenter.ObjectInfoHelper; +import com.google.common.base.Optional; +import com.teamcenter.soa.client.model.ModelObject; +import com.teamcenter.soa.client.model.strong.Item; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import lombok.EqualsAndHashCode; +import lombok.extern.slf4j.Slf4j; + +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; + +/** + * Abstract Class whose goal is to prepare common data to R15 R16 R17 reports. + * + * @param the report {@link AbstractExecutionR15R16R17} + */ +@Slf4j +@EqualsAndHashCode +public abstract class AbstractDataReportPreparatorR15R16R17> implements IDataReportPreparator { + private static final long serialVersionUID = 4533353562306975227L; + + private static final String REC_DEFINITION = "REC-Définition de récupération / Recovery design"; + private static final String MCI_MASSE_CENTRE_DE_GRAVITE = "MCI-Masse, Centre de gravité et inertie / Mass, gravity center and inertia"; + private static final int MINIMUM_SECURITY_LEVEL_FOR_WATERMARK = 3; + private static final String PROP_PS_PARENTS = "ps_parents"; + private static final String REALISATION_ACHIEVEMENT = "Réalisation / Achievement"; + + /** + * Get the date in a specific format for Reports. + * + * @param calendar {@link Calendar} - a calendar + * @return the {@link String} value + */ + protected String getDateFormatDayMonthYear(final Calendar calendar) { + SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy"); + return sdf.format(calendar.getTime()); + } + + /** + * Returns true if the watermark should be present in the report.
    + * It should be present if any of the DocNorm or DocTechnic is considered as "sensible". + * + * @param report - the execution report which provide all informations for the report + * @return true if the watermark should be present in the report + */ + protected boolean isConfidential(final T report) { + for (DocNorm docNorm : report.docNormList) { + String niveauSensibilite = docNorm.getNiveauSensibilite(); + String sensibiliteSecurite = docNorm.getSensibiliteSecurite(); + log.debug("DocNorm " + docNorm.getDocId() + ": niveauSensibilite = " + niveauSensibilite + ", sensibiliteSecurite = " + sensibiliteSecurite); + if (sensibiliteAttributesAreConfidential(niveauSensibilite, sensibiliteSecurite)) { + return true; + } + } + for (DocTechnic docTechnic : report.docTechnicList) { + String niveauSensibilite = docTechnic.getNiveauSensibilite(); + String sensibiliteSecurite = docTechnic.getSensibiliteSecurite(); + log.debug("DocTechnic " + docTechnic.getDocId() + ": niveauSensibilite = " + niveauSensibilite + ", sensibiliteSecurite = " + sensibiliteSecurite); + if (sensibiliteAttributesAreConfidential(niveauSensibilite, sensibiliteSecurite)) { + return true; + } + } + return false; + } + + /** + * This method check values of attributes ip_classification and pv_sensibilite_securite of a DocNorm or a DocTechnic. + * + * @param niveauSensibilite value of ip_classification attribute + * @param sensibiliteSecurite value of pv_sensibilite_securite attribute + * @return true if 'niveau de sensibilite' value contains 'C3' or C4' string + * or if 'niveau de sensibilite' is empty or doesn't contain 'C3' or 'C4' but 'sensibilité securité' has a value of 3 or 4. + * */ + protected boolean sensibiliteAttributesAreConfidential(String niveauSensibilite, String sensibiliteSecurite) { + if (niveauSensibilite != null && (niveauSensibilite.contains("C3") || niveauSensibilite.contains("C4"))) { + return true; + } else { + if (sensibiliteSecurite != null && !sensibiliteSecurite.isEmpty() + && Integer.valueOf(sensibiliteSecurite) >= MINIMUM_SECURITY_LEVEL_FOR_WATERMARK) { + return true; + } + } + return false; + } + + /** + * Returns true if this report execution generated an empty table of documents (no doc found). + * + * @param report - the execution report which provide all informations for the report + * @return true if the table of documents is empty + */ + public boolean isEmptyTable(final T report) { + return report.getDocNormList().isEmpty() && report.getDocNormStandardList().isEmpty() && report.getDocTechnicList().isEmpty(); + } + + /** + * Get the parents with the ps_parents property.
    + * Filter with a wanted type. + * + * @param session {@link TcSession} - the tc session + * @param refObject {@link ItemRevision} - the reference object + * @param typeWanted {@link SnecmaObjectTypes} the selected type we need + * @return List the parents of the reference object + */ + protected List getPsParentsOfPart(final TcSession session, final ItemRevision refObject, final String typeWanted) { + List results = new ArrayList<>(); + session.loadProperties(refObject, PROP_PS_PARENTS); + ModelObject[] parents = refObject.get_ps_parents(); + session.loadProperties(parents); + for (ModelObject object : parents) { + ItemRevision itemRev = (ItemRevision) object; + if (typeWanted.equals(itemRev.getTypeObject().getName())) { + results.add(itemRev); + } + } + return results; + } + + /** + * Retrieve the {@link DocNorm} and the {@link DocNormStandard} in their respective {@link List}s. + * + * @param session {@link TcSession} - the tc session + * @param itemRevision {@link ItemRevision} - the object which possess all the documents + * @param report - the execution report which provide all informations for the report + */ + protected void retrieveDocNormAndDocNormStandardLists(final TcSession session, final ItemRevision itemRevision, final T report) { + List referenceDoclist = AbstractPart.returnReferenceDocuments(session, itemRevision); + if (!referenceDoclist.isEmpty()) { + for (Item docItem : referenceDoclist) { + if (docItem == null) { + continue; + } + String docType = docItem.getTypeObject().getName(); + if (SnecmaObjectTypes.DOC_NORM.equals(docType)) { + ItemRevision selectedDocRev = getDocNormAndDocNormStandardRevisions(session, docItem.get_item_id()); + report.docNormList.add(new DocNorm(session, selectedDocRev)); + } else if (SnecmaObjectTypes.DOC_NORM_STANDARD.equals(docType)) { + ItemRevision selectedDocRev = getDocNormAndDocNormStandardRevisions(session, docItem.get_item_id()); + report.docNormStandardList.add(new DocNormStandard(session, selectedDocRev)); + } + } + } + } + + private ItemRevision getDocNormAndDocNormStandardRevisions(final TcSession session, final String docId) { + // Retrieve the revisions + List listOfDocNormRev = new ItemRevisionQuery(session).searchID(docId).findAll(); + // Try to obtain the revision with the latest release date... + Optional selectedDocRev = ObjectInfoHelper.getRevisionFromStatusWithMostRecentReleaseDate(session, listOfDocNormRev, Calendar.getInstance(), StatusEnum.PUBLISHED, StatusEnum.FROZEN); + if (selectedDocRev.isPresent()) { + return selectedDocRev.get(); + } else { + // No release date found, now obtain the revision with latest modification date + RevisionStatusAndDate revAndStatus = ObjectInfoHelper.getRevisionAndStatusWithMostRecentModificationDate(listOfDocNormRev, Calendar.getInstance()); + return revAndStatus.getItemRevision(); + } + } + + /** + * Retrieve the {@link DocTechnic} in a {@link List}. + */ + protected void retrieveDocTechnicList(final TcSession session, final ItemRevision partItemRevision, final T report) { + List technicDocObjects = AbstractPart.returnDefinitionDocuments(session, partItemRevision); + if (!technicDocObjects.isEmpty()) { + for (ItemRevision docTechnicRev : technicDocObjects) { + if (docTechnicRev != null) { + report.docTechnicList.add(new DocTechnic(session, docTechnicRev)); + } + } + } + } + + /** + * Filter the DocTechnic with specific values on the type_doc_technic_1 and type_doc_technic_2 properties. + * + * @param report - the execution report which provide all informations for the report + */ + protected void filterDocTechnic(final T report) { + List transitList = new ArrayList<>(); + for (DocTechnic docTechnic : report.docTechnicList) { + // These values are forbidden + String typeDocTechnic1 = docTechnic.getTypeDocTechnic1(); + String typeDocTechnic2 = docTechnic.getTypeDocTechnic2(); + if (!(REALISATION_ACHIEVEMENT.equals(typeDocTechnic1) + && (MCI_MASSE_CENTRE_DE_GRAVITE.equals(typeDocTechnic2) || REC_DEFINITION.equals(typeDocTechnic2)))) { + transitList.add(docTechnic); + } + } + report.docTechnicList.clear(); + report.docTechnicList.addAll(transitList); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/AbstractExecutionR15R16R17.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/AbstractExecutionR15R16R17.java new file mode 100644 index 0000000..d139712 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/AbstractExecutionR15R16R17.java @@ -0,0 +1,66 @@ +package com.capgemini.reports.definition.r15r16r17reports; + +import com.capgemini.reports.ReportLaunchTypeEnum; +import com.capgemini.reports.documentationobjects.DocNorm; +import com.capgemini.reports.documentationobjects.DocNormStandard; +import com.capgemini.reports.documentationobjects.DocTechnic; +import com.capgemini.reports.execution.AbstractExecutionReport; +import com.capgemini.reports.execution.IDataReportPreparator; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; + +import java.util.ArrayList; +import java.util.List; + + +/** + * Prepare the common data for report 15, 16 and 17. + * + * @param Generic object for a report + */ +@Getter +@Setter +@EqualsAndHashCode(callSuper = true) +public abstract class AbstractExecutionR15R16R17> extends AbstractExecutionReport { + protected static final String FRENCH_LANGUAGE = "Francais"; + private static final long serialVersionUID = 4911952011990726425L; + // Report parameters + protected final boolean french; + protected final String frenchInput; + protected final String itemId; + // Documents gathered + protected final List docNormList = new ArrayList<>(); + protected final List docNormStandardList = new ArrayList<>(); + protected final List docTechnicList = new ArrayList<>(); + // Data gathered + protected String dateReleased = ""; + protected String revisionArticle = ""; + protected String produitUnit = ""; + protected String typeProduit; + protected String clausePropriete; + + /** + * Builds the super class which helps to execute a R15 R16 or 17 reports. + * + * @param itemID {@link String} - the Id of the top Item + * @param language {@link String} - the chosen language + * @param priorityCode int - the priority code found in the reporting.properties file associated to a report. + * @param revisionRule {@link String} - the revision rule for resolution structure + * @param launchType {@link ReportLaunchTypeEnum} - the launch type of the report + */ + public AbstractExecutionR15R16R17(final String itemID, final String language, final int priorityCode, final String revisionRule, + final ReportLaunchTypeEnum launchType) { + super(priorityCode, revisionRule, launchType); + this.frenchInput = language; + this.french = isFrench(language); + this.itemId = itemID; + } + + protected static boolean isFrench(final String language) { + return FRENCH_LANGUAGE.equals(language); + } + + @Override + public abstract IDataReportPreparator getDataPreparator(); +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/AbstractR15R16R17Printer.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/AbstractR15R16R17Printer.java new file mode 100644 index 0000000..0cb70b5 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/AbstractR15R16R17Printer.java @@ -0,0 +1,190 @@ +package com.capgemini.reports.definition.r15r16r17reports; + +import com.capgemini.framework.common.LanguageHelper; +import com.capgemini.framework.common.ResourceHelper; +import com.capgemini.framework.common.SettingsHelper; +import com.capgemini.reports.definition.r15r16r17reports.R15R16R17R24R25Keys.Page2; +import com.capgemini.reports.documentationobjects.DocNorm; +import com.capgemini.reports.documentationobjects.DocNormStandard; +import com.capgemini.reports.documentationobjects.DocTechnic; +import com.capgemini.reports.exceptions.FileLoadingException; +import com.capgemini.reports.execution.AbstractExecutionReport; +import com.capgemini.reports.execution.mapconstructor.AbstractStaticTemplateMapConstructor; +import com.capgemini.reports.printing.PrintParameters; +import com.capgemini.reports.snecmaobjects.visitor.IComponentVisitor; +import lombok.EqualsAndHashCode; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.EnumMap; +import java.util.List; +import java.util.Map; + +/** + * This class allows printing of severel elements that are found in both the R15, R16 and R17 reports. + * + * @param describes which report's {@link AbstractExecutionReport} this printer will print. Must be a subclass of {@link AbstractExecutionR15R16R17}. + */ +@Slf4j +@EqualsAndHashCode(callSuper = true) +public abstract class AbstractR15R16R17Printer> extends AbstractStaticTemplateMapConstructor { + private static final long serialVersionUID = 6114330530182125707L; + + private static final String SNECMA_LOGO_PNG = "/Jasper/images/Snecma_logo.png"; + private static final String CONFIDENTIEL_INDUSTRIE_JPG = "/Jasper/images/confidentiel_industrie.jpg"; + private static final String N_A = "N/A"; + private static final int INT_3 = 3; + private static final List PRODUCT_TYPES_LIST = SettingsHelper.getProductTypes(); + + /** + * Returns true if the product is in the product types list.
    + * It means that the DocDrawing id could'nt be available in the report.
    + * Their id values should be replaced by the id of the Part. + * + * @param productType {@link String} - the product type + * @return true if it is not authorized, false otherwise + */ + protected static boolean isNotAuthorized(final String productType) { + if (productType == null || productType.isEmpty()) { + return false; + } + + // Take the three letters of the left side of the product type value + String type =(productType.length() preparator = (AbstractDataReportPreparatorR15R16R17) execution.getDataPreparator(); + mainReport.addReportParameters(setupStringParameters(execution)); + mainReport.addReportParameter(R15R16R17R24R25Keys.EMPTY_TABLE.toString(), preparator.isEmptyTable(execution)); + try { + mainReport.addReportParameter(R15R16R17R24R25Keys.SNECMA_LOGO, ResourceHelper.loadImage(SNECMA_LOGO_PNG)); + } catch (FileLoadingException e) { + log.warn("Could not read the Snecma logo", e); + } + + if (preparator.isConfidential(execution)) { + try { + mainReport.addReportParameter(R15R16R17R24R25Keys.WATERMARK, ResourceHelper.loadImage(CONFIDENTIEL_INDUSTRIE_JPG)); + } catch (FileLoadingException e) { + log.warn("Could not read the 'confidentiel industrie' watermark", e); + } + } + mainReport.addReportDataFromEnum(setupData(execution)); + + // Now add the specific stuff + addOptionalParameters(execution, mainReport); + } + + protected Map setupStringParameters(final T execution) { + Map params = new EnumMap<>(R15R16R17R24R25Keys.class); + params.put(R15R16R17R24R25Keys.CLAUSE_PROPRIETE, execution.getClausePropriete()); + params.put(R15R16R17R24R25Keys.PRODUCT_TYPE, execution.getTypeProduit()); + params.put(R15R16R17R24R25Keys.REPORT_TITLE, getTitle(execution)); + params.put(R15R16R17R24R25Keys.ITEM_REVISION_ID, execution.getRevisionArticle()); + String dateReleased = execution.getDateReleased(); + params.put(R15R16R17R24R25Keys.RELEASE_DATE, execution.isFrench() ? french(dateReleased) : english(dateReleased)); + return params; + } + + private List> setupData(final T execution) { + List> dataTable = new ArrayList<>(); + boolean isFrench = execution.isFrench(); + for (DocNorm norm : execution.getDocNormList()) { + dataTable.add(getDocNormLine(norm, isFrench)); + } + for (DocNormStandard normStd : execution.getDocNormStandardList()) { + dataTable.add(getDocNormStandardLine(normStd, isFrench)); + } + for (DocTechnic technic : execution.getDocTechnicList()) { + dataTable.add(getDocTechnicLine(technic, isFrench)); + } + + dataTable.addAll(addExtraDocLines(execution)); + + // If there are no documents, add an empty line to provoke band printing + if (dataTable.isEmpty()) { + Map line = new EnumMap<>(Page2.class); + line.put(Page2.DOC_NUMBER, "(No document found)"); + line.put(Page2.ISSUE, N_A); + line.put(Page2.DOC_TYPE, N_A); + line.put(Page2.DOC_TITLE, N_A); + dataTable.add(line); + } + return dataTable; + } + + protected abstract List> addExtraDocLines(final T execution); + + protected Map getDocNormLine(final DocNorm docNorm, final boolean isFrench) { + String idOrigine = docNorm.getIdOrigine(); + Map line = new EnumMap<>(Page2.class); + line.put(Page2.DOC_NUMBER, (idOrigine == null || idOrigine.isEmpty()) ? docNorm.getDocId() : idOrigine); + line.put(Page2.ISSUE, "-"); + String typeDocNorm = docNorm.getTypeDocNorm(); + line.put(Page2.DOC_TYPE, isFrench ? french(typeDocNorm) : english(typeDocNorm)); + line.put(Page2.DOC_TITLE, isFrench ? docNorm.getItemName() : docNorm.getDesignationEn()); + return line; + } + + protected Map getDocNormStandardLine(final DocNormStandard normStd, final boolean isFrench) { + Map line = new EnumMap<>(Page2.class); + String idOrigine = normStd.getIdOrigine(); + line.put(Page2.DOC_NUMBER, (idOrigine == null || idOrigine.isEmpty()) ? normStd.getDocId() : idOrigine); + line.put(Page2.ISSUE, "-"); + line.put(Page2.DOC_TYPE, isFrench ? "Norme pour articles standards" : "Norm for standards items"); + line.put(Page2.DOC_TITLE, isFrench ? normStd.getItemName() : normStd.getDesignationEn()); + return line; + } + + protected Map getDocTechnicLine(final DocTechnic technic, final boolean isFrench) { + Map line = new EnumMap<>(Page2.class); + String idOrigine = technic.getIdOrigine(); + line.put(Page2.DOC_NUMBER, (idOrigine == null || idOrigine.isEmpty()) ? technic.getDocId() : idOrigine); + line.put(Page2.ISSUE, technic.getIndice()); + + String typeDocTechnic1 = technic.getTypeDocTechnic1(); + String type1 = isFrench ? french(typeDocTechnic1) : english(typeDocTechnic1); + String typeDocTechnic2 = technic.getTypeDocTechnic2(); + String type2 = isFrench ? french(typeDocTechnic2) : english(typeDocTechnic2); + line.put(Page2.DOC_TYPE, type1 + " / " + type2); + + line.put(Page2.DOC_TITLE, isFrench ? technic.getName() : technic.getDesignationEn()); + return line; + } + + /** + * Adds parameters that are not common to R15-R16-R17 reports. + * + * @param execution the data-bearing {@link AbstractExecutionR15R16R17} + * @param mainReport the {@link PrintParameters} + */ + protected abstract void addOptionalParameters(final T execution, final PrintParameters mainReport); + + protected abstract String getTitle(final T execution); + + protected abstract IComponentVisitor> getVisitor(final boolean isFrench); +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/CommunR15R16R17ComponentVisitor.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/CommunR15R16R17ComponentVisitor.java new file mode 100644 index 0000000..e3823c4 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/CommunR15R16R17ComponentVisitor.java @@ -0,0 +1,222 @@ +package com.capgemini.reports.definition.r15r16r17reports; + +import com.capgemini.framework.common.LanguageHelper; +import com.capgemini.framework.common.StringHelper; +import com.capgemini.reports.snecmaobjects.admin.RFAdminAGRevision; +import com.capgemini.reports.snecmaobjects.admin.RFAdminAPRevision; +import com.capgemini.reports.snecmaobjects.admin.RFAdminARevision; +import com.capgemini.reports.snecmaobjects.admin.RFAdminRevision; +import com.capgemini.reports.snecmaobjects.descriptif.DescriptifRevision; +import com.capgemini.reports.snecmaobjects.generic.AbstractGenericRevision; +import com.capgemini.reports.snecmaobjects.generic.GenericAssembRevision; +import com.capgemini.reports.snecmaobjects.generic.GenericRevision; +import com.capgemini.reports.snecmaobjects.mockup.MockupRevision; +import com.capgemini.reports.snecmaobjects.part.*; +import com.capgemini.reports.snecmaobjects.product.ProductRevision; +import com.capgemini.reports.snecmaobjects.rf.RFGenericRevision; +import com.capgemini.reports.snecmaobjects.rf.RFPartAssembRevision; +import com.capgemini.reports.snecmaobjects.rf.RFPartRevision; +import com.capgemini.reports.snecmaobjects.supermodel.SuperModelRevision; +import com.capgemini.reports.snecmaobjects.visitor.IComponentVisitor; + +import java.util.EnumMap; +import java.util.Map; + +/** + * Visitor for a R15 or a R17 report. + */ +public class CommunR15R16R17ComponentVisitor implements IComponentVisitor> { + + private static final String YES = "Yes"; + private static final String OUI = "Oui"; + private static final String DASH_STR = "-"; + private static final long serialVersionUID = -4111258059351094185L; + private static final String SANS_OBJET = "Sans objet"; + private static final String NOT_APPLICABLE = "Not applicable "; + private final boolean isFrench; + + /** + * Constructor. + * + * @param isFrench boolean - the language of the report. + */ + public CommunR15R16R17ComponentVisitor(final boolean isFrench) { + this.isFrench = isFrench; + } + + private static String french(final String string) { + return LanguageHelper.french(string); + } + + private static String english(final String string) { + return LanguageHelper.english(string); + } + + @Override + public Map visitComponent(final ProductRevision aProductRev) { + // No use + return null; + } + + @Override + public Map visitComponent(final GenericRevision aGenericRev) { + return giveGenericProperties(aGenericRev); + } + + @Override + public Map visitComponent(SuperModelRevision aSuperModelRev) { + return null; + } + + @Override + public Map visitComponent(final GenericAssembRevision aGenericAssembRev) { + return giveGenericProperties(aGenericAssembRev); + } + + private Map giveGenericProperties(final AbstractGenericRevision aGenericRev) { + Map theMap = new EnumMap<>(R15R16R17R24R25Keys.class); + theMap.put(R15R16R17R24R25Keys.ITEM_ID, aGenericRev.getItemId()); + theMap.put(R15R16R17R24R25Keys.PART_NUMBER, aGenericRev.getItemId()); + theMap.put(R15R16R17R24R25Keys.MANUFACTURER_CODE, aGenericRev.getResponsableConception()); + theMap.put(R15R16R17R24R25Keys.FRENCH_DESIGNATION, aGenericRev.getName()); + theMap.put(R15R16R17R24R25Keys.ENGLISH_DESIGNATION, aGenericRev.getDesignationEN()); + theMap.put(R15R16R17R24R25Keys.OBTURATION, isFrench ? SANS_OBJET : NOT_APPLICABLE); + theMap.put(R15R16R17R24R25Keys.CLASSIFICATION, DASH_STR); + theMap.put(R15R16R17R24R25Keys.FIELD_OPN_SERIALISATION, isFrench ? OUI : YES); + theMap.put(R15R16R17R24R25Keys.LOG_DOCUMENT, isFrench ? SANS_OBJET : NOT_APPLICABLE); + theMap.put(R15R16R17R24R25Keys.PART_VERSION, StringHelper.EMPTY); + return theMap; + } + + @Override + public Map visitComponent(final AlternateRevision aAlternateRev) { + Map theMap = giveNotPartMatProperties(aAlternateRev); + String obturation = aAlternateRev.getObturation(); + theMap.put(R15R16R17R24R25Keys.OBTURATION, isFrench ? french(obturation) : english(obturation)); + return theMap; + } + + @Override + public Map visitComponent(final DETRevision aDetRev) { + Map theMap = giveNotPartMatProperties(aDetRev); + String obturation = aDetRev.getObturation(); + theMap.put(R15R16R17R24R25Keys.OBTURATION, isFrench ? french(obturation) : english(obturation)); + return theMap; + } + + @Override + public Map visitComponent(final PartAeroRevision aPartAeroRev) { + Map theMap = giveNotPartMatProperties(aPartAeroRev); + String obturation = aPartAeroRev.getObturation(); + theMap.put(R15R16R17R24R25Keys.OBTURATION, isFrench ? french(obturation) : english(obturation)); + return theMap; + } + + @Override + public Map visitComponent(final PartNoAeroRevision aPartNoAeroRev) { + Map theMap = giveNotPartMatProperties(aPartNoAeroRev); + theMap.put(R15R16R17R24R25Keys.OBTURATION, isFrench ? SANS_OBJET : NOT_APPLICABLE); + return theMap; + } + + @Override + public Map visitComponent(final PartAssembRevision aPartAssembRev) { + Map theMap = giveNotPartMatProperties(aPartAssembRev); + theMap.put(R15R16R17R24R25Keys.OBTURATION, isFrench ? SANS_OBJET : NOT_APPLICABLE); + return theMap; + } + + @Override + public Map visitComponent(final PartMatRevision aPartMatRev) { + Map theMap = givePartProperties(aPartMatRev); // This one does NOT use giveNotPartMatProperties (obviously) + theMap.put(R15R16R17R24R25Keys.OBTURATION, isFrench ? SANS_OBJET : NOT_APPLICABLE); + String classementMat = aPartMatRev.getClassementMat(); + theMap.put(R15R16R17R24R25Keys.CLASSIFICATION, (classementMat == null || classementMat.isEmpty()) ? DASH_STR : classementMat); + theMap.put(R15R16R17R24R25Keys.FIELD_OPN_SERIALISATION, isFrench ? SANS_OBJET : NOT_APPLICABLE); + theMap.put(R15R16R17R24R25Keys.LOG_DOCUMENT, isFrench ? SANS_OBJET : NOT_APPLICABLE); + return theMap; + } + + @Override + public Map visitComponent(final StandardRevision aStandardRev) { + Map theMap = giveNotPartMatProperties(aStandardRev); + theMap.put(R15R16R17R24R25Keys.OBTURATION, isFrench ? SANS_OBJET : NOT_APPLICABLE); + return theMap; + } + + private Map givePartProperties(final AbstractPart aPart) { + Map theMap = new EnumMap<>(R15R16R17R24R25Keys.class); + theMap.put(R15R16R17R24R25Keys.ITEM_ID, aPart.getItemId()); + theMap.put(R15R16R17R24R25Keys.PART_NUMBER, aPart.getItemId()); + theMap.put(R15R16R17R24R25Keys.MANUFACTURER_CODE, aPart.getResponsableConception()); + theMap.put(R15R16R17R24R25Keys.PART_VERSION, aPart.getRevisionId()); + theMap.put(R15R16R17R24R25Keys.FRENCH_DESIGNATION, aPart.getName()); + theMap.put(R15R16R17R24R25Keys.ENGLISH_DESIGNATION, aPart.getDesignationEN()); + return theMap; + } + + private Map giveNotPartMatProperties(final AbstractPart aPart) { + Map theMap = givePartProperties(aPart); + String classement = aPart.getClassement(); + theMap.put(R15R16R17R24R25Keys.CLASSIFICATION, (classement == null || classement.isEmpty()) ? DASH_STR : classement); + String suiviUtilisation = aPart.getSuiviUtilisation(); + theMap.put(R15R16R17R24R25Keys.FIELD_OPN_SERIALISATION, isFrench ? french(suiviUtilisation) : english(suiviUtilisation)); + String documentControle = aPart.getDocumentControle(); + theMap.put(R15R16R17R24R25Keys.LOG_DOCUMENT, isFrench ? french(documentControle) : english(documentControle)); + return theMap; + } + + @Override + public Map visitComponent(final RFGenericRevision aRfGenericRev) { + // No use + return null; + } + + @Override + public Map visitComponent(final RFPartAssembRevision aRfPartAssembRev) { + // No use + return null; + } + + @Override + public Map visitComponent(final RFPartRevision aRfPartRev) { + // No use + return null; + } + + @Override + public Map visitComponent(final RFAdminRevision aRfAdminRev) { + // No use + return null; + } + + @Override + public Map visitComponent(final RFAdminARevision aRfAdminARev) { + // No use + return null; + } + + @Override + public Map visitComponent(final RFAdminAPRevision aRfAdminAPRev) { + // No use + return null; + } + + @Override + public Map visitComponent(final RFAdminAGRevision aRfAdminAGRev) { + // No use + return null; + } + + @Override + public Map visitComponent(final MockupRevision aMockupRev) { + // This object is not use in this report + return null; + } + + @Override + public Map visitComponent(final DescriptifRevision aDescriptifRev) { + // This object is not use in this report + return null; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/R15R16R17R24R25Keys.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/R15R16R17R24R25Keys.java new file mode 100644 index 0000000..340e1ab --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/R15R16R17R24R25Keys.java @@ -0,0 +1,52 @@ +package com.capgemini.reports.definition.r15r16r17reports; + +/** + * Main Parameter keys for R17 report. + */ +public enum R15R16R17R24R25Keys { + REPORT_TITLE, + ITEM_ID, + ITEM_REVISION_ID, + RELEASE_DATE, + CLAUSE_PROPRIETE, + EMPTY_TABLE, + SNECMA_LOGO, + WATERMARK, + PRODUCT_TYPE, + PART_NUMBER, + MANUFACTURER_CODE, + PART_VERSION, + FRENCH_DESIGNATION, + ENGLISH_DESIGNATION, + CLASSIFICATION, + FIELD_OPN_SERIALISATION, + LOG_DOCUMENT, + OBTURATION, + MT_NUMBER, + PREVIOUS_RELEASE_DATE; + + /** + * Report Data. Specific for R15 and R16. + */ + public enum SpecificR15R16 { + PRODUCT_UNIT, + INSTALLATION_INTERFACE, + PARTNER_INTERFACE, + SUB_TITLE, + IS_PREVIOUS_DEF + } + + /** + * Report Data. + */ + public enum Page2 { + REF_DESCRIPTIF, + REV_DESCRIPTIF, + STATUS, + MATURITY_STATUS, + DOC_NUMBER, + ISSUE, + DOC_TYPE, + DOC_TITLE + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/r15r17reports/AbstractDataReportPreparatorR15R17.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/r15r17reports/AbstractDataReportPreparatorR15R17.java new file mode 100644 index 0000000..1161b5a --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/r15r17reports/AbstractDataReportPreparatorR15R17.java @@ -0,0 +1,357 @@ +package com.capgemini.reports.definition.r15r16r17reports.r15r17reports; + +import com.capgemini.framework.common.LanguageHelper; +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.object.pom.status.StatusEnum; +import com.capgemini.framework.teamcenter.object.pom.status.StatusEnum.AbstractStatusFilter; +import com.capgemini.framework.teamcenter.object.pom.status.TcReleaseStatus; +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.capgemini.reports.definition.r15r16r17reports.AbstractDataReportPreparatorR15R16R17; +import com.capgemini.reports.documentationobjects.DocDrawing; +import com.capgemini.reports.documentationobjects.DocGeometry; +import com.capgemini.reports.exceptions.InvalidUserInputException; +import com.capgemini.reports.exceptions.NotSupportedException; +import com.capgemini.reports.exceptions.UserInputErrorEnum; +import com.capgemini.reports.snecmaobjects.SnecmaObjectFactory; +import com.capgemini.reports.snecmaobjects.part.AbstractPart; +import com.capgemini.reports.teamcenter.ObjectInfoHelper; +import com.capgemini.reports.teamcenter.ObjectInfoLoader; +import com.capgemini.reports.teamcenter.queries.saved.ChangeFromPartQuery; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import com.teamcenter.soa.client.model.strong.ReleaseStatus; +import lombok.EqualsAndHashCode; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; + +import static com.capgemini.framework.teamcenter.object.SnecmaObjectProperties.PV4_TYPE_MODIFICATION; + +/** + * Abstract Class whose goal is to prepare common data to R15 R17 reports. + * + * @param the report {@link AbstractExecutionR15R17} + */ +@Slf4j +@EqualsAndHashCode(callSuper = true) +public abstract class AbstractDataReportPreparatorR15R17> extends AbstractDataReportPreparatorR15R16R17 { + private static final long serialVersionUID = -7130318844369564083L; + + private static final AbstractStatusFilter APPROVED_STATUS = StatusEnum.allow(StatusEnum.DEF_APPROVED, StatusEnum.PRELIM_DEF_APPROVED); + private static final AbstractStatusFilter CANCELLED_STATUS = StatusEnum.allow(StatusEnum.CANCELLED); + private static final String REVISION_ENG_CHANGE = SnecmaObjectTypes.REVISION_ENG_CHANGE; + private static final String DEFINITION_EN_COURS = "définition en cours"; + private static final String DEFINITION_ANNULEE = "définition annulée"; + private static final String WHITESPACE = " "; + + /** + * Find the top ItemRevision in the list of all the revisions. + * + * @param wantedRevision {@link String} - the wanted revision + * @param revisionsSnecmaObject List<{@link ItemRevision}> - the list of all the revisions of the top object + * @return the selected ItemRevision + */ + protected ItemRevision retrieveTopItemRevision(final String wantedRevision, final List revisionsSnecmaObject) { + ItemRevision topItemRevision = null; + for (ItemRevision itemRev : revisionsSnecmaObject) { + if (itemRev == null || !SnecmaObjectTypes.isPartRevision(itemRev.getTypeObject().getName())) { + continue; + } + String revision = itemRev.get_item_revision_id(); + if (revision != null && revision.equals(wantedRevision)) { + topItemRevision = itemRev; + break; + } + } + return topItemRevision; + } + + /** + * Prepare all common data between report 15 , report 16 and report 17. + * + * @param session {@link TcSession} - the tc session + * @param topItemRevision {@link ItemRevision} - the top object + * @param revisionsSnecmaObject List<{@link ItemRevision}> - the list of all the revisions of the top object + * @param report - the execution report which provide all informations for the report + * @throws KurtException if anything else goes wrong + * @throws InvalidUserInputException the user-provided top item doesn't seem to exist + */ + protected void doPrepareCommonDataForAllReports(final TcSession session, final ItemRevision topItemRevision, + final List revisionsSnecmaObject, final T report) + throws KurtException { + // Verify the object type: any Part but not an Alternate + checkAndBuildSnecmaObject(session, topItemRevision, report); + + report.setTypeProduit(ObjectInfoLoader.getProductType(session, topItemRevision)); + report.setClausePropriete(ObjectInfoLoader.getClausePropriete(report.getTypeProduit(), session)); + retrieveDateReleased(session, topItemRevision, report); + + retrieveDateLancementAndMT(revisionsSnecmaObject, report.itemRevision, session, report); + retrieveRevisionArticle(session, report); + + retrieveDocGeometryAndDocDrawingLists(session, topItemRevision, report); + retrieveDocNormAndDocNormStandardLists(session, topItemRevision, report); + retrieveDocTechnicList(session, topItemRevision, report); + } + + /** + * Check and build the SnecmaObject. + */ + protected void checkAndBuildSnecmaObject(final TcSession session, final ItemRevision topItemRevision, final T report) + throws InvalidUserInputException, NotSupportedException { + String itemType = topItemRevision.getTypeObject().getName(); + if (!SnecmaObjectTypes.isA(itemType, SnecmaObjectTypes.PART_AERO_REVISION, SnecmaObjectTypes.PART_NO_AERO_REVISION, + SnecmaObjectTypes.PART_ASSEMB_REVISION, SnecmaObjectTypes.PART_MAT_REVISION, SnecmaObjectTypes.DET_REVISION, + SnecmaObjectTypes.STANDARD_REVISION)) { + throw new InvalidUserInputException(UserInputErrorEnum.THE_SELECTED_OBJECT_IS_NOT_PERMITTED_ON_THIS_REPORT); + } + report.snecmaObject = SnecmaObjectFactory.build(session, topItemRevision); + } + + /** + * Retrieve the parameter RevisionArticle. + */ + protected void retrieveRevisionArticle(final TcSession session, final T report) { + // Find an associate Change with the Part + // Maybe the change is a ChangeRequest Revision or a ChangeNotice Revision + List selectedChanges = new ArrayList<>(); + if (report.mostRecentDateReleased != null) { + selectedChanges = returnChangeItemWithSameDateReleased(report.mostRecentDateReleased, report.getItemId(), report.itemRevision, session, + report.statusName); + } + + // Put revision article's parameter for the report + if (selectedChanges.isEmpty() || selectedChanges.size() > 1) { + report.setRevisionArticle(report.snecmaObject.getRevisionId()); + } else { + ItemRevision selectedChange = selectedChanges.get(0); + String typeModif = selectedChange.getPropertyObject(PV4_TYPE_MODIFICATION).getStringValue(); + report.setRevisionArticle(selectedChange.get_item_id() + WHITESPACE + (report.isFrench() ? LanguageHelper.french(typeModif) : LanguageHelper.english(typeModif))); + } + } + + /** + * Return the ChangeItem (ChangeRequest or TcChangeNoticeRevision) with the same date released as the provided Calendar. + * + * @param referenceDate {@link Calendar} - the reference date of the reference object + * @param itemId {@link String} - the id of the reference object + * @param itemRevisionId {@link String} - the revision id of the reference object + * @param session {@link TcSession} - the TC session for query + * @param statusName {@link String} - the reference name of TcReleaseStatus of the reference object + * @return the selected ChangeItem Revision + */ + protected List returnChangeItemWithSameDateReleased(final Calendar referenceDate, final String itemId, final String itemRevisionId, + final TcSession session, final String statusName) { + // Query of all associated Change with the Part + List listChangeRev = new ChangeFromPartQuery(session).searchIDAndRevision(itemId, itemRevisionId).findAll(); + + // Select ONE change associated to the precedent selected ReleaseStatus of the date released of the Part + List selectedChanges = new ArrayList<>(); + for (ItemRevision changeRev : listChangeRev) { + if (changeRev == null) { + continue; + } + + // Filter the Revision EngChange + String typeChange = changeRev.getTypeObject().getName(); + if (REVISION_ENG_CHANGE.equals(typeChange)) { + continue; + } + + // Compare the status name and the date released to the references + boolean isValidated = validChange(session, changeRev, referenceDate, statusName); + if (isValidated) { + selectedChanges.add(changeRev); + } + } + return selectedChanges; + } + + private boolean validChange(final TcSession session, final ItemRevision changeRev, final Calendar referenceDate, final String statusName) { + boolean isValidated = false; + ReleaseStatus[] releaseStatusList = getReleaseStatusList(session, changeRev); + for (ReleaseStatus status : releaseStatusList) { + if (status == null) { + continue; + } + + Calendar changeCalendar = status.get_date_released(); + if (changeCalendar == null) { + continue; + } + + // Filter with the name of the reference ReleaseStatus + if (!statusName.equals(status.get_name())) { + break; + } + + // Only ONE change can have the same ReleaseStatus with the same date released + // Warning : Calendar.MONTH return 0 for January and 11 for December + if (changeCalendar.get(Calendar.DAY_OF_MONTH) == referenceDate.get(Calendar.DAY_OF_MONTH) + && changeCalendar.get(Calendar.MONTH) == referenceDate.get(Calendar.MONTH) + && changeCalendar.get(Calendar.YEAR) == referenceDate.get(Calendar.YEAR)) { + isValidated = true; + } + } + return isValidated; + } + + private void retrieveDocGeometryAndDocDrawingLists(final TcSession session, final ItemRevision partItemRevision, final T report) { + List representedDocObjects = AbstractPart.returnRepresentedDocuments(session, partItemRevision); + for (ItemRevision representedDoc : representedDocObjects) { + if (representedDoc == null) { + continue; + } + String type = representedDoc.getTypeObject().getName(); + if (SnecmaObjectTypes.DOC_GEOMETRY_REVISION.equals(type)) { + DocGeometry docGeo = new DocGeometry(session, representedDoc); + report.docGeometryList.add(docGeo); + } else if (SnecmaObjectTypes.DOC_DRAWING_REVISION.equals(type)) { + DocDrawing docDrawing = new DocDrawing(session, representedDoc); + report.docDrawingList.add(docDrawing); + } + } + } + + /** + * Retrieve the date released of the report through the main itemRevision's properties. + * + * @param partItemRevision {@link ItemRevision} - the part object + * @param report - the execution report which provide all informations for the report + */ + public void retrieveDateReleased(final TcSession session, final ItemRevision partItemRevision, final T report) { + // Find the selected ReleaseStatus + ReleaseStatus selectStatus = selectStatus(session, partItemRevision); + if (selectStatus == null) { + report.setDateReleased(DEFINITION_EN_COURS); + log.warn("No ReleaseStatus were found on the {} {}.", partItemRevision.getTypeObject().getName(), partItemRevision.getUid()); + return; + } + + // Retrieve the date released + Calendar selectedDate = selectStatus.get_date_released(); + if (selectedDate == null) { + report.setDateReleased(DEFINITION_EN_COURS); + log.warn("Unable to retrieve the date released of the selected ReleaseStatus {} {}.", selectStatus.getTypeObject().getName(), + selectStatus.getUid()); + return; + } + + // Retrieve informations about TcReleaseStatus in order to compare with revision article + report.mostRecentDateReleased = selectedDate; + report.statusName = selectStatus.get_name(); + + // Put date released's appropriate value for report + if (APPROVED_STATUS.isIncluded(report.statusName)) { + report.setDateReleased(getDateFormatDayMonthYear(selectedDate)); + } else { + if (CANCELLED_STATUS.isIncluded(report.statusName)) { + report.setDateReleased(DEFINITION_ANNULEE); + } else { + report.setDateReleased(DEFINITION_EN_COURS); + } + } + } + + private ReleaseStatus selectStatus(final TcSession session, final ItemRevision partItemRevision) { + return ObjectInfoHelper.getStatusWithMostRecentReleaseDate(session, partItemRevision, StatusEnum.J3A, StatusEnum.J3B, StatusEnum.EFFECTIVITY); + } + + /** + * Retrieve the Date Lancement and the MT property. + * + * @param revisionsSnecmaObject List<{@link ItemRevision}> - the list of revisions of the top Part + * @param revisionTopPart {@link String} - the revision of the top Part + * @param session {@link TcSession} - the tc session + * @param report - the execution report which provide all informations for the report + */ + public void retrieveDateLancementAndMT(final List revisionsSnecmaObject, + final String revisionTopPart, final TcSession session, final T report) { + // Date released of the part (may be the date system) + Calendar dateRefFormatcalendar = selectCalendar(report); + + // Find the previous ItemRevision (may not be the direct predecessor) and the previous Date + ItemRevision previousRev = null; + Calendar selectedDate = null; + for (ItemRevision itemRev : revisionsSnecmaObject) { + if (itemRev == null) { + continue; + } + String revision = itemRev.get_item_revision_id(); + if (revision == null) { + continue; + } + if (revision.compareTo(revisionTopPart) < 0) { + List listRsPrecedentRev = TcReleaseStatus.getChosenStatus(session, itemRev, StatusEnum.J3B); + if (listRsPrecedentRev.isEmpty()) { + continue; + } + for (ReleaseStatus status : listRsPrecedentRev) { + if (status == null) { + continue; + } + Calendar date = status.get_date_released(); + if (date != null && date.compareTo(dateRefFormatcalendar) < 0) { + if (selectedDate == null) { + previousRev = itemRev; + selectedDate = date; + } else if (selectedDate.compareTo(date) < 0) { + previousRev = itemRev; + selectedDate = date; + } + } + } + } + } + + // Put MT and previousDateReleased data + putPrecedentRevisionParameters(session, previousRev, selectedDate, report); + } + + private void putPrecedentRevisionParameters(final TcSession session, final ItemRevision previousRev, final Calendar selectedDate, + final T report) { + if (previousRev == null) { + report.varMt = ""; + report.previousReleaseDate = ""; + } else { + // Previous date released parameter for report + report.previousReleaseDate = getDateFormatDayMonthYear(selectedDate); + + // MT parameter for report + String previousId = previousRev.get_item_id(); + String previousRevisionId = previousRev.get_item_revision_id(); + List selectedPrecedentChange = + returnChangeItemWithSameDateReleased(selectedDate, previousId, previousRevisionId, session, StatusEnum.J3B.getIdentifier()); + if (selectedPrecedentChange.isEmpty() || selectedPrecedentChange.size() > 1) { + report.varMt = ""; + } else { + report.varMt = selectedPrecedentChange.get(0).get_item_id(); + } + } + } + + private Calendar selectCalendar(final T report) { + Calendar refCalendarForPrecedentRev; + if (DEFINITION_EN_COURS.equals(report.getDateReleased()) || DEFINITION_ANNULEE.equals(report.getDateReleased()) + || (report.mostRecentDateReleased == null)) { + refCalendarForPrecedentRev = Calendar.getInstance(); + } else { + refCalendarForPrecedentRev = report.mostRecentDateReleased; + } + return refCalendarForPrecedentRev; + } + + private ReleaseStatus[] getReleaseStatusList(final TcSession session, final ItemRevision itemRev) { + session.loadProperties(itemRev, "release_status_list"); + ReleaseStatus[] releaseStatuses = itemRev.get_release_status_list(); + session.loadProperties(releaseStatuses); + return releaseStatuses; + } + + @Override + public boolean isEmptyTable(final T report) { + return super.isEmptyTable(report) && report.getDocDrawingList().isEmpty() && report.getDocGeometryList().isEmpty(); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/r15r17reports/AbstractExecutionR15R17.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/r15r17reports/AbstractExecutionR15R17.java new file mode 100644 index 0000000..fb04a29 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/r15r17reports/AbstractExecutionR15R17.java @@ -0,0 +1,76 @@ +package com.capgemini.reports.definition.r15r16r17reports.r15r17reports; + +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.capgemini.reports.ReportLaunchTypeEnum; +import com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum; +import com.capgemini.reports.database.manager.MngCriteriaVal.CriteriaValue; +import com.capgemini.reports.definition.r15r16r17reports.AbstractExecutionR15R16R17; +import com.capgemini.reports.documentationobjects.DocDrawing; +import com.capgemini.reports.documentationobjects.DocGeometry; +import com.capgemini.reports.reports.parameters.IChecker; +import com.capgemini.reports.reports.parameters.checker.ObjectTypeChecker; +import com.capgemini.reports.snecmaobjects.ISnecmaObject; +import lombok.EqualsAndHashCode; +import lombok.Getter; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; + +/** + * Prepare the common data for report 15 and 17. + * + * @param Generic object for a report + */ +@Getter +@EqualsAndHashCode(callSuper = true) +public abstract class AbstractExecutionR15R17> extends AbstractExecutionR15R16R17 { + private static final long serialVersionUID = 1041606367467834895L; + + // Documents gathered + protected final List docGeometryList = new ArrayList<>(); + protected final List docDrawingList = new ArrayList<>(); + + // Data gathered + protected final String itemRevision; + protected ISnecmaObject snecmaObject; + protected String varMt = ""; + protected String previousReleaseDate = ""; + + // Configuration data + protected Calendar mostRecentDateReleased; + protected String statusName; + + /** + * Constructs some parameters requested for R15 and R17 reports execution. + * + * @param partId the ID of the part + * @param partRevision the revision f the Part + * @param language the selected language (French or English) + * @param priorityCode int - the priority code found in the reporting.properties file associated to a report + * @param revisionRule {@link String} - the revision rule for resolution structure + * @param launchType {@link ReportLaunchTypeEnum} - the launch type of the report + */ + public AbstractExecutionR15R17(final String partId, final String partRevision, final String language, final int priorityCode, + final String revisionRule, final ReportLaunchTypeEnum launchType) { + super(partId, language, priorityCode, revisionRule, launchType); + this.itemRevision = partRevision; + } + + @Override + public List getLaunchData() { + List theCriteria = new ArrayList<>(); + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.PART_ID, super.itemId)); + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.PART_REVISION, itemRevision)); + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.LANGUAGE, super.frenchInput)); + return theCriteria; + } + + @Override + public List getQuickChecks() { + ArrayList quickChecks = new ArrayList<>(); + quickChecks.add(new ObjectTypeChecker(itemId, SnecmaObjectTypes.DET, SnecmaObjectTypes.PART_AERO, SnecmaObjectTypes.PART_ASSEMB, + SnecmaObjectTypes.PART_MAT, SnecmaObjectTypes.PART_NO_AERO, SnecmaObjectTypes.STANDARD)); + return quickChecks; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/r15r17reports/AbstractR15R17Printer.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/r15r17reports/AbstractR15R17Printer.java new file mode 100644 index 0000000..576673f --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/r15r17reports/AbstractR15R17Printer.java @@ -0,0 +1,94 @@ +package com.capgemini.reports.definition.r15r16r17reports.r15r17reports; + +import com.capgemini.reports.definition.r15r16r17reports.AbstractR15R16R17Printer; +import com.capgemini.reports.definition.r15r16r17reports.CommunR15R16R17ComponentVisitor; +import com.capgemini.reports.definition.r15r16r17reports.R15R16R17R24R25Keys; +import com.capgemini.reports.definition.r15r16r17reports.R15R16R17R24R25Keys.Page2; +import com.capgemini.reports.definition.r15r16r17reports.r15r17reports.r17report.ExecutionR17; +import com.capgemini.reports.documentationobjects.DocDrawing; +import com.capgemini.reports.documentationobjects.DocGeometry; +import com.capgemini.reports.execution.AbstractExecutionReport; +import com.capgemini.reports.printing.PrintParameters; +import com.capgemini.reports.snecmaobjects.visitor.IComponentVisitor; +import lombok.EqualsAndHashCode; + +import java.util.ArrayList; +import java.util.EnumMap; +import java.util.List; +import java.util.Map; + +/** + * This class allows printing of several elements that are found in both the R17 and R15 reports. + * + * @param describes which report's {@link AbstractExecutionReport} this printer will print. Must be a subclass of {@link AbstractExecutionR15R17}. + */ +@EqualsAndHashCode(callSuper = true) +public abstract class AbstractR15R17Printer> extends AbstractR15R16R17Printer { + + private static final long serialVersionUID = 6353372020574746542L; + + @Override + protected List> addExtraDocLines(final T execution) { + List> dataTable = new ArrayList<>(); + boolean isFrench = execution.isFrench(); + for (DocGeometry geometry : execution.getDocGeometryList()) { + dataTable.add(getDocGeometryLine(geometry, isFrench)); + } + String itemId = execution.getItemId(); + for (DocDrawing drawing : execution.getDocDrawingList()) { + dataTable.add(getDocDrawingLine(drawing, isFrench, execution.getTypeProduit(), itemId)); + } + return dataTable; + } + + private Map getDocDrawingLine(final DocDrawing drawing, final boolean isFrench, final String typeProduit, final String itemID) { + String identifier; + if (isNotAuthorized(typeProduit)) { + identifier = itemID; + } else { + identifier = drawing.getDocId(); + } + Map line = new EnumMap<>(Page2.class); + line.put(Page2.DOC_NUMBER, identifier); + line.put(Page2.ISSUE, drawing.getIndicePlan()); + line.put(Page2.DOC_TYPE, isFrench ? "Représentation 2D" : "Drawing"); + line.put(Page2.DOC_TITLE, isFrench ? drawing.getName() : drawing.getDesignationEn()); + return line; + } + + private Map getDocGeometryLine(final DocGeometry geometry, final boolean isFrench) { + Map line = new EnumMap<>(Page2.class); + line.put(Page2.DOC_NUMBER, geometry.getDocId()); + line.put(Page2.ISSUE, geometry.getIndiceCartouche()); + line.put(Page2.DOC_TYPE, isFrench ? "Modèle 3D" : "3D Model"); + line.put(Page2.DOC_TITLE, geometry.getDesignationEN()); + return line; + } + + @Override + protected void addOptionalParameters(final T execution, final PrintParameters mainReport) { + // Add common parameters between R15 and R17 + Map params = new EnumMap<>(R15R16R17R24R25Keys.class); + params.put(R15R16R17R24R25Keys.MT_NUMBER, execution.getVarMt()); + params.put(R15R16R17R24R25Keys.PREVIOUS_RELEASE_DATE, execution.getPreviousReleaseDate()); + params.putAll(execution.getSnecmaObject().accept(getVisitor(execution.isFrench()))); + mainReport.addReportParameters(params); + + // Add specific parameters to each sub-report + addSpecificParameters(execution, mainReport); + } + + /** + * Adds parameters that are specific to each subclass and not common to R15-R17. In particular, R15Printer will want to add a few values. + * + * @param execution the data-bearing {@link ExecutionR17} + * @param mainReport the {@link PrintParameters} + */ + protected abstract void addSpecificParameters(final T execution, final PrintParameters mainReport); + + @Override + protected IComponentVisitor> getVisitor(final boolean isFrench) { + return new CommunR15R16R17ComponentVisitor(isFrench); + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/r15r17reports/r15report/AttachDatasetR15Action.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/r15r17reports/r15report/AttachDatasetR15Action.java new file mode 100644 index 0000000..a343f09 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/r15r17reports/r15report/AttachDatasetR15Action.java @@ -0,0 +1,109 @@ +package com.capgemini.reports.definition.r15r16r17reports.r15r17reports.r15report; + +import com.capgemini.framework.common.FileHelper; +import com.capgemini.framework.common.SettingsHelper; +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.object.pom.status.StatusEnum; +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.framework.teamcenter.queries.saved.modelobject.ItemQuery; +import com.capgemini.reports.database.javabean.DbReport; +import com.capgemini.reports.exceptions.NotFoundException; +import com.capgemini.reports.execution.actions.AbstractPostExecutionStep; +import com.capgemini.reports.execution.actions.ondataset.CreateDatasetAction; +import com.capgemini.reports.execution.actions.ondataset.DestroyRelationshipsAction; +import com.capgemini.reports.execution.actions.ondataset.LinkFicheArticleAction; +import com.capgemini.reports.execution.actions.ondataset.SetStatusAction; +import com.teamcenter.services.loose.core._2006_03.FileManagement.GetDatasetWriteTicketsInputData; +import com.teamcenter.soa.client.model.strong.Item; +import lombok.EqualsAndHashCode; +import lombok.extern.slf4j.Slf4j; + +import java.io.File; +import java.util.List; + +/** + * This action can be triggered upon report completion. Once triggered, it will: + *
      + *
    1. Rename the document
    2. + *
    3. Upload the created report to a dataset
    4. + *
    5. Attach the dataset to the Part
    6. + *
    7. Set a Frozen status on the dataset
    8. + *
    + */ +@Slf4j +@EqualsAndHashCode(callSuper = true) +public class AttachDatasetR15Action extends AbstractPostExecutionStep { + private static final long serialVersionUID = 5891187265385234600L; + + private static final String OUTPUT_FOLDER = SettingsHelper.getReportLocation(); + private static final PolicyLocation POLICY_XML_DATASET = PolicyLocation.make("R15_policy_wkf", "/xml/policies/r15report/R15_policy_wkf.xml"); + + /** + * Creates an instance. + */ + public AttachDatasetR15Action() { + super(ExecutionR15.class); + } + + private static Item getItem(final TcSession session, String targetID) throws NotFoundException { + List results = new ItemQuery(session).searchID(targetID).findAll(); + + for(Item currentResult : results){ + if(SnecmaObjectTypes.isPart(currentResult.getTypeObject().getName())){ + return currentResult; + } + } + + if (results.isEmpty()) { + throw new NotFoundException("Could not find the original part " + targetID); + } else { + throw new NotFoundException(targetID + " part not found other type found instead"); + } + + } + + @Override + public Void performPostActionOnReport(final TcSession session, final ExecutionR15 report, final DbReport theExecutingReport, + final String fileNameWithExtension) throws KurtException { + session.setObjectPropPolicy(POLICY_XML_DATASET); + + // Prepare naming & Make a copy with the correct name + log.debug("Workflow launch: Beginning file copy"); + File fileCopy = copyFile(report.getDatasetFileNameWithExtension(), report.getOriginalDatasetFileNameWithExtension()); + + // Obtain the Part + String targetID = report.getItemId(); + Item target = getItem(session, targetID); + + // Detect & destroy conflicting datasets on the part, if any + String datasetName = report.getDatasetName(); + log.debug("Workflow launch: Destroying previous datasets..."); + DestroyRelationshipsAction.destroyConflictingDatasets(session, datasetName, targetID); + + // Create a new dataset + log.debug("Workflow launch: Creating dataset {}", datasetName); + GetDatasetWriteTicketsInputData dataset = CreateDatasetAction.createDataset(session, datasetName, fileCopy, report); + + // Link the part to the dataset (if it fails, it will cleanup the dataset as well) + log.debug("Workflow launch: Linking Part {} to newly created dataset {}", target.getUid(), dataset.dataset.getUid()); + LinkFicheArticleAction.linkDatasetToPart(session, target, dataset.dataset); + + // Set status on the dataset + log.debug("Workflow launch: Adding 'Frozen' status to the dataset {}", dataset.dataset.getUid()); + SetStatusAction.setStatus(session, dataset.dataset, StatusEnum.FROZEN.getIdentifier()); + + log.debug("Workflow launch has completed successfully for R15 on ", targetID); + + return null; + } + + private File copyFile(final String datasetFileNameWithExtension, String originalFileName) throws NotFoundException { + File copy = new File(OUTPUT_FOLDER + datasetFileNameWithExtension); + File original = new File(OUTPUT_FOLDER + originalFileName); + FileHelper.copy(original, copy); + return copy; + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/r15r17reports/r15report/DataReportPreparatorR15.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/r15r17reports/r15report/DataReportPreparatorR15.java new file mode 100644 index 0000000..56b3894 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/r15r17reports/r15report/DataReportPreparatorR15.java @@ -0,0 +1,178 @@ +package com.capgemini.reports.definition.r15r16r17reports.r15r17reports.r15report; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.object.SnecmaObjectProperties; +import com.capgemini.framework.teamcenter.queries.saved.modelobject.ItemRevisionQuery; +import com.capgemini.reports.definition.r15r16r17reports.r15r17reports.AbstractDataReportPreparatorR15R17; +import com.capgemini.reports.exceptions.InvalidUserInputException; +import com.capgemini.reports.execution.strategies.IExecutionStrategy; +import com.capgemini.reports.printing.PrintParameters; +import com.capgemini.reports.releasestatus.RevisionStatusAndDate; +import com.capgemini.reports.snecmaobjects.admin.RFAdminRevision; +import com.capgemini.reports.teamcenter.ObjectInfoHelper; +import com.google.common.base.Optional; +import com.teamcenter.soa.client.model.ModelObject; +import com.teamcenter.soa.client.model.strong.Form; +import com.teamcenter.soa.client.model.strong.Item; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import org.slf4j.Logger; + +import java.util.*; + +import static com.capgemini.framework.teamcenter.TeamcenterObjectProperties.ASSEMBLY_BOM; +import static com.capgemini.framework.teamcenter.TeamcenterObjectProperties.RF_PART_BOM; +import static com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes.*; + + +/** + * This class will allow to prepare data and findAll back data for making report R15. + */ +public class DataReportPreparatorR15 extends AbstractDataReportPreparatorR15R17 { + private static final long serialVersionUID = -1615860676063048572L; + + private static final String NON_NO = "Non / No"; + private static final String OUI_YES = "Oui / Yes"; + private static final String DASH_STRING = "-"; + private static final Logger log = org.slf4j.LoggerFactory.getLogger(DataReportPreparatorR15.class); + + @Override + public String print(TcSession session, ExecutionR15 execution, IExecutionStrategy executionStrategy) throws KurtException { + PrintParameters printParameters = prepareData(session, execution); + executionStrategy.print(printParameters, execution); + return executionStrategy.getReportFileName(execution) + printParameters.getOuputFileExtension(); + } + + private PrintParameters prepareData(final TcSession session, final ExecutionR15 report) throws KurtException { + log.trace("PrepareData started on: " + report.getReportIdentifier().getReportTitle()); + long start = System.currentTimeMillis(); + + // Setup the policy + session.setObjectPropPolicy(report.getFullPolicy()); + + List revisionsSnecmaObject = new ItemRevisionQuery(session).searchID(report.getItemId()).findAll(); + if (revisionsSnecmaObject.isEmpty()) { + throw new InvalidUserInputException("Unabled to retrieve the list of revisons of the Part " + report.getItemId()); + } + + // Retrieve topItemRev + ItemRevision topItemRevision = retrieveTopItemRevision(report.getItemRevision(), revisionsSnecmaObject); + + // Retrieve all common data + doPrepareCommonDataForAllReports(session, topItemRevision, revisionsSnecmaObject, report); + + // Specificities of the report + filterDocTechnic(report); + if (PART_ASSEMB_REVISION.equals(report.getSnecmaObject().getType())) { + retrieveFrontiereAvionAndFrontiereCooperant(topItemRevision, RF_PART_ASSEMB_REVISION, ASSEMBLY_BOM, + session, report); + } else { + retrieveFrontiereAvionAndFrontiereCooperant(topItemRevision, RF_PART_REVISION, RF_PART_BOM, + session, report); + } + report.setProduitUnit(""); + + R15Printer printer = new R15Printer(); + PrintParameters printParameters = printer.makeMasterTemplate(report, report); + printer.constructDataMaps(session, printParameters, report); + + log.debug(EXECUTION_TIME_XXX_MS_FOR_YYY, System.currentTimeMillis() - start, "data gathering"); + return printParameters; + } + + private void retrieveFrontiereAvionAndFrontiereCooperant(final ItemRevision topItemRevision, final String typeTopItemRev, + final String propertyPseudoFolder, final TcSession session, final ExecutionR15 report) + throws KurtException { + List repereResults = session.whereUsed(topItemRevision, typeTopItemRev); + if (repereResults.isEmpty()) { + + report.setFrontiereAvion(DASH_STRING); + report.setFrontiereCooperant(DASH_STRING); + return; + } + Set selectedRfAdminList = new HashSet<>(); + for (ItemRevision rfPartAssemb : repereResults) { + List resultsPseudoFolder = + ObjectInfoHelper.getModelObjectsInPseudoFolderUnderItemRevision(session, rfPartAssemb, propertyPseudoFolder); + if (resultsPseudoFolder.isEmpty()) { + continue; + } + treatRfAdminInPseudofolder(session, selectedRfAdminList, resultsPseudoFolder); + } + putvaluesFrontiereCooperantAndAvion(session, selectedRfAdminList, report); + } + + private void treatRfAdminInPseudofolder(final TcSession session, final Set selectedRfAdminList, final List resultsPseudoFolder) { + for (ModelObject objectItem : resultsPseudoFolder) { + Item item = (Item) objectItem; + if (!RF_ADMIN.equals(item.getTypeObject().getName())) { + continue; + } + + session.loadProperties(item, "revision_list"); + ModelObject[] listRevision = item.get_revision_list(); + session.loadProperties(listRevision); + + // Convert List to List + List interList = new ArrayList<>(); + for (ModelObject object : listRevision) { + interList.add((ItemRevision) object); + } + + // Find the appropriate Admin for the current RF Part or RF Part Assemb + Optional selectedRfAdmin = retrieveAdminWithMostRecentDateRelease(session, interList); + + if (selectedRfAdmin.isPresent()) { + selectedRfAdminList.add(selectedRfAdmin.get()); + } + } + } + + private Optional retrieveAdminWithMostRecentDateRelease(final TcSession session, final List interList) { + return ObjectInfoHelper.getRevisionFromStatusWithMostRecentReleaseDateNotCancelled(session, interList, Calendar.getInstance()); + } + + private void putvaluesFrontiereCooperantAndAvion(final TcSession session, final Set selectedRfAdminList, + final ExecutionR15 report) { + if (selectedRfAdminList.isEmpty()) { + report.setFrontiereAvion(DASH_STRING); + report.setFrontiereCooperant(DASH_STRING); + + } else { + + report.setFrontiereAvion(getFrontiereAvionOrCooperantProperty(session, selectedRfAdminList, SnecmaObjectProperties.PV_FRONTIERE_AVION)); + report.setFrontiereCooperant(getFrontiereAvionOrCooperantProperty(session, selectedRfAdminList, SnecmaObjectProperties.PV_FRONTIERE_COOPERANT)); + + } + } + + private String getFrontiereAvionOrCooperantProperty(final TcSession session, final Set selectedRfAdminList, final String prop) { + boolean isYes = findValueOfPropertyInList(session, selectedRfAdminList, prop, OUI_YES); + + if (isYes) { + return OUI_YES; + } else { + boolean isNo = findValueOfPropertyInList(session, selectedRfAdminList, prop, NON_NO); + if (isNo) { + return NON_NO; + } else { + return DASH_STRING; + } + } + } + + private boolean findValueOfPropertyInList(final TcSession session, final Set selectedRfAdmins, final String property, final String wantedValue) { + for (ItemRevision rfAdmin : selectedRfAdmins) { + rfAdmin.get_item_id(); + Form form = rfAdmin.get_item_master_tag(); + if (form != null) { + session.loadProperties(form); + String valueProp = form.getPropertyObject(property).getStringValue(); + if (wantedValue.equals(valueProp)) { + return true; + } + } + } + return false; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/r15r17reports/r15report/ExecutionR15.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/r15r17reports/r15report/ExecutionR15.java new file mode 100644 index 0000000..90a42f4 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/r15r17reports/r15report/ExecutionR15.java @@ -0,0 +1,174 @@ +package com.capgemini.reports.definition.r15r16r17reports.r15r17reports.r15report; + +import com.capgemini.framework.common.SettingsHelper; +import com.capgemini.framework.common.StringHelper; +import com.capgemini.framework.common.TeamcenterDateFormatter; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.reports.JasperTemplate; +import com.capgemini.reports.ReportEnum; +import com.capgemini.reports.ReportLaunchTypeEnum; +import com.capgemini.reports.builder.R15Builder; +import com.capgemini.reports.builder.ReportBuilder; +import com.capgemini.reports.definition.r15r16r17reports.AbstractExecutionR15R16R17; +import com.capgemini.reports.definition.r15r16r17reports.r15r17reports.AbstractExecutionR15R17; +import com.capgemini.reports.execution.AbstractExecutionReport; +import com.capgemini.reports.execution.IDataReportPreparator; +import com.capgemini.reports.printing.Printer.PrintFormat; +import com.capgemini.reports.reports.parameters.IChecker; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +/** + * This class controls the execution of a R15 report. + */ +@Getter +@Slf4j +@Setter(value = AccessLevel.PROTECTED) +public class ExecutionR15 extends AbstractExecutionR15R17 { + + private static final int TO_SECONDS = 1000; + + private static final String PDF_EXTENSION = ".pdf"; + + private static final String ENGLISH_DATASET = "_ENG"; + + private static final String FICHE_ARTICLE_REALISATION = "FA_Real"; + + private static final long serialVersionUID = -4306188095393629328L; + + private static final String FILE_SEPARATOR = "_"; + + // Policies + private static final PolicyLocation R15_POLICY_XML_FULL = PolicyLocation.make("R15_policy_full", "/xml/policies/r15report/R15_policy_full.xml"); + private static final PolicyLocation R15_POLICY_XML_LIGHT = + PolicyLocation.make("R15_policy_light", "/xml/policies/r15report/R15_policy_light.xml"); + // Priority parameter + private static final int REPORT_PRIORITY = SettingsHelper.getPriority(ReportEnum.REPORT_R15); + // Revision rule parameter + private static final String REPORT_REVISION_RULE = + SettingsHelper.getPropertyWithDefaultValue("common.bom.revisionRule.REPORT_R15", DEFAULT_REVISION_RULE); + // Launch type parameter + private static final ReportLaunchTypeEnum REPORT_LAUNCH_TYPE = ReportLaunchTypeEnum.getReportLaunchType("common.launch.launchType.REPORT_R15"); + // Data gathered + private String frontiereAvion; + private String frontiereCooperant; + + /** + * Constructor. + * + * @param partId {@link String} - the ID of the Part + * @param partRevision {@link String} - the Revision of the Part + * @param language {@link String} - the language selected by the user + */ + public ExecutionR15(final String partId, final String partRevision, final String language) { + super(partId, partRevision, language, REPORT_PRIORITY, REPORT_REVISION_RULE, REPORT_LAUNCH_TYPE); + } + + /** + * Constructor for R15 in French. + * + * @param partId {@link String} - the ID of the Part + * @param partRevision {@link String} - the Revision of the Part + */ + public ExecutionR15(final String partId, final String partRevision) { + super(partId, partRevision, AbstractExecutionR15R16R17.FRENCH_LANGUAGE, REPORT_PRIORITY, REPORT_REVISION_RULE, REPORT_LAUNCH_TYPE); + } + + @Override + public String getTemplateLocation() { + return JasperTemplate.TEMPLATE_R15R16.getFilepath(); + } + + @Override + public PolicyLocation getPropertyPolicyForLongChecks() { + return R15_POLICY_XML_LIGHT; + } + + @Override + public PolicyLocation getFullPolicy() { + return R15_POLICY_XML_FULL; + } + + @Override + public List getLongChecks() { + return new ArrayList<>(); + } + + @Override + public ReportEnum getReportIdentifier() { + return wkf ? ReportEnum.REPORT_W15 : ReportEnum.REPORT_R15; + } + + @Override + public String getSpecifiedFileName() { + StringBuilder filename = + new StringBuilder(itemId).append(FILE_SEPARATOR).append(itemRevision).append(FILE_SEPARATOR).append(FICHE_ARTICLE_REALISATION); + if (!isFrench()) { + filename.append(ENGLISH_DATASET); + } + return filename.toString(); + } + + @Override + public PrintFormat getPrintingFormat() { + return PrintFormat.PDF; + } + + @Override + public IDataReportPreparator getDataPreparator() { + return new DataReportPreparatorR15(); + } + + @Override + public AbstractExecutionReport cloneTemplateToExecution() { + return new ExecutionR15(itemId, itemRevision, frenchInput); + } + + @Override + public Class getReportBuilderClass() { + return R15Builder.class; + } + + // ******************** Methods for Automatic Workflow execution ********************** + + /** + * The dataset name (if the the report is executed by a workflow). + * + * @return the dataset name + */ + String getDatasetName() { + return StringHelper.implode(FILE_SEPARATOR, getItemId(), getItemRevision(), FICHE_ARTICLE_REALISATION); + } + + /** + * The filename in the dataset (if the the report is executed by a workflow). + * + * @return the file name (with extension) + */ + String getDatasetFileNameWithExtension() { + Date startDate; + try { + startDate = new SimpleDateFormat(TeamcenterDateFormatter.DD_MM_YYYY_HH_MM_SS).parse(getStartTime()); + } catch (ParseException e) { + log.warn("Unable to parse stored start date, generating a date using NOW for W15 " + getReportTechnicalUid(), e); + startDate = new Date(); + } + String dateStr = new SimpleDateFormat(TeamcenterDateFormatter.YYYYMMDD).format(startDate); + long timestamp = startDate.getTime() / TO_SECONDS; + String timestampStr = String.valueOf(timestamp); + String bareFilename = StringHelper.implode(FILE_SEPARATOR, getItemId(), getItemRevision(), FICHE_ARTICLE_REALISATION, dateStr, timestampStr); + return bareFilename + PDF_EXTENSION; + } + + String getOriginalDatasetFileNameWithExtension() { + return getFileNameOnDisc() + PDF_EXTENSION; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/r15r17reports/r15report/R15Printer.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/r15r17reports/r15report/R15Printer.java new file mode 100644 index 0000000..abd8db0 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/r15r17reports/r15report/R15Printer.java @@ -0,0 +1,48 @@ +package com.capgemini.reports.definition.r15r16r17reports.r15r17reports.r15report; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.reports.definition.r15r16r17reports.R15R16R17R24R25Keys.SpecificR15R16; +import com.capgemini.reports.definition.r15r16r17reports.r15r17reports.AbstractR15R17Printer; +import com.capgemini.reports.execution.mapconstructor.IMapConstructor; +import com.capgemini.reports.printing.PrintParameters; +import lombok.extern.slf4j.Slf4j; + +import java.util.EnumMap; +import java.util.Map; + +/** + * This class is able to put the data gathered by an {@link ExecutionR15} into some {@link PrintParameters} for printing. + */ +@Slf4j +public final class R15Printer extends AbstractR15R17Printer implements IMapConstructor { + + private static final long serialVersionUID = 4102259712529027708L; + + @Override + protected void addSpecificParameters(final ExecutionR15 execution, final PrintParameters mainReport) { + Map map = new EnumMap<>(SpecificR15R16.class); + boolean isFrench = execution.isFrench(); + String frontiereAvion = execution.getFrontiereAvion(); + map.put(SpecificR15R16.INSTALLATION_INTERFACE, isFrench ? french(frontiereAvion) : english(frontiereAvion)); + String frontiereCooperant = execution.getFrontiereCooperant(); + map.put(SpecificR15R16.PARTNER_INTERFACE, isFrench ? french(frontiereCooperant) : english(frontiereCooperant)); + map.put(SpecificR15R16.PRODUCT_UNIT, execution.getProduitUnit()); + map.put(SpecificR15R16.SUB_TITLE, + "Documents de définition et procédés et pratiques de réalisation\nDefinition and process documents and manufacturing practices"); + mainReport.addReportParameters(map); + mainReport.addReportParameter(SpecificR15R16.IS_PREVIOUS_DEF.toString(), true); + } + + @Override + protected String getTitle(final ExecutionR15 execution) { + return "Définition de réalisation de l'article\nPart Manufacturing definition"; + } + + @Override + public void constructDataMaps(TcSession session, final PrintParameters printParameters, final ExecutionR15 report) throws KurtException { + long start = System.currentTimeMillis(); + this.print(report, printParameters); + log.trace(EXECUTION_TIME_XXX_MS_FOR_YYY, System.currentTimeMillis() - start, "data filtering"); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/r15r17reports/r17report/DataReportPreparatorR17.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/r15r17reports/r17report/DataReportPreparatorR17.java new file mode 100644 index 0000000..f167d50 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/r15r17reports/r17report/DataReportPreparatorR17.java @@ -0,0 +1,53 @@ +package com.capgemini.reports.definition.r15r16r17reports.r15r17reports.r17report; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.queries.saved.modelobject.ItemRevisionQuery; +import com.capgemini.reports.definition.r15r16r17reports.r15r17reports.AbstractDataReportPreparatorR15R17; +import com.capgemini.reports.exceptions.InvalidUserInputException; +import com.capgemini.reports.execution.strategies.IExecutionStrategy; +import com.capgemini.reports.printing.PrintParameters; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +/** + * Prepares the Data for the R17 report. + */ +public class DataReportPreparatorR17 extends AbstractDataReportPreparatorR15R17 { + private static final long serialVersionUID = -6169580009749438941L; + private static final Logger LOGGER = LoggerFactory.getLogger(DataReportPreparatorR17.class); + + @Override + public String print(TcSession session, ExecutionR17 execution, IExecutionStrategy executionStrategy) throws KurtException { + PrintParameters printParameters = prepareData(session, execution); + executionStrategy.print(printParameters, execution); + return executionStrategy.getReportFileName(execution) + printParameters.getOuputFileExtension(); + } + + private PrintParameters prepareData(final TcSession session, final ExecutionR17 report) throws KurtException { + LOGGER.debug("PrepareData started on: {}", report.getReportIdentifier().getReportTitle()); + + session.setObjectPropPolicy(report.getFullPolicy()); + + List revisionsSnecmaObject = new ItemRevisionQuery(session).searchID(report.getItemId()).findAll(); + if (revisionsSnecmaObject.isEmpty()) { + throw new InvalidUserInputException("Unabled to retrieve the list of revisons of the Part " + report.getItemId()); + } + + // Retrieve topItemRev + ItemRevision topItemRevision = retrieveTopItemRevision(report.getItemRevision(), revisionsSnecmaObject); + + // Retrieve all common data + doPrepareCommonDataForAllReports(session, topItemRevision, revisionsSnecmaObject, report); + + R17Printer printer = new R17Printer(); + PrintParameters printParameters = printer.makeMasterTemplate(report, report); + printer.constructDataMaps(session, printParameters, report); + + LOGGER.debug("PrepareData ended on: {}", report.getReportIdentifier().getReportTitle()); + return printParameters; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/r15r17reports/r17report/ExecutionR17.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/r15r17reports/r17report/ExecutionR17.java new file mode 100644 index 0000000..bd63572 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/r15r17reports/r17report/ExecutionR17.java @@ -0,0 +1,109 @@ +package com.capgemini.reports.definition.r15r16r17reports.r15r17reports.r17report; + +import com.capgemini.framework.common.SettingsHelper; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.reports.JasperTemplate; +import com.capgemini.reports.ReportEnum; +import com.capgemini.reports.ReportLaunchTypeEnum; +import com.capgemini.reports.builder.R17Builder; +import com.capgemini.reports.builder.ReportBuilder; +import com.capgemini.reports.definition.r15r16r17reports.r15r17reports.AbstractExecutionR15R17; +import com.capgemini.reports.execution.AbstractExecutionReport; +import com.capgemini.reports.execution.IDataReportPreparator; +import com.capgemini.reports.printing.Printer.PrintFormat; +import com.capgemini.reports.reports.parameters.IChecker; +import lombok.EqualsAndHashCode; +import lombok.Getter; + +import java.util.ArrayList; +import java.util.List; + +/** + * This class controls the execution of a R17 report. + */ +@Getter +@EqualsAndHashCode(callSuper = true) +public class ExecutionR17 extends AbstractExecutionR15R17 { + private static final long serialVersionUID = -7971226717525563715L; + + private static final String FILE_SEPARATOR = "_"; + + // Policies + private static final PolicyLocation R17_POLICY_XML_FULL = PolicyLocation.make("R17_policy_full", "/xml/policies/r17report/R17_policy_full.xml"); + private static final PolicyLocation R17_POLICY_XML_LIGHT = PolicyLocation.make("R17_policy_light", "/xml/policies/r17report/R17_policy_light.xml"); + + // Priority parameter + private static final int REPORT_PRIORITY = SettingsHelper.getPriority(ReportEnum.REPORT_R17); + + // Revision rule parameter + private static final String REPORT_REVISION_RULE = SettingsHelper.getPropertyWithDefaultValue("common.bom.revisionRule.REPORT_R17", DEFAULT_REVISION_RULE); + + // Launch type parameter + private static final ReportLaunchTypeEnum REPORT_LAUNCH_TYPE = ReportLaunchTypeEnum.getReportLaunchType("common.launch.launchType.REPORT_R17"); + + /** + * Constructor. + * + * @param partId {@link String} - the ID of the Part + * @param partRevision {@link String} - the Revision of the Part + * @param langue {@link String} - the language selected by the user + */ + public ExecutionR17(final String partId, final String partRevision, final String langue) { + super(partId, partRevision, langue, REPORT_PRIORITY, REPORT_REVISION_RULE, REPORT_LAUNCH_TYPE); + } + + @Override + public String getTemplateLocation() { + return JasperTemplate.TEMPLATE_R17.getFilepath(); + } + + @Override + public PolicyLocation getPropertyPolicyForLongChecks() { + return R17_POLICY_XML_LIGHT; + } + + @Override + public PolicyLocation getFullPolicy() { + return R17_POLICY_XML_FULL; + } + + @Override + public List getLongChecks() { + return new ArrayList<>(); + } + + @Override + public ReportEnum getReportIdentifier() { + return ReportEnum.REPORT_R17; + } + + @Override + public String getSpecifiedFileName() { + StringBuilder filename = + new StringBuilder(itemId).append(FILE_SEPARATOR).append(itemRevision).append(FILE_SEPARATOR).append("ListeDocRefart"); + if (!isFrench()) { + filename.append("_ENG"); + } + return filename.toString(); + } + + @Override + public PrintFormat getPrintingFormat() { + return PrintFormat.PDF; + } + + @Override + public IDataReportPreparator getDataPreparator() { + return new DataReportPreparatorR17(); + } + + @Override + public AbstractExecutionReport cloneTemplateToExecution() { + return new ExecutionR17(itemId, itemRevision, frenchInput); + } + + @Override + public Class getReportBuilderClass() { + return R17Builder.class; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/r15r17reports/r17report/R17Printer.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/r15r17reports/r17report/R17Printer.java new file mode 100644 index 0000000..66e7abe --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/r15r17reports/r17report/R17Printer.java @@ -0,0 +1,36 @@ +package com.capgemini.reports.definition.r15r16r17reports.r15r17reports.r17report; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.reports.definition.r15r16r17reports.r15r17reports.AbstractR15R17Printer; +import com.capgemini.reports.execution.mapconstructor.IMapConstructor; +import com.capgemini.reports.printing.PrintParameters; +import lombok.EqualsAndHashCode; +import lombok.extern.slf4j.Slf4j; + +/** + * This class is able to put the data gathered by an {@link ExecutionR17} into some {@link PrintParameters} for printing. + */ +@Slf4j +@EqualsAndHashCode(callSuper = true) +public final class R17Printer extends AbstractR15R17Printer implements IMapConstructor { + + private static final long serialVersionUID = -5917435254556072157L; + + @Override + protected void addSpecificParameters(final ExecutionR17 execution, final PrintParameters mainReport) { + // Nothing to add, all the job is performed by the AbstractR15R17Printer + } + + @Override + protected String getTitle(final ExecutionR17 execution) { + return "Définition technique de l'article et Définition de réalisation de l'article\nPart Definition and Part Manufacturing Definition"; + } + + @Override + public void constructDataMaps(TcSession session, final PrintParameters printParameters, final ExecutionR17 report) throws KurtException { + long start = System.currentTimeMillis(); + this.print(report, printParameters); + log.trace(EXECUTION_TIME_XXX_MS_FOR_YYY, System.currentTimeMillis() - start, "data filtering"); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/r16report/DataReportPreparatorR16.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/r16report/DataReportPreparatorR16.java new file mode 100644 index 0000000..e5db21e --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/r16report/DataReportPreparatorR16.java @@ -0,0 +1,179 @@ +package com.capgemini.reports.definition.r15r16r17reports.r16report; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcBomObject; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcBomObjectFactory; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcRevisionRule; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcRevisionRuleProperties; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.product.TcProduct; +import com.capgemini.framework.teamcenter.object.runtime.TcBomWindow; +import com.capgemini.framework.teamcenter.object.runtime.TcBomWindowConfiguration; +import com.capgemini.framework.teamcenter.object.runtime.TcRevisionRulesConfiguration; +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.capgemini.framework.teamcenter.queries.saved.modelobject.ItemRevisionQuery; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.definition.r15r16r17reports.AbstractDataReportPreparatorR15R16R17; +import com.capgemini.reports.documentationobjects.DocTechnic; +import com.capgemini.reports.exceptions.InvalidUserInputException; +import com.capgemini.reports.execution.strategies.IExecutionStrategy; +import com.capgemini.reports.printing.PrintParameters; +import com.capgemini.reports.snecmaobjects.admin.RFAdminRevision; +import com.capgemini.reports.snecmaobjects.generic.GenericAssembRevision; +import com.capgemini.reports.snecmaobjects.generic.GenericRevision; +import com.capgemini.reports.snecmaobjects.part.PartAeroRevision; +import com.capgemini.reports.snecmaobjects.rf.RFGenericRevision; +import com.capgemini.reports.teamcenter.ObjectInfoHelper; +import com.capgemini.reports.teamcenter.ObjectInfoLoader; +import com.capgemini.reports.teamcenter.resolution.structureservice.SingleStructureServiceCaller; +import com.teamcenter.soa.client.model.ModelObject; +import com.teamcenter.soa.client.model.strong.Form; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.List; + + +/** + * This class will allow to prepare data and findAll back data for making report R16. + */ +public class DataReportPreparatorR16 extends AbstractDataReportPreparatorR15R16R17 { + private static final long serialVersionUID = 3714231249482402544L; + private static final Logger LOGGER = LoggerFactory.getLogger(DataReportPreparatorR16.class); + private static final String EMPTY_STR = ""; + + @Override + public String print(TcSession session, ExecutionR16 execution, IExecutionStrategy executionStrategy) throws KurtException { + PrintParameters printParameters = prepareData(session, execution); + executionStrategy.print(printParameters, execution); + return executionStrategy.getReportFileName(execution) + printParameters.getOuputFileExtension(); + } + + private PrintParameters prepareData(final TcSession session, final ExecutionR16 report) throws KurtException { + LOGGER.debug("PrepareData started on: {}", report.getReportIdentifier().getReportTitle()); + // Retrieve the ProductRevision and the UnitRevision + // Note: a check performed earlier made sure that this list is NOT empty + session.setObjectPropPolicy(report.getFullPolicy()); + ItemRevision productRev = + new ItemRevisionQuery(session).searchID(report.getTheProduitUnitObject().getProductID()).findAll().get(0); + report.setTypeProduit(ObjectInfoLoader.getProductType(session, productRev)); + report.setClausePropriete(ObjectInfoLoader.getClausePropriete(report.getTypeProduit(), session)); + report.setProduitUnit(report.getTheProduitUnitObject().getProductID() + "-" + report.getTheProduitUnitObject().getUnitStr()); + + // All the checks are realised (Product-Unit-Generic) + // The appropriate revision is selected via the method getGenericItemRevision + ItemRevision generic = getGenericItemRevision(session, report); + String typeGeneric = generic.getTypeObject().getName(); + if (SnecmaObjectTypes.GENERIC_REVISION.equals(typeGeneric)) { + report.setGenericRev(new GenericRevision(session, generic)); + } else if (SnecmaObjectTypes.GENERIC_ASSEMB_REVISION.equals(typeGeneric)) { + report.setGenericRev(new GenericAssembRevision(session, generic)); + } else { + throw new KurtException("Object should be a Generic but is a: " + typeGeneric); + } + + TcBomObject topLineObject = new TcBomObjectFactory(session, generic).create(); + TcProduct productObject = new TcProduct(session, report.getTheProduitUnitObject().getProduct(session)); + int unit = report.getTheProduitUnitObject().getUnit(); + + TcRevisionRuleProperties revisionRuleProperties = new TcRevisionRuleProperties(productObject, unit); + + TcRevisionRule revisionRule = session.findRevRule(report.getRevisionRule()); + TcRevisionRulesConfiguration revRulesConfiguration = new TcRevisionRulesConfiguration(revisionRule, revisionRuleProperties); + + // Build the Generic and return the GenericBom + try (TcBomWindow bomWindow = session.createBomWindow(new TcBomWindowConfiguration(topLineObject, revRulesConfiguration))) { + session.setObjectPropPolicy(report.getFullPolicy()); + + BOMLineHolder rfGenericBom = new SingleStructureServiceCaller(session).resolve(bomWindow.topLine(), new R16BOMLineExplorer()); + List itemRevMaster = rfGenericBom.getAllItemRevMasters(); + session.loadProperties(itemRevMaster.toArray(new ModelObject[itemRevMaster.size()])); + + report.setArticleId(report.getGenericRev().getItemId()); + report.setArticleRevision(report.getGenericRev().getRevisionId()); + + // Treatment of the RFGenericBom + ItemRevision rfGeneric = rfGenericBom.getItemRevision(); + report.setRfGenericRev(new RFGenericRevision(session, rfGeneric)); + + List bomChildMap = rfGenericBom.getBomChilds(); + if (!bomChildMap.isEmpty()) { + for (BOMLineHolder currentChild : bomChildMap) { + ItemRevision itemRevChild = currentChild.getItemRevision(); + String childType = itemRevChild.getTypeObject().getName(); + if (SnecmaObjectTypes.PART_AERO_REVISION.equals(childType)) { + report.getPartNumberRevList().add(new PartAeroRevision(session, itemRevChild)); + } else if (SnecmaObjectTypes.DESCRIPTIF_REVISION.equals(childType)) { + retrieveDocNormAndDocNormStandardLists(session, itemRevChild, report); + retrieveDocTechnicList(session, itemRevChild, report); + } else if (SnecmaObjectTypes.RF_ADMIN_REVISION.equals(childType)) { + report.setRfAdminRev(new RFAdminRevision(session, itemRevChild)); + report.setFrontiereAvion(report.getRfAdminRev().getFrontiereAvion()); + report.setFrontiereCooperant(report.getRfAdminRev().getFrontiereCooperant()); + } else { + LOGGER.debug("The child {} have a type {} which has not selected", itemRevChild.getUid(), childType); + } + } + } else { + LOGGER.debug("No child has been found under the RF Generic Bom {}.", rfGenericBom.getUid()); + } + + // Specific treatment of DocTechnic + filterDocTechnic(report); + filterForDefinitionCertifiee(report); + + // Empty parameters + report.setRevisionArticle(EMPTY_STR); + report.setDateReleased(EMPTY_STR); + + R16Printer printer = new R16Printer(); + PrintParameters printParameters = printer.makeMasterTemplate(report, report); + printer.constructDataMaps(session, printParameters, report); + + LOGGER.debug("PrepareData ended on: {}", report.getReportIdentifier().getReportTitle()); + return printParameters; + } + } + + /** + * Get the appropriate Generic Revision. + * + * @param session {@link TcSession} - the tc session + * @param report - the execution report which provide all informations for the report + * @return the generic {@link ItemRevision} + * @throws InvalidUserInputException for the throwable exception + * @throws KurtException for the throwable exception + */ + ItemRevision getGenericItemRevision(final TcSession session, final ExecutionR16 report) throws KurtException { + List genericRevisions = new ItemRevisionQuery(session).searchID(report.getItemId()).findAll(); + + // Keep only the ItemRevision whose end item is the Product + List checkedGenerics = ObjectInfoHelper.getRevisionWithSameEndItem(session, genericRevisions, report.getTheProduitUnitObject().getProductID()); + genericRevisions.clear(); + + // Compare effectivities + List results = ObjectInfoHelper.getRevisionWithHighestRange(session, checkedGenerics, report.getTheProduitUnitObject().getUnitStr()); + checkedGenerics.clear(); + if (results.isEmpty()) { + // This error should not occur because it was already tested + throw new InvalidUserInputException("No generic found for item Id= " + report.getItemId()); + } + return results.get(0); + } + + private void filterForDefinitionCertifiee(final ExecutionR16 report) { + if (report.isDefCertifiee()) { + List transitList = new ArrayList<>(); + for (DocTechnic docTechnic : report.getDocTechnicList()) { + // These values are forbidden + if ("Définition / Design".equals(docTechnic.getTypeDocTechnic1())) { + transitList.add(docTechnic); + } + } + report.getDocTechnicList().clear(); + report.getDocTechnicList().addAll(transitList); + } + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/r16report/ExecutionR16.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/r16report/ExecutionR16.java new file mode 100644 index 0000000..5d68bf4 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/r16report/ExecutionR16.java @@ -0,0 +1,166 @@ +package com.capgemini.reports.definition.r15r16r17reports.r16report; + +import com.capgemini.framework.common.SettingsHelper; +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.reports.JasperTemplate; +import com.capgemini.reports.ReportEnum; +import com.capgemini.reports.ReportLaunchTypeEnum; +import com.capgemini.reports.builder.R16Builder; +import com.capgemini.reports.builder.ReportBuilder; +import com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum; +import com.capgemini.reports.database.manager.MngCriteriaVal.CriteriaValue; +import com.capgemini.reports.definition.r15r16r17reports.AbstractExecutionR15R16R17; +import com.capgemini.reports.execution.AbstractExecutionReport; +import com.capgemini.reports.execution.IDataReportPreparator; +import com.capgemini.reports.printing.Printer.PrintFormat; +import com.capgemini.reports.reports.parameters.IChecker; +import com.capgemini.reports.reports.parameters.ProductUnit; +import com.capgemini.reports.reports.parameters.checker.ObjectTypeChecker; +import com.capgemini.reports.reports.parameters.checker.ProductUnitGenericChecker; +import com.capgemini.reports.snecmaobjects.admin.RFAdminRevision; +import com.capgemini.reports.snecmaobjects.generic.AbstractGenericRevision; +import com.capgemini.reports.snecmaobjects.part.PartAeroRevision; +import com.capgemini.reports.snecmaobjects.rf.RFGenericRevision; +import lombok.AccessLevel; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; + +import java.util.ArrayList; +import java.util.List; + +/** + * This class controls the execution of a R16 report. + */ +@Getter +@Setter(value = AccessLevel.PROTECTED) +@EqualsAndHashCode(callSuper = true) +public class ExecutionR16 extends AbstractExecutionR15R16R17 { + private static final long serialVersionUID = -3158586550831992551L; + + // Policies + private static final PolicyLocation R16_POLICY_XML_FULL = PolicyLocation.make("R16_policy_full", "/xml/policies/r16report/R16_policy_full.xml"); + private static final PolicyLocation R16_POLICY_XML_LIGHT = PolicyLocation.make("R16_policy_light", "/xml/policies/r16report/R16_policy_light.xml"); + // Priority parameter + private static final int REPORT_PRIORITY = SettingsHelper.getPriority(ReportEnum.REPORT_R16); + // Revision rule parameter + private static final String REPORT_REVISION_RULE = SettingsHelper.getPropertyWithDefaultValue("common.bom.revisionRule.REPORT_R16", DEFAULT_REVISION_RULE); + // Launch type parameter + private static final ReportLaunchTypeEnum REPORT_LAUNCH_TYPE = ReportLaunchTypeEnum.getReportLaunchType("common.launch.launchType.REPORT_R16"); + // Raw input parameters + protected final ProductUnit theProduitUnitObject; + // Internal working data + @Getter(value = AccessLevel.NONE) + protected final String typeImpression; + // Data gathered + protected final boolean isDefCertifiee; + @Getter(value = AccessLevel.NONE) + protected RFGenericRevision rfGenericRev; + protected String articleId; + protected AbstractGenericRevision genericRev; + protected List partNumberRevList = new ArrayList<>(); + protected RFAdminRevision rfAdminRev; + protected String frontiereAvion = ""; + protected String frontiereCooperant = ""; + @Getter(value = AccessLevel.NONE) + private String articleRevision; + + /** + * Constructor. + * + * @param produitUnit {@link ProductUnit} - the Product id and the Unit range. + * @param idTopGeneric {@link String} - the id of the top Generic. + * @param typeImpression {@link String} - the type of impression of the report + * @param langage {@link String} - the language selected by the user + */ + public ExecutionR16(final ProductUnit produitUnit, final String idTopGeneric, final String typeImpression, final String langage) { + super(idTopGeneric, langage, REPORT_PRIORITY, REPORT_REVISION_RULE, REPORT_LAUNCH_TYPE); + this.theProduitUnitObject = produitUnit; + this.isDefCertifiee = "Def_certifiee".equals(typeImpression); + this.typeImpression = typeImpression; + } + + @Override + public List getLaunchData() { + List theCriteria = new ArrayList<>(); + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.PART_ID, itemId)); + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.PRODUCT, theProduitUnitObject.getProductID())); + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.UNIT, theProduitUnitObject.getUnitStr())); + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.TYPE_IMPRESSION, typeImpression)); + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.LANGUAGE, frenchInput)); + return theCriteria; + } + + @Override + public List getQuickChecks() { + ArrayList quickChecks = new ArrayList<>(); + quickChecks.add(new ProductUnitGenericChecker(itemId, theProduitUnitObject)); + quickChecks.add(new ObjectTypeChecker(itemId, SnecmaObjectTypes.GENERIC)); + return quickChecks; + } + + @Override + public String getTemplateLocation() { + return JasperTemplate.TEMPLATE_R15R16.getFilepath(); + } + + @Override + public PolicyLocation getPropertyPolicyForLongChecks() { + return R16_POLICY_XML_LIGHT; + } + + @Override + public PolicyLocation getFullPolicy() { + return R16_POLICY_XML_FULL; + } + + @Override + public List getLongChecks() { + return new ArrayList<>(); + } + + @Override + public ReportEnum getReportIdentifier() { + return ReportEnum.REPORT_R16; + } + + @Override + public String getSpecifiedFileName() { + String separator = "_"; + StringBuilder filename = new StringBuilder(articleId).append(separator).append(articleRevision).append(separator).append("FA_"); + + // Type impression + if (isDefCertifiee) { + filename.append("Certif"); + } else { + filename.append("Real"); + } + + // Language + if (!isFrench()) { + filename.append("_ENG"); + } + return filename.toString(); + } + + @Override + public PrintFormat getPrintingFormat() { + return PrintFormat.PDF; + } + + @Override + public IDataReportPreparator getDataPreparator() { + return new DataReportPreparatorR16(); + } + + @Override + public AbstractExecutionReport cloneTemplateToExecution() { + return new ExecutionR16(theProduitUnitObject, articleId, typeImpression, frenchInput); + } + + @Override + public Class getReportBuilderClass() { + return R16Builder.class; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/r16report/R16BOMLineExplorer.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/r16report/R16BOMLineExplorer.java new file mode 100644 index 0000000..41d7235 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/r16report/R16BOMLineExplorer.java @@ -0,0 +1,35 @@ +package com.capgemini.reports.definition.r15r16r17reports.r16report; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.EmptyNomenclatureException; +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.capgemini.framework.teamcenter.resolution.filtering.ITcTypeFilter; +import com.capgemini.framework.teamcenter.resolution.filtering.TcTypeInclusionFilter; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.bomlineholder.BOMLineHolderHelper; +import com.capgemini.reports.exceptions.InvalidInputException; +import com.capgemini.reports.exceptions.MalformedNomenclatureException; +import com.capgemini.reports.teamcenter.resolution.IBOMLineExplorer; +import com.capgemini.reports.teamcenter.resolution.structureservice.SingleStructureServiceCaller; +import com.capgemini.reports.teamcenter.resolution.structureservice.SingleStructureServiceCaller.SingleLevelExpander; + +/** + * Explorer of {@link BOMLineHolder}s used in {@link SingleStructureServiceCaller} for R16 report.
    + * Thanks to this class, the SINGLE resolution structure could carry on and the Part Number could be taken.
    + * The Rf Generic is returned, and its children PArt Aero / RF Admin and Descriptif are loaded + */ +public class R16BOMLineExplorer implements IBOMLineExplorer { + + private static final ITcTypeFilter FILTER_PART_ADMIN_DESCRIPTION = new TcTypeInclusionFilter(SnecmaObjectTypes.PART_AERO_REVISION, + SnecmaObjectTypes.RF_ADMIN_REVISION, SnecmaObjectTypes.DESCRIPTIF_REVISION); + private static final ITcTypeFilter FILTER_RF_GENERIC_REVISION = new TcTypeInclusionFilter(SnecmaObjectTypes.RF_GENERIC_REVISION); + + @Override + public BOMLineHolder explore(TcSession session, final SingleLevelExpander expander, final BOMLineHolder genericBom) throws EmptyNomenclatureException, + InvalidInputException, MalformedNomenclatureException { + BOMLineHolder expandedGenericBom = expander.expand(genericBom, FILTER_RF_GENERIC_REVISION); + BOMLineHolder rfGeneric = BOMLineHolderHelper.findRfGenericBL(expandedGenericBom); + return expander.expand(rfGeneric, FILTER_PART_ADMIN_DESCRIPTION); + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/r16report/R16Printer.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/r16report/R16Printer.java new file mode 100644 index 0000000..05f1579 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r15r16r17reports/r16report/R16Printer.java @@ -0,0 +1,105 @@ +package com.capgemini.reports.definition.r15r16r17reports.r16report; + +import com.capgemini.framework.common.StringHelper; +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.reports.definition.r15r16r17reports.AbstractR15R16R17Printer; +import com.capgemini.reports.definition.r15r16r17reports.CommunR15R16R17ComponentVisitor; +import com.capgemini.reports.definition.r15r16r17reports.R15R16R17R24R25Keys; +import com.capgemini.reports.definition.r15r16r17reports.R15R16R17R24R25Keys.Page2; +import com.capgemini.reports.definition.r15r16r17reports.R15R16R17R24R25Keys.SpecificR15R16; +import com.capgemini.reports.execution.mapconstructor.IMapConstructor; +import com.capgemini.reports.printing.PrintParameters; +import com.capgemini.reports.snecmaobjects.part.PartAeroRevision; +import com.capgemini.reports.snecmaobjects.visitor.IComponentVisitor; +import lombok.EqualsAndHashCode; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.EnumMap; +import java.util.List; +import java.util.Map; + +/** + * This class is able to put the data gathered by an {@link ExecutionR16} into some {@link PrintParameters} for printing. + */ +@Slf4j +@EqualsAndHashCode(callSuper = true) +public class R16Printer extends AbstractR15R16R17Printer implements IMapConstructor { + + private static final long serialVersionUID = -7722864354275704498L; + + private static final String EMPTY_STRING = StringHelper.EMPTY; + private static final String UNKNOWN_STR = "???"; + private static final String SANS_OBJET = "Sans objet"; + private static final String NOT_APPLICABLE = "Not applicable "; + + @Override + protected List> addExtraDocLines(final ExecutionR16 execution) { + return new ArrayList<>(); + } + + @Override + protected void addOptionalParameters(final ExecutionR16 execution, final PrintParameters mainReport) { + Map params = new EnumMap<>(R15R16R17R24R25Keys.class); + List partNumberRevList = execution.getPartNumberRevList(); + if (partNumberRevList != null && !partNumberRevList.isEmpty()) { + Map map = new EnumMap<>(R15R16R17R24R25Keys.class); + if (partNumberRevList.size() == 1) { + map = partNumberRevList.get(0).accept(getVisitor(execution.isFrench())); + map.remove(R15R16R17R24R25Keys.PART_VERSION); + map.put(R15R16R17R24R25Keys.PART_VERSION, EMPTY_STRING); + } else { + map.put(R15R16R17R24R25Keys.ITEM_ID, UNKNOWN_STR); + map.put(R15R16R17R24R25Keys.PART_NUMBER, UNKNOWN_STR); + map.put(R15R16R17R24R25Keys.MANUFACTURER_CODE, UNKNOWN_STR); + map.put(R15R16R17R24R25Keys.PART_VERSION, EMPTY_STRING); + map.put(R15R16R17R24R25Keys.FRENCH_DESIGNATION, UNKNOWN_STR); + map.put(R15R16R17R24R25Keys.ENGLISH_DESIGNATION, UNKNOWN_STR); + map.put(R15R16R17R24R25Keys.OBTURATION, execution.isFrench() ? SANS_OBJET : NOT_APPLICABLE); + map.put(R15R16R17R24R25Keys.CLASSIFICATION, "-"); + map.put(R15R16R17R24R25Keys.FIELD_OPN_SERIALISATION, UNKNOWN_STR); + map.put(R15R16R17R24R25Keys.LOG_DOCUMENT, execution.isFrench() ? SANS_OBJET : NOT_APPLICABLE); + } + params.putAll(map); + } else { + params.putAll(execution.getGenericRev().accept(getVisitor(execution.isFrench()))); + } + params.put(R15R16R17R24R25Keys.MT_NUMBER, EMPTY_STRING); + params.put(R15R16R17R24R25Keys.PREVIOUS_RELEASE_DATE, EMPTY_STRING); + params.put(R15R16R17R24R25Keys.ITEM_ID, execution.getArticleId()); + mainReport.addReportParameters(params); + + Map map = new EnumMap<>(SpecificR15R16.class); + boolean isFrench = execution.isFrench(); + String frontiereAvion = execution.getFrontiereAvion(); + map.put(SpecificR15R16.INSTALLATION_INTERFACE, isFrench ? french(frontiereAvion) : english(frontiereAvion)); + String frontiereCooperant = execution.getFrontiereCooperant(); + map.put(SpecificR15R16.PARTNER_INTERFACE, isFrench ? french(frontiereCooperant) : english(frontiereCooperant)); + map.put(SpecificR15R16.PRODUCT_UNIT, execution.getProduitUnit()); + map.put(SpecificR15R16.SUB_TITLE, execution.isDefCertifiee() + ? "Documents de définition et procédés\nDefinition and process documents" + : "Documents de définition et procédés et pratiques de réalisation\nDefinition and process documents and manufacturing practices"); + mainReport.addReportParameters(map); + mainReport.addReportParameter(SpecificR15R16.IS_PREVIOUS_DEF.toString(), false); + } + + @Override + protected String getTitle(final ExecutionR16 execution) { + return execution.isDefCertifiee() + ? "Définition technique de l'article\nPart Definition" + : "Définition de réalisation de l'article\nPart Manufacturing definition"; + } + + @Override + protected IComponentVisitor> getVisitor(final boolean isFrench) { + return new CommunR15R16R17ComponentVisitor(isFrench); + } + + @Override + public void constructDataMaps(TcSession session, final PrintParameters printParameters, final ExecutionR16 data) throws KurtException { + long start = System.currentTimeMillis(); + this.print(data, printParameters); + log.trace("Execution time : {} ms for {}", System.currentTimeMillis() - start, "data filtering"); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r19report/DataReportPreparatorR19.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r19report/DataReportPreparatorR19.java new file mode 100644 index 0000000..080e5f9 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r19report/DataReportPreparatorR19.java @@ -0,0 +1,251 @@ +package com.capgemini.reports.definition.r19report; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.object.SnecmaObjectProperties; +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.capgemini.reports.definition.r19report.ExecutionR19.ReportDataR19; +import com.capgemini.reports.documentationobjects.*; +import com.capgemini.reports.exceptions.InvalidInputException; +import com.capgemini.reports.exceptions.InvalidUserInputException; +import com.capgemini.reports.exceptions.NotFoundException; +import com.capgemini.reports.execution.IDataReportPreparator; +import com.capgemini.reports.execution.strategies.IExecutionStrategy; +import com.capgemini.reports.printing.PrintParameters; +import com.capgemini.reports.snecmaobjects.AbstractSnecmaObject; +import com.capgemini.reports.snecmaobjects.SnecmaObjectFactory; +import com.capgemini.reports.snecmaobjects.part.AbstractPart; +import com.capgemini.reports.teamcenter.ObjectInfoHelper; +import com.capgemini.reports.teamcenter.queries.DirectQuery; +import com.capgemini.reports.teamcenter.queries.TypeQuery; +import com.teamcenter.soa.client.model.ModelObject; +import com.teamcenter.soa.client.model.strong.Item; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import com.teamcenter.soa.client.model.strong.RevisionRule; +import com.teamcenter.soa.client.model.strong.WorkspaceObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.*; + + +/** + * This class will allow to prepare data and findAll back data for making report R19. + */ +public class DataReportPreparatorR19 implements IDataReportPreparator { + private static final long serialVersionUID = -7227615200390008230L; + private static final Logger LOGGER = LoggerFactory.getLogger(DataReportPreparatorR19.class); + + private static final String OBJECT_NOT_FOUND_PREFIX = "Object not found with UID '"; + private static final String OBJECT_NOT_FOUND_SUFFIX = "'"; + private static final int LEVEL = 1; + + /** + * Construct a map which contain folder use to extract parts referencing document. This function is specific for Report 19. + */ + static Map> buildMapRelationTypeFilter(final String documentType) throws KurtException { + Map> map = new HashMap<>(); + List relation = new ArrayList<>(); + + if (documentType.isEmpty()) { + throw new KurtException("Document type musn't be emtpy to construct map relation type and filter"); + } + + if (SnecmaObjectTypes.DOC_DRAWING_REVISION.equals(documentType)) { + relation.add(SnecmaObjectProperties.TC_IS_REPRESENTED_BY); + map.put(documentType, relation); + } else if (SnecmaObjectTypes.DOC_NORM.equals(documentType) || SnecmaObjectTypes.DOC_NORM_STANDARD.equals(documentType)) { + relation.add(SnecmaObjectTypes.FOLDER_REFERENCED_DOCS); + map.put(documentType, relation); + } else if (SnecmaObjectTypes.DOC_TECHNIC_REVISION.equals(documentType)) { + relation.add(SnecmaObjectProperties.FOLDER_PV_REACH_DOCS); + relation.add(SnecmaObjectProperties.FOLDER_PV_ITAR_DOCS); + relation.add(SnecmaObjectProperties.FOLDER_PV_DEFINITION_DOCS); + map.put(documentType, relation); + } + return map; + } + + /** + * Construct a list containing autorized part type for a given document type. + */ + static List getAuthorizedPartTypes(final String documentType) throws InvalidInputException { + List authorizedTpes = new ArrayList<>(); + if (documentType == null || documentType.isEmpty()) { + throw new InvalidInputException("Document type may not be emtpy to construct list authorized types"); + } + if (SnecmaObjectTypes.DOC_DRAWING_REVISION.equals(documentType)) { + authorizedTpes.add(SnecmaObjectTypes.DET_REVISION); + authorizedTpes.add(SnecmaObjectTypes.PART_AERO_REVISION); + authorizedTpes.add(SnecmaObjectTypes.PART_NO_AERO_REVISION); + } else if (SnecmaObjectTypes.DOC_NORM.equals(documentType)) { + authorizedTpes.add(SnecmaObjectTypes.DET_REVISION); + authorizedTpes.add(SnecmaObjectTypes.PART_AERO_REVISION); + authorizedTpes.add(SnecmaObjectTypes.PART_MAT_REVISION); + authorizedTpes.add(SnecmaObjectTypes.PART_NO_AERO_REVISION); + } else if (SnecmaObjectTypes.DOC_NORM_STANDARD.equals(documentType)) { + authorizedTpes.add(SnecmaObjectTypes.STANDARD_REVISION); + } else if (SnecmaObjectTypes.DOC_TECHNIC_REVISION.equals(documentType)) { + authorizedTpes.add(SnecmaObjectTypes.ALTERNATE_REVISION); + authorizedTpes.add(SnecmaObjectTypes.DET_REVISION); + authorizedTpes.add(SnecmaObjectTypes.PART_AERO_REVISION); + authorizedTpes.add(SnecmaObjectTypes.PART_NO_AERO_REVISION); + authorizedTpes.add(SnecmaObjectTypes.PART_MAT_REVISION); + authorizedTpes.add(SnecmaObjectTypes.STANDARD_REVISION); + } + return authorizedTpes; + } + + /** + * Construct a list containing descriptif revision type for document types DocNorm and DocTechnic only + */ + static List getAuthorizedDescriptifType(final String documentType) throws InvalidInputException { + List authorizedTypes = new ArrayList<>(); + if (documentType == null || documentType.isEmpty()) { + throw new InvalidInputException("Document type may not be emtpy to construct list authorized types"); + } + if (SnecmaObjectTypes.DOC_NORM.equals(documentType) || SnecmaObjectTypes.DOC_TECHNIC_REVISION.equals(documentType)) { + authorizedTypes.add(SnecmaObjectTypes.DESCRIPTIF_REVISION); + } + return authorizedTypes; + } + + @Override + public String print(TcSession session, ExecutionR19 execution, IExecutionStrategy executionStrategy) throws KurtException { + PrintParameters printParameters = prepareData(session, execution); + executionStrategy.print(printParameters, execution); + return executionStrategy.getReportFileName(execution) + printParameters.getOuputFileExtension(); + } + + private PrintParameters prepareData(final TcSession session, final ExecutionR19 report) throws KurtException { + LOGGER.info("PrepareData started for : " + report.getReportIdentifier().getReportCode()); + session.setObjectPropPolicy(report.getFullPolicy()); + + // STEP 1 : Obtain document + WorkspaceObject modelObject; + try { + modelObject = new DirectQuery(session).searchByUID(report.getDocumentUID()); + } catch (NotFoundException e) { + throw new InvalidUserInputException(OBJECT_NOT_FOUND_PREFIX + report.getDocumentUID() + OBJECT_NOT_FOUND_SUFFIX, e); + } + + // STEP 2 : Obtain the list of all ItemRevision where the document is referenced + // Build filter map and relation for current document + String documentType = modelObject.getTypeObject().getName(); + Map> relationAndTypesFilter = buildMapRelationTypeFilter(documentType); + List itemsRevisions = session.whereReferenced(modelObject, LEVEL, relationAndTypesFilter); + LOGGER.debug("List of item revision where the doc is referenced contains {} objects", itemsRevisions.size()); + + // STEP 3 : Filter only parts referencing the doc + List authorizedPartTypes = getAuthorizedPartTypes(documentType); + List partFilteringResult = ObjectInfoHelper.filteringObjectsReferencer(session, itemsRevisions, authorizedPartTypes); + LOGGER.debug("Number of parts filtered : {}", partFilteringResult.size()); + + // Convert ItemRevision corresponding to Parts to AbstractPart then sort it by item_id and revision_id + List abstractPartList = new ArrayList<>(); + for (ItemRevision itemRevision : partFilteringResult) { + AbstractPart theSnecmaObject = (AbstractPart) SnecmaObjectFactory.build(session, itemRevision); + abstractPartList.add(theSnecmaObject); + } + Collections.sort(abstractPartList, new PartIdRevComparator()); + + // STEP 4 : For DocNorm and DocTechnic only we use of a specific revision rule to ascend from Descriptif referencing the doc and find the Generic and Generic Assemb using it + // Filter Descriptif Revision referencing the doc + List authorizedDescriptifType = getAuthorizedDescriptifType(documentType); + List descriptifFilteringResult = filteringObjectsDescription(session, itemsRevisions, authorizedDescriptifType); + LOGGER.debug("Number Descriptif filtered : {}", descriptifFilteringResult.size()); + + // Get the R19 specific revision rule to get Generic and Generic Assemb using the Descriptif as input + List revisionRuleList = TypeQuery.getRevisionRule(session, report.getRevisionRule()); + List generics = new ArrayList<>(); + if (revisionRuleList == null || revisionRuleList.size() == 0) { + LOGGER.warn("The revision rules \"{}\" has not been found in Teamcenter! The Generic and GenericAssemb object will not be managed.", report.getRevisionRule()); + } else { + LOGGER.debug("The revision rules \"{}\" will be used.", report.getRevisionRule()); + RevisionRule reportRevisionRule = revisionRuleList.get(0); + + for (ItemRevision descriptifRevision : descriptifFilteringResult) { + // With level 2 whereUsed we get RF Generic Revision, Generic Revision and Generic Assemb Revision objects + List genericList = session.whereUsed(descriptifRevision, 2, reportRevisionRule); + if (genericList != null && genericList.size() != 0) { + List idList = new ArrayList<>(); + // We keep only one revision by Generic or Generic Assemb. RF Generic Revision are ignored. + for (ItemRevision generic : genericList) { + session.loadProperties(generic, "item_id", "object_name", "object_type"); + String objectType = generic.get_object_type(); + String itemId = generic.get_item_id(); + LOGGER.debug("Object item_id : {}, object_name : {}, object_type : {}", itemId, generic.get_object_name(), generic.get_object_type()); + if ("Generic Revision".equals(objectType) || "Generic Assemb Revision".equals(objectType)) { + if (!idList.contains(itemId)) { + idList.add(itemId); + generics.add(generic); + LOGGER.debug("Object item_id : {} selected.", itemId); + } + } + } + } + } + LOGGER.debug("Total number of Generic/Generic Assemb found : {}", generics.size()); + } + + // STEP 5 : Prepare data for ReportDataR19 and R19Printer + // Convert ItemRevision corresponding to Generic and Generic Assemb to AbstractSnecmaObject + List abstractGenericRevisionList = new ArrayList<>(); + for (ItemRevision itemRevision : generics) { + AbstractSnecmaObject abstractGenericRevision = SnecmaObjectFactory.build(session, itemRevision); + abstractGenericRevisionList.add(abstractGenericRevision); + } + + // Document + AbstractDoc theDoc = buildDocument(session, modelObject); + + // Convert all objects (Parts and Generic/GenericAssemb to a list of AbstractSnecmaObject to include in ReportDataR19 + List abstractSnecmaObjectList = new ArrayList<>(); + abstractSnecmaObjectList.addAll(abstractPartList); + abstractSnecmaObjectList.addAll(abstractGenericRevisionList); + + ReportDataR19 dataR19 = new ReportDataR19(theDoc, abstractSnecmaObjectList); + + R19Printer printer = new R19Printer(); + PrintParameters printParameters = printer.makeMasterTemplate(report, dataR19); + printer.constructDataMaps(session, printParameters, dataR19); + + LOGGER.debug("PrepareData ended on: {}", report.getReportIdentifier().getReportTitle()); + + return printParameters; + } + + private AbstractDoc buildDocument(final TcSession session, final ModelObject modelObject) { + AbstractDoc doc = null; + if (SnecmaObjectTypes.DOC_DRAWING_REVISION.equals(modelObject.getTypeObject().getName())) { + doc = new DocDrawing(session, (ItemRevision) modelObject); + } else if (SnecmaObjectTypes.DOC_NORM.equals(modelObject.getTypeObject().getName())) { + doc = new DocNorm(session, (Item) modelObject); + } else if (SnecmaObjectTypes.DOC_NORM_STANDARD.equals(modelObject.getTypeObject().getName())) { + doc = new DocNormStandard(session, (Item) modelObject); + } else if (SnecmaObjectTypes.DOC_TECHNIC_REVISION.equals(modelObject.getTypeObject().getName())) { + doc = new DocTechnic(session, (ItemRevision) modelObject); + } + return doc; + } + + /** + * Returns a list of object referencer answering to the specification
    + * Has statuts Def Approved And is the the highest sequence between object have the same item_id and revision_id .
    + * You must give a list objects referencing a document, a list object revision authorized and a list status authorized + */ + + public static List filteringObjectsDescription(final TcSession session, final List objectsToFilter, final List authorizedTypes) { + List results = new ArrayList<>(); + // getAuthorized types + for (ItemRevision object : objectsToFilter) { + LOGGER.debug("Object description type={} item_id={}", object.getTypeObject().getName(), object.get_item_id()); + if (authorizedTypes.contains(object.getTypeObject().getName())) { + results.add(object); + } else { + LOGGER.info("Object description Rejected unauthorized type={} item_id={}", object.getTypeObject().getName(), object.get_item_id()); + } + } + return results; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r19report/ExecutionR19.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r19report/ExecutionR19.java new file mode 100644 index 0000000..cd8217c --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r19report/ExecutionR19.java @@ -0,0 +1,151 @@ +package com.capgemini.reports.definition.r19report; + +import com.capgemini.framework.common.SettingsHelper; +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.reports.JasperTemplate; +import com.capgemini.reports.ReportEnum; +import com.capgemini.reports.ReportLaunchTypeEnum; +import com.capgemini.reports.builder.R19Builder; +import com.capgemini.reports.builder.ReportBuilder; +import com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum; +import com.capgemini.reports.database.manager.MngCriteriaVal.CriteriaValue; +import com.capgemini.reports.definition.r19report.ExecutionR19.ReportDataR19; +import com.capgemini.reports.documentationobjects.AbstractDoc; +import com.capgemini.reports.execution.AbstractExecutionReport; +import com.capgemini.reports.execution.IDataReportPreparator; +import com.capgemini.reports.printing.Printer.PrintFormat; +import com.capgemini.reports.reports.parameters.IChecker; +import com.capgemini.reports.reports.parameters.checker.ModelObjectChecker; +import com.capgemini.reports.snecmaobjects.AbstractSnecmaObject; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.ArrayList; +import java.util.List; + +/** + * This class controls the execution of an R19 report. + */ +@Getter +public class ExecutionR19 extends AbstractExecutionReport { + + private static final long serialVersionUID = 4050093665599652815L; + + // Policies parameters + private static final PolicyLocation R19_POLICY_XML_FULL = PolicyLocation.make("R19_policy_full", "/xml/policies/r19report/R19_policy_full.xml"); + private static final PolicyLocation R19_POLICY_XML_LIGHT = PolicyLocation.make("R19_policy_light", "/xml/policies/r19report/R19_policy_light.xml"); + + // Configuration + private static final String FILE_SEPARATOR = "_"; + // Launch type parameter + private static final ReportLaunchTypeEnum REPORT_LAUNCH_TYPE = ReportLaunchTypeEnum.getReportLaunchType("common.launch.launchType.REPORT_R19"); + // Revision rule parameter + private static final String REPORT_REVISION_RULE = SettingsHelper.getPropertyWithDefaultValue("common.bom.revisionRule.REPORT_R19", DEFAULT_REVISION_RULE); + // Priority parameter + private static final int REPORT_PRIORITY = SettingsHelper.getPriority(ReportEnum.REPORT_R19); + private final String documentId; + private final String documentRev; + private final String documentType; + private final String documentUID; + + /** + * Executes the Report R19. + * + * @param documentId the ID of the document + * @param documentRev the revision of the Document + * @param documentType the Type of the document + * @param documentUID the UID of the document + */ + public ExecutionR19(final String documentId, final String documentRev, final String documentType, final String documentUID) { + super(REPORT_PRIORITY, REPORT_REVISION_RULE, REPORT_LAUNCH_TYPE); + this.documentId = documentId; + this.documentRev = documentRev; + this.documentType = documentType; + this.documentUID = documentUID; + } + + + @Override + public List getQuickChecks() { + List quickChecks = new ArrayList<>(); + quickChecks.add(new ModelObjectChecker(documentUID, SnecmaObjectTypes.DOC_NORM, SnecmaObjectTypes.DOC_NORM_STANDARD, + SnecmaObjectTypes.DOC_DRAWING_REVISION, SnecmaObjectTypes.DOC_TECHNIC_REVISION)); + return quickChecks; + } + + @Override + public PolicyLocation getPropertyPolicyForLongChecks() { + return R19_POLICY_XML_LIGHT; + } + + @Override + public PolicyLocation getFullPolicy() { + return R19_POLICY_XML_FULL; + } + + @Override + public List getLongChecks() { + return new ArrayList<>(); + } + + @Override + public String getTemplateLocation() { + return JasperTemplate.TEMPLATE_R19.getFilepath(); + } + + @Override + public ReportEnum getReportIdentifier() { + return ReportEnum.REPORT_R19; + } + + + @Override + public PrintFormat getPrintingFormat() { + return PrintFormat.XLSX; + } + + @Override + public List getLaunchData() { + List theCriteria = new ArrayList<>(); + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.DOCUMENT_ID, documentId)); + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.DOCUMENT_REVISION, documentRev)); + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.TYPE_OBJET, documentType)); + return theCriteria; + } + + + @Override + public String getSpecifiedFileName() { + if (documentRev.isEmpty()) { + return "R19_" + documentId; + } else { + return "R19_" + documentId + FILE_SEPARATOR + documentRev; + } + } + + @Override + public IDataReportPreparator getDataPreparator() { + return new DataReportPreparatorR19(); + } + + @Override + public AbstractExecutionReport cloneTemplateToExecution() { + return new ExecutionR19(documentId, documentRev, documentType, documentUID); + } + + @Override + public Class getReportBuilderClass() { + return R19Builder.class; + } + + /** + * POJO container of all data required for this report. + */ + @AllArgsConstructor + @Getter + static class ReportDataR19 { + private final AbstractDoc document; + private final List objectsWhereReferenced; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r19report/PartIdRevComparator.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r19report/PartIdRevComparator.java new file mode 100644 index 0000000..7bc3eb9 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r19report/PartIdRevComparator.java @@ -0,0 +1,28 @@ +package com.capgemini.reports.definition.r19report; + +import com.capgemini.reports.snecmaobjects.part.AbstractPart; + +import java.io.Serializable; +import java.util.Comparator; + +/** + * {@link AbstractPart} {@link Comparator}. Compares the Item ID, then the Revision ID. If both are equal, parts are considered equal. + */ +public class PartIdRevComparator implements Comparator, Serializable { + private static final long serialVersionUID = 618467339673492686L; + + /** + * Compare two Abstract by their item_id and revision_id. + * + * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object) + */ + @Override + public int compare(final AbstractPart part1, final AbstractPart part2) { + int comparatorValue = part1.getItemId().compareTo(part2.getItemId()); + if (comparatorValue == 0) { + comparatorValue = part1.getRevisionId().compareTo(part2.getRevisionId()); + } + return comparatorValue; + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r19report/R19Keys.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r19report/R19Keys.java new file mode 100644 index 0000000..a9a210f --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r19report/R19Keys.java @@ -0,0 +1,30 @@ +package com.capgemini.reports.definition.r19report; + +/** + * Enumeration of all the keys to the R19 report fields column. + */ +public enum R19Keys { + REFERENCE_DOCUMENT, + REVISION_DOCUMENT, + TYPE_DOCUMENT, + INDICE_DOCUMENT, + NOM_DOCUMENT, + DESIGNATION_ANGLAISE_DOCUMENT, + OBJET, + REFERENCE, + REVISION_REFERENCE, + NOM_REFERENCE, + TYPE_REFERENCE, + DESIGNATION_ENG, + RESPONSABLE_CONCEPTION, + PRODUIT, + CLASSEMENT, + SUIVI_UTILISATION, + DOCUMENT_DE_CONTROLE, + OBTURATION, + SUIVI_DUREE_VIE, + DUREE_VIE, + UNITE_DUREE_VIE, + DMD, + DMF +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r19report/R19Printer.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r19report/R19Printer.java new file mode 100644 index 0000000..0db50ff --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r19report/R19Printer.java @@ -0,0 +1,169 @@ +package com.capgemini.reports.definition.r19report; + +import com.capgemini.framework.common.LanguageHelper; +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.capgemini.reports.definition.r19report.ExecutionR19.ReportDataR19; +import com.capgemini.reports.definition.r19report.snecmaobject.R19ComponentVisitor; +import com.capgemini.reports.documentationobjects.*; +import com.capgemini.reports.execution.mapconstructor.AbstractStaticTemplateMapConstructor; +import com.capgemini.reports.printing.PrintParameters; +import com.capgemini.reports.snecmaobjects.AbstractSnecmaObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.*; + +/** + * Printer R19 Report construct a final list of datas for jasper. + */ +public class R19Printer extends AbstractStaticTemplateMapConstructor { + private static final long serialVersionUID = 5734951633170674016L; + + private static final String NORME_POUR_ARTICLES_STANDARDS = "Norme pour articles standards"; + private static final String REPRESENTATION_2D_DRAWING = "Représentation 2D"; + private static final String EMPTY = ""; + private static final Logger LOGGER = LoggerFactory.getLogger(R19Printer.class); + + private final R19ComponentVisitor componentBehaviour = new R19ComponentVisitor(); + + private static String check(final Object anInput) { + return anInput == null ? EMPTY : anInput.toString(); + } + + /* Extracts left side of a string of the form "French text / English text". */ + /* Separator slash may have *any* number (0+) of white spaces around them. */ + private static String french(final String string) { + return LanguageHelper.french(string); + } + + @Override + public void constructDataMaps(TcSession session, final PrintParameters printParameters, final ReportDataR19 data) throws KurtException { + // Retrieve parts properties + boolean isDocumentDataPrint = false; + AbstractDoc abstractDoc = data.getDocument(); + + List> lstMapData = new ArrayList<>(); + // If no object give an empty list with document + if (data.getObjectsWhereReferenced().isEmpty()) { + lstMapData.add(giveDocumentData(abstractDoc)); + lstMapData.add(giveEmptyPart()); + } else { + for (AbstractSnecmaObject elem : data.getObjectsWhereReferenced()) { + Map component = elem.accept(componentBehaviour); + + // Retrieve other properties + if (!isDocumentDataPrint) { + component.putAll(giveDocumentData(abstractDoc)); + isDocumentDataPrint = true; + } else { + component.putAll(giveEmptyDocument()); + } + + // Add to list + lstMapData.add(component); + } + } + // Give the list to jasper + printParameters.addReportData(translate(lstMapData)); + } + + private Map giveDocumentData(final AbstractDoc abstractDoc) { + String refDoc = ""; + String revDoc = ""; + String typeDoc = ""; + String indiceDoc = ""; + String nomDoc = ""; + String designationAnglaise = ""; + + if (SnecmaObjectTypes.DOC_DRAWING_REVISION.equals(abstractDoc.getType())) { + DocDrawing docDrawing = (DocDrawing) abstractDoc; + refDoc = docDrawing.getDocId(); + revDoc = docDrawing.getRevision(); + typeDoc = REPRESENTATION_2D_DRAWING; + indiceDoc = docDrawing.getIndicePlan(); + nomDoc = docDrawing.getName(); + designationAnglaise = docDrawing.getDesignationEn(); + } else if (SnecmaObjectTypes.DOC_NORM.equals(abstractDoc.getType())) { + DocNorm docNorm = (DocNorm) abstractDoc; + refDoc = docNorm.getDocId(); + revDoc = ""; + typeDoc = ""; + indiceDoc = ""; + nomDoc = docNorm.getItemName(); + designationAnglaise = ""; + } else if (SnecmaObjectTypes.DOC_NORM_STANDARD.equals(abstractDoc.getType())) { + DocNormStandard docNormStandard = (DocNormStandard) abstractDoc; + refDoc = docNormStandard.getDocId(); + revDoc = ""; + typeDoc = NORME_POUR_ARTICLES_STANDARDS; + indiceDoc = ""; + nomDoc = docNormStandard.getItemName(); + designationAnglaise = ""; + } else if (SnecmaObjectTypes.DOC_TECHNIC_REVISION.equals(abstractDoc.getType())) { + DocTechnic docTechnic = (DocTechnic) abstractDoc; + refDoc = docTechnic.getDocId(); + revDoc = docTechnic.getRevision(); + typeDoc = french(docTechnic.getTypeDocTechnic1()) + " / " + french(docTechnic.getTypeDocTechnic2()); + indiceDoc = docTechnic.getIndice(); + nomDoc = docTechnic.getName(); + designationAnglaise = docTechnic.getDesignationEn(); + } + + Map theMap = new EnumMap<>(R19Keys.class); + theMap.put(R19Keys.REFERENCE_DOCUMENT, refDoc); + theMap.put(R19Keys.REVISION_DOCUMENT, revDoc); + theMap.put(R19Keys.TYPE_DOCUMENT, typeDoc); + theMap.put(R19Keys.INDICE_DOCUMENT, indiceDoc); + theMap.put(R19Keys.NOM_DOCUMENT, nomDoc); + theMap.put(R19Keys.DESIGNATION_ANGLAISE_DOCUMENT, designationAnglaise); + return theMap; + } + + private Map giveEmptyDocument() { + Map theMap = new EnumMap<>(R19Keys.class); + theMap.put(R19Keys.REFERENCE_DOCUMENT, EMPTY); + theMap.put(R19Keys.REVISION_DOCUMENT, EMPTY); + theMap.put(R19Keys.TYPE_DOCUMENT, EMPTY); + theMap.put(R19Keys.INDICE_DOCUMENT, EMPTY); + theMap.put(R19Keys.NOM_DOCUMENT, EMPTY); + theMap.put(R19Keys.DESIGNATION_ANGLAISE_DOCUMENT, EMPTY); + return theMap; + } + + private Map giveEmptyPart() { + Map theMap = new EnumMap<>(R19Keys.class); + theMap.put(R19Keys.OBJET, EMPTY); + theMap.put(R19Keys.REFERENCE, EMPTY); + theMap.put(R19Keys.REVISION_REFERENCE, EMPTY); + theMap.put(R19Keys.NOM_REFERENCE, EMPTY); + theMap.put(R19Keys.TYPE_REFERENCE, EMPTY); + theMap.put(R19Keys.DESIGNATION_ENG, EMPTY); + theMap.put(R19Keys.RESPONSABLE_CONCEPTION, EMPTY); + theMap.put(R19Keys.PRODUIT, EMPTY); + theMap.put(R19Keys.CLASSEMENT, EMPTY); + theMap.put(R19Keys.DOCUMENT_DE_CONTROLE, EMPTY); + theMap.put(R19Keys.OBTURATION, EMPTY); + theMap.put(R19Keys.SUIVI_DUREE_VIE, EMPTY); + theMap.put(R19Keys.DUREE_VIE, EMPTY); + theMap.put(R19Keys.UNITE_DUREE_VIE, EMPTY); + theMap.put(R19Keys.DMD, EMPTY); + theMap.put(R19Keys.DMF, EMPTY); + return theMap; + } + + private List> translate(final List> visitorMaps) { + // Construct the map list expected by the printer + List> printerMaps = new ArrayList<>(); + for (Map visitorMap : visitorMaps) { + Map printerMap = new HashMap<>(); + for (R19Keys key : R19Keys.values()) { + printerMap.put(key.toString(), check(visitorMap.get(key))); + } + printerMaps.add(printerMap); + } + LOGGER.debug("Translate map " + printerMaps); + return printerMaps; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r19report/snecmaobject/AbstractR19ComponentVisitor.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r19report/snecmaobject/AbstractR19ComponentVisitor.java new file mode 100644 index 0000000..3f43db1 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r19report/snecmaobject/AbstractR19ComponentVisitor.java @@ -0,0 +1,95 @@ +package com.capgemini.reports.definition.r19report.snecmaobject; + +import com.capgemini.reports.definition.r19report.R19Keys; +import com.capgemini.reports.snecmaobjects.admin.RFAdminAGRevision; +import com.capgemini.reports.snecmaobjects.admin.RFAdminAPRevision; +import com.capgemini.reports.snecmaobjects.admin.RFAdminARevision; +import com.capgemini.reports.snecmaobjects.admin.RFAdminRevision; +import com.capgemini.reports.snecmaobjects.descriptif.DescriptifRevision; +import com.capgemini.reports.snecmaobjects.generic.GenericAssembRevision; +import com.capgemini.reports.snecmaobjects.generic.GenericRevision; +import com.capgemini.reports.snecmaobjects.mockup.MockupRevision; +import com.capgemini.reports.snecmaobjects.part.PartAssembRevision; +import com.capgemini.reports.snecmaobjects.product.ProductRevision; +import com.capgemini.reports.snecmaobjects.rf.RFGenericRevision; +import com.capgemini.reports.snecmaobjects.rf.RFPartAssembRevision; +import com.capgemini.reports.snecmaobjects.rf.RFPartRevision; +import com.capgemini.reports.snecmaobjects.visitor.IComponentVisitor; + +import java.util.EnumMap; +import java.util.Map; + + +/** + * Abstract Visitor for Components of the r19 report. + */ +public abstract class AbstractR19ComponentVisitor implements IComponentVisitor> { + private static final long serialVersionUID = 1002247758669375790L; + + @Override + public Map visitComponent(ProductRevision aProductRev) { + // Not use + return new EnumMap<>(R19Keys.class); + } + + @Override + public Map visitComponent(PartAssembRevision aPartAssembRev) { + // Not use + return new EnumMap<>(R19Keys.class); + } + + @Override + public Map visitComponent(RFGenericRevision aRfGenericRev) { + // Not use + return new EnumMap<>(R19Keys.class); + } + + @Override + public Map visitComponent(RFPartAssembRevision aRfPartAssembRev) { + // Not use + return new EnumMap<>(R19Keys.class); + } + + @Override + public Map visitComponent(RFPartRevision aRfPartRev) { + // Not use + return new EnumMap<>(R19Keys.class); + } + + @Override + public Map visitComponent(RFAdminRevision aRfAdminRev) { + // Not use + return new EnumMap<>(R19Keys.class); + } + + @Override + public Map visitComponent(RFAdminARevision aRfAdminARev) { + // Not use + return new EnumMap<>(R19Keys.class); + } + + @Override + public Map visitComponent(RFAdminAPRevision aRfAdminAPRev) { + // Not use + return new EnumMap<>(R19Keys.class); + } + + @Override + public Map visitComponent(RFAdminAGRevision aRfAdminAGRev) { + // Not use + return new EnumMap<>(R19Keys.class); + } + + @Override + public Map visitComponent(MockupRevision aMockupRev) { + // Not use + return new EnumMap<>(R19Keys.class); + } + + @Override + public Map visitComponent(DescriptifRevision aDescriptifRev) { + // Not use + return new EnumMap<>(R19Keys.class); + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r19report/snecmaobject/R19ComponentVisitor.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r19report/snecmaobject/R19ComponentVisitor.java new file mode 100644 index 0000000..9e8a637 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r19report/snecmaobject/R19ComponentVisitor.java @@ -0,0 +1,203 @@ +package com.capgemini.reports.definition.r19report.snecmaobject; + +import com.capgemini.framework.common.LanguageHelper; +import com.capgemini.framework.common.StringHelper; +import com.capgemini.reports.definition.r19report.R19Keys; +import com.capgemini.reports.snecmaobjects.AbstractSnecmaObject; +import com.capgemini.reports.snecmaobjects.generic.AbstractGenericRevision; +import com.capgemini.reports.snecmaobjects.generic.GenericAssembRevision; +import com.capgemini.reports.snecmaobjects.generic.GenericRevision; +import com.capgemini.reports.snecmaobjects.part.*; +import com.capgemini.reports.snecmaobjects.supermodel.SuperModelRevision; + +import java.util.EnumMap; +import java.util.Map; + + +/** + * Visitor for component objects for the R19. + */ +public class R19ComponentVisitor extends AbstractR19ComponentVisitor { + private static final long serialVersionUID = 6744199471997128399L; + + private static final String SUFFIXE_REVISION = " Revision"; + private static final String EMPTY_STRING = StringHelper.EMPTY; + private static final String MATIERE = "matière"; + private static final String SANS_OBJET = "Sans objet"; + private static final String PART_NO_AERO = "Part No Aero"; + private static final String TRANSLATE_TO_PARTNONAERO_FR = "PartNonAéro"; + + /** + * Extracts left side of a string of the form "French text / English text".
    + * Separator slash may have *any* number (0+) of white spaces around them. + */ + private static String french(final String string) { + return LanguageHelper.french(string); + } + + @Override + public Map visitComponent(final DETRevision aDetRev) { + Map theMap = getAbstractSnecmaObjectProperties(aDetRev); + theMap.putAll(getAbstractPartProperties(aDetRev)); + theMap.put(R19Keys.TYPE_REFERENCE, french(aDetRev.getTypeDet1()) + " / " + french(aDetRev.getTypeDet2())); + theMap.put(R19Keys.OBTURATION, french(aDetRev.getObturation())); + theMap.put(R19Keys.SUIVI_DUREE_VIE, aDetRev.getSuiviDureeVie()); + theMap.put(R19Keys.DUREE_VIE, String.valueOf(aDetRev.getDureeVie())); + theMap.put(R19Keys.UNITE_DUREE_VIE, aDetRev.getUniteDureeVie()); + theMap.put(R19Keys.DMD, aDetRev.getDMD()); + theMap.put(R19Keys.DMF, aDetRev.getDMF()); + return theMap; + } + + @Override + public Map visitComponent(final PartAeroRevision aPartAeroRev) { + Map theMap = getAbstractSnecmaObjectProperties(aPartAeroRev); + theMap.putAll(getAbstractPartProperties(aPartAeroRev)); + theMap.put(R19Keys.TYPE_REFERENCE, french(aPartAeroRev.getTypeAero1()) + " / " + french(aPartAeroRev.getTypeAero2()) + " / " + + french(aPartAeroRev.getTypeAero3())); + theMap.put(R19Keys.OBTURATION, french(aPartAeroRev.getObturation())); + theMap.put(R19Keys.SUIVI_DUREE_VIE, aPartAeroRev.getSuiviDureeVie()); + theMap.put(R19Keys.DUREE_VIE, String.valueOf(aPartAeroRev.getDureeVie())); + theMap.put(R19Keys.UNITE_DUREE_VIE, aPartAeroRev.getUniteDureeVie()); + theMap.put(R19Keys.DMD, aPartAeroRev.getDMD()); + theMap.put(R19Keys.DMF, aPartAeroRev.getDMF()); + return theMap; + } + + @Override + public Map visitComponent(final PartNoAeroRevision aPartNoAeroRev) { + Map theMap = getAbstractSnecmaObjectProperties(aPartNoAeroRev); + theMap.putAll(getAbstractPartProperties(aPartNoAeroRev)); + theMap.put(R19Keys.TYPE_REFERENCE, french(aPartNoAeroRev.getTypeNoAero())); + theMap.put(R19Keys.OBTURATION, SANS_OBJET); + theMap.put(R19Keys.SUIVI_DUREE_VIE, aPartNoAeroRev.getSuiviDureeVie()); + theMap.put(R19Keys.DUREE_VIE, String.valueOf(aPartNoAeroRev.getDureeVie())); + theMap.put(R19Keys.UNITE_DUREE_VIE, aPartNoAeroRev.getUniteDureeVie()); + theMap.put(R19Keys.DMD, aPartNoAeroRev.getDMD()); + theMap.put(R19Keys.DMF, aPartNoAeroRev.getDMF()); + return theMap; + } + + @Override + public Map visitComponent(final PartMatRevision aPartMatRev) { + Map theMap = getAbstractSnecmaObjectProperties(aPartMatRev); + theMap.putAll(getAbstractPartProperties(aPartMatRev)); + theMap.put(R19Keys.TYPE_REFERENCE, MATIERE); + theMap.put(R19Keys.CLASSEMENT, aPartMatRev.getClassementMat()); + theMap.put(R19Keys.SUIVI_UTILISATION, SANS_OBJET); + theMap.put(R19Keys.DOCUMENT_DE_CONTROLE, SANS_OBJET); + theMap.put(R19Keys.OBTURATION, SANS_OBJET); + theMap.put(R19Keys.SUIVI_DUREE_VIE, SANS_OBJET); + theMap.put(R19Keys.DUREE_VIE, SANS_OBJET); + theMap.put(R19Keys.UNITE_DUREE_VIE, SANS_OBJET); + theMap.put(R19Keys.DMD, aPartMatRev.getDMD()); + theMap.put(R19Keys.DMF, aPartMatRev.getDMF()); + return theMap; + } + + @Override + public Map visitComponent(final StandardRevision aStandardRev) { + Map theMap = getAbstractSnecmaObjectProperties(aStandardRev); + theMap.putAll(getAbstractPartProperties(aStandardRev)); + theMap.put(R19Keys.TYPE_REFERENCE, french(aStandardRev.getTypeStandard())); + theMap.put(R19Keys.OBTURATION, SANS_OBJET); + theMap.put(R19Keys.SUIVI_DUREE_VIE, aStandardRev.getSuiviDureeVie()); + theMap.put(R19Keys.DUREE_VIE,String.valueOf(aStandardRev.getDureeVie())); + theMap.put(R19Keys.UNITE_DUREE_VIE, aStandardRev.getUniteDureeVie()); + theMap.put(R19Keys.DMD, aStandardRev.getDMD()); + theMap.put(R19Keys.DMF, aStandardRev.getDMF()); + return theMap; + } + + @Override + public Map visitComponent(SuperModelRevision aSuperModelRev) { + return null; + } + + @Override + public Map visitComponent(final AlternateRevision aAlternateRev) { + Map theMap = getAbstractSnecmaObjectProperties(aAlternateRev); + theMap.putAll(getAbstractPartProperties(aAlternateRev)); + theMap.put(R19Keys.TYPE_REFERENCE, french(aAlternateRev.getTypeAlt1()) + " / " + french(aAlternateRev.getTypeAlt2())); + theMap.put(R19Keys.OBTURATION, french(aAlternateRev.getObturation())); + theMap.put(R19Keys.SUIVI_DUREE_VIE, aAlternateRev.getSuiviDureeVie()); + theMap.put(R19Keys.DUREE_VIE, String.valueOf(aAlternateRev.getDureeVie())); + theMap.put(R19Keys.UNITE_DUREE_VIE, aAlternateRev.getUniteDureeVie()); + theMap.put(R19Keys.DMD, aAlternateRev.getDMD()); + theMap.put(R19Keys.DMF, aAlternateRev.getDMF()); + return theMap; + } + + @Override + public Map visitComponent(final GenericRevision aGenericRev) { + Map theMap = getAbstractGenericRevisionProperties(aGenericRev); + return theMap; + } + + @Override + public Map visitComponent(final GenericAssembRevision aGenericAssembRev) { + Map theMap = getAbstractGenericRevisionProperties(aGenericAssembRev); + return theMap; + } + + private Map getAbstractPartProperties(final AbstractPart anAbstractPart) { + Map theMap = new EnumMap<>(R19Keys.class); + theMap.put(R19Keys.DESIGNATION_ENG, anAbstractPart.getDesignationEN()); + theMap.put(R19Keys.RESPONSABLE_CONCEPTION, anAbstractPart.getResponsableConception()); + theMap.put(R19Keys.PRODUIT, anAbstractPart.getTypeProduit()); + theMap.put(R19Keys.CLASSEMENT, anAbstractPart.getClassement()); + theMap.put(R19Keys.SUIVI_UTILISATION, french(anAbstractPart.getSuiviUtilisation())); + theMap.put(R19Keys.DOCUMENT_DE_CONTROLE, french(anAbstractPart.getDocumentControle())); + return theMap; + } + + private Map getAbstractSnecmaObjectProperties(final AbstractSnecmaObject anAbstractSnecmaObject) { + Map theMap = new EnumMap<>(R19Keys.class); + + String valueForKeyObject = removeSuffixeRevision(anAbstractSnecmaObject.getType()); + if (valueForKeyObject.equals(PART_NO_AERO)) { + valueForKeyObject = translateToPartNonAero(valueForKeyObject); + } + + theMap.put(R19Keys.OBJET, valueForKeyObject); + theMap.put(R19Keys.REFERENCE, anAbstractSnecmaObject.getItemId()); + theMap.put(R19Keys.REVISION_REFERENCE, anAbstractSnecmaObject.getRevisionId()); + theMap.put(R19Keys.NOM_REFERENCE, anAbstractSnecmaObject.getName()); + return theMap; + } + + private Map getAbstractGenericRevisionProperties(final AbstractGenericRevision anAbstractGenericRevision) { + Map theMap = new EnumMap<>(R19Keys.class); + + String valueForKeyObject = removeSuffixeRevision(anAbstractGenericRevision.getType()); + + theMap.put(R19Keys.OBJET, valueForKeyObject); + theMap.put(R19Keys.REFERENCE, anAbstractGenericRevision.getItemId()); + theMap.put(R19Keys.REVISION_REFERENCE, SANS_OBJET); + theMap.put(R19Keys.NOM_REFERENCE, anAbstractGenericRevision.getName()); + theMap.put(R19Keys.TYPE_REFERENCE, SANS_OBJET); + theMap.put(R19Keys.DESIGNATION_ENG, anAbstractGenericRevision.getDesignationEN()); + theMap.put(R19Keys.RESPONSABLE_CONCEPTION, anAbstractGenericRevision.getResponsableConception()); + theMap.put(R19Keys.PRODUIT, SANS_OBJET); + theMap.put(R19Keys.CLASSEMENT, SANS_OBJET); + theMap.put(R19Keys.SUIVI_UTILISATION, SANS_OBJET); + theMap.put(R19Keys.DOCUMENT_DE_CONTROLE, SANS_OBJET); + theMap.put(R19Keys.OBTURATION, SANS_OBJET); + theMap.put(R19Keys.SUIVI_DUREE_VIE, SANS_OBJET); + theMap.put(R19Keys.DUREE_VIE, SANS_OBJET); + theMap.put(R19Keys.UNITE_DUREE_VIE, SANS_OBJET); + theMap.put(R19Keys.DMD, SANS_OBJET); + theMap.put(R19Keys.DMF, SANS_OBJET); + return theMap; + } + + /* Remove suffix Revision from an Part ex: Part Revision become Part */ + private String removeSuffixeRevision(final String part) { + return part.replace(SUFFIXE_REVISION, EMPTY_STRING).trim(); + } + + private String translateToPartNonAero(final String partNoAero) { + return partNoAero.replace(partNoAero, TRANSLATE_TO_PARTNONAERO_FR); + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r20report/Classe.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r20report/Classe.java new file mode 100644 index 0000000..8ae11ca --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r20report/Classe.java @@ -0,0 +1,51 @@ +package com.capgemini.reports.definition.r20report; + +import lombok.extern.slf4j.Slf4j; + +/** + * Enumeration of the Classe field's possible values. + */ +@Slf4j +public enum Classe { + /** + * The value 1. + */ + CLASSE_1 { + @Override + public String toString() { + return "1"; + } + }, + /** + * The value 2. + */ + CLASSE_2 { + @Override + public String toString() { + return "2"; + } + }; + + /** + * Parses the input {@link String} and returns the corresponding enum instance.
    + * Default value: Classe 1 + * + * @param classeStr the input string + * @return the enum instance + */ + public static Classe parse(final String classeStr) { + try { + int intValue = Integer.parseInt(classeStr); + if (intValue == 1) { + return CLASSE_1; + } else if (intValue == 2) { + return CLASSE_2; + } else { + log.warn("Could not decide between Classe 1 and Classe 2 for input '{}', defaulting to Classe 1", classeStr); + } + } catch (NumberFormatException e) { + log.info("Bad user input: not a number", e); + } + return CLASSE_2; // Default value + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r20report/ConjointUnique.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r20report/ConjointUnique.java new file mode 100644 index 0000000..ac0090f --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r20report/ConjointUnique.java @@ -0,0 +1,51 @@ +package com.capgemini.reports.definition.r20report; + +import lombok.extern.slf4j.Slf4j; + +import java.util.Locale; + +/** + * Enumeration of the ConjointUnique's values. + */ +@Slf4j +public enum ConjointUnique { + /** + * The value Conjoint. + */ + CONJOINT { + @Override + public String toString() { + return "Conjoint"; + } + }, + /** + * The value Unique. + */ + UNIQUE { + @Override + public String toString() { + return "Unique"; + } + }; + + /** + * Parses an input {@link String} and returns the corresponding enum instance.
    + * Default value: Conjoint + * + * @param conjointUniqueStr the input string + * @return the instance + */ + public static ConjointUnique parse(final String conjointUniqueStr) { + String conjointUniqueLC = conjointUniqueStr.toLowerCase(Locale.FRENCH); + if ("conjoint".equals(conjointUniqueLC)) { + return CONJOINT; + } else { + if ("unique".equals(conjointUniqueLC)) { + return UNIQUE; + } else { + log.warn("Could not decide between Conjoint and Unique for input '{}', defaulting to Conjoint", conjointUniqueLC); + return CONJOINT; + } + } + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r20report/DataReportPreparatorR20.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r20report/DataReportPreparatorR20.java new file mode 100644 index 0000000..ddc7cfb --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r20report/DataReportPreparatorR20.java @@ -0,0 +1,439 @@ +package com.capgemini.reports.definition.r20report; + +import com.capgemini.framework.common.HashMapComparingStringIDs; +import com.capgemini.framework.common.HashMapComparingStringIDs.IdMaker; +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.EmptyNomenclatureException; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.exceptions.NoSuchBomViewException; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcBomObject; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcBomObjectFactory; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcRevisionRule; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcRevisionRuleProperties; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.product.TcProduct; +import com.capgemini.framework.teamcenter.object.runtime.TcBomWindow; +import com.capgemini.framework.teamcenter.object.runtime.TcBomWindowConfiguration; +import com.capgemini.framework.teamcenter.object.runtime.TcRevisionRulesConfiguration; +import com.capgemini.framework.teamcenter.queries.saved.modelobject.ItemRevisionQuery; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.bomlineholder.BOMLineHolderFactory; +import com.capgemini.reports.changeobjects.UnitRevision; +import com.capgemini.reports.changeobjects.change.TcChangeNoticeRevision; +import com.capgemini.reports.changeobjects.change.TcChangeRequestRevision; +import com.capgemini.reports.definition.r20report.ExecutionR20.ReportDataR20; +import com.capgemini.reports.definition.r20report.comparator.ChangeComparator; +import com.capgemini.reports.definition.r20report.comparator.GenericComparator; +import com.capgemini.reports.definition.r20report.printing.R20Printer; +import com.capgemini.reports.exceptions.MalformedNomenclatureException; +import com.capgemini.reports.exceptions.NotFoundException; +import com.capgemini.reports.execution.IDataReportPreparator; +import com.capgemini.reports.execution.strategies.IExecutionStrategy; +import com.capgemini.reports.filter.AllIsGoodFilter; +import com.capgemini.reports.printing.PrintParameters; +import com.capgemini.reports.reports.parameters.Generics; +import com.capgemini.reports.reports.parameters.ProductUnit; +import com.capgemini.reports.snecmaobjects.generic.AbstractGeneric; +import com.capgemini.reports.snecmaobjects.generic.Generic; +import com.capgemini.reports.snecmaobjects.generic.GenericAssemb; +import com.capgemini.reports.snecmaobjects.part.PartAeroRevision; +import com.capgemini.reports.snecmaobjects.product.ProductRevision; +import com.capgemini.reports.teamcenter.queries.saved.ChangeRequestQuery; +import com.capgemini.reports.teamcenter.resolution.structureservice.SingleStructureServiceCaller; +import com.capgemini.reports.teamcenter.resolution.structureservice.explorer.PartNumberFinder; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.*; + +import static com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes.GENERIC; + + +/** + * This class will allow to prepare data and findAll back data for making report R20. + */ +public class DataReportPreparatorR20 implements IDataReportPreparator { + private static final long serialVersionUID = -2545511620931881872L; + private static final Logger LOGGER = LoggerFactory.getLogger(DataReportPreparatorR20.class); + + + /** + * Comparator used by all the {@link Set}s of {@link TcChangeRequestRevision}, which only uses Item IDs to compare and no revision, so that two revisions of a same Item are recognised as equal. + */ + private static final Comparator CHANGE_COMPARATOR = new ChangeComparator(); + + /** + * Comparator used by all the Sets, which only uses Item IDs to compare, so that two revisions of a same Item are recognized as equal. + */ + private static final Comparator GENERIC_COMPARATOR = new GenericComparator(); + + /** + * Class of a {@link Set} of {@link TcChangeRequestRevision}. + */ + @SuppressWarnings({"unchecked", "rawtypes"}) + private static final Class> CLASS_LIST_CHANGE = (Class) Set.class; + + // Sets of generics + /** + * This IdMaker uses only the Generic's ID to make an identifier, not his Revision. + */ + private static final IdMaker GENERIC_ID_MAKER = new IdMaker() { + private static final long serialVersionUID = 5794106087600351583L; + + @Override + public String makeId(final AbstractGeneric gen) { + return gen.getItemId(); + } + }; + // Unit After + /** + * {@link SortedSet} of all the Generics. + */ + private final SortedSet totalGenerics = new TreeSet<>(GENERIC_COMPARATOR); + /** + * {@link Map} of all the Generics under the Unit After. Points to the (maybe empty) list of {@link TcChangeRequestRevision} that made a change to key generic. + */ + private final Map> totalGenericsAfter = + new HashMapComparingStringIDs<>(GENERIC_ID_MAKER, AbstractGeneric.class, CLASS_LIST_CHANGE); + /** + * {@link Set} of all the Generics under the Unit After, which do not have any changes from previous unit. + */ + private final Set totalGenericsAfterNoMod = new TreeSet<>(GENERIC_COMPARATOR); + /** + * {@link Map} of all the Generics under the Unit After, which undergo a rupture of interchangeability. Points to the non-empty list of {@link TcChangeRequestRevision} that made a change to key generic. + */ + private final Map> totalGenericsAfterWithRupture = + new HashMapComparingStringIDs<>(GENERIC_ID_MAKER, AbstractGeneric.class, CLASS_LIST_CHANGE); + // Unit Before + /** + * {@link Map} of all the Generics under the Unit After, which do not have a rupture of interchangeability.Points to the non-empty list of {@link TcChangeRequestRevision} that made a change to key generic. + */ + private final Map> totalGenericsAfterWithoutRupture = + new HashMapComparingStringIDs<>(GENERIC_ID_MAKER, AbstractGeneric.class, CLASS_LIST_CHANGE); + /** + * {@link Map} of all the Generics under the Unit Before. Points to the (maybe empty) list of {@link TcChangeRequestRevision} that made a change to key generic. + */ + private final Map> totalGenericsBefore = + new HashMapComparingStringIDs<>(GENERIC_ID_MAKER, AbstractGeneric.class, CLASS_LIST_CHANGE); + /** + * {@link Set} of all the Generics under the Unit Before, which do not have any changes made to them in the unit after. + */ + private final Set totalGenericsBeforeNoMod = new TreeSet<>(GENERIC_COMPARATOR); + /** + * {@link Map} of all the Generics mentioned by a Removed Modification (LMR). Points to the non-empty list of {@link TcChangeRequestRevision} Points to the non-empty list of {@link TcChangeRequestRevision} from the LMR that mentionned this key generic. + */ + private final Map> totalGenericsBeforeLMR = + new HashMapComparingStringIDs<>(GENERIC_ID_MAKER, AbstractGeneric.class, CLASS_LIST_CHANGE); + /** + * {@link Map} of all the Generics under the Unit Before, which undergo a removed modification with rupture. Points to the non-empty {@link Set} of {@link TcChangeRequestRevision} from the LMR that mentionned this key generic. + */ + private final Map> totalGenericsBeforeLMRWithRupture = + new HashMapComparingStringIDs<>(GENERIC_ID_MAKER, AbstractGeneric.class, CLASS_LIST_CHANGE); + + // Sets of Change Requests + /** + * {@link Map} of all the Generics under the Unit Before, which undergo a removed modification without rupture (from the LMR that mentionned this key generic). + */ + private final Map> totalGenericsBeforeLMRWithoutRupture = + new HashMapComparingStringIDs<>(GENERIC_ID_MAKER, AbstractGeneric.class, CLASS_LIST_CHANGE); + /** + * The List of Removed Modifications objects, LMR or not. + */ + private final Set totalChangeRequest = new TreeSet<>(CHANGE_COMPARATOR); + /** + * The List of Removed Modifications objects found in the unit After. + */ + private final Set totalChangeRequestNotLMR = new TreeSet<>(CHANGE_COMPARATOR); + /** + * The List of Removed Modifications objects that the user requested as LMR. + */ + private final Set totalChangeRequestLMR = new TreeSet<>(CHANGE_COMPARATOR); + + /** + * Retrieve the PartNumbers of the generics using a Nomenclature Explosion, and associate them in a map. + */ + private static Map retrieveGenericsAndPartNumbers(final TcSession session, + ExecutionR20 report, final Set setOfGenerics, final ProductUnit productUnit) throws KurtException { + + Map genericsAndPartNumber = + new HashMapComparingStringIDs<>(GENERIC_ID_MAKER, AbstractGeneric.class, PartAeroRevision.class); + + for (AbstractGeneric generic : setOfGenerics) { + // Setup parameters + Generics generics; + if (generic instanceof Generic) { + generics = new Generics(productUnit, generic.getItemId(), null); + } else if (generic instanceof GenericAssemb) { + generics = new Generics(productUnit, null, generic.getItemId()); + } else { + LOGGER.warn("Object should be a Generic but is a: {}", generic.getType()); + continue; + } + + TcBomObject topLineObject = new TcBomObjectFactory(session, generics.getItem(session)).create(); + TcProduct productObject = new TcProduct(session, productUnit.getProduct(session)); + int unit = productUnit.getUnit(); + + TcRevisionRuleProperties revisionRuleProperties = new TcRevisionRuleProperties(productObject, unit); + + TcRevisionRule revisionRule = session.findRevRule(report.getRevisionRule()); + TcRevisionRulesConfiguration revRulesConfiguration = new TcRevisionRulesConfiguration(revisionRule, revisionRuleProperties); + + // Perform the job + SingleStructureServiceCaller theStructCaller = new SingleStructureServiceCaller(session); + try (TcBomWindow bomWindow = session.createBomWindow(new TcBomWindowConfiguration(topLineObject, revRulesConfiguration))) { + BOMLineHolder unbuiltPartAeroHolder = theStructCaller.resolve(bomWindow.topLine(), new PartNumberFinder()); + if (unbuiltPartAeroHolder == null) { + LOGGER.warn("Nomenclature explosion failed to obtain a Part Number for Generic={}, product={} and Unit={}", generic.getItemId(), + productUnit.getProductID(), productUnit.getUnit()); + continue; + } + + // Build Part number + BOMLineHolder partAeroHolder = BOMLineHolderFactory.buildTopBom(session, unbuiltPartAeroHolder, new AllIsGoodFilter()); + unbuiltPartAeroHolder.freeze(); + + // Put the PartNumber in the Map + genericsAndPartNumber.put(generic, (PartAeroRevision) partAeroHolder.getSnecmaObject()); + } catch (EmptyNomenclatureException e) { + String msg = String.format("Nomenclature explosion failed to obtain the GenericBom for Generic=%s, product=%s and Unit=%d", + generic.getItemId(), productUnit.getProductID(), productUnit.getUnit()); + LOGGER.error(msg, e); + } catch (NoSuchBomViewException e) { + LOGGER.error("Unable to find the GenericBom of the Generic: " + generic.getItemId(), e); + } catch (MalformedNomenclatureException e) { + LOGGER.error("Unable to find the Part Number of the Generic: " + generic.getItemId(), e); + } + } + return genericsAndPartNumber; + } + + @Override + public String print(TcSession session, ExecutionR20 execution, IExecutionStrategy executionStrategy) throws KurtException { + PrintParameters printParameters = prepareData(session, execution); + executionStrategy.print(printParameters, execution); + return executionStrategy.getReportFileName(execution) + printParameters.getOuputFileExtension(); + } + + private PrintParameters prepareData(final TcSession session, final ExecutionR20 report) throws KurtException { + LOGGER.debug("PrepareData started on: {}", report.getReportIdentifier().getReportTitle()); + + session.setObjectPropPolicy(report.getFullPolicy()); + + // Config ProduitUnits + report.getProductUnitBefore().parseUserUnit(); + report.getProductUnitAfter().parseUserUnit(); + + // Retrieve the Items of the provided LMR + retrieveLMR(session, report); + + // Build ProductRevision and UnitRevision before and after + ProductRevision product = retrieveProductRevisionBefore(session, report); + UnitRevision unitBefore = retrieveUnitBefore(report, product); + UnitRevision unitAfter = retrieveUnitAfter(report, product); + ReportDataR20 data = new ReportDataR20(product, unitBefore, unitAfter, report.getMatriculeMoteur(), report.getClasse(), + report.getMajorMinor(), report.getConjointUnique()); + + // Build ChangeRequests and generics + retrieveChangeRequests(unitAfter); + retrieveAllGenerics(unitBefore, unitAfter); + + // Put all retrieved data in the ReportData object + data.setGenericsAndPartNumbersAfter(retrieveGenericsAndPartNumbers(session, report, totalGenericsAfter.keySet(), report.getProductUnitAfter())); + data.setGenericsAndPartNumbersBefore(retrieveGenericsAndPartNumbers(session, report, totalGenericsBefore.keySet(), report.getProductUnitBefore())); + data.setTotalChangeRequest(totalChangeRequest); + data.setTotalChangeRequestLMR(totalChangeRequestLMR); + data.setTotalChangeRequestNotLMR(totalChangeRequestNotLMR); + data.setTotalGenerics(totalGenerics); + data.setTotalGenericsAfterWithoutRupture(totalGenericsAfterWithoutRupture); + data.setTotalGenericsAfterWithRupture(totalGenericsAfterWithRupture); + data.setTotalGenericsBeforeLMRWithoutRupture(totalGenericsBeforeLMRWithoutRupture); + data.setTotalGenericsBeforeLMRWithRupture(totalGenericsBeforeLMRWithRupture); + + R20Printer printer = new R20Printer(); + PrintParameters printParameters = printer.makeMasterTemplate(report, data); + printer.constructDataMaps(session, printParameters, data); + + LOGGER.debug("PrepareData ended on: {}", report.getReportIdentifier().getReportTitle()); + + return printParameters; + } + + UnitRevision retrieveUnitAfter(final ExecutionR20 report, final ProductRevision product) { + return UnitRevision.chooseRevisionOfUnitFromRange(report.getProductUnitAfter().getUnitStr(), product.getUnits(), + ExecutionR20.R20_STATUS_AFTER); + } + + private UnitRevision retrieveUnitBefore(final ExecutionR20 report, final ProductRevision product) { + return UnitRevision.chooseRevisionOfUnitFromRange(report.getProductUnitBefore().getUnitStr(), product.getUnits(), + ExecutionR20.R20_STATUS_BEFORE); + } + + /** + * This method uses the lmrString list of Modification IDs to produce a {@link List} of {@link TcChangeRequestRevision}.
    + * these {@link TcChangeRequestRevision} are built using TC objects queried from the input IDs. + * + * @param session the session to connect to TC + * @param report will provide the informations of the report which is executing + */ + private void retrieveLMR(final TcSession session, final ExecutionR20 report) { + for (String changeID : report.getLmrList()) { + List list = new ChangeRequestQuery(session).searchID(changeID).findAll(); + for (ItemRevision itemRev : list) { + totalChangeRequestLMR.add(new TcChangeRequestRevision(session, itemRev)); + } + } + } + + /** + * Retrieve the ProductRevision for the R20 report. + * + * @param session an active teamcenter session + * @param report will provide the informations of the report which is executing + * @return the built Product Revision + * @throws NotFoundException if no revisions of the product Before could be found + */ + ProductRevision retrieveProductRevisionBefore(final TcSession session, final ExecutionR20 report) throws NotFoundException { + ItemRevisionQuery queryProductBefore = new ItemRevisionQuery(session); + queryProductBefore.searchID(report.getProductUnitBefore().getProductID()); + List revisionsProductBefore = queryProductBefore.findAll(); + if (revisionsProductBefore.isEmpty()) { + throw new NotFoundException("Could not find the requested product before"); + } + return new ProductRevision(session, revisionsProductBefore.get(0)); + } + + private void retrieveChangeRequests(final UnitRevision unitAfter) { + for (TcChangeRequestRevision change : unitAfter.getChangeRequestsList()) { + if (change.isCadOrDCadOrMace()) { // filter: only CAD , DCAD or MACE + totalChangeRequestNotLMR.add(change); + } + } + totalChangeRequest.addAll(totalChangeRequestLMR); + totalChangeRequest.addAll(totalChangeRequestNotLMR); + } + + /** + * Retrieve the list of all the Generics in the pseudo folders of each ChangeNotice of each Removed Modification. + * + * @param unitBefore the unit before + * @param unitAfter the unit after + */ + private void retrieveAllGenerics(final UnitRevision unitBefore, final UnitRevision unitAfter) { + // FIRST GENERICS BEFORE ********************************************************************************** + // Gather all generics before, make them point to an empty list of mods, which will be enriched later as needed with LMR + for (AbstractGeneric generic : unitBefore.getGenerics()) { + if (GENERIC.equals(generic.getType())) { // Technical view only + totalGenericsBefore.put(generic, new TreeSet<>(CHANGE_COMPARATOR)); + } + } + totalGenericsBeforeNoMod.addAll(totalGenericsBefore.keySet()); // Preventively add them all the generics here, when we see they undergo a change, remove them from here + + // Retrieve the list of all the generics in the pseudo folders of each ChangeNotices of the Unit Before. + retrieveGenericsOfUnitBefore(); + + // NOW GENERICS AFTER ********************************************************************************** + + // Gather all generics after, make them point to an empty list of mods, which will be enriched later as needed with some Changes after + for (AbstractGeneric generic : unitAfter.getGenerics()) { + if (GENERIC.equals(generic.getType())) { // Technical view only + totalGenericsAfter.put(generic, new TreeSet<>(CHANGE_COMPARATOR)); + } + } + totalGenericsAfterNoMod.addAll(totalGenericsAfter.keySet()); // Preventively add them all, when we see they undergo a change, remove them from here + + // Retrieve the list of all the generics in the pseudo folders of each ChangeNotices of the Unit After. + retrieveGenericsOfUnitAfter(); + + // Gather all generics ever encountered *********************************************************** + totalGenerics.addAll(totalGenericsBefore.keySet()); + totalGenerics.addAll(totalGenericsAfter.keySet()); + } + + private void retrieveGenericsOfUnitBefore() { + for (TcChangeRequestRevision changeRequest : totalChangeRequestLMR) { + if (changeRequest.isCadOrDCadOrMace()) { + for (TcChangeNoticeRevision changeNotice : changeRequest.getChangeNoticesList()) { + if (changeNotice.isEtude()) { // Only keep change Notice "ETUDE" ! + extractGenericsFromChangeNotice(changeRequest, changeNotice); + } + } + } + } + totalGenericsBeforeLMR.putAll(totalGenericsBeforeLMRWithRupture); + totalGenericsBeforeLMR.putAll(totalGenericsBeforeLMRWithoutRupture); + } + + /** + * Retrieve the generic for the report R20. + */ + private void retrieveGenericsOfUnitAfter() { + for (TcChangeRequestRevision changeRequest : totalChangeRequestNotLMR) { + for (TcChangeNoticeRevision changeNotice : changeRequest.getChangeNoticesList()) { + for (AbstractGeneric genericWithRupture : changeNotice.getListOfGenericRevWithRupture()) { + if (GENERIC.equals(genericWithRupture.getType())) { // Technical view only + Set setOfModWithRupture = totalGenericsAfterWithRupture.get(genericWithRupture); + if (setOfModWithRupture == null) { + setOfModWithRupture = new TreeSet<>(CHANGE_COMPARATOR); + totalGenericsAfterWithRupture.put(genericWithRupture, setOfModWithRupture); + } + setOfModWithRupture.add(changeRequest); + totalGenericsAfterNoMod.remove(genericWithRupture); + } + } + for (AbstractGeneric genericWithoutRupture : changeNotice.getListOfGenericRevWithoutRupture()) { + if (GENERIC.equals(genericWithoutRupture.getType())) { // Technical view only + Set setOfModWithoutRupture = totalGenericsAfterWithoutRupture.get(genericWithoutRupture); + if (setOfModWithoutRupture == null) { + setOfModWithoutRupture = new TreeSet<>(CHANGE_COMPARATOR); + totalGenericsAfterWithoutRupture.put(genericWithoutRupture, setOfModWithoutRupture); + } + setOfModWithoutRupture.add(changeRequest); + totalGenericsAfterNoMod.remove(genericWithoutRupture); + } + } + } + } + } + + /** + * Adds the provided Change Notice's Generics with and withour rupture to the list of Generics LMR (IF they also are mentionned in the unit Before).
    + * By the end og this method: + *
      + *
    • {@code totalGenericsBeforeLMRWithRupture} will contain, for each GenericBefore concerned with this LMR, a link to the CR
    • + *
    • + *
    • + *
    • + *
    + */ + private void extractGenericsFromChangeNotice(final TcChangeRequestRevision changeRequest, final TcChangeNoticeRevision changeNotice) { + + for (AbstractGeneric genericWithOrWithoutRupture : changeNotice.getListOfGenericRevWithOrWithoutRupture()) { + + // A change notice 'Etude' may still contain Generic Assembs, we don't want them + // also, a Generic contained in an LMR than has nothing to do with the Unit Before, must be ignored + if (GENERIC.equals(genericWithOrWithoutRupture.getType()) && totalGenericsBefore.containsKey(genericWithOrWithoutRupture)) { + Set setOfModWithRupture = totalGenericsBeforeLMRWithRupture.get(genericWithOrWithoutRupture); + if (setOfModWithRupture == null) { + setOfModWithRupture = new TreeSet<>(CHANGE_COMPARATOR); + totalGenericsBeforeLMRWithRupture.put(genericWithOrWithoutRupture, setOfModWithRupture); + } + setOfModWithRupture.add(changeRequest); + totalGenericsBeforeNoMod.remove(genericWithOrWithoutRupture); + } + } + for (AbstractGeneric genericWithoutRupture : changeNotice.getListOfGenericRevWithoutRupture()) { + // A change notice 'Etude' may still contain Generic Assembs, we don't want them + // also, a Generic contained in an LMR than has nothing to do with the Unit Before, must be ignored + if (GENERIC.equals(genericWithoutRupture.getType()) && totalGenericsBefore.containsKey(genericWithoutRupture)) { + Set setOfModWithoutRupture = totalGenericsBeforeLMRWithoutRupture.get(genericWithoutRupture); + if (setOfModWithoutRupture == null) { + setOfModWithoutRupture = new TreeSet<>(CHANGE_COMPARATOR); + totalGenericsBeforeLMRWithRupture.put(genericWithoutRupture, setOfModWithoutRupture); + } + setOfModWithoutRupture.add(changeRequest); + totalGenericsBeforeNoMod.remove(genericWithoutRupture); + } + } + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r20report/ExecutionR20.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r20report/ExecutionR20.java new file mode 100644 index 0000000..be6397e --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r20report/ExecutionR20.java @@ -0,0 +1,261 @@ +package com.capgemini.reports.definition.r20report; + +import com.capgemini.framework.common.SettingsHelper; +import com.capgemini.framework.teamcenter.object.pom.status.StatusEnum; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.reports.ReportEnum; +import com.capgemini.reports.ReportLaunchTypeEnum; +import com.capgemini.reports.builder.R20Builder; +import com.capgemini.reports.builder.ReportBuilder; +import com.capgemini.reports.changeobjects.UnitRevision; +import com.capgemini.reports.changeobjects.change.TcChangeRequestRevision; +import com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum; +import com.capgemini.reports.database.manager.MngCriteriaVal.CriteriaValue; +import com.capgemini.reports.definition.r20report.ExecutionR20.ReportDataR20; +import com.capgemini.reports.definition.r20report.checker.R20LMRChecker; +import com.capgemini.reports.definition.r20report.checker.R20UnitRevisionChecker; +import com.capgemini.reports.execution.AbstractExecutionReport; +import com.capgemini.reports.execution.IDataReportPreparator; +import com.capgemini.reports.printing.Printer.PrintFormat; +import com.capgemini.reports.reports.parameters.IChecker; +import com.capgemini.reports.reports.parameters.ProductUnit; +import com.capgemini.reports.reports.parameters.checker.ProductChecker; +import com.capgemini.reports.snecmaobjects.generic.AbstractGeneric; +import com.capgemini.reports.snecmaobjects.part.PartAeroRevision; +import com.capgemini.reports.snecmaobjects.product.ProductRevision; +import lombok.AccessLevel; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Executes a R20 report. + */ +@Getter +@Setter(value = AccessLevel.PROTECTED) +@EqualsAndHashCode(callSuper = true) +public class ExecutionR20 extends AbstractExecutionReport { + + /** + * The authorized status for unit before. + */ + public static final StatusEnum[] R20_STATUS_BEFORE = + {StatusEnum.OPENING_IN_PROCESS, StatusEnum.OPEN, StatusEnum.J3A, StatusEnum.J3B, StatusEnum.FROZEN_IN_PROCESS, StatusEnum.FROZEN}; + /** + * The authorized status for units after. + */ + public static final StatusEnum[] R20_STATUS_AFTER = + {StatusEnum.OPENING_IN_PROCESS, StatusEnum.OPEN, StatusEnum.J3A, StatusEnum.J3B, StatusEnum.FROZEN_IN_PROCESS}; + // Revision rule parameter + static final String REPORT_REVISION_RULE = + SettingsHelper.getPropertyWithDefaultValue("common.bom.revisionRule.REPORT_R20", DEFAULT_REVISION_RULE); + private static final long serialVersionUID = -1700414458622831247L; + // Policies + private static final PolicyLocation R20_POLICY_XML_LIGHT = + PolicyLocation.make("R20_policy_light", "/xml/policies/r20report/R20_policy_light.xml"); + private static final PolicyLocation R20_POLICY_XML_FULL = PolicyLocation.make("R20_policy_full", "/xml/policies/r20report/R20_policy_full.xml"); + // Priority parameter + private static final int REPORT_PRIORITY = SettingsHelper.getPriority(ReportEnum.REPORT_R20); + // Launch type parameter + private static final ReportLaunchTypeEnum REPORT_LAUNCH_TYPE = ReportLaunchTypeEnum.getReportLaunchType("common.launch.launchType.REPORT_R20"); + // Report parameters + private final ProductUnit productUnitBefore; + private final ProductUnit productUnitAfter; + private final String matriculeMoteur; + private final Classe classe; + private final MajorMinor majorMinor; + private final ConjointUnique conjointUnique; + + /** + * The List of Removed Modifications IDs. + */ + private final List lmrList; + + + /** + * Constructor of an Execution for R20. + * + * @param aProductUnitBefore {@link ProductUnit} before + * @param aProductUnitAfter {@link ProductUnit} after + * @param aMatricule String + * @param lmr {@link List} of String + * @param aClasse enum {@link Classe} + * @param aMajorMinor enum {@link MajorMinor} + * @param aConjointUnique enum {@link ConjointUnique} + */ + public ExecutionR20(final ProductUnit aProductUnitBefore, final ProductUnit aProductUnitAfter, final String aMatricule, final List lmr, + final Classe aClasse, final MajorMinor aMajorMinor, final ConjointUnique aConjointUnique) { + super(REPORT_PRIORITY, REPORT_REVISION_RULE, REPORT_LAUNCH_TYPE); + productUnitBefore = aProductUnitBefore; + productUnitAfter = aProductUnitAfter; + matriculeMoteur = aMatricule; + lmrList = lmr; + classe = aClasse; + majorMinor = aMajorMinor; + conjointUnique = aConjointUnique; + } + + @Override + public List getLaunchData() { + List theCriteria = new ArrayList<>(); + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.UNIT_BEFORE, productUnitBefore.getUnitStr())); + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.PRODUCT_BEFORE, productUnitBefore.getProductID())); + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.UNIT_AFTER, productUnitAfter.getUnitStr())); + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.PRODUCT_AFTER, productUnitAfter.getProductID())); + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.MATRICULE, matriculeMoteur)); + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.LMR, R20Builder.packLMR(lmrList))); + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.CLASSE, classe.toString())); + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.MAJOR_MINOR, majorMinor.toString())); + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.CONJOINT_UNIQUE, conjointUnique.toString())); + return theCriteria; + } + + @Override + public String getSpecifiedFileName() { + return "R20_" + productUnitAfter.getProductID() + "_" + productUnitAfter.getUnitStr() + "_" + productUnitBefore.getUnitStr(); + } + + @Override + public PrintFormat getPrintingFormat() { + return PrintFormat.PDF; + } + + @Override + public ReportEnum getReportIdentifier() { + return ReportEnum.REPORT_R20; + } + + @Override + public List getQuickChecks() { + List quickChecks = new ArrayList<>(); + ProductChecker productChecker = new ProductChecker(productUnitAfter.getProductID()); + quickChecks.add(productChecker); + quickChecks.add(new R20UnitRevisionChecker(productUnitAfter, true)); + quickChecks.add(new R20UnitRevisionChecker(productUnitBefore, false)); + if (!lmrList.isEmpty()) { + quickChecks.add(new R20LMRChecker(lmrList, productUnitBefore, productChecker)); + } + return quickChecks; + } + + @Override + public List getLongChecks() { + return new ArrayList<>(); + } + + @Override + public PolicyLocation getPropertyPolicyForLongChecks() { + return R20_POLICY_XML_LIGHT; + } + + @Override + public PolicyLocation getFullPolicy() { + return R20_POLICY_XML_FULL; + } + + @Override + public String getTemplateLocation() { + return "/Jasper/template/report_r20/report_r20_master.jrxml"; + } + + @Override + public IDataReportPreparator getDataPreparator() { + return new DataReportPreparatorR20(); + } + + @Override + public AbstractExecutionReport cloneTemplateToExecution() { + return new ExecutionR20(productUnitBefore, productUnitAfter, matriculeMoteur, lmrList, classe, majorMinor, conjointUnique); + } + + @Override + public Class getReportBuilderClass() { + return R20Builder.class; + } + + /** + * POJO container for all data used in R20 report. + */ + @Getter + @Setter(value = AccessLevel.PROTECTED) + public static class ReportDataR20 { + // From TC datas + private final ProductRevision product; + private final UnitRevision unitBefore; + private final UnitRevision unitAfter; + // Report parameters + private final String matriculeMoteur; + private final Classe classe; + private final MajorMinor majorMinor; + private final ConjointUnique conjointUnique; + + /** + * The List of Removed Modifications objects found in the unit After. + */ + private Set totalChangeRequestNotLMR; + /** + * The List of Removed Modifications objects that the user requested as LMR. + */ + private Set totalChangeRequestLMR; + /** + * {@link Map} of all the Generics under the Unit Before, which undergo a removed modification with rupture. Points to the non-empty {@link Set} of {@link TcChangeRequestRevision} from the LMR that mentionned this key generic. + */ + private Map> totalGenericsBeforeLMRWithRupture; + /** + * {@link Map} of all the Generics under the Unit After, which do not have a rupture of interchangeability.Points to the non-empty list of {@link TcChangeRequestRevision} that made a change to key generic. + */ + private Map> totalGenericsBeforeLMRWithoutRupture; + /** + * {@link Map} of all the Generics under the Unit After, which undergo a rupture of interchangeability. Points to the non-empty list of {@link TcChangeRequestRevision} that made a change to key generic. + */ + private Map> totalGenericsAfterWithRupture; + /** + * {@link Map} of all the Generics under the Unit After, which do not have a rupture of interchangeability.Points to the non-empty list of {@link TcChangeRequestRevision} that made a change to key generic. + */ + private Map> totalGenericsAfterWithoutRupture; + /** + * The List of Removed Modifications objects, LMR or not. + */ + private Set totalChangeRequest; + /** + * Maps each Generic with its PartAeroRevision, using the Unit Before. + */ + private Map genericsAndPartNumbersBefore; + /** + * Maps each Generic with its PartAeroRevision, using the Unit After. + */ + private Map genericsAndPartNumbersAfter; + /** + * {@link Set} of all the Generics. + */ + private Set totalGenerics; + + /** + * Simple constructor. + * + * @param product the product + * @param unitBefore the unit before + * @param unitAfter the unit after + * @param matriculeMoteur the 'matricule moteur' parameter + * @param classe the 'classe' parameter + * @param majorMinor the 'Major / minor' parameter + * @param conjointUnique the 'Conjoint/unique' parameter + */ + ReportDataR20(final ProductRevision product, final UnitRevision unitBefore, final UnitRevision unitAfter, final String matriculeMoteur, + final Classe classe, final MajorMinor majorMinor, final ConjointUnique conjointUnique) { + super(); + this.product = product; + this.unitBefore = unitBefore; + this.unitAfter = unitAfter; + this.matriculeMoteur = matriculeMoteur; + this.classe = classe; + this.majorMinor = majorMinor; + this.conjointUnique = conjointUnique; + } + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r20report/MajorMinor.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r20report/MajorMinor.java new file mode 100644 index 0000000..5018a49 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r20report/MajorMinor.java @@ -0,0 +1,51 @@ +package com.capgemini.reports.definition.r20report; + +import lombok.extern.slf4j.Slf4j; + +import java.util.Locale; + +/** + * Enumeration of the MajorMinor field's possible values. + */ +@Slf4j +public enum MajorMinor { + /** + * The value Major. + */ + MAJOR { + @Override + public String toString() { + return "Majeur"; + } + }, + /** + * The value Minor. + */ + MINOR { + @Override + public String toString() { + return "Mineur"; + } + }; + + /** + * Parses an input {@link String} and returns the corresponding enum instance.
    + * Default value: Major + * + * @param majorMinorStr the input string + * @return the instance + */ + public static MajorMinor parse(final String majorMinorStr) { + String majorMinorLC = majorMinorStr.toLowerCase(Locale.FRENCH); + if ("majeur".equals(majorMinorLC)) { + return MAJOR; + } else { + if ("mineur".equals(majorMinorLC)) { + return MINOR; + } else { + log.warn("Could not decide between major and Minor for input '{}', defaulting to Major", majorMinorLC); + return MAJOR; + } + } + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r20report/checker/R20LMRChecker.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r20report/checker/R20LMRChecker.java new file mode 100644 index 0000000..aed96d4 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r20report/checker/R20LMRChecker.java @@ -0,0 +1,233 @@ +package com.capgemini.reports.definition.r20report.checker; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.object.pom.status.StatusEnum; +import com.capgemini.framework.teamcenter.object.pom.status.StatusEnum.AbstractStatusFilter; +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.capgemini.reports.changeobjects.UnitRevision; +import com.capgemini.reports.definition.r20report.ExecutionR20; +import com.capgemini.reports.exceptions.InvalidUserInputException; +import com.capgemini.reports.exceptions.UserInputErrorEnum; +import com.capgemini.reports.releasestatus.RevisionStatusAndDate; +import com.capgemini.reports.reports.parameters.IChecker; +import com.capgemini.reports.reports.parameters.ProductUnit; +import com.capgemini.reports.reports.parameters.checker.ProductChecker; +import com.capgemini.reports.teamcenter.ObjectInfoHelper; +import com.capgemini.reports.teamcenter.queries.saved.ChangeRequestQuery; +import com.capgemini.reports.teamcenter.queries.saved.UnitFromChangeRequestQuery; +import com.google.common.base.Optional; +import com.teamcenter.soa.client.model.ModelObject; +import com.teamcenter.soa.client.model.strong.Form; +import com.teamcenter.soa.client.model.strong.Item; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Pattern; + +import static com.capgemini.framework.teamcenter.TeamcenterObjectProperties.REVISION_LIST; +import static com.capgemini.framework.teamcenter.object.SnecmaObjectProperties.*; + +/** + * This class checks if a given "Liste de Modifications Retirées" is valid for a R20 report. + */ +@Getter +@Slf4j +public class R20LMRChecker implements IChecker { + + private static final Pattern YES_CHECKER = Pattern.compile(".*(Oui|Yes).*"); + + private static final String MACE = SnecmaObjectTypes.PV4_MACE_REVISION; + private static final String DCAD = SnecmaObjectTypes.PV4_DCAD_REVISION; + private static final String CAD_ACR = SnecmaObjectTypes.PV4_CAD_ACR_REVISION; + + private final List lmrList; + private final String productId; + private final ProductChecker productChecker; // Will provide the pruduct Item + private final String unitBeforeEffectivity; + + /** + * Simple constructor. + * + * @param lmrList List the list of modifications that need to be checked. + * @param productUnitBefore ProductUnit + * @param productChecker this productChecker is supposed to have been executed prior to this check, so that its produc titem will be available for this test + */ + public R20LMRChecker(final List lmrList, final ProductUnit productUnitBefore, final ProductChecker productChecker) { + this.lmrList = lmrList; + this.productId = productUnitBefore.getProductID(); + this.unitBeforeEffectivity = productUnitBefore.getUnitStr(); + this.productChecker = productChecker; + } + + private static boolean isUnitExceptionnel(final ItemRevision unitBefore) { + Form form = unitBefore.get_item_master_tag(); + if (form != null) { + String result = form.getPropertyObject(PV_UNIT_EXCEPTIONNEL).getStringValue(); + return YES_CHECKER.matcher(result).matches(); + } else { + return false; + } + } + + @Override + public void check(final TcSession session) throws InvalidUserInputException { + // Retrieve the list of Units for the used Product + List unitListOfProduct = retrieveListOfUnitsOfProduct(session); + ItemRevision unitBefore = choseRevision(session, unitListOfProduct); + List totalChangeRequestLMR = new ArrayList<>(); + for (String changeID : lmrList) { + // retrieve the ChangeRequest + ItemRevision changeRequestLmr = retrieveChangeRequest(session, changeID); + totalChangeRequestLMR.add(changeRequestLmr); + + // Test unit exceptionnel + boolean exceptionnel = isUnitExceptionnel(unitBefore); + if (exceptionnel) { + List listOfChangeOfUnitBefore = retrieveChangeRequestsOfUnit(session, unitBefore); + + int occurrencesInUnitBefore = occurrencesInListOfChangeOfUnit(changeID, listOfChangeOfUnitBefore); + // No change found in the Unit Before + if (occurrencesInUnitBefore == 0) { + throw new InvalidUserInputException(UserInputErrorEnum.REMOVED_CHANGE_REQUEST_IS_NOT_COMPATIBLE_WITH_BEFORE_EFFECTIVITY, + changeID); + } + // More than one revision found in the Unit Before + else if (occurrencesInUnitBefore > 1) { + throw new InvalidUserInputException( + UserInputErrorEnum.SEVERAL_REVISIONS_OF_RETRIEVED_CHANGE_REQUEST_ARE_COMPATIBLE_WITH_BEFORE_EFFECTIVITY, changeID); + } + } else { + // Retrieve the associated Units thanks to the pseudofolders + List listUnitRevFromCR = new UnitFromChangeRequestQuery(session).searchID(changeID).findAll(); + if (listUnitRevFromCR.isEmpty()) { + throw new InvalidUserInputException(UserInputErrorEnum.REMOVED_CHANGE_REQUEST_IS_NOT_COMPATIBLE_WITH_BEFORE_EFFECTIVITY, + changeID); + } + + // Find an appropriate Unit (contained in the list of units of the Product) + ItemRevision selectedUnit = findAppropriateUnitInProductListOfUnits(session, unitListOfProduct, listUnitRevFromCR); + if (selectedUnit == null) { + throw new InvalidUserInputException(UserInputErrorEnum.REMOVED_CHANGE_REQUEST_IS_NOT_COMPATIBLE_WITH_BEFORE_EFFECTIVITY, + changeID); + } + + List listOfChangeOfSelectedUnit = retrieveChangeRequestsOfUnit(session, selectedUnit); + int occurrencesInUnitBefore = occurrencesInListOfChangeOfUnit(changeID, listOfChangeOfSelectedUnit); + if (occurrencesInUnitBefore > 1) { + throw new InvalidUserInputException( + UserInputErrorEnum.SEVERAL_REVISIONS_OF_RETRIEVED_CHANGE_REQUEST_ARE_COMPATIBLE_WITH_BEFORE_EFFECTIVITY, changeID); + } + } + } + } + + private ItemRevision findAppropriateUnitInProductListOfUnits(final TcSession session, final List unitListOfProduct, final List listUnitRevFromCR) { + ItemRevision selectedUnit = null; + String selectedRange = ""; + for (ItemRevision unit : listUnitRevFromCR) { + String unitRange = UnitRevision.getRangeOfItemRevision(session, unit); + if (unitRange == null) { + continue; + } + if (unitListOfProduct.contains(unit) && Integer.parseInt(unitRange) <= Integer.parseInt(unitBeforeEffectivity)) { + if (selectedUnit == null) { + selectedUnit = unit; + selectedRange = unitRange; + } + // Choose the revision + if (Integer.parseInt(selectedRange) < Integer.parseInt(unitRange)) { + selectedUnit = unit; + selectedRange = unitRange; + } + } + } + return selectedUnit; + } + + private int occurrencesInListOfChangeOfUnit(final String changeID, final List listOfChangeOfUnitBefore) { + int indicatorIsinUnit = 0; + for (ItemRevision changeOfUnitBefore : listOfChangeOfUnitBefore) { + if (changeID.equals(changeOfUnitBefore.get_item_id())) { + indicatorIsinUnit++; + } + } + return indicatorIsinUnit; + } + + private ItemRevision retrieveChangeRequest(final TcSession session, final String changeID) throws InvalidUserInputException { + List listChangeRev = new ChangeRequestQuery(session).searchID(changeID).findAll(); + if (listChangeRev.isEmpty()) { + throw new InvalidUserInputException(UserInputErrorEnum.UNKNOWN_CHANGE_REQUEST, changeID); + } + // ChangeRequest only have one revision + ItemRevision theChange = listChangeRev.get(0); + if (SnecmaObjectTypes.PV4_CR_DEPREC_REVISION.equals(theChange.getTypeObject().getName())) { + throw new InvalidUserInputException(UserInputErrorEnum.REMOVED_CHANGE_REQUEST_IS_DEPRECATED, changeID); + } + return theChange; + } + + private List retrieveChangeRequestsOfUnit(final TcSession session, final ItemRevision referenceUnit) { + List changeRequestOfUnitBefore = new ArrayList<>(); + session.loadProperties(referenceUnit, PV_CHANGE_LIST); + ModelObject[] changes = referenceUnit.getPropertyObject(PV_CHANGE_LIST).getModelObjectArrayValue(); + session.loadProperties(changes); + for (ModelObject currentChange : changes) { + if (currentChange == null) { + log.warn("A Null ChangeRequest was obtained from the pseudo-folder 'PV_change_list' of a UnitRevision."); + continue; + } + ItemRevision currentItemRev = (ItemRevision) currentChange; + String objectTypeStr = currentItemRev.getTypeObject().getName(); + if (CAD_ACR.equals(objectTypeStr) || DCAD.equals(objectTypeStr) || MACE.equals(objectTypeStr)) { + changeRequestOfUnitBefore.add(currentItemRev); + } + } + return changeRequestOfUnitBefore; + } + + private List retrieveListOfUnitsOfProduct(final TcSession session) { + List unitListOfProduct = new ArrayList<>(); + Item product = productChecker.getProduct(); + session.loadProperties(product, REVISION_LIST); + ModelObject[] productRevs = product.getPropertyObject(REVISION_LIST).getModelObjectArrayValue(); + session.loadProperties(productRevs); + ItemRevision productRev = (ItemRevision) productRevs[0]; + + session.loadProperties(productRev, PV_UNIT); + ModelObject[] listOfUnitsBelowProduct = productRev.getPropertyObject(PV_UNIT).getModelObjectArrayValue(); + session.loadProperties(listOfUnitsBelowProduct); + for (ModelObject unit : listOfUnitsBelowProduct) { + if (unit != null) { + unitListOfProduct.add((ItemRevision) unit); + } + } + return unitListOfProduct; + } + + private ItemRevision choseRevision(final TcSession session, final List unitListOfProduct) throws InvalidUserInputException { + // Choose the revision of the Unit + // Obtain the list of all the UnitRevision with same range + List resultUnits = UnitRevision.getItemRevisionWithSameRange(session, unitBeforeEffectivity, unitListOfProduct); + + // Select the latest maturity unit + Optional potentialLatestUnitBefore = ObjectInfoHelper.getRevisionAndStatusWithMostRecentReleaseDate(session, resultUnits, null, StatusEnum.UNIT_MATURITY); + + if (!potentialLatestUnitBefore.isPresent()) { + throw new InvalidUserInputException(UserInputErrorEnum.PRODUCT_AND_UNIT_DOES_NOT_EXIST); + } else { + RevisionStatusAndDate latestUnitBefore = potentialLatestUnitBefore.get(); + AbstractStatusFilter filter = StatusEnum.allow(ExecutionR20.R20_STATUS_BEFORE); + + // Verify the status of the latest maturity status + if (filter.isIncluded(latestUnitBefore.getReleaseStatus().get_name())) { + return latestUnitBefore.getItemRevision(); + } else { + throw new InvalidUserInputException(UserInputErrorEnum.PRODUCT_AND_UNIT_DOES_NOT_EXIST); + } + } + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r20report/checker/R20UnitRevisionChecker.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r20report/checker/R20UnitRevisionChecker.java new file mode 100644 index 0000000..12b139a --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r20report/checker/R20UnitRevisionChecker.java @@ -0,0 +1,92 @@ +package com.capgemini.reports.definition.r20report.checker; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.object.pom.status.StatusEnum; +import com.capgemini.reports.definition.r20report.ExecutionR20; +import com.capgemini.reports.exceptions.InvalidUserInputException; +import com.capgemini.reports.exceptions.UserInputErrorEnum; +import com.capgemini.reports.releasestatus.RevisionStatusAndDate; +import com.capgemini.reports.reports.parameters.ProductUnit; +import com.capgemini.reports.reports.parameters.checker.ProductUnitChecker; +import com.capgemini.reports.reports.parameters.checker.UnitRevisionChecker; +import com.capgemini.reports.teamcenter.ObjectInfoHelper; +import com.google.common.base.Optional; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +import java.util.ArrayList; +import java.util.List; + +/** + * This class checks if a given UnitRevision is valid for a R20 report.
    + * It assumes that the Product and the unit exist (using a {@link ProductUnitChecker}.
    + * It fails if the unit does not have an effectivity matching the product ID. + */ +public class R20UnitRevisionChecker extends UnitRevisionChecker { + + private final BeforeOrAfter beforeOrAfter; + + /** + * Constructor for R20 report. + * + * @param productUnit the {@link ProductUnit Product and the Unit} that need to be checked. + * @param isAfter boolean Take true if this ProductUnit is an "After". Take false if it is a "Before". + */ + public R20UnitRevisionChecker(final ProductUnit productUnit, final boolean isAfter) { + super(productUnit); + if (isAfter) { + this.beforeOrAfter = BeforeOrAfter.AFTER; + } else { + this.beforeOrAfter = BeforeOrAfter.BEFORE; + } + } + + @Override + protected List checkUnits(final TcSession session) throws InvalidUserInputException { + List unitsOfProductInRange = super.checkUnits(session); + StatusEnum[] allowedStatuses = beforeOrAfter == BeforeOrAfter.BEFORE ? ExecutionR20.R20_STATUS_BEFORE : ExecutionR20.R20_STATUS_AFTER; + // Obtain the latest maturity status overall + RevisionStatusAndDate latest; + Optional maybeLatestUnit = + ObjectInfoHelper.getRevisionAndStatusWithMostRecentReleaseDate(session, unitsOfProductInRange, null, StatusEnum.UNIT_MATURITY); + if (!maybeLatestUnit.isPresent()) { + throw latestUnitDoesNotHaveTheCorrectMaturity(); // Actually, it doesn't have a maturity status at all :O + } else { + latest = maybeLatestUnit.get(); + } + + // Verify the latest maturity status is of an allowed type + if (StatusEnum.allow(allowedStatuses).isExcluded(latest.getReleaseStatus())) { + throw latestUnitDoesNotHaveTheCorrectMaturity(); // Maturity is excluded! + } + List result = new ArrayList<>(); + result.add(latest.getItemRevision()); + return result; + } + + /** + * Just adapting this error message for R20. + * + * @return the custom exception + */ + @Override + protected InvalidUserInputException unitNotAssociatedToProduct() { + if (this.beforeOrAfter.equals(BeforeOrAfter.AFTER)) { + return new InvalidUserInputException(UserInputErrorEnum.THE_UNIT_AFTER_IS_NOT_ASSOCIATED_TO_THE_PRODUCT_AFTER); + } else { + return new InvalidUserInputException(UserInputErrorEnum.THE_UNIT_BEFORE_IS_NOT_ASSOCIATED_TO_THE_PRODUCT_BEFORE); + } + } + + private InvalidUserInputException latestUnitDoesNotHaveTheCorrectMaturity() { + if (this.beforeOrAfter.equals(BeforeOrAfter.AFTER)) { + return new InvalidUserInputException(UserInputErrorEnum.THE_LATEST_UNIT_AFTER_DOES_NOT_HAVE_THE_APPROPRIATE_MATURITY); + } else { + return new InvalidUserInputException(UserInputErrorEnum.THE_LATEST_UNIT_BEFORE_DOES_NOT_HAVE_THE_APPROPRIATE_MATURITY); + } + } + + private enum BeforeOrAfter { + BEFORE, + AFTER + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r20report/comparator/ChangeComparator.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r20report/comparator/ChangeComparator.java new file mode 100644 index 0000000..eeea4fd --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r20report/comparator/ChangeComparator.java @@ -0,0 +1,22 @@ +package com.capgemini.reports.definition.r20report.comparator; + +import com.capgemini.reports.changeobjects.change.TcChangeRequestRevision; + +import java.io.Serializable; +import java.util.Comparator; + +/** + * This class will allow to compare two changes. + */ +public class ChangeComparator implements Comparator, Serializable { + private static final long serialVersionUID = -2191199657528201566L; + + /** + * @param obj1 first change to compare + * @param obj2 second change to compare + */ + @Override + public int compare(final TcChangeRequestRevision obj1, final TcChangeRequestRevision obj2) { + return obj1.getItemId().compareTo(obj2.getItemId()); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r20report/comparator/GenericComparator.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r20report/comparator/GenericComparator.java new file mode 100644 index 0000000..7aaae2e --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r20report/comparator/GenericComparator.java @@ -0,0 +1,15 @@ +package com.capgemini.reports.definition.r20report.comparator; + +import com.capgemini.reports.snecmaobjects.generic.AbstractGeneric; + +import java.io.Serializable; +import java.util.Comparator; + +public class GenericComparator implements Comparator, Serializable { + private static final long serialVersionUID = -2723597994389438L; + + @Override + public int compare(final AbstractGeneric obj1, final AbstractGeneric obj2) { + return obj1.getItemId().compareTo(obj2.getItemId()); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r20report/printing/Page3TemplateGenerator.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r20report/printing/Page3TemplateGenerator.java new file mode 100644 index 0000000..0b0d3cc --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r20report/printing/Page3TemplateGenerator.java @@ -0,0 +1,342 @@ +package com.capgemini.reports.definition.r20report.printing; + +import com.capgemini.framework.common.FileTemplate; +import com.capgemini.framework.common.HashMapComparingStringIDs; +import com.capgemini.framework.common.HashMapComparingStringIDs.IdMaker; +import com.capgemini.framework.common.ResourceHelper; +import com.capgemini.framework.common.StringHelper; +import com.capgemini.reports.changeobjects.change.TcChangeRequestRevision; +import com.capgemini.reports.definition.r20report.ExecutionR20.ReportDataR20; +import com.capgemini.reports.exceptions.FileLoadingException; +import com.capgemini.reports.exceptions.InvalidInputException; +import com.capgemini.reports.exceptions.ReportPrintException; +import com.capgemini.reports.jasper.compilers.JasperCompiler; +import com.capgemini.reports.printing.PrintParameters; +import com.capgemini.reports.snecmaobjects.generic.AbstractGeneric; +import com.capgemini.reports.templates.Alignment; +import com.capgemini.reports.templates.CellFormat; +import com.capgemini.reports.templates.DynamicGridTemplateBuilder; +import lombok.extern.slf4j.Slf4j; +import net.sf.jasperreports.engine.JRException; +import net.sf.jasperreports.engine.JasperReport; + +import java.util.*; +import java.util.Map.Entry; + +/** + * Generates a template for the page 3 of the R20 report.
    + * Adds a number of Dynamic tables as sub-reports to this page. + */ +@Slf4j +public class Page3TemplateGenerator extends FileTemplate { + + private static final String NO_GENERIC_FOUND = "(Aucun générique n'a pu être trouvé)"; + + private static final String KEY_COLUMN = "COL"; + private static final String ROW_HEADER_KEY = "ROW_HEADER"; + + private static final String TEMPLATE_PAGE3 = "/Jasper/template/report_r20/page3/report_r20_p3.jrxml"; + private static final String LINE1 = "\n "; + private static final String LINE2 = "\n "; + private static final String LINE3 = "\n >)$P{CROSS_TABLE}.get(\"DATA_"; + private static final String LINE3_P2 = "\"))]]>"; + private static final String LINE4 = "\n "; + private static final String LINE5 = "\n "; + + private static final String DATA_KEY_PREFIX = "DATA_SUBREPORT"; + private static final String TEMPLATE_KEY_PREFIX = "TEMPLATE_SUBREPORT"; + private static final String CROSS_TABLE = "CROSS_TABLE"; + + private static final int ONE_LINE_HEIGHT_PX = 13; + private static final int TWO_LINE_HEIGHT_PX = 28; + private static final int COLUMN_WIDTH_PX = 80; // 60 + private static final int FIRST_COLUMN_WIDTH_PX = 160; // 200 + + private static final String GREY_BACKGROUND = "#E3E3E3"; + private static final int COLUMNS_PER_PAGE = 8; // 10 + private static final int HEIGHT = 20; + /** + * Vertical spacing between consecutive tables. + */ + private static final int SPACING = 10; + + private static final String SANS = "Sans"; + private static final String AVEC = "Avec"; + private static final String EMPTY_STRING = ""; + /** + * This idMaker says two generics are equal if they have the same ID (it igniores their revisions). + */ + private static final IdMaker GENERIC_ID_MAKER = new IdMaker() { + private static final long serialVersionUID = 6329281427084937878L; + + @Override + public String makeId(final AbstractGeneric gen) { + return gen.getItemId(); + } + }; + @SuppressWarnings({"unchecked", "rawtypes"}) + private static final Class> CLASS_MAP_CHANGE_TO_STRING = (Class) Map.class; + /** + * Number of 'Data' columns to generate. + */ + private final int totalColumnNumber; + /** + * Number of lines (show the generic objects). + */ + private final int totalLines; + /** + * Number of tables to generate . + */ + private final int numSubGrid; + private final String page3RawTemplateAsString; + private final String ligneProduitApres; + private final List modNames; + private final List contentKeys; + private final List lineNames; + /** + * Columns, then line: gridData[col][line]. + */ + private final String[][] gridData; + + /** + * Creates a template Generator.
    + * A table may only contain 1 header column, an no more than 10 data columns. Everytime a column is added beyond, a new table is created for it. + * + * @param data will allow to prepare data for the report + * @throws FileLoadingException if unable yo load page 3 template + */ + Page3TemplateGenerator(final ReportDataR20 data) throws FileLoadingException { + super(); + this.totalColumnNumber = data.getTotalChangeRequest().size(); // At least 1 column, otherwise we'd findAll nullpointers + this.totalLines = data.getTotalGenerics().size(); + this.numSubGrid = 1 + totalColumnNumber / COLUMNS_PER_PAGE; + this.page3RawTemplateAsString = ResourceHelper.getResourceContent(TEMPLATE_PAGE3); + this.ligneProduitApres = data.getProduct().getProductLine(); + this.contentKeys = setupContentKeys(totalColumnNumber); + this.modNames = setupModNames(data); + this.lineNames = setupLineNames(data.getTotalGenerics()); + this.gridData = setupGridData(data, this.modNames); + } + + private static List setupContentKeys(final int numCol) { + List list = new ArrayList<>(); + for (int num = 0; num < numCol; num++) { + list.add(KEY_COLUMN + num); + } + return list; + } + + /** + * This methods sets up the name of the columns (the name of the generics). + * + * @param allGenerics all the generics that will be in the table + * @return a List of strings + */ + private static List setupLineNames(final Set allGenerics) { + List list = new ArrayList<>(); + for (AbstractGeneric generic : allGenerics) { + list.add(generic.getName()); + } + return list; + } + + /** + * creates a list of all the Modification names.
    + */ + private static List setupModNames(final ReportDataR20 data) { + List list = new ArrayList<>(); + for (TcChangeRequestRevision changeLMR : data.getTotalChangeRequestLMR()) { + list.add("Non Application
    " + changeLMR.getItemId()); + } + for (TcChangeRequestRevision changeNotLMR : data.getTotalChangeRequestNotLMR()) { + list.add("Application
    " + changeNotLMR.getItemId()); + } + return list; + } + + /** + * Columns BEFORE lines!. + */ + private static String[][] setupGridData(final ReportDataR20 data, final List modNames) { + int numCol = data.getTotalChangeRequest().size(); + int numLine = data.getTotalGenerics().size(); + + // Initialize the array + String[][] grid = new String[numCol][numLine]; + + if (!modNames.isEmpty()) { + Map> dataMap = + new HashMapComparingStringIDs<>(GENERIC_ID_MAKER, AbstractGeneric.class, + CLASS_MAP_CHANGE_TO_STRING); + // Put the generics in + putGenericsInDataMap(dataMap, data.getTotalGenericsAfterWithRupture(), AVEC); + putGenericsInDataMap(dataMap, data.getTotalGenericsBeforeLMRWithRupture(), AVEC); + putGenericsInDataMap(dataMap, data.getTotalGenericsAfterWithoutRupture(), SANS); + putGenericsInDataMap(dataMap, data.getTotalGenericsBeforeLMRWithoutRupture(), SANS); + + // Use the map to buid the array + int line = 0; + for (AbstractGeneric gen : data.getTotalGenerics()) { + int col = 0; + for (TcChangeRequestRevision mod : data.getTotalChangeRequest()) { + if (dataMap.containsKey(gen)) { + if (dataMap.get(gen).containsKey(mod)) { + grid[col][line] = dataMap.get(gen).get(mod); + } else { + grid[col][line] = EMPTY_STRING; + } + } else { + grid[col][line] = EMPTY_STRING; + } + col++; + } + line++; + } + } + return grid; + } + + private static void putGenericsInDataMap(final Map> data, + final Map> map, final String withOrWithout) { + for (Entry> genEntry : map.entrySet()) { + if (!data.containsKey(genEntry.getKey())) { + data.put(genEntry.getKey(), new HashMap()); + } + for (TcChangeRequestRevision changeRequest : genEntry.getValue()) { + data.get(genEntry.getKey()).put(changeRequest, withOrWithout); + } + } + } + + static String subReportGrid(final int positionX, final int positionY, final String subReportKey) { + return StringHelper.concatToString(LINE1, LINE2, String.valueOf(positionX), LINE2_P3, String.valueOf(positionY), LINE2_P4, LINE3, + subReportKey, LINE3_P2, LINE4, subReportKey, LINE4_P2, LINE5); + } + + /** + * Generates the page's {@link PrintParameters}. + * + * @return the printing instructions, as a {@link PrintParameters} object + * @throws FileLoadingException if a template could not be loaded + * @throws ReportPrintException if a template could not be compiled + * @throws InvalidInputException if the table cannot be constructed properly in the template (invalid columns/rows count) + */ + PrintParameters generatePrintParameters() throws ReportPrintException, FileLoadingException, InvalidInputException { + PrintParameters page3 = PrintParameters.createSubReport(this.generateCode()); + + // For each Table... + Map crossTable = new HashMap<>(); + for (int tableNum = 0; tableNum < numSubGrid; tableNum++) { + int columnsDone = tableNum * COLUMNS_PER_PAGE; + int columnsLeft = totalColumnNumber - columnsDone; + int numColInThisTable = Math.min(columnsLeft, COLUMNS_PER_PAGE); // Total number of columns in this table, max is COLUMNS_PER_PAGE + String dataKey = DATA_KEY_PREFIX + tableNum; + String templateKey = TEMPLATE_KEY_PREFIX + tableNum; + String templateString = setupGridTemplate(columnsDone, columnsDone + numColInThisTable); + JasperReport compiledTemplate; + try { + compiledTemplate = JasperCompiler.compile(templateString); + } catch (JRException e) { + throw new ReportPrintException("Could not compile the sub-table template", e); + } + + // Copy all the lines... + List> tableData = new ArrayList<>(); + if (gridData.length > 0) { + for (int lineNum = 0; lineNum < gridData[0].length; lineNum++) { + Map line = new HashMap<>(); + line.put(ROW_HEADER_KEY, lineNames.get(lineNum)); + // ... of each columns of THIS sub-table + for (int tableColNum = 0; tableColNum < numColInThisTable; tableColNum++) { // Index of the working column in the sub-table + int gridColNum = tableColNum + columnsDone; // Index of the working column in the main data grid + String contentKey = contentKeys.get(gridColNum); + String contentVal = gridData[gridColNum][lineNum]; + line.put(contentKey, contentVal); + } + tableData.add(line); // One full line is generated + } + } + // If there was nothing in the table, put a fake line to make it show up anyway + if (tableData.isEmpty()) { + // If there was some lines (Generic objects to show) + if (totalLines > 0) { + for (int lineNum = 0; lineNum < totalLines; lineNum++) { + Map line = new HashMap<>(); + line.put(ROW_HEADER_KEY, lineNames.get(lineNum)); + tableData.add(line); // One full line is generated + } + } + // Otherwise + else { + Map line = new HashMap<>(); + line.put(ROW_HEADER_KEY, NO_GENERIC_FOUND); + tableData.add(line); // One full line is generated + } + } + crossTable.put(templateKey, compiledTemplate); + crossTable.put(dataKey, tableData); + } + page3.addReportParameter(CROSS_TABLE, crossTable); + page3.addReportData(setupEmptyData()); + return page3; + } + + private String setupGridTemplate(final int startcol, final int endCol) throws FileLoadingException, InvalidInputException { + // Setup each column's properties: width, headers and content keys (first column is different) + List widths = new ArrayList<>(); + List keys = new ArrayList<>(); + List headers = new ArrayList<>(); + List firstLine = new ArrayList<>(); + List nothingIsDynamic = new ArrayList<>(); + List headerFormats = new ArrayList<>(); + List contentsformats = new ArrayList<>(); + List allIsStretchingwithOverflow = new ArrayList<>(); + widths.add(FIRST_COLUMN_WIDTH_PX); + keys.add(ROW_HEADER_KEY); + headers.add("Modifications Techniques"); + firstLine.add(ligneProduitApres); + nothingIsDynamic.add(false); + headerFormats.add(new CellFormat().setColor(GREY_BACKGROUND)); // Keep default alignment (left) + contentsformats.add(new CellFormat()); // Keep default alignment (left) + allIsStretchingwithOverflow.add(true); + for (int col = startcol; col < endCol; col++) { + widths.add(COLUMN_WIDTH_PX); + keys.add(contentKeys.get(col)); + headers.add(modNames.get(col)); + firstLine.add(EMPTY_STRING); // Empty because only first column has data: "Modifications Techniques" + nothingIsDynamic.add(false); + headerFormats.add(new CellFormat().setColor(GREY_BACKGROUND).setAlignment(Alignment.CENTER)); + contentsformats.add(new CellFormat().setAlignment(Alignment.CENTER)); + allIsStretchingwithOverflow.add(true); + } + DynamicGridTemplateBuilder template = + new DynamicGridTemplateBuilder(widths, keys, contentsformats, allIsStretchingwithOverflow, ONE_LINE_HEIGHT_PX); + template.addHeaderLine(ONE_LINE_HEIGHT_PX, firstLine, nothingIsDynamic, headerFormats, allIsStretchingwithOverflow); + template.addHeaderLine(TWO_LINE_HEIGHT_PX, headers, nothingIsDynamic, headerFormats, allIsStretchingwithOverflow); + String generatedTemplate = template.generateCode(); + log.trace(generatedTemplate); + return generatedTemplate; + } + + private List> setupEmptyData() { + List> list = new ArrayList<>(); + list.add(new HashMap()); + return list; + } + + @Override + public String generateCode() { + // Generates the template, containing a number of grid sub-tables + this.setTemplateContent(page3RawTemplateAsString); + this.setTagValue("BAND_HEIGHT", String.valueOf(numSubGrid * HEIGHT + SPACING * (numSubGrid - 1))); + StringBuilder subTables = new StringBuilder(); + for (int num = 0; num < numSubGrid; num++) { + subTables.append(subReportGrid(0, num * (HEIGHT + SPACING), "SUBREPORT" + num)); + } + this.setTagValue("SUBTABLES", subTables.toString()); + return super.generateCode(); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r20report/printing/R20Printer.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r20report/printing/R20Printer.java new file mode 100644 index 0000000..45677bf --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r20report/printing/R20Printer.java @@ -0,0 +1,416 @@ +package com.capgemini.reports.definition.r20report.printing; + +import com.capgemini.framework.common.LanguageHelper; +import com.capgemini.framework.common.ResourceHelper; +import com.capgemini.framework.common.StringHelper; +import com.capgemini.framework.common.TeamcenterDateFormatter; +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.reports.changeobjects.UnitRevision; +import com.capgemini.reports.changeobjects.change.TcChangeRequestRevision; +import com.capgemini.reports.definition.r20report.ExecutionR20; +import com.capgemini.reports.definition.r20report.ExecutionR20.ReportDataR20; +import com.capgemini.reports.definition.r20report.visitors.R20Keys; +import com.capgemini.reports.definition.r20report.visitors.R20Keys.Page1; +import com.capgemini.reports.definition.r20report.visitors.R20Keys.Page4; +import com.capgemini.reports.documentationobjects.DocTechnic; +import com.capgemini.reports.exceptions.FileLoadingException; +import com.capgemini.reports.exceptions.InvalidInputException; +import com.capgemini.reports.exceptions.ReportPrintException; +import com.capgemini.reports.execution.mapconstructor.AbstractStaticTemplateMapConstructor; +import com.capgemini.reports.printing.PrintParameters; +import com.capgemini.reports.snecmaobjects.generic.AbstractGeneric; +import com.capgemini.reports.snecmaobjects.part.PartAeroRevision; +import com.capgemini.reports.snecmaobjects.product.ProductRevision; +import com.capgemini.reports.users.SnecmaUser; +import com.capgemini.reports.workflows.Task; +import lombok.EqualsAndHashCode; +import lombok.extern.slf4j.Slf4j; + +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.io.InputStream; +import java.util.*; +import java.util.Map.Entry; + +/** + * Printer of the R20 report. + */ +@Slf4j +@EqualsAndHashCode(callSuper = true) +public final class R20Printer extends AbstractStaticTemplateMapConstructor { + + private static final long serialVersionUID = -5470510531792553291L; + private static final String NONE = "(Aucun)"; + private static final String NO_GENERIC_FOUND = "(Aucun générique n'a pu être trouvé)"; + private static final String NOT_APPLICABLE = "(N/A)"; + private static final String WKF_VALIDATION_SO_UNIT = "Validation SO UNIT"; + private static final String COMMA_DELIMITER = ", "; + + private static final String SANS = "Sans"; + private static final String AVEC = "Avec"; + private static final String EMPTY_STRING = ""; + private static final String EXCEPTIONNEL = "Exceptionnel"; + private static final String NON_APPLICATION = "Non Application "; + private static final String APPLICATION = "Application "; + + private static final String SUBREPORT_NOIMPACTS = "SUBREPORT_NOIMPACTS"; + private static final String SUBREPORT_IMPACTS = "SUBREPORT_IMPACTS"; + private static final String SUBREPORT_GENERIC = "SUBREPORT_GENERIC"; + private static final String SUBREPORT_P1 = "SUBREPORT_P1"; + private static final String SUBREPORT_P2 = "SUBREPORT_P2"; + private static final String SUBREPORT_P3 = "SUBREPORT_P3"; + private static final String SUBREPORT_P4 = "SUBREPORT_P4"; + + private static final String JASPER_TEMPLATE_PAGE1 = "/Jasper/template/report_r20/report_r20_p1.jrxml"; + private static final String JASPER_TEMPLATE_PAGE2 = "/Jasper/template/report_r20/report_r20_p2.jrxml"; + private static final String JASPER_TEMPLATE_PAGE4 = "/Jasper/template/report_r20/report_r20_p4.jrxml"; + private static final String JASPER_TEMPLATE_PAGE2_GENERIC = "/Jasper/template/report_r20/page2/r20_p2_generics.jrxml"; + private static final String JASPER_TEMPLATE_PAGE2_IMPACTS = "/Jasper/template/report_r20/page2/r20_p2_impacts.jrxml"; + private static final String JASPER_TEMPLATE_PAGE2_NOIMPACTS = "/Jasper/template/report_r20/page2/r20_p2_noimpacts.jrxml"; + + /** + * Print the R20 report. + * + * @param mainReport the {@link PrintParameters} of the main report, to which the data and the sub-reports will be added + * @param data will allow to prepare data for the report + * @throws ReportPrintException if unable to setup the report's page templates + * @throws FileLoadingException if unable to read the report's page templates + * @throws InvalidInputException if date could not be printed properly (page 3) + */ + public static void print(final ReportDataR20 data, final PrintParameters mainReport) + throws ReportPrintException, FileLoadingException, InvalidInputException { + setupPage1(data, mainReport); + setupPage2(data, mainReport); + setupPage3(data, mainReport); + setupPage4(data, mainReport); + + // Setup main report + mainReport.addReportData(setupEmptyData()); + mainReport.addReportParameters(setupMainParameters(data)); + mainReport.addReportParameter(R20Keys.IS_CR_LIST_EMPTY, data.getTotalChangeRequest().isEmpty()); + mainReport.setReportTitle("Titre rapport principal"); + } + + private static void setupPage1(final ReportDataR20 data, final PrintParameters mainReport) throws FileLoadingException, ReportPrintException { + // Setup page 1 + try (InputStream page1Stream = ResourceHelper.getResourceAsStream(JASPER_TEMPLATE_PAGE1)) { + Collection> page1Data = setupPage1Data(data); + Map page1Params = new EnumMap<>(R20Keys.Page1.class); + mainReport.addSubReport(SUBREPORT_P1, page1Stream, page1Data, page1Params); + } catch (IOException e) { + log.error("Unable to close template for Page 1 of the R20 report", e); + } + + } + + private static void setupPage2(final ReportDataR20 data, final PrintParameters mainReport) throws ReportPrintException, FileLoadingException { + // Setup template streams + try (InputStream page2stream = ResourceHelper.getResourceAsStream(JASPER_TEMPLATE_PAGE2); + InputStream page2GenericStream = ResourceHelper.getResourceAsStream(JASPER_TEMPLATE_PAGE2_GENERIC); + InputStream page2ImpactStream = ResourceHelper.getResourceAsStream(JASPER_TEMPLATE_PAGE2_IMPACTS); + InputStream pageNoImactStream = ResourceHelper.getResourceAsStream(JASPER_TEMPLATE_PAGE2_NOIMPACTS)) { + // Setup print parameters + PrintParameters page2 = PrintParameters.createSubReport(page2stream); + page2.addSubReport(SUBREPORT_GENERIC, page2GenericStream, setupPage2GenericData(data), new EnumMap<>(R20Keys.Page2.Generics.class)); + page2.addSubReport(SUBREPORT_IMPACTS, page2ImpactStream, setupPage2ImpactsData(data), new EnumMap<>(R20Keys.Page2.Generics.class)); + page2.addSubReport(SUBREPORT_NOIMPACTS, pageNoImactStream, setupPage2NoImpactsData(data), new EnumMap<>(R20Keys.Page2.NoImpacts.class)); + page2.addReportData(setupEmptyData()); + page2.addReportParameters(new EnumMap<>(R20Keys.Page2.class)); + mainReport.addSubReport(SUBREPORT_P2, page2); + } catch (IOException e) { + log.warn("Exception encountered while closing input stream for R20 report", e); + } + } + + private static void setupPage3(final ReportDataR20 data, final PrintParameters mainReport) + throws FileLoadingException, ReportPrintException, InvalidInputException { + Page3TemplateGenerator page3TemplateGenerator = new Page3TemplateGenerator(data); + PrintParameters page3 = page3TemplateGenerator.generatePrintParameters(); + mainReport.addSubReport(SUBREPORT_P3, page3); + } + + private static void setupPage4(final ReportDataR20 data, final PrintParameters mainReport) throws FileLoadingException, ReportPrintException { + List> page4Data = setPage4Data(data); + Map page4Params = new EnumMap<>(R20Keys.Page4.class); + try (InputStream page4Stream = ResourceHelper.getResourceAsStream(JASPER_TEMPLATE_PAGE4)) { + mainReport.addSubReport(SUBREPORT_P4, page4Stream, page4Data, page4Params); + } catch (IOException e) { + log.warn("Unable to close template for Page 4 of the R20 report", e); + } + } + + private static List> setupEmptyData() { + List> list = new ArrayList<>(); + list.add(new HashMap()); + return list; + } + + private static Map setupMainParameters(final ReportDataR20 data) throws FileLoadingException { + Map parametersMap = new EnumMap<>(R20Keys.class); + BufferedImage image = ResourceHelper.loadImage("/Jasper/images/Snecma_logo.png"); + ProductRevision product = data.getProduct(); + UnitRevision unitBefore = data.getUnitBefore(); + UnitRevision unitAfter = data.getUnitAfter(); + String productLine = product.getProductLine(); + String productdomain = LanguageHelper.french(product.getDomain()); + + printDocGelData(parametersMap, unitAfter); + + printWorkflowData(parametersMap, unitAfter); + + // Put it all in the map + parametersMap.put(R20Keys.SNECMA_LOGO, image); + parametersMap.put(R20Keys.PRODUIT, product.getName()); + parametersMap.put(R20Keys.UNIT_AVANT, unitBefore.getName()); + parametersMap.put(R20Keys.UNIT_APRES, unitAfter.getName()); + parametersMap.put(R20Keys.EXCEPTIONNEL_AVANT, unitBefore.isExceptionnel() ? EXCEPTIONNEL : EMPTY_STRING); + parametersMap.put(R20Keys.EXCEPTIONNEL_APRES, unitAfter.isExceptionnel() ? EXCEPTIONNEL : EMPTY_STRING); + parametersMap.put(R20Keys.DOMAINE_PRODUIT_AVANT, productdomain); + parametersMap.put(R20Keys.DOMAINE_PRODUIT_APRES, productdomain); + parametersMap.put(R20Keys.LIGNE_PRODUIT_AVANT, productLine); + parametersMap.put(R20Keys.LIGNE_PRODUIT_APRES, productLine); + parametersMap.put(R20Keys.MATRICULE_MOTEUR, data.getMatriculeMoteur()); + parametersMap.put(R20Keys.CLASSE, data.getClasse().toString()); + parametersMap.put(R20Keys.MAJEUR_MINEUR, data.getMajorMinor().toString()); + parametersMap.put(R20Keys.CONJOINT_UNIQUE, data.getConjointUnique().toString()); + + return parametersMap; + } + + private static void printDocGelData(final Map parametersMap, final UnitRevision unitAfter) { + // Obtain data from Doc Gel + String docGelReference; + String docGelIndice; + DocTechnic docGel = unitAfter.getTechnicalDocGel(); + if (docGel != null && docGel.getTypeDocTechnic1() != null && docGel.getTypeDocTechnic1().contains("Document de gel")) { + docGelReference = docGel.getReference(); + docGelIndice = docGel.getIndice(); + } else { + docGelReference = NONE; + docGelIndice = NONE; + } + parametersMap.put(R20Keys.IDENTIFIANT_DOC_GEL_UNIT_APRES, docGelReference); + parametersMap.put(R20Keys.INDICE_DOCUMENT_GEL_UNIT_APRES, docGelIndice); + } + + private static void printWorkflowData(final Map parametersMap, final UnitRevision unitAfter) { + // Obtain data from workflow + String wkfOwner = ""; + Calendar wkfCreationDate = null; + String wkfApprobator = ""; + Calendar wkfValidationDate = null; + if (!unitAfter.getWorkflowsValidationUnitParSO().isEmpty()) { + Task validationUnit = unitAfter.getWorkflowsValidationUnitParSO().get(0); + wkfOwner = makeNameAndId(validationUnit.getOwningUser()); + wkfCreationDate = validationUnit.getCreationDate(); + for (Task childTask : validationUnit.getCompletedChildTasks()) { + if (WKF_VALIDATION_SO_UNIT.equals(childTask.getName())) { + wkfApprobator = makeNameAndId(childTask.getLastModUser()); + wkfValidationDate = childTask.getLastModDate(); + break; + } + } + } + // Handle null wkf (none found) + String wkfcreationDateStr = wkfCreationDate == null ? "" : TeamcenterDateFormatter.formatCalendarToFrench(wkfCreationDate); + String wkfValidationDateStr = wkfValidationDate == null ? "" : TeamcenterDateFormatter.formatCalendarToFrench(wkfValidationDate); + + parametersMap.put(R20Keys.DATE_CREATION, wkfcreationDateStr); + parametersMap.put(R20Keys.DATE_VALIDATION, wkfValidationDateStr); + parametersMap.put(R20Keys.NOM_CREATEUR_WORKFLOW, wkfOwner); + parametersMap.put(R20Keys.NOM_APPROBATEUR_TACHE, wkfApprobator); + } + + private static String makeNameAndId(final SnecmaUser owner) { + return owner.getName() + " (" + owner.getUserId() + ")"; + } + + /** + * Sets up the a table containing all the Modifications applied to form the unit After.
    + * The table is fist sorted by Application (LMR before regular mods) then by Change ID + */ + private static List> setupPage1Data(final ReportDataR20 data) { + List> changeRequestList = new ArrayList<>(); + for (TcChangeRequestRevision changeRequest : data.getTotalChangeRequestLMR()) { + String approbationSO = changeRequest.getApprobationSO(); + if (approbationSO == null) { + approbationSO = EMPTY_STRING; + } + Map lmrMap = new EnumMap<>(R20Keys.Page1.class); + lmrMap.put(R20Keys.Page1.CHANGE_REQUEST_APPLI, NON_APPLICATION); + lmrMap.put(R20Keys.Page1.CHANGE_REQUEST_ID, changeRequest.getItemId()); + lmrMap.put(R20Keys.Page1.CHANGE_REQUEST_NOM, changeRequest.getChangeName()); + lmrMap.put(R20Keys.Page1.CHANGE_REQUEST_NO_APPRO_SO, approbationSO); + changeRequestList.add(lmrMap); + } + for (TcChangeRequestRevision changeRequest : data.getTotalChangeRequestNotLMR()) { + String approbationSO = changeRequest.getApprobationSO(); + if (approbationSO == null) { + approbationSO = EMPTY_STRING; + } + Map lmrMap = new EnumMap<>(R20Keys.Page1.class); + lmrMap.put(R20Keys.Page1.CHANGE_REQUEST_APPLI, APPLICATION); + lmrMap.put(R20Keys.Page1.CHANGE_REQUEST_ID, changeRequest.getItemId()); + lmrMap.put(R20Keys.Page1.CHANGE_REQUEST_NOM, changeRequest.getChangeName()); + lmrMap.put(R20Keys.Page1.CHANGE_REQUEST_NO_APPRO_SO, approbationSO); + changeRequestList.add(lmrMap); + } + if (changeRequestList.isEmpty()) { + changeRequestList.add(new EnumMap(R20Keys.Page1.class)); + } + return changeRequestList; + } + + /** + * Sets up the a table containing all the generics taking part of a Modification with rupture (from unit After or LMR) with their PartAero Before (if any) and After (if any). + * + * @param data the executionR20 to findAll the data + * @return the table data as a List of Map + */ + private static List> setupPage2GenericData(final ReportDataR20 data) { + List> tableContent = new ArrayList<>(); + for (AbstractGeneric generic : data.getTotalGenericsBeforeLMRWithRupture().keySet()) { + putOneLineInPage2GenericsData(data, tableContent, generic); + } + for (AbstractGeneric generic : data.getTotalGenericsAfterWithRupture().keySet()) { + putOneLineInPage2GenericsData(data, tableContent, generic); + } + return tableContent; + } + + private static void putOneLineInPage2GenericsData(final ReportDataR20 data, final List> tableContent, + final AbstractGeneric generic) { + PartAeroRevision partBefore = data.getGenericsAndPartNumbersBefore().get(generic); + PartAeroRevision partAfter = data.getGenericsAndPartNumbersAfter().get(generic); + String idPartAvant = partBefore == null ? EMPTY_STRING : partBefore.getItemId(); + String idPartApres = partAfter == null ? EMPTY_STRING : partAfter.getItemId(); + Map line = new EnumMap<>(R20Keys.Page2.Generics.class); + line.put(R20Keys.Page2.Generics.GENERIC_AVEC_RUPTURE, generic.getName()); + line.put(R20Keys.Page2.Generics.ID_PART_AVANT, idPartAvant); + line.put(R20Keys.Page2.Generics.ID_PART_APRES, idPartApres); + tableContent.add(line); + } + + /** + * Sets up the a table containing all the generics which take part in at least one Modification with Rupture (from unit After or LMR), regardless of if they also take part in a modif without rupture. + * + * @param data the executionR20 to findAll the data + * @return the table data as a List of Map + */ + private static List> setupPage2ImpactsData(final ReportDataR20 data) { + List> tableContent = new ArrayList<>(); + for (Entry> genericEntry : data.getTotalGenericsBeforeLMRWithRupture().entrySet()) { + List listOfModifs = new ArrayList<>(); + for (TcChangeRequestRevision changeRequest : genericEntry.getValue()) { + listOfModifs.add(changeRequest.getItemId()); + if (changeRequest.getApprobationSO() != null) { + listOfModifs.add(changeRequest.getApprobationSO()); + } + } + Map line = new EnumMap<>(R20Keys.Page2.Impacts.class); + line.put(R20Keys.Page2.Impacts.NOM_GENERIC, genericEntry.getKey().getName()); + line.put(R20Keys.Page2.Impacts.LIST_MODIFICATIONS_GENERIC, StringHelper.implodeList(COMMA_DELIMITER, listOfModifs)); + tableContent.add(line); + } + for (Entry> genericEntry : data.getTotalGenericsAfterWithRupture().entrySet()) { + List listOfModifs = new ArrayList<>(); + for (TcChangeRequestRevision changeRequest : genericEntry.getValue()) { + listOfModifs.add(changeRequest.getItemId()); + if (changeRequest.getApprobationSO() != null) { + listOfModifs.add(changeRequest.getApprobationSO()); + } + } + Map line = new EnumMap<>(R20Keys.Page2.Impacts.class); + line.put(R20Keys.Page2.Impacts.NOM_GENERIC, genericEntry.getKey().getName()); + line.put(R20Keys.Page2.Impacts.LIST_MODIFICATIONS_GENERIC, StringHelper.implodeList(COMMA_DELIMITER, listOfModifs)); + tableContent.add(line); + } + return tableContent; + } + + /** + * Sets up the a table containing all the generics which take part in at least one Modification without Rupture (from unit After or LMR), regardless of if they also take part in a modif with rupture. + * + * @param data the executionR20 to findAll the data + * @return the table data as a List of Map + */ + private static List> setupPage2NoImpactsData(final ReportDataR20 data) { + List> tableContent = new ArrayList<>(); + for (Entry> genericEntry : data.getTotalGenericsBeforeLMRWithoutRupture().entrySet()) { + List listOfModifs = new ArrayList<>(); + for (TcChangeRequestRevision changeRequest : genericEntry.getValue()) { + listOfModifs.add(changeRequest.getItemId()); + if (changeRequest.getApprobationSO() != null) { + listOfModifs.add(changeRequest.getApprobationSO()); + } + } + Map line = new EnumMap<>(R20Keys.Page2.NoImpacts.class); + line.put(R20Keys.Page2.NoImpacts.NOM_GENERIC, genericEntry.getKey().getName()); + line.put(R20Keys.Page2.NoImpacts.LIST_MODIFICATIONS_GENERIC, StringHelper.implodeList(COMMA_DELIMITER, listOfModifs)); + tableContent.add(line); + } + for (Entry> genericEntry : data.getTotalGenericsAfterWithoutRupture().entrySet()) { + List listOfModifs = new ArrayList<>(); + for (TcChangeRequestRevision changeRequest : genericEntry.getValue()) { + listOfModifs.add(changeRequest.getItemId()); + if (changeRequest.getApprobationSO() != null) { + listOfModifs.add(changeRequest.getApprobationSO()); + } + } + Map line = new EnumMap<>(R20Keys.Page2.NoImpacts.class); + line.put(R20Keys.Page2.NoImpacts.NOM_GENERIC, genericEntry.getKey().getName()); + line.put(R20Keys.Page2.NoImpacts.LIST_MODIFICATIONS_GENERIC, StringHelper.implodeList(COMMA_DELIMITER, listOfModifs)); + tableContent.add(line); + } + return tableContent; + } + + private static List> setPage4Data(final ReportDataR20 data) { + List> tableContent = new ArrayList<>(); + for (AbstractGeneric generic : data.getTotalGenerics()) { + Map lmrMap = new EnumMap<>(R20Keys.Page4.class); + PartAeroRevision partBefore = data.getGenericsAndPartNumbersBefore().get(generic); + PartAeroRevision partAfter = data.getGenericsAndPartNumbersAfter().get(generic); + String idPartAvant = partBefore == null ? EMPTY_STRING : partBefore.getItemId(); + String idPartApres = partAfter == null ? EMPTY_STRING : partAfter.getItemId(); + String impact = evaluateImpact(data, generic); + + // Put the data in the table + lmrMap.put(R20Keys.Page4.NOM_GENERIQUE, generic.getName()); + lmrMap.put(R20Keys.Page4.IMPACT_PN, impact); + lmrMap.put(R20Keys.Page4.ID_PART_AVANT, idPartAvant); + lmrMap.put(R20Keys.Page4.ID_PART_APRES, idPartApres); + tableContent.add(lmrMap); + } + if (tableContent.isEmpty()) { + Map line = new EnumMap<>(R20Keys.Page4.class); + line.put(R20Keys.Page4.NOM_GENERIQUE, NO_GENERIC_FOUND); + line.put(R20Keys.Page4.IMPACT_PN, NOT_APPLICABLE); + line.put(R20Keys.Page4.ID_PART_AVANT, NOT_APPLICABLE); + line.put(R20Keys.Page4.ID_PART_APRES, NOT_APPLICABLE); + tableContent.add(line); + } + return tableContent; + } + + private static String evaluateImpact(final ReportDataR20 data, final AbstractGeneric generic) { + String impact; + if (data.getTotalGenericsAfterWithRupture().containsKey(generic) || data.getTotalGenericsBeforeLMRWithRupture().containsKey(generic)) { + impact = AVEC; + } else if (data.getTotalGenericsAfterWithoutRupture().containsKey(generic) + || data.getTotalGenericsBeforeLMRWithoutRupture().containsKey(generic)) { + impact = SANS; + } else { + impact = EMPTY_STRING; + } + return impact; + } + + @Override + public void constructDataMaps(TcSession session, final PrintParameters printParameters, final ReportDataR20 data) throws KurtException { + long start = System.currentTimeMillis(); + print(data, printParameters); + log.trace(EXECUTION_TIME_XXX_MS_FOR_YYY, System.currentTimeMillis() - start, "data filtering"); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r20report/visitors/R20Keys.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r20report/visitors/R20Keys.java new file mode 100644 index 0000000..124ed99 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r20report/visitors/R20Keys.java @@ -0,0 +1,84 @@ +package com.capgemini.reports.definition.r20report.visitors; + +/** + * Keys for R20 report. + */ +public enum R20Keys { + SUBREPORT_P1, + SUBREPORT_P2, + SNECMA_LOGO, + PRODUIT, + UNIT_AVANT, + UNIT_APRES, + EXCEPTIONNEL_AVANT, + EXCEPTIONNEL_APRES, + DOMAINE_PRODUIT_AVANT, + DOMAINE_PRODUIT_APRES, + LIGNE_PRODUIT_AVANT, + LIGNE_PRODUIT_APRES, + MATRICULE_MOTEUR, + IDENTIFIANT_DOC_GEL_UNIT_APRES, + INDICE_DOCUMENT_GEL_UNIT_APRES, + CLASSE, + MAJEUR_MINEUR, + CONJOINT_UNIQUE, + NOM_CREATEUR_WORKFLOW, + NOM_APPROBATEUR_TACHE, + DATE_CREATION, + DATE_VALIDATION, + IS_CR_LIST_EMPTY; + + /** + * Keys for the Page1 of the R20 report. + */ + public enum Page1 { + CHANGE_REQUEST_APPLI, + CHANGE_REQUEST_ID, + CHANGE_REQUEST_NOM, + CHANGE_REQUEST_NO_APPRO_SO + } + + /** + * Keys for the Page2 of the R20 report. + */ + public enum Page2 { + SUBREPORT_NOIMPACTS, + SUBREPORT_IMPACTS, + SUBREPORT_GENERIC; + + /** + * Keys for the Generics-Part relationship, in the Page2 of the R20 report. + */ + public enum Generics { + GENERIC_AVEC_RUPTURE, + ID_PART_AVANT, + ID_PART_APRES + } + + /** + * Keys for the Generics with Rupture, in the Page2 of the R20 report. + */ + public enum Impacts { + NOM_GENERIC, + LIST_MODIFICATIONS_GENERIC + } + + /** + * Keys for the Generics without rupture, in the Page2 of the R20 report. + */ + public enum NoImpacts { + NOM_GENERIC, + LIST_MODIFICATIONS_GENERIC + } + } + + /** + * Keys for the Page4 of the R20 report. + */ + public enum Page4 { + NOM_GENERIQUE, + IMPACT_PN, + ID_PART_AVANT, + ID_PART_APRES + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r21report/DataReportPreparatorR21.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r21report/DataReportPreparatorR21.java new file mode 100644 index 0000000..2c43f12 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r21report/DataReportPreparatorR21.java @@ -0,0 +1,117 @@ +package com.capgemini.reports.definition.r21report; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.EmptyNomenclatureException; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcBomObject; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcBomObjectFactory; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcRevisionRule; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcRevisionRuleProperties; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.product.TcProduct; +import com.capgemini.framework.teamcenter.object.runtime.TcBomWindow; +import com.capgemini.framework.teamcenter.object.runtime.TcBomWindowConfiguration; +import com.capgemini.framework.teamcenter.object.runtime.TcRevisionRulesConfiguration; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.bomlineholder.BOMLineHolderFactory; +import com.capgemini.reports.definition.r21report.ExecutionR21.ReportDataR21; +import com.capgemini.reports.definition.r21report.visitors.R21Visitor; +import com.capgemini.reports.exceptions.InvalidUserInputException; +import com.capgemini.reports.exceptions.UserInputErrorEnum; +import com.capgemini.reports.execution.IDataReportPreparator; +import com.capgemini.reports.execution.strategies.IExecutionStrategy; +import com.capgemini.reports.filter.AllIsGoodFilter; +import com.capgemini.reports.printing.PrintParameters; +import com.capgemini.reports.reports.parameters.EffectivityDate; +import com.capgemini.reports.reports.parameters.Generics; +import com.capgemini.reports.teamcenter.resolution.structureservice.MultiStructureServiceCaller; +import com.teamcenter.soa.client.model.ModelObject; +import com.teamcenter.soa.client.model.strong.Form; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +/** + * This class will allow to prepare data and findAll back data for making report R21. + */ +public class DataReportPreparatorR21 implements IDataReportPreparator { + private static final long serialVersionUID = -5941160681518152189L; + private static final Logger LOGGER = LoggerFactory.getLogger(DataReportPreparatorR21.class); + private static final AllIsGoodFilter ACCEPT_ALL = new AllIsGoodFilter(); + + @Override + public String print(TcSession session, ExecutionR21 execution, IExecutionStrategy executionStrategy) throws KurtException { + PrintParameters printParameters = prepareData(session, execution); + executionStrategy.print(printParameters, execution); + return executionStrategy.getReportFileName(execution) + printParameters.getOuputFileExtension(); + } + + private PrintParameters prepareData(final TcSession session, final ExecutionR21 report) throws KurtException { + LOGGER.debug("PrepareData started on: {}", report.getReportIdentifier().getReportTitle()); + + BOMLineHolder topLineAssembly = prepareAssemblyOrTechnicalBOM(session, report.getDualGeneric().asGenericAssemb(), report); + BOMLineHolder topLineTechnical = prepareAssemblyOrTechnicalBOM(session, report.getDualGeneric().asGeneric(), report); + + ReportDataR21 dataR21 = new ReportDataR21(topLineAssembly, topLineTechnical); + + R21Visitor visitor = new R21Visitor(report.getProductUnit(), report.getEffectivity()); + PrintParameters printParameters = visitor.makeMasterTemplate(report, dataR21); + visitor.constructDataMaps(session, printParameters, dataR21); + + LOGGER.debug("PrepareData ended on: {}", report.getReportIdentifier().getReportTitle()); + + return printParameters; + } + + private BOMLineHolder prepareAssemblyOrTechnicalBOM(final TcSession session, final Generics generics, final ExecutionR21 report) + throws KurtException { + String stringType; + switch (generics.getType()) { + case GENERIC: + stringType = "Technical view"; + break; + case GENERIC_ASSEMB: + stringType = "Assembly view"; + break; + default: + stringType = "Undefined view"; + break; + } + + TcBomObject topLineObject = new TcBomObjectFactory(session, generics.getItem(session)).create(); + TcProduct productObject = new TcProduct(session, report.getProductUnit().getProduct(session)); + int unit = report.getProductUnit().getUnit(); + EffectivityDate effectivityDate = report.getEffectivity(); + + TcRevisionRuleProperties revisionRuleProperties = new TcRevisionRuleProperties(productObject, unit, effectivityDate.isNow() ? null : effectivityDate.getDateTime()); + + TcRevisionRule revisionRule = session.findRevRule(report.getRevisionRule()); + TcRevisionRulesConfiguration revRulesConfiguration = new TcRevisionRulesConfiguration(revisionRule, revisionRuleProperties); + + // Perform the job + LOGGER.info("Data configured for the {}, now starting nomenclature resolution", stringType); + try (TcBomWindow bomWindow = session.createBomWindow(new TcBomWindowConfiguration(topLineObject, revRulesConfiguration))) { + session.setObjectPropPolicy(report.getFullPolicy()); + + BOMLineHolder unbuiltTopLine = new MultiStructureServiceCaller(session).resolve(bomWindow.topLine(), ACCEPT_ALL); + + List itemRevMaster = unbuiltTopLine.getAllItemRevMasters(); + session.loadProperties(itemRevMaster.toArray(new ModelObject[0])); + + BOMLineHolderFactory.buildTopBom(session, unbuiltTopLine, ACCEPT_ALL); + unbuiltTopLine.freeze(); + + return unbuiltTopLine; + } + catch (EmptyNomenclatureException e) { + switch (generics.getType()) { + case GENERIC: + throw new InvalidUserInputException(UserInputErrorEnum.NO_DATA_COULD_BE_EXTRACTED_FOR_GENERIC_PRODUCT_AND_UNIT, e); + case GENERIC_ASSEMB: + throw new InvalidUserInputException(UserInputErrorEnum.NO_DATA_COULD_BE_EXTRACTED_FOR_GENERIC_ASSEMB_PRODUCT_AND_UNIT, e); + default: + throw new KurtException("The TC Nomenclature Resolution returned null", e); + } + } + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r21report/ExecutionR21.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r21report/ExecutionR21.java new file mode 100644 index 0000000..98613fe --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r21report/ExecutionR21.java @@ -0,0 +1,148 @@ +package com.capgemini.reports.definition.r21report; + +import com.capgemini.framework.common.SettingsHelper; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.reports.JasperTemplate; +import com.capgemini.reports.ReportEnum; +import com.capgemini.reports.ReportLaunchTypeEnum; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.builder.R21Builder; +import com.capgemini.reports.builder.ReportBuilder; +import com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum; +import com.capgemini.reports.database.manager.MngCriteriaVal.CriteriaValue; +import com.capgemini.reports.definition.r21report.ExecutionR21.ReportDataR21; +import com.capgemini.reports.execution.AbstractExecutionReport; +import com.capgemini.reports.execution.IDataReportPreparator; +import com.capgemini.reports.printing.Printer.PrintFormat; +import com.capgemini.reports.reports.parameters.DualGenerics; +import com.capgemini.reports.reports.parameters.EffectivityDate; +import com.capgemini.reports.reports.parameters.IChecker; +import com.capgemini.reports.reports.parameters.ProductUnit; +import com.capgemini.reports.reports.parameters.checker.*; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.ArrayList; +import java.util.List; + +public class ExecutionR21 extends AbstractExecutionReport { + private static final long serialVersionUID = -2930624274965581115L; + + private static final PolicyLocation R21_POLICY_XML_LIGHT = PolicyLocation.make("R21_policy_light", "/xml/policies/r21report/R21_policy_light.xml"); + private static final PolicyLocation R21_POLICY_XML_FULL = PolicyLocation.make("R21_policy_full", "/xml/policies/r21report/R21_policy_full.xml"); + private static final String REPORT_REVISION_RULE = SettingsHelper.getPropertyWithDefaultValue("common.bom.revisionRule.REPORT_R21", DEFAULT_REVISION_RULE); + private static final int REPORT_PRIORITY = SettingsHelper.getPriority(ReportEnum.REPORT_R21); + private static final ReportLaunchTypeEnum REPORT_LAUNCH_TYPE = ReportLaunchTypeEnum.getReportLaunchType("common.launch.launchType.REPORT_R21"); + + private final ProductUnit productUnit; + private final EffectivityDate effectivity; + private final DualGenerics dualGeneric; + + public ExecutionR21(final ProductUnit aProductUnit, final DualGenerics aDualGeneric, final EffectivityDate anEffectivity) { + super(REPORT_PRIORITY, REPORT_REVISION_RULE, REPORT_LAUNCH_TYPE); + productUnit = aProductUnit; + dualGeneric = aDualGeneric; + effectivity = anEffectivity; + } + + @Override + public List getLaunchData() { + List theCriteria = new ArrayList<>(); + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.PRODUCT, productUnit.getProductID())); + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.UNIT, productUnit.getUnitStr())); + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.GENERIC, dualGeneric.asGeneric().getID())); + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.GENERIC_ASSEMB, dualGeneric.asGenericAssemb().getID())); + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.EFFECTIVITY_DATE, effectivity.formatAsInputCriteria())); + return theCriteria; + } + + @Override + public List getQuickChecks() { + // Sort the quick checks + List quickChecks = new ArrayList<>(); + quickChecks.add(new GenericExistenceChecker(dualGeneric.asGeneric())); + quickChecks.add(new GenericExistenceChecker(dualGeneric.asGenericAssemb())); + quickChecks.add(new ProductChecker(productUnit.getProductID())); + quickChecks.add(new ProductUnitChecker(productUnit)); + quickChecks.add(new EffectivityChecker(effectivity)); + return quickChecks; + } + + @Override + public PolicyLocation getPropertyPolicyForLongChecks() { + return R21_POLICY_XML_LIGHT; + } + + @Override + public PolicyLocation getFullPolicy() { + return R21_POLICY_XML_FULL; + } + + @Override + public List getLongChecks() { + // Sort the Long checks + List longChecks = new ArrayList<>(); + longChecks.add(new GenericConditionR21Checker(productUnit, dualGeneric)); + return longChecks; + } + + @Override + public ReportEnum getReportIdentifier() { + return ReportEnum.REPORT_R21; + } + + @Override + public String getSpecifiedFileName() { + String separator = "-"; + return "R21-" + dualGeneric.asGeneric().getID() + separator + dualGeneric.asGenericAssemb().getID() + + separator + productUnit.getProductID() + separator + productUnit.getUnit() + separator + + effectivity.formatAsInputCriteria(); + } + + @Override + public PrintFormat getPrintingFormat() { + return PrintFormat.XLSX; + } + + @Override + public String getTemplateLocation() { + return JasperTemplate.TEMPLATE_R21.getFilepath(); + } + + @Override + public IDataReportPreparator getDataPreparator() { + return new DataReportPreparatorR21(); + } + + @Override + public AbstractExecutionReport cloneTemplateToExecution() { + return new ExecutionR21(productUnit, dualGeneric, effectivity); + } + + @Override + public Class getReportBuilderClass() { + return R21Builder.class; + } + + public DualGenerics getDualGeneric() { + return dualGeneric; + } + + public ProductUnit getProductUnit() { + return productUnit; + } + + public EffectivityDate getEffectivity() { + return effectivity; + } + + /** + * POJO container of all data required for this report. + */ + @AllArgsConstructor + @Getter + public static class ReportDataR21 { + private final BOMLineHolder topLineAssembly; + private final BOMLineHolder topLineTechnical; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r21report/R21ReportKeys.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r21report/R21ReportKeys.java new file mode 100644 index 0000000..6f58f0f --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r21report/R21ReportKeys.java @@ -0,0 +1,38 @@ +package com.capgemini.reports.definition.r21report; + +/** + * Enumeration of the keys of a R21 report. + */ +public enum R21ReportKeys { + EFFECTIVITE, + ETUDE_REPERE_FONCTIONNEL_RECEPTEUR, + ETUDE_REVISION_REPERE_FONCTIONNEL_RECEPTEUR, + ETUDE_IDENTIFIANT_RECEPTEUR, + ETUDE_REVISION_RECEPTEUR, + ETUDE_NOM_RECEPTEUR, + ETUDE_REPERE_FONCTIONNEL_COMPOSANT, + ETUDE_REVISION_REPERE_FONCTIONNEL_COMPOSANT, + ETUDE_REF_FABRICANT_REF_SNECMA, + ETUDE_REVISION_REFERENCE, + ETUDE_TYPE_REFERENCE, + ETUDE_NOM_REFERENCE, + ETUDE_NOMBRE_REPERE_FONCTIONNEL, + ETUDE_IS_YELLOW_BACKGROUND, + ETUDE_RF_IS_YELLOW_BACKGROUND, + MONTAGE_REPERE_FONCTIONNEL_RECEPTEUR, + MONTAGE_REVISION_REPERE_FONCTIONNEL_RECEPTEUR, + MONTAGE_IDENTIFIANT_RECEPTEUR, + MONTAGE_REVISION_RECEPTEUR, + MONTAGE_NOM_RECEPTEUR, + MONTAGE_REPERE_FONCTIONNEL_COMPOSANT, + MONTAGE_REVISION_REPERE_FONCTIONNEL_COMPOSANT, + MONTAGE_REF_FABRICANT_REF_SNECMA, + MONTAGE_REVISION_REFERENCE, + MONTAGE_TYPE_REFERENCE, + MONTAGE_NOM_REFERENCE, + MONTAGE_IDENTIFIANT_RECEPTEUR_ORIGINE, + MONTAGE_NOM_RECEPTEUR_ORIGINE, + MONTAGE_NOMBRE_REPERE_FONCTIONNEL, + MONTAGE_IS_YELLOW_BACKGROUND, + MONTAGE_RF_IS_YELLOW_BACKGROUND +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r21report/visitors/R21Visitor.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r21report/visitors/R21Visitor.java new file mode 100644 index 0000000..4c4b6ce --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r21report/visitors/R21Visitor.java @@ -0,0 +1,577 @@ +package com.capgemini.reports.definition.r21report.visitors; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.bomlineholder.IBOMTree; +import com.capgemini.reports.definition.r21report.ExecutionR21; +import com.capgemini.reports.definition.r21report.ExecutionR21.ReportDataR21; +import com.capgemini.reports.definition.r21report.R21ReportKeys; +import com.capgemini.reports.definition.r21report.visitors.bomlineholder.R21BOMLineHolderVisitor; +import com.capgemini.reports.execution.mapconstructor.AbstractStaticTemplateMapConstructor; +import com.capgemini.reports.printing.PrintParameters; +import com.capgemini.reports.reports.parameters.EffectivityDate; +import com.capgemini.reports.reports.parameters.ProductUnit; +import org.apache.commons.collections.ListUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.*; + +import static com.capgemini.reports.definition.r21report.visitors.R21VisitorKeys.*; + + +public class R21Visitor extends AbstractStaticTemplateMapConstructor { + private static final long serialVersionUID = 7945453397269802050L; + private static final Logger LOGGER = LoggerFactory.getLogger(R21Visitor.class); + + private final List> listOfAssemblyLines; + private final List> listOfTechnicalLines; + + private final ProductUnit productUnit; + private final EffectivityDate effectivity; + + /** + * Constructor. + * + * @param productUnit ProductUnit + * @param effectivity EffectivityDate + */ + public R21Visitor(final ProductUnit productUnit, final EffectivityDate effectivity) { + super(); + this.productUnit = productUnit; + this.effectivity = effectivity; + this.listOfAssemblyLines = new ArrayList<>(); + this.listOfTechnicalLines = new ArrayList<>(); + } + + + @Override + public void constructDataMaps(TcSession session, final PrintParameters printParameters, final ReportDataR21 data) { + long start = System.currentTimeMillis(); + if (data.getTopLineAssembly() == null || data.getTopLineTechnical() == null) { + throw new NoSuchElementException("No Product structure found"); + } + + // Parse all the snecma objects... + List> theResultReport = visitReport(data.getTopLineAssembly(), data.getTopLineTechnical()); + printParameters.addReportData(theResultReport); + LOGGER.info(EXECUTION_TIME_XXX_MS_FOR_YYY, System.currentTimeMillis() - start, "Data Map Construction"); + } + + /** + * Visit a R21 report. + * + * @param holderAssembly BOMLineHolder + * @param holderTechnical BOMLineHolder + * @return theR21report List> the known format of the printer + */ + private List> visitReport(final BOMLineHolder holderAssembly, final BOMLineHolder holderTechnical) { + parseExpansionBomAndRemoveRFandPartAssembs(holderAssembly); + + List> assemblyResult = visitReportAssembly(holderAssembly); + List> technicalResult = visitReportTechnical(holderTechnical); + LOGGER.info("There are {} initial element(s) in the Assembly view", assemblyResult.size()); + LOGGER.info("There are {} initial element(s) in the Technical view", technicalResult.size()); + + completeReportData(assemblyResult, technicalResult); + LOGGER.info("There are {} element(s) remaining in the Assembly view", listOfAssemblyLines.size()); + LOGGER.info("There are {} element(s) remaining in the Technical view", listOfTechnicalLines.size()); + + List> theR21report = createReport(); + + // Add the effectivity column + addEffectivityToReport(theR21report); + + // Translate the report in a known format for the printer and return it + return translate(theR21report); + } + + /** + * Create a R21 report. + * + * @return theR21report List> + */ + private List> createReport() { + List> theR21report; + if ((listOfAssemblyLines.isEmpty()) || (listOfTechnicalLines.isEmpty())) { + // Create the empty line if the Assembly or Technical are empty + theR21report = createEmptyLine(); + } + else { + // Retrieve the R21 report properties + theR21report = getListOfReportLines(listOfAssemblyLines, listOfTechnicalLines); + } + return theR21report; + } + + /** + * Create an empty line. + * + * @return List> a list with the only empty map + */ + private List> createEmptyLine() { + List> theR21report = new ArrayList<>(); + Map firstLine = new EnumMap<>(R21ReportKeys.class); + + // Technical view + firstLine.put(R21ReportKeys.ETUDE_REPERE_FONCTIONNEL_RECEPTEUR, ""); + firstLine.put(R21ReportKeys.ETUDE_REVISION_REPERE_FONCTIONNEL_RECEPTEUR, ""); + firstLine.put(R21ReportKeys.ETUDE_IDENTIFIANT_RECEPTEUR, ""); + firstLine.put(R21ReportKeys.ETUDE_REVISION_RECEPTEUR, ""); + firstLine.put(R21ReportKeys.ETUDE_NOM_RECEPTEUR, ""); + firstLine.put(R21ReportKeys.ETUDE_REPERE_FONCTIONNEL_COMPOSANT, ""); + firstLine.put(R21ReportKeys.ETUDE_REVISION_REPERE_FONCTIONNEL_COMPOSANT, ""); + firstLine.put(R21ReportKeys.ETUDE_REF_FABRICANT_REF_SNECMA, ""); + firstLine.put(R21ReportKeys.ETUDE_REVISION_REFERENCE, ""); + firstLine.put(R21ReportKeys.ETUDE_TYPE_REFERENCE, ""); + firstLine.put(R21ReportKeys.ETUDE_NOM_REFERENCE, ""); + firstLine.put(R21ReportKeys.ETUDE_NOMBRE_REPERE_FONCTIONNEL, ""); + + // Assembly view + firstLine.put(R21ReportKeys.MONTAGE_REPERE_FONCTIONNEL_RECEPTEUR, ""); + firstLine.put(R21ReportKeys.MONTAGE_REVISION_REPERE_FONCTIONNEL_RECEPTEUR, ""); + firstLine.put(R21ReportKeys.MONTAGE_IDENTIFIANT_RECEPTEUR, ""); + firstLine.put(R21ReportKeys.MONTAGE_REVISION_RECEPTEUR, ""); + firstLine.put(R21ReportKeys.MONTAGE_NOM_RECEPTEUR, ""); + firstLine.put(R21ReportKeys.MONTAGE_REPERE_FONCTIONNEL_COMPOSANT, ""); + firstLine.put(R21ReportKeys.MONTAGE_REVISION_REPERE_FONCTIONNEL_COMPOSANT, ""); + firstLine.put(R21ReportKeys.MONTAGE_REF_FABRICANT_REF_SNECMA, ""); + firstLine.put(R21ReportKeys.MONTAGE_REVISION_REFERENCE, ""); + firstLine.put(R21ReportKeys.MONTAGE_TYPE_REFERENCE, ""); + firstLine.put(R21ReportKeys.MONTAGE_NOM_REFERENCE, ""); + firstLine.put(R21ReportKeys.MONTAGE_IDENTIFIANT_RECEPTEUR_ORIGINE, ""); + firstLine.put(R21ReportKeys.MONTAGE_NOM_RECEPTEUR_ORIGINE, ""); + firstLine.put(R21ReportKeys.MONTAGE_NOMBRE_REPERE_FONCTIONNEL, ""); + + theR21report.add(firstLine); + return theR21report; + } + + /** + * Create the R21 report by mixing the Assembly list and the Technical list. + */ + private List> getListOfReportLines(final List> assemblyList, + final List> technicalList) { + List> theR21report = new ArrayList<>(); + + // Create the Technical view in the R21 report + for (Map curentMapInTechnicalList : technicalList) { + theR21report.add(makeTechnicalLine(curentMapInTechnicalList)); + } + + // Create the Assembly view in the R21 report + for (Map curentMapInAssemblyList : assemblyList) { + theR21report.add(makeAssemblyLine(curentMapInAssemblyList)); + } + return theR21report; + } + + private Map makeAssemblyLine(final Map curentMapInAssemblyList) { + Map theLine = new EnumMap<>(R21ReportKeys.class); + + theLine.put(R21ReportKeys.MONTAGE_REPERE_FONCTIONNEL_RECEPTEUR, curentMapInAssemblyList.get(REPERE_FONCTIONNEL_RECEPTEUR)); + theLine.put(R21ReportKeys.MONTAGE_REVISION_REPERE_FONCTIONNEL_RECEPTEUR, curentMapInAssemblyList.get(REVISION_REPERE_FONCTIONNEL_RECEPTEUR)); + theLine.put(R21ReportKeys.MONTAGE_IDENTIFIANT_RECEPTEUR, curentMapInAssemblyList.get(IDENTIFIANT_RECEPTEUR)); + theLine.put(R21ReportKeys.MONTAGE_REVISION_RECEPTEUR, curentMapInAssemblyList.get(REVISION_RECEPTEUR)); + theLine.put(R21ReportKeys.MONTAGE_NOM_RECEPTEUR, curentMapInAssemblyList.get(NOM_RECEPTEUR)); + theLine.put(R21ReportKeys.MONTAGE_REPERE_FONCTIONNEL_COMPOSANT, curentMapInAssemblyList.get(REPERE_FONCTIONNEL_COMPOSANT)); + theLine.put(R21ReportKeys.MONTAGE_REVISION_REPERE_FONCTIONNEL_COMPOSANT, curentMapInAssemblyList.get(REVISION_REPERE_FONCTIONNEL_COMPOSANT)); + theLine.put(R21ReportKeys.MONTAGE_REF_FABRICANT_REF_SNECMA, curentMapInAssemblyList.get(REF_FABRICANT_REF_SNECMA)); + theLine.put(R21ReportKeys.MONTAGE_REVISION_REFERENCE, curentMapInAssemblyList.get(REVISION_REFERENCE)); + theLine.put(R21ReportKeys.MONTAGE_TYPE_REFERENCE, curentMapInAssemblyList.get(TYPE_REFERENCE)); + theLine.put(R21ReportKeys.MONTAGE_NOM_REFERENCE, curentMapInAssemblyList.get(NOM_REFERENCE)); + theLine.put(R21ReportKeys.MONTAGE_IDENTIFIANT_RECEPTEUR_ORIGINE, curentMapInAssemblyList.get(IDENTIFIANT_RECEPTEUR_ORIGINE)); + theLine.put(R21ReportKeys.MONTAGE_NOM_RECEPTEUR_ORIGINE, curentMapInAssemblyList.get(NOM_RECEPTEUR_ORIGINE)); + theLine.put(R21ReportKeys.MONTAGE_NOMBRE_REPERE_FONCTIONNEL, curentMapInAssemblyList.get(NOMBRE_REPERE_FONCTIONNEL)); + theLine.put(R21ReportKeys.MONTAGE_IS_YELLOW_BACKGROUND, curentMapInAssemblyList.get(IS_YELLOW_BACKGROUND)); + theLine.put(R21ReportKeys.MONTAGE_RF_IS_YELLOW_BACKGROUND, curentMapInAssemblyList.get(RF_IS_YELLOW_BACKGROUND)); + + return theLine; + } + + private Map makeTechnicalLine(final Map curentMapInTechnicalList) { + Map theLine = new EnumMap<>(R21ReportKeys.class); + + theLine.put(R21ReportKeys.ETUDE_REPERE_FONCTIONNEL_RECEPTEUR, curentMapInTechnicalList.get(REPERE_FONCTIONNEL_RECEPTEUR)); + theLine.put(R21ReportKeys.ETUDE_REVISION_REPERE_FONCTIONNEL_RECEPTEUR, curentMapInTechnicalList.get(REVISION_REPERE_FONCTIONNEL_RECEPTEUR)); + theLine.put(R21ReportKeys.ETUDE_IDENTIFIANT_RECEPTEUR, curentMapInTechnicalList.get(IDENTIFIANT_RECEPTEUR)); + theLine.put(R21ReportKeys.ETUDE_REVISION_RECEPTEUR, curentMapInTechnicalList.get(REVISION_RECEPTEUR)); + theLine.put(R21ReportKeys.ETUDE_NOM_RECEPTEUR, curentMapInTechnicalList.get(NOM_RECEPTEUR)); + theLine.put(R21ReportKeys.ETUDE_REPERE_FONCTIONNEL_COMPOSANT, curentMapInTechnicalList.get(REPERE_FONCTIONNEL_COMPOSANT)); + theLine.put(R21ReportKeys.ETUDE_REVISION_REPERE_FONCTIONNEL_COMPOSANT, curentMapInTechnicalList.get(REVISION_REPERE_FONCTIONNEL_COMPOSANT)); + theLine.put(R21ReportKeys.ETUDE_REF_FABRICANT_REF_SNECMA, curentMapInTechnicalList.get(REF_FABRICANT_REF_SNECMA)); + theLine.put(R21ReportKeys.ETUDE_REVISION_REFERENCE, curentMapInTechnicalList.get(REVISION_REFERENCE)); + theLine.put(R21ReportKeys.ETUDE_TYPE_REFERENCE, curentMapInTechnicalList.get(TYPE_REFERENCE)); + theLine.put(R21ReportKeys.ETUDE_NOM_REFERENCE, curentMapInTechnicalList.get(NOM_REFERENCE)); + theLine.put(R21ReportKeys.ETUDE_NOMBRE_REPERE_FONCTIONNEL, curentMapInTechnicalList.get(NOMBRE_REPERE_FONCTIONNEL)); + theLine.put(R21ReportKeys.ETUDE_IS_YELLOW_BACKGROUND, curentMapInTechnicalList.get(IS_YELLOW_BACKGROUND)); + theLine.put(R21ReportKeys.ETUDE_RF_IS_YELLOW_BACKGROUND, curentMapInTechnicalList.get(RF_IS_YELLOW_BACKGROUND)); + + return theLine; + } + + /** + * Parse the expansion Bom and remove all the RF Part Assemb and the Part Assemb. + * + * @param aBom BOMLineHolder + */ + private void parseExpansionBomAndRemoveRFandPartAssembs(final BOMLineHolder aBom) { + // Parse the expansion Bom + List children = aBom.getBomChilds(); + if (!children.isEmpty()) { + for (BOMLineHolder actualChild : aBom.getBomChilds()) { + parseExpansionBomAndRemoveRFandPartAssembs(actualChild); + } + } + + // Treatment of the object by raising the expansion bom + // Avoid the ConcurrentModificationExecption by this way + if ((aBom.getSnecmaObject() != null) && (aBom.getParentBomLine() != null)) { + String parentType = aBom.getParentBomLine().getSnecmaObject().getType(); + + // Modify the value parent of the Bom + if (SnecmaObjectTypes.RF_PART_ASSEMB_REVISION.equals(parentType) || SnecmaObjectTypes.PART_ASSEMB_REVISION.equals(parentType)) { + BOMLineHolder newParentFound = getParentNoAssembs(aBom); + aBom.setParent(newParentFound); + } + } + + // Modify the value bomChildMap of the Bom + if (!children.isEmpty()) { + findAssembChildAndRemoveIt(aBom); + } + } + + /** + * Find RF Part Assemb or Part Assemb children.
    + * Remove this Assemb children and add their own children to the Bom's children. + * + * @param aBom BOMLineHolder + */ + private void findAssembChildAndRemoveIt(final BOMLineHolder aBom) { + List children = aBom.getBomChilds(); + List removedChildren = new ArrayList<>(); + List addedChildren = new ArrayList<>(); + + // Check if there are a RF Part Assemb or Part Assemb children + if (!children.isEmpty()) { + for (BOMLineHolder child : children) { + if (child.getSnecmaObject() != null) { + String entryChildType = child.getSnecmaObject().getType(); + if (SnecmaObjectTypes.RF_PART_ASSEMB_REVISION.equals(entryChildType) || SnecmaObjectTypes.PART_ASSEMB_REVISION.equals(entryChildType)) { + // List the RF Part Assemb or Part Assemb children + removedChildren.add(child); + + // Retrieve the bomChildMap of the RF Part Assemb or Part Assemb children + // No need to remove the Admin under a RF Part Assemb + // Because, for a R21 report, the Admin are treated only for a RF Part Assemb + addedChildren.addAll(child.getBomChilds()); + } + } + } + } + + // Removed the RF Part Assemb or Part Assemb children + if (!removedChildren.isEmpty()) { + for (BOMLineHolder toRemove : removedChildren) { + children.remove(toRemove); + } + } + + // Add the bomChildMap of the removed RF Part Assemb or Part Assemb children + // to the Bom's bomChildMap + if (!addedChildren.isEmpty()) { + children.addAll(addedChildren); + } + } + + /** + * Get a parent which is not a RF Part Assemb or a Part Assemb. + * + * @param aBom BOMLineHolder + */ + private BOMLineHolder getParentNoAssembs(final IBOMTree aBom) { + String parentBomType = aBom.getParentBomLine().getSnecmaObject().getType(); + if (!SnecmaObjectTypes.RF_PART_ASSEMB_REVISION.equals(parentBomType) + && !SnecmaObjectTypes.PART_ASSEMB_REVISION.equals(parentBomType)) { + return new BOMLineHolder(aBom); + } + else { + return getParentNoAssembs(aBom.getParentBomLine()); + } + } + + /** + * Find an Remove duplicate keys between two maps. + * + * @param assemblyList a List of key-values that exist in assembly view + * @param technicalList a List of key-values that exist in technical view + */ + private void completeReportData(final List> assemblyList, final List> technicalList) { + List comparativeAssemblyList = transformListForComparaisonInRemoveKeys(assemblyList); + List comparativeTechnicalList = transformListForComparaisonInRemoveKeys(technicalList); + + List consolidatedAssemblyList = countDuplicatedLines(comparativeAssemblyList); + List consolidateTechnicalList = countDuplicatedLines(comparativeTechnicalList); + + List theRemovedList = ListUtils.intersection(consolidatedAssemblyList, consolidateTechnicalList); + List uniqueAssembLines = ListUtils.removeAll(consolidatedAssemblyList, theRemovedList); + List uniqueTechnicalLines = ListUtils.removeAll(consolidateTechnicalList, theRemovedList); + + addReceptorOriginsData(uniqueAssembLines, uniqueTechnicalLines); + addBackgroundColor(uniqueAssembLines, uniqueTechnicalLines); + + listOfAssemblyLines.addAll(uniqueAssembLines); + listOfTechnicalLines.addAll(uniqueTechnicalLines); + } + + private void addBackgroundColor(List uniqueAssembLines, List uniqueTechnicalLines) { + addBackgroundColorAttributes(uniqueAssembLines, uniqueTechnicalLines); + addBackgroundColorAttributes(uniqueTechnicalLines, uniqueAssembLines); + } + + private void addBackgroundColorAttributes(List toCompare, List from) { + for (SuperMap fromSuperMap : from) { + SuperMap toCompareSuperMap = getSuperMapEquals(toCompare, fromSuperMap); + if (fromSuperMap.containsKey(NOMBRE_REPERE_FONCTIONNEL) + && Integer.parseInt(fromSuperMap.get(NOMBRE_REPERE_FONCTIONNEL)) > 1 + && toCompareSuperMap.isEmpty()) { + fromSuperMap.put(R21VisitorKeys.IS_YELLOW_BACKGROUND, "true"); + fromSuperMap.put(R21VisitorKeys.RF_IS_YELLOW_BACKGROUND, "true"); + } + else if (toCompareSuperMap.containsKey(NOMBRE_REPERE_FONCTIONNEL) + && fromSuperMap.containsKey(NOMBRE_REPERE_FONCTIONNEL) + && Integer.parseInt(toCompareSuperMap.get(NOMBRE_REPERE_FONCTIONNEL)) != Integer.parseInt(fromSuperMap.get(NOMBRE_REPERE_FONCTIONNEL))) { + fromSuperMap.put(R21VisitorKeys.IS_YELLOW_BACKGROUND, "true"); + } + } + } + + private void addReceptorOriginsData(List uniqueAssembLines, List uniqueTechnicalLines) { + for (SuperMap uniqueAssembLine : uniqueAssembLines) { + SuperMap superMap = getSuperMapOnlyDiffByRfReceptor(uniqueTechnicalLines, uniqueAssembLine); + uniqueAssembLine.put(IDENTIFIANT_RECEPTEUR_ORIGINE, superMap.containsKey(IDENTIFIANT_RECEPTEUR) ? superMap.get(IDENTIFIANT_RECEPTEUR) : ""); + uniqueAssembLine.put(NOM_RECEPTEUR_ORIGINE, superMap.containsKey(NOM_RECEPTEUR) ? superMap.get(NOM_RECEPTEUR) : ""); + } + } + + private SuperMap getSuperMapOnlyDiffByRfReceptor(List superMaps, SuperMap uniqueLine) { + for (SuperMap superMap : superMaps) { + if (uniqueLine.isOnlyDiffByRfReceptor(superMap) + && !uniqueLine.get(IDENTIFIANT_RECEPTEUR).equals(superMap.get(IDENTIFIANT_RECEPTEUR)) + && !uniqueLine.get(NOM_RECEPTEUR).equals(superMap.get(NOM_RECEPTEUR)) + ) { + return superMap; + } + } + return new SuperMap(); + } + + private SuperMap getSuperMapEquals(List superMaps, SuperMap uniqueLine) { + for (SuperMap superMap : superMaps) { + if (uniqueLine.isEquals(superMap)) { + return superMap; + } + } + return new SuperMap(); + } + + private List countDuplicatedLines(List comparativeList) { + List consolidatedList = new ArrayList<>(); + for (SuperMap map : comparativeList) { + if (consolidatedList.contains(map)) { + SuperMap superMap = consolidatedList.get(consolidatedList.indexOf(map)); + superMap.put(NOMBRE_REPERE_FONCTIONNEL, Integer.toString(Integer.parseInt(superMap.get(NOMBRE_REPERE_FONCTIONNEL)) + 1)); + } + else { + map.put(NOMBRE_REPERE_FONCTIONNEL, Integer.toString(1)); + consolidatedList.add(map); + } + } + return consolidatedList; + } + + private List transformListForComparaisonInRemoveKeys(final List> aListToTransform) { + List aListToReturn = new ArrayList<>(); + + for (Map currentMap : aListToTransform) { + SuperMap simpleMap = new SuperMap(); + simpleMap.putAll(currentMap); + aListToReturn.add(simpleMap); + } + return aListToReturn; + } + + /** + * Visit an Assembly BOM. + * + * @param holderAssembly BOMLineHolder + */ + private List> visitReportAssembly(final BOMLineHolder holderAssembly) { + return new R21BOMLineHolderVisitor().visitTopReceptorBom(holderAssembly); + } + + /** + * Visit a Technical BOM. + * + * @param holderTechnical BOMLineHolder + */ + private List> visitReportTechnical(final BOMLineHolder holderTechnical) { + return new R21BOMLineHolderVisitor().visitTopReceptorBom(holderTechnical); + } + + /** + * Add the value of the column TcEffectivity to the Report. + */ + private void addEffectivityToReport(final List> theResultReport) { + // Create the value of the effectivity for the R21 report + String theEffectivity = productUnit.getProductID() + " / " + productUnit.getUnit() + " / " + formatEffectivityDate(effectivity); + + // Put the effectivity in all the lines of the report + for (Map actualMap : theResultReport) { + actualMap.put(R21ReportKeys.EFFECTIVITE, theEffectivity); + } + } + + private static String formatEffectivityDate(final EffectivityDate eff) { + Calendar date; + if (eff.isNow()) { + date = Calendar.getInstance(); + } + else { + date = eff.getDateTime(); + } + DateFormat dateFormat = new SimpleDateFormat("dd-MMMMM-yy", Locale.FRENCH); + return dateFormat.format(date.getTime()); + } + + /** + * Translate the specific result of the visitor into something the printer can understand. + */ + private List> translate(final List> theActualReportList) { + // Construct the map list expected by the printer + List> printerMaps = new ArrayList<>(); + for (Map visitorMap : theActualReportList) { + Map printerMap = new HashMap<>(); + for (R21ReportKeys key : R21ReportKeys.values()) { + printerMap.put(key.toString(), visitorMap.get(key)); + } + printerMaps.add(printerMap); + } + + return printerMaps; + } + + @Override + public boolean equals(Object o) { + if (o == this) return true; + if (!(o instanceof R21Visitor)) return false; + R21Visitor other = (R21Visitor) o; + if (!other.canEqual(this)) return false; + if (!super.equals(o)) return false; + if (this.listOfAssemblyLines == null ? other.listOfAssemblyLines != null : !this.listOfAssemblyLines.equals(other.listOfAssemblyLines)) + return false; + if (this.listOfTechnicalLines == null ? other.listOfTechnicalLines != null : !this.listOfTechnicalLines.equals(other.listOfTechnicalLines)) + return false; + if (this.productUnit == null ? other.productUnit != null : !this.productUnit.equals(other.productUnit)) + return false; + return this.effectivity == null ? other.effectivity == null : this.effectivity.equals(other.effectivity); + } + + @Override + public int hashCode() { + final int PRIME = 59; + int result = 1; + result = result * PRIME + super.hashCode(); + result = result * PRIME + (this.listOfAssemblyLines == null ? 43 : this.listOfAssemblyLines.hashCode()); + result = result * PRIME + (this.listOfTechnicalLines == null ? 43 : this.listOfTechnicalLines.hashCode()); + result = result * PRIME + (this.productUnit == null ? 43 : this.productUnit.hashCode()); + result = result * PRIME + (this.effectivity == null ? 43 : this.effectivity.hashCode()); + return result; + } + + @Override + protected boolean canEqual(Object other) { + return other instanceof R21Visitor; + } + + /** + * This class is a HashMap with a special {@code equals} method. + */ + class SuperMap extends HashMap { + + private static final long serialVersionUID = 7843304491480106535L; + + @Override + public boolean equals(final Object other) { + if (other instanceof SuperMap) { + Map otherMap = (SuperMap) other; + for (Map.Entry entry : this.entrySet()) { + R21VisitorKeys key = entry.getKey(); + if (key != IDENTIFIANT_RECEPTEUR + && key != REVISION_RECEPTEUR + && key != NOM_RECEPTEUR + && key != TYPE_REFERENCE + && key != NOM_REFERENCE + && key != IS_YELLOW_BACKGROUND + && key != RF_IS_YELLOW_BACKGROUND + && key != NOM_RECEPTEUR_ORIGINE + && key != IDENTIFIANT_RECEPTEUR_ORIGINE + && !entry.getValue().equals(otherMap.get(key))) { + return false; + } + } + return true; + } + else { + return false; + } + } + + boolean isEquals(SuperMap otherMap) { + for (Map.Entry entry : this.entrySet()) { + R21VisitorKeys key = entry.getKey(); + if (key != IDENTIFIANT_RECEPTEUR + && key != REVISION_RECEPTEUR + && key != NOM_RECEPTEUR + && key != TYPE_REFERENCE + && key != NOM_REFERENCE + && key != NOMBRE_REPERE_FONCTIONNEL + && key != IS_YELLOW_BACKGROUND + && key != RF_IS_YELLOW_BACKGROUND + && key != NOM_RECEPTEUR_ORIGINE + && key != IDENTIFIANT_RECEPTEUR_ORIGINE + && !entry.getValue().equals(otherMap.get(key))) { + return false; + } + } + return true; + } + + boolean isOnlyDiffByRfReceptor(SuperMap otherMap) { + for (Map.Entry entry : this.entrySet()) { + R21VisitorKeys key = entry.getKey(); + if ( + key != REPERE_FONCTIONNEL_RECEPTEUR + && key != REVISION_REPERE_FONCTIONNEL_RECEPTEUR + && key != IDENTIFIANT_RECEPTEUR + && key != REVISION_RECEPTEUR + && key != NOM_RECEPTEUR + && key != TYPE_REFERENCE + && key != NOM_REFERENCE + && key != NOMBRE_REPERE_FONCTIONNEL + && key != IS_YELLOW_BACKGROUND + && key != RF_IS_YELLOW_BACKGROUND + && key != NOM_RECEPTEUR_ORIGINE + && key != IDENTIFIANT_RECEPTEUR_ORIGINE + && !entry.getValue().equals(otherMap.get(key))) { + return false; + } + } + return true; + } + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r21report/visitors/R21VisitorKeys.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r21report/visitors/R21VisitorKeys.java new file mode 100644 index 0000000..74acbbb --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r21report/visitors/R21VisitorKeys.java @@ -0,0 +1,20 @@ +package com.capgemini.reports.definition.r21report.visitors; + +public enum R21VisitorKeys { + REPERE_FONCTIONNEL_RECEPTEUR, + REVISION_REPERE_FONCTIONNEL_RECEPTEUR, + IDENTIFIANT_RECEPTEUR, + REVISION_RECEPTEUR, + NOM_RECEPTEUR, + REPERE_FONCTIONNEL_COMPOSANT, + REVISION_REPERE_FONCTIONNEL_COMPOSANT, + REF_FABRICANT_REF_SNECMA, + REVISION_REFERENCE, + TYPE_REFERENCE, + NOM_REFERENCE, + NOMBRE_REPERE_FONCTIONNEL, + IDENTIFIANT_RECEPTEUR_ORIGINE, + NOM_RECEPTEUR_ORIGINE, + IS_YELLOW_BACKGROUND, + RF_IS_YELLOW_BACKGROUND +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r21report/visitors/bomlineholder/R21AltOrDetBehaviour.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r21report/visitors/bomlineholder/R21AltOrDetBehaviour.java new file mode 100644 index 0000000..3c267a8 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r21report/visitors/bomlineholder/R21AltOrDetBehaviour.java @@ -0,0 +1,36 @@ +package com.capgemini.reports.definition.r21report.visitors.bomlineholder; + +import com.capgemini.reports.bomlineholder.processor.AltOrDetBehaviour; +import com.capgemini.reports.definition.r21report.visitors.R21VisitorKeys; + +import java.util.Map; + +/** + * This class defines the behaviour of the R21 reprot regarding Alts or Dets: it does nothing at all. + */ +public class R21AltOrDetBehaviour implements AltOrDetBehaviour { + + private static final long serialVersionUID = 5831924152460249403L; + + @Override + public boolean shouldVisitPartsInPseudoFolder() { + // No use in the R21 report + return false; + } + + @Override + public boolean shouldVisitPartsBelowAlt() { + // No use in the R21 report + return false; + } + + @Override + public void treatPartsInPseudoFolder(final Map map) { + // No use in the R21 report + } + + @Override + public void treatAlternateOrDETAsReceptor(final Map receptorMap) { + // No use in the R21 report + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r21report/visitors/bomlineholder/R21BOMLineHolderVisitor.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r21report/visitors/bomlineholder/R21BOMLineHolderVisitor.java new file mode 100644 index 0000000..d33eaa2 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r21report/visitors/bomlineholder/R21BOMLineHolderVisitor.java @@ -0,0 +1,71 @@ +package com.capgemini.reports.definition.r21report.visitors.bomlineholder; + +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.bomlineholder.visitor.AbstractBOMLineHolderVisitor; +import com.capgemini.reports.definition.r21report.visitors.R21VisitorKeys; +import com.capgemini.reports.definition.r21report.visitors.snecmaobject.R21ComponentVisitor; +import com.capgemini.reports.definition.r21report.visitors.snecmaobject.R21ReceptorVisitor; +import com.capgemini.reports.releasestatus.EffectivityBehaviourHelper; +import lombok.EqualsAndHashCode; +import lombok.extern.slf4j.Slf4j; + +import java.util.Map; + +/** + * Visitor of an expansion of BOMLineHolder for the R21 report. + */ +@Slf4j +@EqualsAndHashCode(callSuper = true) +public class R21BOMLineHolderVisitor extends AbstractBOMLineHolderVisitor { + private static final long serialVersionUID = -2637811314864998456L; + + public R21BOMLineHolderVisitor() { + super(new R21ReceptorVisitor(), new R21ComponentVisitor(), EffectivityBehaviourHelper.visitOnlyUnitManagedParts(), + new R21AltOrDetBehaviour(), true, false, false); + } + + @Override + protected Map visitThisReceptor(final BOMLineHolder aBomLine) { + return aBomLine.getSnecmaObject().accept(receptorVisitor); + } + + @Override + protected Map visitThisComponent(final BOMLineHolder aBomLine) { + return aBomLine.getSnecmaObject().accept(componentVisitor); + } + + @Override + protected void mergeReceptorAndRepereReceptor(final Map aReceptor, final Map aRepereReceptor) { + aReceptor.putAll(aRepereReceptor); + } + + @Override + protected void mergeComponentAndRepereComponent(final Map aComponent, final Map aRepereComponent) { + aComponent.putAll(aRepereComponent); + } + + @Override + protected void mergeRepereReceptorandAdmin(final Map aRepereReceptor, final Map anAdmin) { + // No used in the R21 report + } + + @Override + protected void mergeRepereComponentandAdmin(final Map aRepereComponent, final Map anAdmin) { + // No used in the R21 report + } + + @Override + protected void addToReport(final Map aReceptor, final Map aComponent) { + // Put the Receptor and Repere Receptor in the Component and modify the Component + // Do not modify the receptor + aComponent.putAll(aReceptor); + + // Add to the R21 report + theReportTable.add(aComponent); + } + + @Override + protected void visitSpecificFirstLine(final BOMLineHolder bomHolder) { + // No use for R21 report + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r21report/visitors/snecmaobject/R21ComponentVisitor.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r21report/visitors/snecmaobject/R21ComponentVisitor.java new file mode 100644 index 0000000..165d0a1 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r21report/visitors/snecmaobject/R21ComponentVisitor.java @@ -0,0 +1,157 @@ +package com.capgemini.reports.definition.r21report.visitors.snecmaobject; + +import com.capgemini.reports.definition.r21report.visitors.R21VisitorKeys; +import com.capgemini.reports.snecmaobjects.AbstractSnecmaObject; +import com.capgemini.reports.snecmaobjects.admin.RFAdminAGRevision; +import com.capgemini.reports.snecmaobjects.admin.RFAdminAPRevision; +import com.capgemini.reports.snecmaobjects.admin.RFAdminARevision; +import com.capgemini.reports.snecmaobjects.admin.RFAdminRevision; +import com.capgemini.reports.snecmaobjects.descriptif.DescriptifRevision; +import com.capgemini.reports.snecmaobjects.generic.GenericAssembRevision; +import com.capgemini.reports.snecmaobjects.generic.GenericRevision; +import com.capgemini.reports.snecmaobjects.mockup.MockupRevision; +import com.capgemini.reports.snecmaobjects.part.*; +import com.capgemini.reports.snecmaobjects.product.ProductRevision; +import com.capgemini.reports.snecmaobjects.rf.RFGenericRevision; +import com.capgemini.reports.snecmaobjects.rf.RFPartAssembRevision; +import com.capgemini.reports.snecmaobjects.rf.RFPartRevision; +import com.capgemini.reports.snecmaobjects.supermodel.SuperModelRevision; +import com.capgemini.reports.snecmaobjects.visitor.IComponentVisitor; + +import java.util.EnumMap; +import java.util.Map; + +/** + * Visit a Component for the R21 report. + */ +public class R21ComponentVisitor implements IComponentVisitor> { + private static final long serialVersionUID = -4065760039190332050L; + + private static String formatType(final String type) { + return type.substring(0, type.length() - " Revision".length()); + } + + @Override + public Map visitComponent(final ProductRevision aProductRev) { + return getComponentProperties(aProductRev); + } + + @Override + public Map visitComponent(final GenericRevision aGenericRev) { + return getComponentProperties(aGenericRev); + } + + @Override + public Map visitComponent(SuperModelRevision aSuperModelRev) { + return null; + } + + @Override + public Map visitComponent(final GenericAssembRevision aGenericAssembRev) { + return getComponentProperties(aGenericAssembRev); + } + + @Override + public Map visitComponent(final AlternateRevision aAlternateRev) { + return getComponentProperties(aAlternateRev); + } + + @Override + public Map visitComponent(final DETRevision aDetRev) { + return getComponentProperties(aDetRev); + } + + @Override + public Map visitComponent(final PartAeroRevision aPartAeroRev) { + return getComponentProperties(aPartAeroRev); + } + + @Override + public Map visitComponent(final PartNoAeroRevision aPartNoAeroRev) { + return getComponentProperties(aPartNoAeroRev); + } + + @Override + public Map visitComponent(final PartAssembRevision aPartAssembRev) { + return getComponentProperties(aPartAssembRev); + } + + @Override + public Map visitComponent(final PartMatRevision aPartMatRev) { + return getComponentProperties(aPartMatRev); + } + + @Override + public Map visitComponent(final StandardRevision aStandardRev) { + return getComponentProperties(aStandardRev); + } + + @Override + public Map visitComponent(final RFGenericRevision aRfGenericRev) { + return getComponentRepereProperties(aRfGenericRev); + } + + @Override + public Map visitComponent(final RFPartAssembRevision aRfPartAssembRev) { + return getComponentRepereProperties(aRfPartAssembRev); + } + + @Override + public Map visitComponent(final RFPartRevision aRfPartRev) { + return getComponentRepereProperties(aRfPartRev); + } + + @Override + public Map visitComponent(final RFAdminRevision aRfAdminRev) { + return new EnumMap<>(R21VisitorKeys.class); + } + + @Override + public Map visitComponent(final RFAdminARevision aRfAdminARev) { + return new EnumMap<>(R21VisitorKeys.class); + } + + @Override + public Map visitComponent(final RFAdminAPRevision aRfAdminAPRev) { + return new EnumMap<>(R21VisitorKeys.class); + } + + @Override + public Map visitComponent(final RFAdminAGRevision aRfAdminAGRev) { + return new EnumMap<>(R21VisitorKeys.class); + } + + /** + * Recover the Component properties to make a R21 report. + */ + private Map getComponentProperties(final AbstractSnecmaObject aPartOrGeneric) { + Map theMap = new EnumMap<>(R21VisitorKeys.class); + theMap.put(R21VisitorKeys.REF_FABRICANT_REF_SNECMA, aPartOrGeneric.getItemId()); + theMap.put(R21VisitorKeys.REVISION_REFERENCE, aPartOrGeneric.getRevisionId()); + theMap.put(R21VisitorKeys.TYPE_REFERENCE, formatType(aPartOrGeneric.getType())); + theMap.put(R21VisitorKeys.NOM_REFERENCE, aPartOrGeneric.getName()); + return theMap; + } + + /** + * Recover the Component Repere properties to make a R21 report. + */ + private Map getComponentRepereProperties(final AbstractSnecmaObject aRf) { + Map theMap = new EnumMap<>(R21VisitorKeys.class); + theMap.put(R21VisitorKeys.REPERE_FONCTIONNEL_COMPOSANT, aRf.getName()); + theMap.put(R21VisitorKeys.REVISION_REPERE_FONCTIONNEL_COMPOSANT, aRf.getRevisionId()); + return theMap; + } + + @Override + public Map visitComponent(final MockupRevision aMockupRev) { + // This object is not use in this report + return null; + } + + @Override + public Map visitComponent(final DescriptifRevision aDescriptifRev) { + // This object is not use in this report + return null; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r21report/visitors/snecmaobject/R21ReceptorVisitor.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r21report/visitors/snecmaobject/R21ReceptorVisitor.java new file mode 100644 index 0000000..c5c39be --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r21report/visitors/snecmaobject/R21ReceptorVisitor.java @@ -0,0 +1,158 @@ +package com.capgemini.reports.definition.r21report.visitors.snecmaobject; + +import com.capgemini.reports.definition.r21report.visitors.R21VisitorKeys; +import com.capgemini.reports.snecmaobjects.AbstractSnecmaObject; +import com.capgemini.reports.snecmaobjects.admin.RFAdminAGRevision; +import com.capgemini.reports.snecmaobjects.admin.RFAdminAPRevision; +import com.capgemini.reports.snecmaobjects.admin.RFAdminARevision; +import com.capgemini.reports.snecmaobjects.admin.RFAdminRevision; +import com.capgemini.reports.snecmaobjects.descriptif.DescriptifRevision; +import com.capgemini.reports.snecmaobjects.generic.GenericAssembRevision; +import com.capgemini.reports.snecmaobjects.generic.GenericRevision; +import com.capgemini.reports.snecmaobjects.mockup.MockupRevision; +import com.capgemini.reports.snecmaobjects.part.*; +import com.capgemini.reports.snecmaobjects.product.ProductRevision; +import com.capgemini.reports.snecmaobjects.rf.RFGenericRevision; +import com.capgemini.reports.snecmaobjects.rf.RFPartAssembRevision; +import com.capgemini.reports.snecmaobjects.rf.RFPartRevision; +import com.capgemini.reports.snecmaobjects.supermodel.SuperModelRevision; +import com.capgemini.reports.snecmaobjects.visitor.IReceptorVisitor; + +import java.util.EnumMap; +import java.util.Map; + +/** + * Visit a Receptor for the R21 report. + */ +public class R21ReceptorVisitor implements IReceptorVisitor> { + private static final long serialVersionUID = -6416544750772729050L; + + @Override + public Map visitReceptor(final ProductRevision aProductRev) { + return getReceptorProperties(aProductRev); + } + + @Override + public Map visitReceptor(final GenericRevision aGenericRev) { + return getReceptorProperties(aGenericRev); + } + + @Override + public Map visitReceptor(final GenericAssembRevision aGenericAssembRev) { + return getReceptorProperties(aGenericAssembRev); + } + + @Override + public Map visitReceptor(SuperModelRevision aSuperModelRev) { + return null; + } + + @Override + public Map visitReceptor(final AlternateRevision aAlternateRev) { + return getReceptorProperties(aAlternateRev); + } + + @Override + public Map visitReceptor(final DETRevision aDetRev) { + return getReceptorProperties(aDetRev); + } + + @Override + public Map visitReceptor(final PartAeroRevision aPartAeroRev) { + return getReceptorProperties(aPartAeroRev); + } + + @Override + public Map visitReceptor(final PartNoAeroRevision aPartNoAeroRev) { + return getReceptorProperties(aPartNoAeroRev); + } + + @Override + public Map visitReceptor(final PartAssembRevision aPartAssembRev) { + return getReceptorProperties(aPartAssembRev); + } + + @Override + public Map visitReceptor(final PartMatRevision aPartMatRev) { + return getReceptorProperties(aPartMatRev); + } + + @Override + public Map visitReceptor(final StandardRevision aStandardRev) { + return getReceptorProperties(aStandardRev); + } + + @Override + public Map visitReceptor(final RFGenericRevision aRfGenericRev) { + return getRepereReceptorProperties(aRfGenericRev); + } + + @Override + public Map visitReceptor(final RFPartAssembRevision aRfPartAssembRev) { + return getRepereReceptorProperties(aRfPartAssembRev); + } + + @Override + public Map visitReceptor(final RFPartRevision aRfPartRev) { + return getRepereReceptorProperties(aRfPartRev); + } + + @Override + public Map visitReceptor(final RFAdminRevision aRfAdminRev) { + return new EnumMap<>(R21VisitorKeys.class); + } + + @Override + public Map visitReceptor(final RFAdminARevision aRfAdminARev) { + return new EnumMap<>(R21VisitorKeys.class); + } + + @Override + public Map visitReceptor(final RFAdminAPRevision aRfAdminAPRev) { + return new EnumMap<>(R21VisitorKeys.class); + } + + @Override + public Map visitReceptor(final RFAdminAGRevision aRfAdminAGRev) { + return new EnumMap<>(R21VisitorKeys.class); + } + + /** + * Recover the Receptor properties to make a R21 report. + */ + private Map getReceptorProperties(final AbstractSnecmaObject aPartOrGeneric) { + Map theMap = new EnumMap<>(R21VisitorKeys.class); + theMap.put(R21VisitorKeys.IDENTIFIANT_RECEPTEUR, aPartOrGeneric.getItemId()); + theMap.put(R21VisitorKeys.REVISION_RECEPTEUR, aPartOrGeneric.getRevisionId()); + theMap.put(R21VisitorKeys.NOM_RECEPTEUR, aPartOrGeneric.getName()); + + return theMap; + } + + /** + * Recover the Repere Receptor properties to make a R21 report. + */ + private Map getRepereReceptorProperties(final AbstractSnecmaObject aRf) { + Map theMap = new EnumMap<>(R21VisitorKeys.class); + theMap.put(R21VisitorKeys.REPERE_FONCTIONNEL_RECEPTEUR, aRf.getName()); + theMap.put(R21VisitorKeys.REVISION_REPERE_FONCTIONNEL_RECEPTEUR, aRf.getRevisionId()); + return theMap; + } + + @Override + public Map visitReceptor(final MockupRevision aMockupRev) { + // This object is not use in this report + return null; + } + + @Override + public Map visitReceptor(final DescriptifRevision aDescriptifRev) { + // This object is not use in this report + return null; + } + + @Override + public Map emptyRf() { + return new EnumMap<>(R21VisitorKeys.class); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r22report/DataReportPreparatorR22.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r22report/DataReportPreparatorR22.java new file mode 100644 index 0000000..62d3379 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r22report/DataReportPreparatorR22.java @@ -0,0 +1,112 @@ +package com.capgemini.reports.definition.r22report; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcBomObject; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcBomObjectFactory; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcRevisionRule; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcRevisionRuleProperties; +import com.capgemini.framework.teamcenter.object.runtime.TcBomWindow; +import com.capgemini.framework.teamcenter.object.runtime.TcBomWindowConfiguration; +import com.capgemini.framework.teamcenter.object.runtime.TcRevisionRulesConfiguration; +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.capgemini.framework.teamcenter.queries.saved.modelobject.ItemRevisionQuery; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.bomlineholder.BOMLineHolderFactory; +import com.capgemini.reports.bomlineholder.processor.DefaultAltOrDetBehaviour; +import com.capgemini.reports.definition.r22report.ExecutionR22.ReportDataR22; +import com.capgemini.reports.definition.r22report.visitors.R22Visitor; +import com.capgemini.reports.exceptions.InvalidUserInputException; +import com.capgemini.reports.exceptions.UserInputErrorEnum; +import com.capgemini.reports.execution.IDataReportPreparator; +import com.capgemini.reports.execution.strategies.IExecutionStrategy; +import com.capgemini.reports.filter.AllIsGoodFilter; +import com.capgemini.reports.printing.PrintParameters; +import com.capgemini.reports.reports.parameters.EffectivityDate; +import com.capgemini.reports.teamcenter.ObjectInfoLoader; +import com.capgemini.reports.teamcenter.resolution.structureservice.MultiStructureServiceCaller; +import com.teamcenter.soa.client.model.ModelObject; +import com.teamcenter.soa.client.model.strong.Form; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +/** + * This class will allow to prepare data and findAll back data for making report R22. + */ +class DataReportPreparatorR22 implements IDataReportPreparator { + private static final long serialVersionUID = 1219563840412154089L; + private static final Logger LOGGER = LoggerFactory.getLogger(ExecutionR22.class); + + private static final AllIsGoodFilter ACCEPT_ALL = new AllIsGoodFilter(); + + @Override + public String print(TcSession session, ExecutionR22 execution, IExecutionStrategy executionStrategy) throws KurtException { + PrintParameters printParameters = prepareData(session, execution); + executionStrategy.print(printParameters, execution); + return executionStrategy.getReportFileName(execution) + printParameters.getOuputFileExtension(); + } + + private PrintParameters prepareData(final TcSession session, final ExecutionR22 report) throws KurtException { + LOGGER.debug("PrepareData started on: {}", report.getReportIdentifier().getReportTitle()); + + // Obtain the top Part + List list = + new ItemRevisionQuery(session).searchIDAndRevision(report.getPartId(), report.getPartRevision()).findAll(); + if (list.isEmpty()) { + throw new InvalidUserInputException(UserInputErrorEnum.OBJECT_DOES_NOT_EXIST); + } + + ItemRevision itemRevision = null; + + for(ItemRevision currentItemRev : list) { + if(SnecmaObjectTypes.isPartRevision(currentItemRev.getTypeObject().getName())){ + itemRevision = currentItemRev; + break; + } + } + + if(itemRevision == null){ + throw new InvalidUserInputException(UserInputErrorEnum.THE_SELECTED_OBJECT_IS_NOT_PERMITTED_ON_THIS_REPORT); + } + + TcBomObject topLineObject = new TcBomObjectFactory(session, itemRevision).create(); + EffectivityDate effectivityDate = report.getEffectivity(); + + TcRevisionRuleProperties revisionRuleProperties = new TcRevisionRuleProperties(effectivityDate.isNow() ? null : effectivityDate.getDateTime()); + + TcRevisionRule revisionRule = session.findRevRule(report.getRevisionRule()); + TcRevisionRulesConfiguration revRulesConfiguration = new TcRevisionRulesConfiguration(revisionRule, revisionRuleProperties); + + try (TcBomWindow bomWindow = session.createBomWindow(new TcBomWindowConfiguration(topLineObject, revRulesConfiguration))) { + session.setObjectPropPolicy(report.getFullPolicy()); + + // Obtain the clause de propriete form the ItemRevision that was fetched in the config + String typeProduit = ObjectInfoLoader.getProductType(session, (ItemRevision) bomWindow.topLine().get_bl_line_object()); + String clausePropriete = ObjectInfoLoader.getClausePropriete(typeProduit, session); + + // Perform the job + BOMLineHolder unbuiltTopLine = new MultiStructureServiceCaller(session).resolve(bomWindow.topLine(), ACCEPT_ALL); + + List itemRevMaster = unbuiltTopLine.getAllItemRevMasters(); + session.loadProperties(itemRevMaster.toArray(new ModelObject[itemRevMaster.size()])); + BOMLineHolderFactory.buildTopBom(session, unbuiltTopLine, ACCEPT_ALL); + + DefaultAltOrDetBehaviour altOrDetBehaviour = new DefaultAltOrDetBehaviour<>(session, report.getEffectivity().getDateTime()); + unbuiltTopLine.process(altOrDetBehaviour); + unbuiltTopLine.freeze(); + + ReportDataR22 dataR22 = new ReportDataR22(clausePropriete, unbuiltTopLine); + + R22Visitor visitor = new R22Visitor(); + PrintParameters printParameters = visitor.makeMasterTemplate(report, dataR22); + visitor.constructDataMaps(session, printParameters, dataR22); + + LOGGER.debug("PrepareData ended on: {}", report.getReportIdentifier().getReportTitle()); + + return printParameters; + } + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r22report/ExecutionR22.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r22report/ExecutionR22.java new file mode 100644 index 0000000..4fdd965 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r22report/ExecutionR22.java @@ -0,0 +1,353 @@ +package com.capgemini.reports.definition.r22report; + +import com.capgemini.framework.common.FileHelper; +import com.capgemini.framework.common.SettingsHelper; +import com.capgemini.framework.common.StringHelper; +import com.capgemini.framework.common.TeamcenterDateFormatter; +import com.capgemini.framework.teamcenter.TeamcenterObjectTypes; +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.*; +import com.capgemini.framework.teamcenter.files.FileManagement; +import com.capgemini.framework.teamcenter.files.FileManagement.FileType; +import com.capgemini.framework.teamcenter.object.pom.status.StatusEnum; +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.framework.teamcenter.queries.saved.modelobject.IMANRelationQuery; +import com.capgemini.framework.teamcenter.queries.saved.modelobject.ItemQuery; +import com.capgemini.framework.teamcenter.statuating.StatusSetter; +import com.capgemini.reports.JasperTemplate; +import com.capgemini.reports.ReportEnum; +import com.capgemini.reports.ReportLaunchTypeEnum; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.builder.R22Builder; +import com.capgemini.reports.builder.ReportBuilder; +import com.capgemini.reports.database.javabean.DbReport; +import com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum; +import com.capgemini.reports.database.manager.MngCriteriaVal.CriteriaValue; +import com.capgemini.reports.definition.r22report.ExecutionR22.ReportDataR22; +import com.capgemini.reports.exceptions.InvalidDatasetException; +import com.capgemini.reports.exceptions.NotFoundException; +import com.capgemini.reports.execution.AbstractExecutionReport; +import com.capgemini.reports.execution.IDataReportPreparator; +import com.capgemini.reports.execution.actions.AbstractPostExecutionStep; +import com.capgemini.reports.execution.actions.IPostExecutionStep; +import com.capgemini.reports.printing.Printer.PrintFormat; +import com.capgemini.reports.reports.parameters.EffectivityDate; +import com.capgemini.reports.reports.parameters.IChecker; +import com.capgemini.reports.reports.parameters.MonoMulti; +import com.capgemini.reports.reports.parameters.checker.ObjectTypeChecker; +import com.teamcenter.services.loose.core._2006_03.FileManagement.GetDatasetWriteTicketsInputData; +import com.teamcenter.soa.client.model.ModelObject; +import com.teamcenter.soa.client.model.strong.ImanRelation; +import com.teamcenter.soa.client.model.strong.Item; +import com.teamcenter.soa.client.model.strong.WorkspaceObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.List; + +/** + * This class controls the execution of an R22 report. + */ +public class ExecutionR22 extends AbstractExecutionReport { + /** + * The policy to use if the report is launched by workflow, when attaching it to the part as a dataset. + */ + public static final PolicyLocation R22_POLICY_XML_WKF = PolicyLocation.make("R22_policy_wkf", "/xml/policies/r22report/R22_policy_wkf.xml"); + private static final long serialVersionUID = -1050126556474290283L; + private static final Logger log = LoggerFactory.getLogger(ExecutionR22.class); + private static final int MILLIS_PER_SEC = 1000; + // Global parameters + private static final PolicyLocation R22_POLICY_XML_FULL = PolicyLocation.make("R22_policy_full", "/xml/policies/r22report/R22_policy_full.xml"); + private static final PolicyLocation R22_POLICY_XML_LIGHT = PolicyLocation.make("R22_policy_light", "/xml/policies/r22report/R22_policy_light.xml"); + private static final String OUTPUT_FOLDER = SettingsHelper.getReportLocation(); + private static final int REPORT_PRIORITY = SettingsHelper.getPriority(ReportEnum.REPORT_R22); + private static final String REPORT_REVISION_RULE = SettingsHelper.getPropertyWithDefaultValue("common.bom.revisionRule.REPORT_R22", DEFAULT_REVISION_RULE); + private static final ReportLaunchTypeEnum REPORT_LAUNCH_TYPE = ReportLaunchTypeEnum.getReportLaunchType("common.launch.launchType.REPORT_R22"); + + // Constants + private static final String FILE_SEPARATOR = "_"; + private static final String PATTERN_DATE = "dd-MM-yyyy"; + private static final String BOM_PAR_DATE = "BOMParDate"; + + // Report Configuration + private final EffectivityDate effectivity; + private final String partId; + private final String partRevision; + private final MonoMulti monoMulti; + + + /** + * Executes the Report R22. + * + * @param partId String - the Part Id + * @param partRevision String - the Part Revision + */ + public ExecutionR22(final String partId, final String partRevision) { + super(REPORT_PRIORITY, REPORT_REVISION_RULE, REPORT_LAUNCH_TYPE); + this.partId = partId; + this.partRevision = partRevision; + this.effectivity = new EffectivityDate(); // Always today + this.monoMulti = MonoMulti.MULTI; + } + + @Override + public List getLaunchData() { + List criteriaValues = new ArrayList<>(); + criteriaValues.add(new CriteriaValue(ReportCriteriaEnum.PART_ID, partId)); + criteriaValues.add(new CriteriaValue(ReportCriteriaEnum.PART_REVISION, partRevision)); + criteriaValues.add(new CriteriaValue(ReportCriteriaEnum.MONO_MULTI, monoMulti.toString())); + return criteriaValues; + } + + @Override + public String getTemplateLocation() { + return JasperTemplate.TEMPLATE_R22.getFilepath(); + } + + @Override + public List getQuickChecks() { + List quickChecks = new ArrayList<>(); + quickChecks.add(new ObjectTypeChecker(partId, SnecmaObjectTypes.ALTERNATE, SnecmaObjectTypes.DET, SnecmaObjectTypes.PART_AERO, + SnecmaObjectTypes.PART_ASSEMB, SnecmaObjectTypes.PART_MAT, SnecmaObjectTypes.PART_NO_AERO, SnecmaObjectTypes.STANDARD)); + return quickChecks; + } + + @Override + public PolicyLocation getPropertyPolicyForLongChecks() { + return R22_POLICY_XML_LIGHT; + } + + @Override + public PolicyLocation getFullPolicy() { + return R22_POLICY_XML_FULL; + } + + @Override + public List getLongChecks() { + return new ArrayList<>(); // Empty lists - not used for this report + } + + @Override + public ReportEnum getReportIdentifier() { + return wkf ? ReportEnum.REPORT_W22 : ReportEnum.REPORT_R22; + } + + @Override + public String getSpecifiedFileName() { + // Format file expected : R22-BOMParDATE_{ReferenceArticle}_{RevisionArticle}_{date_systeme}.pdf + String dateSystem = TeamcenterDateFormatter.formatCalendarToPattern(Calendar.getInstance(), PATTERN_DATE); + return "R22-BOMParDATE_" + partId + FILE_SEPARATOR + partRevision + FILE_SEPARATOR + + dateSystem; + } + + @Override + public PrintFormat getPrintingFormat() { + return PrintFormat.PDF; + } + + public String getPartId() { + return partId; + } + + public String getPartRevision() { + return partRevision; + } + + public EffectivityDate getEffectivity() { + return effectivity; + } + + @Override + public IDataReportPreparator getDataPreparator() { + return new DataReportPreparatorR22(); + } + + @Override + public AbstractExecutionReport cloneTemplateToExecution() { + return new ExecutionR22(partId, partRevision); + } + + /** + * Returns a {@link IPostExecutionStep} which attaches the report to the Part as a Dataset (and feezes the Dataset). + * + * @return the action + */ + public IPostExecutionStep makeAttachPdfToPartAction() { + return new R22AttachPdfToPartAction(); + } + + + /* ************************************************************************************ + * Workflow action + * ************************************************************************************ */ + + private File copyFile(final String datasetFileName) throws NotFoundException { + String originalFileNameOnDisc = getFileNameOnDisc(); + File original = new File(OUTPUT_FOLDER + originalFileNameOnDisc + ".pdf"); + final File copy = new File(OUTPUT_FOLDER + datasetFileName + ".pdf"); + FileHelper.copy(original, copy); + return copy; + } + + private String makeDatasetName() { + return StringHelper.implode(FILE_SEPARATOR, BOM_PAR_DATE, partId, partRevision); + } + + private String makeDatasetFileName() { + Date startDate; + try { + startDate = new SimpleDateFormat(TeamcenterDateFormatter.DD_MM_YYYY_HH_MM_SS).parse(getStartTime()); + } catch (ParseException e) { + log.warn("Unable to parse stored start date, generating a date using NOW", e); + startDate = new Date(); + } + String dateStr = new SimpleDateFormat(TeamcenterDateFormatter.YYYYMMDD).format(startDate); + long timestamp = startDate.getTime() / MILLIS_PER_SEC; + String timestampStr = String.valueOf(timestamp); + return StringHelper.implode(FILE_SEPARATOR, BOM_PAR_DATE, partId, partRevision, dateStr, timestampStr); + } + + private Item obtainPart(final TcSession session) throws NotFoundException { + List matchingParts = new ItemQuery(session).searchID(partId).findAll(); + + for(Item currentPart : matchingParts){ + if(SnecmaObjectTypes.isPart(currentPart.getTypeObject().getName())){ + return currentPart; + } + } + + if (matchingParts.isEmpty()) { + throw new NotFoundException("Could not find the original part " + partId); + } else { + throw new NotFoundException(partId + " part not found other type found instead"); + } + + } + + private void destroyConflictingDatasets(final TcSession session, final String datasetName, final Item thePart) + throws FailedRelationshipActionException { + List existingRelations = new IMANRelationQuery(session).find(partId, datasetName); + log.debug("Wokflow launch: destrying previous datasets: {} relations found", existingRelations.size()); + // Let's browse all conflicting datasets + for (ImanRelation relation : existingRelations) { + ModelObject datasetMO = relation.get_secondary_object(); + + // Let's destroy the relation first + log.debug("Wokflow launch: destroying relation between part {} and datasets {}", thePart.getUid(), datasetMO.getUid()); + session.deleteObjects(relation); + + // Net's destroy the Dataset now that it is free from relationships + log.debug("Wokflow launch: destroying datasets {}", datasetMO.getUid()); + session.deleteObjects(datasetMO); + } + } + + private GetDatasetWriteTicketsInputData createDataset(final TcSession session, final String datasetName, final File fileCopy) + throws InvalidDatasetException { + String dataSetDescription = ReportEnum.REPORT_R22.getReportTitle(); + + // Perform the upload + GetDatasetWriteTicketsInputData data; + try { + data = FileManagement.addSingleDataSet(session, datasetName, dataSetDescription, fileCopy, FileType.FICHE_ARTICLE); + } catch (MalformedDataSetException | ConnectionMisconguredException e) { + throw new InvalidDatasetException("Unable to create the dataset for R22 report " + getReportTechnicalUid(), e); + } + return data; + } + + private void linkDatasetToPart(final TcSession session, final Item thePart, final ModelObject dataset) + throws FailedRelationshipActionException { + try { + session.createRelation(thePart, dataset, TeamcenterObjectTypes.IMAN_REFERENCE); + } catch (FailedRelationshipActionException e) { + // Unable to link back the dataset to the part. Let's cleanup behind us and destroy that orphan dataset! + session.deleteObjects(dataset); + throw e; + } + + } + + private void addFrozenStatusToDataset(final TcSession session, final ModelObject dataset) throws UnableToCreateStatusException { + StatusSetter statusMng = new StatusSetter(session); + statusMng.putStatus((WorkspaceObject) dataset, StatusEnum.FROZEN.getIdentifier()); + } + + @Override + public Class getReportBuilderClass() { + return R22Builder.class; + } + + /** + * POJO container of all data required for this report. + */ + public static class ReportDataR22 { + private final String clausePropriete; + private final BOMLineHolder topLine; + + protected ReportDataR22(final String clausePropriete, final BOMLineHolder topLine) { + this.clausePropriete = clausePropriete; + this.topLine = topLine; + } + + public String getClausePropriete() { + return clausePropriete; + } + + public BOMLineHolder getTopLine() { + return topLine; + } + } + + private class R22AttachPdfToPartAction extends AbstractPostExecutionStep { + private static final long serialVersionUID = -1516821856454786852L; + + /** + * Creates an action that will attach the pdf to the part. + */ + private R22AttachPdfToPartAction() { + super(ExecutionR22.class); + } + + @Override + public Void performPostActionOnReport(final TcSession session, final ExecutionR22 report, final DbReport theExecutingReport, + final String fileNameWithExtension) throws KurtException { + session.setObjectPropPolicy(R22_POLICY_XML_WKF); + + // Prepare naming & Make a copy with the correct name + log.debug("Wokflow launch: Beginning file copy"); + String datasetName = report.makeDatasetName(); + String datasetFileName = report.makeDatasetFileName(); + File fileCopy = report.copyFile(datasetFileName); + + // Obtain the Part + Item thePart = report.obtainPart(session); + + // Detect & destroy conflicting datasets on the part, if any + log.debug("Wokflow launch: Destroying previous datasets..."); + report.destroyConflictingDatasets(session, datasetName, thePart); + + // Create a new dataset + log.debug("Wokflow launch: Creating datasets {}", datasetName); + GetDatasetWriteTicketsInputData dataset = report.createDataset(session, datasetName, fileCopy); + + // Link the part to the dataset (if it fails, it will cleanup the dataset as well) + log.debug("Wokflow launch: Linking Part {} to newly created dataset {}", thePart.getUid(), dataset.dataset.getUid()); + report.linkDatasetToPart(session, thePart, dataset.dataset); + + // Freeze the dataset + log.debug("Wokflow launch: Adding 'Frozen' status to the dataset {}", dataset.dataset.getUid()); + report.addFrozenStatusToDataset(session, dataset.dataset); + + log.debug("R22 Execution from workflow has completed successfuly for part {}-{}", partId, partRevision); + return null; + } + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r22report/visitors/R22Visitor.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r22report/visitors/R22Visitor.java new file mode 100644 index 0000000..b410fc3 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r22report/visitors/R22Visitor.java @@ -0,0 +1,123 @@ +package com.capgemini.reports.definition.r22report.visitors; + +import com.capgemini.framework.common.ResourceHelper; +import com.capgemini.framework.common.TeamcenterDateFormatter; +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.definition.r22report.ExecutionR22; +import com.capgemini.reports.definition.r22report.ExecutionR22.ReportDataR22; +import com.capgemini.reports.definition.r22report.visitors.bomlineholder.R22BOMLineHolderVisitor; +import com.capgemini.reports.exceptions.FileLoadingException; +import com.capgemini.reports.execution.mapconstructor.AbstractStaticTemplateMapConstructor; +import com.capgemini.reports.printing.PrintParameters; +import com.capgemini.reports.reports.IReportVisitor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.awt.image.BufferedImage; +import java.util.*; + +/** + * Visit a R22 report. + */ +public class R22Visitor extends AbstractStaticTemplateMapConstructor implements IReportVisitor { + private static final long serialVersionUID = -1530604820422919903L; + private static final Logger LOGGER = LoggerFactory.getLogger(R22Visitor.class); + + private static final String SNECMA_LOGO = "/Jasper/images/Snecma_logo.png"; + private static final String EMPTY = ""; + private static final String MULTI_NIVEAUX = "Multi-niveaux"; + + private final R22BOMLineHolderVisitor r22BOMLineHolderVisitor = new R22BOMLineHolderVisitor(); + + public R22Visitor() { + super(); + } + + private static String check(final Object anInput) { + return anInput == null ? EMPTY : anInput.toString(); + } + + private List> translate(final List> visitorMaps) { + // Add empty fields in the first line + Map firstLine = visitorMaps.get(0); + + // Empty receptor + firstLine.put(R22VisitorKeys.RECEPTEUR, EMPTY); + firstLine.put(R22VisitorKeys.REPERE_FONCTIONNEL_REVISION, EMPTY); + firstLine.put(R22VisitorKeys.RESPONSABLE_REPERE, EMPTY); + firstLine.put(R22VisitorKeys.ALT, EMPTY); + firstLine.put(R22VisitorKeys.SB, EMPTY); + firstLine.put(R22VisitorKeys.NQC, EMPTY); + firstLine.put(R22VisitorKeys.PANACHAGE, EMPTY); + firstLine.put(R22VisitorKeys.COEFF, EMPTY); + + // Construct the map list expected by the printer + List> printerMaps = new ArrayList<>(); + for (Map visitorMap : visitorMaps) { + HashMap printerMap = new HashMap<>(); + for (R22VisitorKeys key : R22VisitorKeys.values()) { + printerMap.put(key.toString(), check(visitorMap.get(key))); + } + printerMaps.add(printerMap); + } + LOGGER.debug("Translate map {}", printerMaps); + return printerMaps; + } + + /** + * Add additional elements for header of R22 report. + * + * @param aDateNow Current date as string + * @param ressource url resource + * @param clausePropriete the 'clause de propriete' Snecma + * @return map of additional elements + */ + private EnumMap addAdditionalParameters(final String aDateNow, final String ressource, + final String clausePropriete) { + EnumMap map = new EnumMap<>(R22VisitorParametersKeys.class); + map.put(R22VisitorParametersKeys.CLAUSE_DE_PROPRIETE, clausePropriete); + map.put(R22VisitorParametersKeys.DATE_EFFECTIVITE, aDateNow); + map.put(R22VisitorParametersKeys.DATE_TRAITEMENT, aDateNow); + map.put(R22VisitorParametersKeys.NIVEAU, MULTI_NIVEAUX); + map.put(R22VisitorParametersKeys.REFERENCE_ARTICLE, r22BOMLineHolderVisitor.getReferenceItem()); + + try { + BufferedImage image = ResourceHelper.loadImage(ressource); + map.put(R22VisitorParametersKeys.LOGO_SNECMA, image); + } catch (FileLoadingException e) { + LOGGER.warn("Could not load Snecma logo", e); + } + + LOGGER.debug("MAP {}", map); + + return map; + } + + @Override + public List> visitReport(final BOMLineHolder holder) { + List> visitorMaps = r22BOMLineHolderVisitor.visitTopReceptorBom(holder); + return translate(visitorMaps); + } + + @Override + public void constructDataMaps(TcSession session, final PrintParameters printParameters, final ReportDataR22 data) throws KurtException { + long start = System.currentTimeMillis(); + if (data.getTopLine() == null) { + throw new NoSuchElementException("No object structure found"); + } + LOGGER.info("ConstructDataMaps "); + + // Parse all the snecma objects... + List> printerMaps = this.visitReport(data.getTopLine()); + LOGGER.debug("Printer map size {}", printerMaps.size()); + printParameters.addReportData(printerMaps); + + String dateNowInFrench = TeamcenterDateFormatter.formatCalendarToFrench(Calendar.getInstance()); + EnumMap additionalParameters = addAdditionalParameters(dateNowInFrench, SNECMA_LOGO, data.getClausePropriete()); + printParameters.addReportParameters(additionalParameters); + + LOGGER.info(EXECUTION_TIME_XXX_MS_FOR_YYY, System.currentTimeMillis() - start, "data filtering"); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r22report/visitors/R22VisitorKeys.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r22report/visitors/R22VisitorKeys.java new file mode 100644 index 0000000..5fc21bc --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r22report/visitors/R22VisitorKeys.java @@ -0,0 +1,25 @@ +package com.capgemini.reports.definition.r22report.visitors; + +/** + * Enumeration of all the keys to the R22 report fields. + */ +public enum R22VisitorKeys { + RECEPTEUR, + REPERE_FONCTIONNEL_REVISION, + RESPONSABLE_REPERE, + ALT, + SB, + NQC, + PANACHAGE, + COEFF, + COMPOSANT, + FABRICANT, + DENOMINATION, + ALTERNATIVE, + CLASSEMENT, + SUIVI_UTILISATION, + SUIVI_MONTAGE, + MASSE_INDICATIVE, + UNITE_DE_MASSE, + CONCEPTEUR +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r22report/visitors/R22VisitorParametersKeys.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r22report/visitors/R22VisitorParametersKeys.java new file mode 100644 index 0000000..a6625cd --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r22report/visitors/R22VisitorParametersKeys.java @@ -0,0 +1,14 @@ +package com.capgemini.reports.definition.r22report.visitors; + +/** + * Enumeration of all the parameters keys to the R22 report fields ( header). + */ + +public enum R22VisitorParametersKeys { + CLAUSE_DE_PROPRIETE, + DATE_TRAITEMENT, + DATE_EFFECTIVITE, + REFERENCE_ARTICLE, + NIVEAU, + LOGO_SNECMA +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r22report/visitors/bomlineholder/R22AltOrDetBehaviour.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r22report/visitors/bomlineholder/R22AltOrDetBehaviour.java new file mode 100644 index 0000000..6986f8c --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r22report/visitors/bomlineholder/R22AltOrDetBehaviour.java @@ -0,0 +1,50 @@ +package com.capgemini.reports.definition.r22report.visitors.bomlineholder; + +import com.capgemini.reports.bomlineholder.processor.AltOrDetBehaviour; +import com.capgemini.reports.definition.r22report.visitors.R22VisitorKeys; +import com.capgemini.reports.snecmaobjects.part.AlternateRevision; +import com.capgemini.reports.snecmaobjects.part.DETRevision; + +import java.util.Map; + +/** + * This class visits Parts that are below an {@link AlternateRevision} or a {@link DETRevision}.
    + * It puts "Oui" in the ALTERNATIVE field of a map. + */ +public class R22AltOrDetBehaviour implements AltOrDetBehaviour { + private static final long serialVersionUID = -6520666717827385535L; + + private static final String OUI = "Oui"; + private static final String EMPTY_STRING = ""; + + @Override + public boolean shouldVisitPartsInPseudoFolder() { + return true; + } + + @Override + public boolean shouldVisitPartsBelowAlt() { + return true; + } + + @Override + public void treatPartsInPseudoFolder(final Map map) { + // EMPTY fields, if current object is an ALTERNATE or DET + map.put(R22VisitorKeys.REPERE_FONCTIONNEL_REVISION, EMPTY_STRING); + map.put(R22VisitorKeys.RESPONSABLE_REPERE, EMPTY_STRING); + map.put(R22VisitorKeys.ALT, EMPTY_STRING); + map.put(R22VisitorKeys.SB, EMPTY_STRING); + map.put(R22VisitorKeys.NQC, EMPTY_STRING); + map.put(R22VisitorKeys.PANACHAGE, EMPTY_STRING); + map.put(R22VisitorKeys.COEFF, EMPTY_STRING); + + // Column alternative must be defined to OUI + map.put(R22VisitorKeys.ALTERNATIVE, OUI); + } + + @Override + public void treatAlternateOrDETAsReceptor(final Map map) { + // Column alternative must be defined to OUI + map.put(R22VisitorKeys.ALTERNATIVE, OUI); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r22report/visitors/bomlineholder/R22BOMLineHolderVisitor.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r22report/visitors/bomlineholder/R22BOMLineHolderVisitor.java new file mode 100644 index 0000000..195d2bd --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r22report/visitors/bomlineholder/R22BOMLineHolderVisitor.java @@ -0,0 +1,97 @@ +package com.capgemini.reports.definition.r22report.visitors.bomlineholder; + +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.bomlineholder.visitor.AbstractBOMLineHolderVisitor; +import com.capgemini.reports.definition.r22report.visitors.R22VisitorKeys; +import com.capgemini.reports.definition.r22report.visitors.snecmaobject.R22ComponentVisitor; +import com.capgemini.reports.definition.r22report.visitors.snecmaobject.R22ReceptorVisitor; +import com.capgemini.reports.releasestatus.EffectivityBehaviourHelper; +import com.capgemini.reports.snecmaobjects.ISnecmaObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Map; + +/** + * Visitor of an expansion of BOMLineHolder for the R22 report. + */ +public class R22BOMLineHolderVisitor extends AbstractBOMLineHolderVisitor { + private static final long serialVersionUID = -8251274449267683067L; + private static final Logger LOGGER = LoggerFactory.getLogger(R22BOMLineHolderVisitor.class); + private static final String SEMICOLON = " ; "; + private static final String SPACE = " "; + private ISnecmaObject topBomLine; + + public R22BOMLineHolderVisitor() { + super(new R22ReceptorVisitor(), new R22ComponentVisitor(), EffectivityBehaviourHelper.visitAnyPart(), new R22AltOrDetBehaviour(), true, + false, true); + } + + @Override + protected Map visitThisReceptor(final BOMLineHolder aBomLine) { + LOGGER.debug("visitThisReceptor {" + aBomLine.getUid() + "}"); + return aBomLine.getSnecmaObject().accept(receptorVisitor); + } + + @Override + protected Map visitThisComponent(final BOMLineHolder aBomLine) { + LOGGER.debug("visitThisComponent {" + aBomLine.getUid() + "}"); + Map aMap = aBomLine.getSnecmaObject().accept(componentVisitor); + // Put the BOMLine properties into the map + if (aBomLine.getSnecmaObject().isGeneric() || aBomLine.getSnecmaObject().isPart()) { + aMap.put(R22VisitorKeys.ALT, aBomLine.getBomAlt()); + aMap.put(R22VisitorKeys.SB, aBomLine.getBomSb()); + aMap.put(R22VisitorKeys.NQC, aBomLine.getBomQtyCumul()); + aMap.put(R22VisitorKeys.PANACHAGE, aBomLine.getBomPanache()); + aMap.put(R22VisitorKeys.COEFF, aBomLine.getBomQty()); + } + return aMap; + } + + @Override + protected void visitSpecificFirstLine(final BOMLineHolder aTopBomLine) { + topBomLine = aTopBomLine.getSnecmaObject(); + Map theFirstLine = topBomLine.accept(getComponentVisitor()); + theReportTable.add(theFirstLine); + } + + @Override + protected void mergeReceptorAndRepereReceptor(final Map aReceptor, final Map aRepereReceptor) { + aReceptor.putAll(aRepereReceptor); + } + + @Override + protected void mergeComponentAndRepereComponent(final Map aComponent, final Map aRepereComponent) { + aComponent.putAll(aRepereComponent); + } + + @Override + protected void mergeRepereReceptorandAdmin(final Map aRepereReceptor, final Map anAdmin) { + aRepereReceptor.putAll(anAdmin); + } + + @Override + protected void mergeRepereComponentandAdmin(final Map aRepereComponent, final Map anAdmin) { + aRepereComponent.putAll(anAdmin); + } + + @Override + protected void addToReport(final Map aReceptor, final Map aComponent) { + // Put the Receptor and Repere Receptor in the Component and modify the Component + // Do not modify the receptor + aComponent.putAll(aReceptor); + + // Add to the R22 report + theReportTable.add(aComponent); + } + + /** + * Format Item to display in report.
    + * EXPECTED : object id ; object revision id object name. + * + * @return reference item + */ + public String getReferenceItem() { + return topBomLine.getItemId() + SEMICOLON + topBomLine.getRevisionId() + SPACE + topBomLine.getName(); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r22report/visitors/snecmaobject/R22ComponentVisitor.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r22report/visitors/snecmaobject/R22ComponentVisitor.java new file mode 100644 index 0000000..c7798cd --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r22report/visitors/snecmaobject/R22ComponentVisitor.java @@ -0,0 +1,218 @@ +package com.capgemini.reports.definition.r22report.visitors.snecmaobject; + +import com.capgemini.framework.common.DoubleFormatter; +import com.capgemini.framework.common.LanguageHelper; +import com.capgemini.reports.definition.r22report.visitors.R22VisitorKeys; +import com.capgemini.reports.snecmaobjects.AbstractSnecmaObject; +import com.capgemini.reports.snecmaobjects.admin.RFAdminAGRevision; +import com.capgemini.reports.snecmaobjects.admin.RFAdminAPRevision; +import com.capgemini.reports.snecmaobjects.admin.RFAdminARevision; +import com.capgemini.reports.snecmaobjects.admin.RFAdminRevision; +import com.capgemini.reports.snecmaobjects.descriptif.DescriptifRevision; +import com.capgemini.reports.snecmaobjects.generic.GenericAssembRevision; +import com.capgemini.reports.snecmaobjects.generic.GenericRevision; +import com.capgemini.reports.snecmaobjects.mockup.MockupRevision; +import com.capgemini.reports.snecmaobjects.part.*; +import com.capgemini.reports.snecmaobjects.product.ProductRevision; +import com.capgemini.reports.snecmaobjects.rf.AbstractRF; +import com.capgemini.reports.snecmaobjects.rf.RFGenericRevision; +import com.capgemini.reports.snecmaobjects.rf.RFPartAssembRevision; +import com.capgemini.reports.snecmaobjects.rf.RFPartRevision; +import com.capgemini.reports.snecmaobjects.supermodel.SuperModelRevision; +import com.capgemini.reports.snecmaobjects.visitor.IComponentVisitor; + +import java.util.EnumMap; +import java.util.HashMap; +import java.util.Map; + +/** + * Visitor for Components of the r22 report. + */ +public class R22ComponentVisitor implements IComponentVisitor> { + private static final long serialVersionUID = -4087090295500160461L; + + // Formatting + private static final int MASS_SIGNIFICANT_DIGITS = 9; + private static final String SEPARATOR = " ; "; + + // Default content + private static final String EMPTY_STRING = ""; + private static final String NON = "Non"; + + /** + * Extracts left side of a string of the form "French text / English text".
    + * Separator slash may have any number (0+) of white spaces around them + * + * @param string + * @return the left side (if any "side" exists), an empty string otherwise + */ + private static String french(final String string) { + return LanguageHelper.french(string); + } + + @Override + public Map visitComponent(final ProductRevision aProductRev) { + // Not used + return new HashMap<>(); + } + + @Override + public Map visitComponent(final GenericRevision aGenericRev) { + // Not used + return new HashMap<>(); + } + + @Override + public Map visitComponent(SuperModelRevision aSuperModelRev) { + return null; + } + + @Override + public Map visitComponent(final GenericAssembRevision aGenericAssembRev) { + // Not used + return new HashMap<>(); + } + + @Override + public Map visitComponent(final AlternateRevision aAlternateRev) { + return getPartProperties(aAlternateRev); + } + + @Override + public Map visitComponent(final DETRevision aDetRev) { + return getPartProperties(aDetRev); + } + + @Override + public Map visitComponent(final PartAeroRevision aPartAeroRev) { + return getPartProperties(aPartAeroRev); + } + + @Override + public Map visitComponent(final PartNoAeroRevision aPartNoAeroRev) { + return getPartProperties(aPartNoAeroRev); + } + + @Override + public Map visitComponent(final PartAssembRevision aPartAssembRev) { + return getPartProperties(aPartAssembRev); + } + + @Override + public Map visitComponent(final PartMatRevision aPartMatRev) { + return getPartMatProperties(aPartMatRev); + } + + @Override + public Map visitComponent(final StandardRevision aStandardRev) { + return getPartProperties(aStandardRev); + } + + @Override + public Map visitComponent(final RFGenericRevision aRfGenericRev) { + // Not used + return new HashMap<>(); + } + + @Override + public Map visitComponent(final RFPartAssembRevision aRfPartAssembRev) { + return getReceptorProperties(aRfPartAssembRev); + } + + @Override + public Map visitComponent(final RFPartRevision aRfPartRev) { + return getReceptorProperties(aRfPartRev); + } + + @Override + public Map visitComponent(final RFAdminRevision aRfAdminRev) { + Map theMap = new EnumMap<>(R22VisitorKeys.class); + theMap.put(R22VisitorKeys.RESPONSABLE_REPERE, aRfAdminRev.getResponsableRepere()); + return theMap; + } + + @Override + public Map visitComponent(final RFAdminARevision aRfAdminARev) { + Map theMap = new EnumMap<>(R22VisitorKeys.class); + // Split because return value like oui/yes or Non/No + theMap.put(R22VisitorKeys.SUIVI_MONTAGE, french(aRfAdminARev.getSuiviMontage())); + theMap.put(R22VisitorKeys.RESPONSABLE_REPERE, aRfAdminARev.getResponsableRepere()); + return theMap; + } + + @Override + public Map visitComponent(final RFAdminAPRevision aRfAdminAPRev) { + Map theMap = new EnumMap<>(R22VisitorKeys.class); + // Split because return value like oui/yes or Non/No + theMap.put(R22VisitorKeys.SUIVI_MONTAGE, french(aRfAdminAPRev.getSuiviMontage())); + return theMap; + } + + @Override + public Map visitComponent(final RFAdminAGRevision aRfAdminAGRev) { + // Not used + return new HashMap<>(); + } + + private Map getAbstractSnecmaObjectProperties(final AbstractSnecmaObject snecmaObject) { + Map theMap = new EnumMap<>(R22VisitorKeys.class); + // Correspond colonne -> Réf. fabricant / Réf. SNECMA ; Révision + theMap.put(R22VisitorKeys.COMPOSANT, + snecmaObject.getItemId() + SEPARATOR + snecmaObject.getRevisionId()); + theMap.put(R22VisitorKeys.DENOMINATION, snecmaObject.getName()); + theMap.put(R22VisitorKeys.ALTERNATIVE, EMPTY_STRING); + return theMap; + } + + private Map getAbstractPartProperties(final AbstractPart part) { + Map theMap = new EnumMap<>(R22VisitorKeys.class); + theMap.put(R22VisitorKeys.FABRICANT, part.getResponsableConception()); + theMap.put(R22VisitorKeys.CLASSEMENT, part.getClassement()); + theMap.put(R22VisitorKeys.SUIVI_UTILISATION, french(part.getSuiviUtilisation())); + theMap.put(R22VisitorKeys.MASSE_INDICATIVE, DoubleFormatter.toSignificantDigits(part.getMass(), MASS_SIGNIFICANT_DIGITS)); + theMap.put(R22VisitorKeys.UNITE_DE_MASSE, part.getMassUnit()); + theMap.put(R22VisitorKeys.CONCEPTEUR, part.getRefCompleteConcepteur()); + return theMap; + } + + private Map getAbstractPartMatProperties(final PartMatRevision partMatRevision) { + Map theMap = new EnumMap<>(R22VisitorKeys.class); + theMap.put(R22VisitorKeys.FABRICANT, partMatRevision.getResponsableConception()); + theMap.put(R22VisitorKeys.CLASSEMENT, partMatRevision.getClassementMat()); + theMap.put(R22VisitorKeys.SUIVI_UTILISATION, NON); + theMap.put(R22VisitorKeys.MASSE_INDICATIVE, EMPTY_STRING); + theMap.put(R22VisitorKeys.UNITE_DE_MASSE, EMPTY_STRING); + theMap.put(R22VisitorKeys.CONCEPTEUR, EMPTY_STRING); + return theMap; + } + + private Map getPartMatProperties(final PartMatRevision anAbstractSnecmaObject) { + Map theMap = getAbstractSnecmaObjectProperties(anAbstractSnecmaObject); + theMap.putAll(getAbstractPartMatProperties(anAbstractSnecmaObject)); + return theMap; + } + + private Map getPartProperties(final AbstractPart anAbstractSnecmaObject) { + Map theMap = getAbstractSnecmaObjectProperties(anAbstractSnecmaObject); + theMap.putAll(getAbstractPartProperties(anAbstractSnecmaObject)); + return theMap; + } + + private Map getReceptorProperties(final AbstractRF rf) { + Map theMap = new EnumMap<>(R22VisitorKeys.class); + theMap.put(R22VisitorKeys.REPERE_FONCTIONNEL_REVISION, rf.getName() + SEPARATOR + rf.getRevisionId()); + return theMap; + } + + @Override + public Map visitComponent(final MockupRevision aMockupRev) { + // This object is not use in this report + return null; + } + + @Override + public Map visitComponent(final DescriptifRevision aDescriptifRev) { + // This object is not use in this report + return null; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r22report/visitors/snecmaobject/R22ReceptorVisitor.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r22report/visitors/snecmaobject/R22ReceptorVisitor.java new file mode 100644 index 0000000..961c191 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r22report/visitors/snecmaobject/R22ReceptorVisitor.java @@ -0,0 +1,160 @@ +package com.capgemini.reports.definition.r22report.visitors.snecmaobject; + +import com.capgemini.reports.definition.r22report.visitors.R22VisitorKeys; +import com.capgemini.reports.snecmaobjects.ISnecmaObject; +import com.capgemini.reports.snecmaobjects.admin.RFAdminAGRevision; +import com.capgemini.reports.snecmaobjects.admin.RFAdminAPRevision; +import com.capgemini.reports.snecmaobjects.admin.RFAdminARevision; +import com.capgemini.reports.snecmaobjects.admin.RFAdminRevision; +import com.capgemini.reports.snecmaobjects.descriptif.DescriptifRevision; +import com.capgemini.reports.snecmaobjects.generic.GenericAssembRevision; +import com.capgemini.reports.snecmaobjects.generic.GenericRevision; +import com.capgemini.reports.snecmaobjects.mockup.MockupRevision; +import com.capgemini.reports.snecmaobjects.part.*; +import com.capgemini.reports.snecmaobjects.product.ProductRevision; +import com.capgemini.reports.snecmaobjects.rf.RFGenericRevision; +import com.capgemini.reports.snecmaobjects.rf.RFPartAssembRevision; +import com.capgemini.reports.snecmaobjects.rf.RFPartRevision; +import com.capgemini.reports.snecmaobjects.supermodel.SuperModelRevision; +import com.capgemini.reports.snecmaobjects.visitor.IReceptorVisitor; + +import java.util.EnumMap; +import java.util.HashMap; +import java.util.Map; + +/** + * Visit a Receptor SnecmaObject to make a R22 report. + */ +public class R22ReceptorVisitor implements IReceptorVisitor> { + private static final long serialVersionUID = -674550302066648191L; + + private static final String SEPARATOR = " ; "; + + @Override + public Map visitReceptor(final ProductRevision aProductRev) { + // No use in R22 report + return new HashMap<>(); + } + + @Override + public Map visitReceptor(final GenericRevision aGenericRev) { + // No use in R22 report + return new HashMap<>(); + } + + @Override + public Map visitReceptor(final GenericAssembRevision aGenericAssembRev) { + // No use in R22 report + return new HashMap<>(); + } + + @Override + public Map visitReceptor(SuperModelRevision aSuperModelRev) { + return null; + } + + @Override + public Map visitReceptor(final AlternateRevision aAlternateRev) { + return getReceptorProperties(aAlternateRev); + } + + @Override + public Map visitReceptor(final DETRevision aDetRev) { + return getReceptorProperties(aDetRev); + } + + @Override + public Map visitReceptor(final PartAeroRevision aPartAeroRev) { + return getReceptorProperties(aPartAeroRev); + } + + @Override + public Map visitReceptor(final PartNoAeroRevision aPartNoAeroRev) { + return getReceptorProperties(aPartNoAeroRev); + } + + @Override + public Map visitReceptor(final PartAssembRevision aPartAssembRev) { + return getReceptorProperties(aPartAssembRev); + } + + @Override + public Map visitReceptor(final PartMatRevision aPartMatRev) { + return getReceptorProperties(aPartMatRev); + } + + @Override + public Map visitReceptor(final StandardRevision aStandardRev) { + return getReceptorProperties(aStandardRev); + } + + @Override + public Map visitReceptor(final RFGenericRevision aRfGenericRev) { + // No use in R22 report + return new HashMap<>(); + } + + @Override + public Map visitReceptor(final RFPartAssembRevision aRfPartAssembRev) { + // No use in R22 report + return new HashMap<>(); + } + + @Override + public Map visitReceptor(final RFPartRevision aRfPartRev) { + // No use in R22 report + return new HashMap<>(); + } + + @Override + public Map visitReceptor(final RFAdminRevision aRfAdminRev) { + // No use in R22 report + return new HashMap<>(); + } + + @Override + public Map visitReceptor(final RFAdminARevision aRfAdminARev) { + // No use in R22 report + return new HashMap<>(); + } + + @Override + public Map visitReceptor(final RFAdminAPRevision aRfAdminAPRev) { + // No use in R22 report + return new HashMap<>(); + } + + @Override + public Map visitReceptor(final RFAdminAGRevision aRfAdminAGRev) { + // No use in R22 report + return new HashMap<>(); + } + + /** + * Get the Receptor properties.
    + *

    + * expected format : (item_id ; item_revision_id) + */ + private Map getReceptorProperties(final ISnecmaObject iSnecmaObject) { + Map theMap = new EnumMap<>(R22VisitorKeys.class); + theMap.put(R22VisitorKeys.RECEPTEUR, iSnecmaObject.getItemId() + SEPARATOR + iSnecmaObject.getRevisionId()); + return theMap; + } + + @Override + public Map visitReceptor(final MockupRevision aMockupRev) { + // This object is not use in this report + return null; + } + + @Override + public Map visitReceptor(DescriptifRevision aDescriptifRev) { + // This object is not use in this report + return null; + } + + @Override + public Map emptyRf() { + return new HashMap<>(); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r23report/DataReportPreparatorR23.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r23report/DataReportPreparatorR23.java new file mode 100644 index 0000000..1ca30b8 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r23report/DataReportPreparatorR23.java @@ -0,0 +1,170 @@ +package com.capgemini.reports.definition.r23report; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.EmptyNomenclatureException; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcBomObject; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcBomObjectFactory; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcRevisionRule; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcRevisionRuleProperties; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.product.TcProduct; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.product.TcProductRevision; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.unit.TcUnitRevision; +import com.capgemini.framework.teamcenter.object.runtime.TcBomWindow; +import com.capgemini.framework.teamcenter.object.runtime.TcBomWindowConfiguration; +import com.capgemini.framework.teamcenter.object.runtime.TcRevisionRulesConfiguration; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.bomlineholder.BOMLineHolderFactory; +import com.capgemini.reports.bomlineholder.processor.DefaultAltOrDetBehaviour; +import com.capgemini.reports.definition.r23report.visitors.R23Visitor; +import com.capgemini.reports.exceptions.InvalidUserInputException; +import com.capgemini.reports.exceptions.NoConfChangesException; +import com.capgemini.reports.exceptions.UserInputErrorEnum; +import com.capgemini.reports.execution.IDataReportPreparator; +import com.capgemini.reports.execution.strategies.IExecutionStrategy; +import com.capgemini.reports.filter.AllIsGoodFilter; +import com.capgemini.reports.optimized.r23report.OptimizedR23Folder; +import com.capgemini.reports.printing.PrintParameters; +import com.capgemini.reports.reports.parameters.EffectivityDate; +import com.capgemini.reports.reports.parameters.MonoMulti; +import com.capgemini.reports.reports.parameters.ProductUnit; +import com.capgemini.reports.teamcenter.resolution.structureservice.IStructureServiceCaller; +import com.capgemini.reports.teamcenter.resolution.structureservice.MultiStructureServiceCaller; +import com.capgemini.reports.teamcenter.resolution.structureservice.TripleStructureServiceCaller; +import com.teamcenter.soa.client.model.ModelObject; +import com.teamcenter.soa.client.model.strong.Form; +import com.teamcenter.soa.client.model.strong.PSBOMView; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.util.List; + +import static com.capgemini.framework.teamcenter.object.pom.status.StatusEnum.*; + +/** + * This class will allow to prepare data and findAll back data for making report R23. + */ +public class DataReportPreparatorR23 implements IDataReportPreparator { + private static final long serialVersionUID = 1758410914529352674L; + private static final Logger LOGGER = LoggerFactory.getLogger(DataReportPreparatorR23.class); + + private static final AllIsGoodFilter ACCEPT_ALL = new AllIsGoodFilter(); + + @Override + public String print(final TcSession session, final ExecutionR23 execution, final IExecutionStrategy executionStrategy) throws KurtException { + ProductUnit productUnit = execution.getProductUnit(); + TcProduct tcProduct = new TcProduct(session, productUnit.getProduct(session)); + TcProductRevision tcProductRevision = tcProduct.revisions().get(0); + execution.setProductLine(tcProductRevision.ligneProduit()); + PrintParameters printParameters = execution.reportParameters(); + + if (new OptimizedR23Folder().configurationHasNotChanged(productUnit)) { + throw new NoConfChangesException(UserInputErrorEnum.NO_CONFIGURATION_CHANGES.getMsgEn()); + } + + if (!hasMoreThanOneEffectiveUnit(session, execution, productUnit, tcProduct, tcProductRevision, printParameters)) { + throw new InvalidUserInputException(UserInputErrorEnum.NO_DATA_EXTRACTED_FOR_CRITERIA); + } + + executionStrategy.print(printParameters, execution); + + return executionStrategy.getReportFileName(execution) + printParameters.getOuputFileExtension(); + } + + private boolean hasMoreThanOneEffectiveUnit(final TcSession session, final ExecutionR23 execution, final ProductUnit productUnit, final TcProduct tcProduct, final TcProductRevision tcProductRevision, final PrintParameters printParameters) throws KurtException { + boolean hasMoreThanOneEffectiveUnit = false; + for (TcUnitRevision unitRevision : unitToProcess(tcProductRevision, execution.isWithFrozenUnit(),execution.getProductUnitForUnit(), execution.getProductUnitFromUnit(), execution.getNbDaysSinceFrozenStr())) { + int unitNumber = unitRevision.unitNumber(); + // Get revision of the unit for usage in the report name + String unitRev = unitRevision.getUnitRev(); + // Get unit frozen information for usage in the report name + boolean isFrozen = false; + if(unitRevision.hasStatus(J3A, J3B, FROZEN, FROZEN_IN_PROCESS)) { + isFrozen = true; + } + LOGGER.debug("Unit [{}] Revision [{}] is Frozen ? = [{}]", unitNumber, unitRev, isFrozen); + ProductUnit subProductUnit = new ProductUnit(productUnit.getProductID(), unitNumber); + ExecutionR23 subExecution = new ExecutionR23(subProductUnit, execution.getGeneric(), execution.getMonoMulti(), execution.getEffectivityDate(), execution.isSuperModelBOM(), + execution.isWithFrozenUnit(), execution.getProductUnitForUnit(), execution.getProductUnitFromUnit(), execution.getNbDaysSinceFrozenStr()); + subExecution.setProductLine(tcProductRevision.ligneProduit()); + subExecution.setUnitRevision(unitRev); + subExecution.setFrozenUnit(isFrozen); + try { + printParameters.addSubReport("R23-" + unitNumber, prepareData(session, subExecution, tcProduct, unitNumber)); + hasMoreThanOneEffectiveUnit = true; + } + catch (KurtException e) { + LOGGER.warn(e.getMessage(), e); + } + } + return hasMoreThanOneEffectiveUnit; + } + + private List unitToProcess(final TcProductRevision tcProductRevision, boolean isWithFrozenUnit, ProductUnit productUnitForUnit, ProductUnit productUnitFromUnit, String nbDaysSinceFrozenStr) throws KurtException { + List unitsToProcess = tcProductRevision.r23UnitRevisions(isWithFrozenUnit, productUnitForUnit, productUnitFromUnit, nbDaysSinceFrozenStr); + if (unitsToProcess.isEmpty()) { + throw new InvalidUserInputException(UserInputErrorEnum.NO_DATA_COULD_BE_EXTRACTED_NO_FROZEN_OR_OPEN_UNIT_TO_THE_PRODUCT); + } + return unitsToProcess; + } + + private PrintParameters prepareData(final TcSession session, final ExecutionR23 report, final TcProduct tcProduct, final int unitNumber) throws KurtException { + LOGGER.debug("PrepareData started on: {}", report.getReportIdentifier().getReportTitle()); + + TcBomObject topLineObject= new TcBomObjectFactory(session, report.getGeneric().getItem(session)).create(); + TcProduct productObject = new TcProduct(session, report.getProductUnit().getProduct(session)); + TcProductRevision productObjectRevision = productObject.revisions().get(0); + + EffectivityDate effectivityDate = report.getEffectivityDate(); + TcRevisionRuleProperties revisionRuleProperties = new TcRevisionRuleProperties(tcProduct, unitNumber, effectivityDate.isNow() ? null : effectivityDate.getDateTime()); + + TcRevisionRule revisionRule = session.findRevRule(report.getRevisionRule()); + TcRevisionRulesConfiguration revRulesConfiguration = new TcRevisionRulesConfiguration(revisionRule, revisionRuleProperties); + + IStructureServiceCaller service; + if (MonoMulti.MONO.equals(report.getMonoMulti())) { + service = new TripleStructureServiceCaller(session); + } else { + service = new MultiStructureServiceCaller(session); + } + + TcBomWindowConfiguration tcBomWindowConfiguration ; + if (report.isSuperModelBOM()) { + PSBOMView modelBom = productObjectRevision.bomViewRev(); + tcBomWindowConfiguration = new TcBomWindowConfiguration (topLineObject,modelBom,revRulesConfiguration); + } else { + tcBomWindowConfiguration = new TcBomWindowConfiguration(topLineObject, revRulesConfiguration); + } + + + try (TcBomWindow bomWindow = session.createBomWindow(tcBomWindowConfiguration)) { + session.setObjectPropPolicy(report.getFullPolicy()); + + BOMLineHolder unbuiltTopLine = service.resolve(bomWindow.topLine(), ACCEPT_ALL); + List itemRevMaster = unbuiltTopLine.getAllItemRevMasters(); + session.loadProperties(itemRevMaster.toArray(new ModelObject[itemRevMaster.size()])); + + BOMLineHolderFactory.buildTopBom(session, unbuiltTopLine, ACCEPT_ALL); + DefaultAltOrDetBehaviour aBOMLineHolderProcessor = new DefaultAltOrDetBehaviour<>(session, effectivityDate.isNow() ? null : effectivityDate.getDateTime()); + unbuiltTopLine.process(aBOMLineHolderProcessor); + PrintParameters printParameters = report.subReportParameters(); + unbuiltTopLine.freeze(); + + new R23Visitor(unitNumber).constructDataMaps(session, printParameters, unbuiltTopLine); + + LOGGER.debug("PrepareData ended on: {}", report.getReportIdentifier().getReportTitle()); + return printParameters; + } + catch (EmptyNomenclatureException e) { + switch (report.getGeneric().getType()) { + case GENERIC: + case GENERIC_ASSEMB: + throw new KurtException("Empty Bom for Unit " + unitNumber, e); + default: + throw new KurtException("The TC Nomenclature Resolution returned null", e); + } + } + finally { + session.emptyPolicy(); + } + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r23report/ExecutionR23.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r23report/ExecutionR23.java new file mode 100644 index 0000000..b4e6ccc --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r23report/ExecutionR23.java @@ -0,0 +1,259 @@ +package com.capgemini.reports.definition.r23report; + +import com.capgemini.framework.common.*; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.reports.JasperTemplate; +import com.capgemini.reports.ReportEnum; +import com.capgemini.reports.ReportLaunchTypeEnum; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.builder.R23Builder; +import com.capgemini.reports.builder.ReportBuilder; +import com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum; +import com.capgemini.reports.database.manager.MngCriteriaVal.CriteriaValue; +import com.capgemini.reports.exceptions.FileLoadingException; +import com.capgemini.reports.exceptions.ReportPrintException; +import com.capgemini.reports.execution.AbstractExecutionReport; +import com.capgemini.reports.execution.IDataReportPreparator; +import com.capgemini.reports.printing.PrintParameters; +import com.capgemini.reports.printing.Printer; +import com.capgemini.reports.printing.Printer.PrintFormat; +import com.capgemini.reports.reports.parameters.*; +import com.capgemini.reports.reports.parameters.Generics.GenericType; +import com.capgemini.reports.reports.parameters.checker.*; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; + +/** + * Obtain data for report R23.
    + * Contain {@link IChecker} for a report's construction + */ +@Getter +@EqualsAndHashCode(callSuper = true) +public class ExecutionR23 extends AbstractExecutionReport { + /** + * Policy for inspecting Alternates and DETs more closely (i.e. looking into their pseudo-folders for alternative parts). + */ + public static final PolicyLocation R23_POLICY_XML_ALT = PolicyLocation.make("R23_policy_alt", "/xml/policies/r23report/R23_policy_alt.xml"); + private static final long serialVersionUID = -1413103619999188847L; + private static final Logger LOGGER = LoggerFactory.getLogger(ExecutionR23.class); + private static final DataReportPreparatorR23 DATA_REPORT_PREPARATOR_R23 = new DataReportPreparatorR23(); + // Policies parameters + private static final PolicyLocation R23_POLICY_XML_LIGHT = PolicyLocation.make("R23_policy_light", "/xml/policies/r23report/R23_policy_light.xml"); + private static final PolicyLocation R23_POLICY_XML_FULL = PolicyLocation.make("R23_policy_full", "/xml/policies/r23report/R23_policy_full.xml"); + // Launch type parameter + private static final ReportLaunchTypeEnum REPORT_LAUNCH_TYPE = ReportLaunchTypeEnum.getReportLaunchType("common.launch.launchType.REPORT_R23"); + + // Revision rule parameter + private static final String REPORT_REVISION_RULE = SettingsHelper.getPropertyWithDefaultValue("common.bom.revisionRule.REPORT_R23", DEFAULT_REVISION_RULE); + + // Priority parameter + private static final int REPORT_PRIORITY = SettingsHelper.getPriority(ReportEnum.REPORT_R23); + + private static final String FILE_SEPARATOR = "_"; + private static final String PATTERN_DATE = "dd-MM-yyyy"; + + // Internal working data + private final Generics generic; + private final MonoMulti monoMulti; + private final ProductUnit productUnit; + private final EffectivityDate effectivityDate; + private final boolean isSuperModelBOM; + private final boolean isWithFrozenUnit; + private final ProductUnit productUnitForUnit; + private final ProductUnit productUnitFromUnit; + private final String nbDaysSinceFrozenStr; + + + @Setter + private BOMLineHolder topLine; + private String productLine; + private String unitRevision; + private boolean isFrozenUnit = false; + + /** + * Constructor. + * + * @param aProductUnit {@link ProductUnit} - the product + * @param aGeneric le generic {@link Generics} - represent the generic. Can be null if the wanted configuration is only with the Product and the Unit. + * @param aMonoMulti {@link MonoMulti} - represent the type of resolution structure + * @param effectivityDate {@link EffectivityDate} - represent the effectivity date + * @param isSuperModelBOM boolean + * @param isWithFrozenUnit boolean. If true ask to include frozen units + * @param productUnitForUnit {@link ProductUnit} - the product and unit. Can be null if the wanted configuration is only with the Product + * @param productUnitFromUnit {@link ProductUnit} - the product and from_unit. Can be null if the wanted configuration is only with the Product or only with one unit + * @param nbDaysSinceFrozen nb of days since frozen status set on unit. + */ + + public ExecutionR23(final ProductUnit aProductUnit, final Generics aGeneric, final MonoMulti aMonoMulti, final EffectivityDate effectivityDate, final boolean isSuperModelBOM, final boolean isWithFrozenUnit, final ProductUnit productUnitForUnit, final ProductUnit productUnitFromUnit, final String nbDaysSinceFrozen) { + super(REPORT_PRIORITY, REPORT_REVISION_RULE, REPORT_LAUNCH_TYPE); + this.productUnit = aProductUnit; + this.generic = aGeneric; + this.monoMulti = aMonoMulti; + this.effectivityDate = effectivityDate; + this.isSuperModelBOM = isSuperModelBOM; + this.isWithFrozenUnit = isWithFrozenUnit; + this.productUnitForUnit = productUnitForUnit; + this.productUnitFromUnit = productUnitFromUnit; + this.nbDaysSinceFrozenStr = nbDaysSinceFrozen; + } + + @Override + public List getLaunchData() { + List theCriteria = new ArrayList<>(); + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.PRODUCT, productUnit.getProductID())); + if (generic.getType() == GenericType.GENERIC) { + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.GENERIC, generic.getID())); + } + if (generic.getType() == GenericType.GENERIC_ASSEMB) { + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.GENERIC_ASSEMB, generic.getID())); + } + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.MONO_MULTI, monoMulti.toString())); + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.SUPERMODEL, Boolean.toString(isSuperModelBOM))); + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.EFFECTIVITY_DATE, effectivityDate.formatAsInputCriteria())); + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.WITH_FROZEN_UNIT, Boolean.toString(isWithFrozenUnit))); + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.UNIT, productUnitForUnit.getUnitStr())); + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.FROM_UNIT, productUnitFromUnit.getUnitStr())); + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.UNITS_FROZEN_SINCE_LESS_THAN, nbDaysSinceFrozenStr)); + + return theCriteria; + } + + @Override + public String getSpecifiedFileName() { + StringBuilder builder = new StringBuilder("R23").append(FILE_SEPARATOR); + if (generic.getType() != GenericType.ONLY_PRODUCT) { + builder.append(generic.getID()).append(FILE_SEPARATOR); + } + builder.append(productUnit.getProductID()).append(FILE_SEPARATOR); + builder.append(productLine.replaceAll(StringHelper.REGEXP_ALPHANUM, " ")).append(FILE_SEPARATOR); + builder.append(TeamcenterDateFormatter.formatCalendarToPattern(Calendar.getInstance(), PATTERN_DATE)).append(FILE_SEPARATOR); + builder.append(monoMulti.toString()); + return builder.toString(); + } + + /** + * Returns the file name as it will be saved to disc locally. + * FEB459 added unit revision and GELE suffix + * + * @return the file name + */ + private String getSubReportFileName() { + StringBuilder builder = new StringBuilder("R23").append(FILE_SEPARATOR); + if (generic.getType() != GenericType.ONLY_PRODUCT) { + builder.append(generic.getID()).append(FILE_SEPARATOR); + } + builder.append(productUnit.getProductID()).append(FILE_SEPARATOR); + builder.append(productLine.replaceAll(StringHelper.REGEXP_ALPHANUM, " ")).append(FILE_SEPARATOR); + builder.append(productUnit.getUnitStr()).append(FILE_SEPARATOR); + builder.append(unitRevision).append(FILE_SEPARATOR); + builder.append(TeamcenterDateFormatter.formatCalendarToPattern(Calendar.getInstance(), PATTERN_DATE)).append(FILE_SEPARATOR); + builder.append(monoMulti.toString()); + if(isFrozenUnit) { + builder.append(FILE_SEPARATOR).append("GELE"); + } + return builder.toString(); + } + + @Override + public Printer getPrinter() { + return new Printer(Printer.AvailablePrinter.ZIP); + } + + @Override + public PrintFormat getPrintingFormat() { + return PrintFormat.XLSX; + } + + @Override + public ReportEnum getReportIdentifier() { + return ReportEnum.REPORT_R23; + } + + @Override + public List getQuickChecks() { + List quickChecks = new ArrayList<>(); + quickChecks.add(new GenericExistenceChecker(generic)); + quickChecks.add(new ProductChecker(productUnit.getProductID())); + quickChecks.add(new EffectivityChecker(effectivityDate)); + if(!productUnitForUnit.getUnitStr().isEmpty()) { // If a Unit is filled -> check product/unit correspondance + quickChecks.add(new ProductUnitChecker(productUnitForUnit)); + } + return quickChecks; + } + + @Override + public List getLongChecks() { + List longChecks = new ArrayList<>(); + longChecks.add(new GenericUnderProductUnitChecker(generic)); + return longChecks; + } + + @Override + public PolicyLocation getPropertyPolicyForLongChecks() { + return R23_POLICY_XML_LIGHT; + } + + @Override + public PolicyLocation getFullPolicy() { + return R23_POLICY_XML_FULL; + } + + @Override + public String getTemplateLocation() { + return JasperTemplate.TEMPLATE_R23.getFilepath(); + } + + @Override + public IDataReportPreparator getDataPreparator() { + return DATA_REPORT_PREPARATOR_R23; + } + + @Override + public AbstractExecutionReport cloneTemplateToExecution() { + return new ExecutionR23(productUnit, generic, monoMulti, effectivityDate, isSuperModelBOM, isWithFrozenUnit, productUnitForUnit, productUnitFromUnit, nbDaysSinceFrozenStr); + } + + @Override + public Class getReportBuilderClass() { + return R23Builder.class; + } + + public PrintParameters reportParameters() { + return new PrintParameters(Printer.PrintFormat.ZIP, getFileNameOnDisc(), ReportFolderOutputHelper.getStorageFolderLocation(getLaunchType())); + } + + public PrintParameters subReportParameters() throws ReportPrintException, FileLoadingException { + String storageFolder = ReportFolderOutputHelper.getStorageFolderLocation(getLaunchType()); + String templateLocation = getTemplateLocation(); + try (InputStream templateStream = ResourceHelper.getResourceAsStream(templateLocation)) { + PrintParameters printParameters = PrintParameters.createMainReport(getPrintingFormat(), getSubReportFileName(), storageFolder, templateStream); + printParameters.setReportTitle(getReportIdentifier().getReportTitle()); + return printParameters; + } + catch (IOException e) { + LOGGER.error("Unable to close the template file properly from " + templateLocation, e); + return null; // IOException is only thrown by close() which, if it ever fails, means you have much bigger problems! + } + } + + public void setProductLine(String productLine) { + this.productLine = productLine; + } + + public void setUnitRevision(String unitRevision) { + this.unitRevision = unitRevision; + } + + public void setFrozenUnit(boolean frozenUnit) { + isFrozenUnit = frozenUnit; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r23report/visitors/R23Visitor.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r23report/visitors/R23Visitor.java new file mode 100644 index 0000000..b030d43 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r23report/visitors/R23Visitor.java @@ -0,0 +1,121 @@ +package com.capgemini.reports.definition.r23report.visitors; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.definition.r23report.ExecutionR23; +import com.capgemini.reports.definition.r23report.visitors.bomlineholder.R23BOMLineHolderVisitor; +import com.capgemini.reports.execution.mapconstructor.AbstractStaticTemplateMapConstructor; +import com.capgemini.reports.printing.PrintParameters; +import com.capgemini.reports.reports.IReportVisitor; +import lombok.EqualsAndHashCode; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.NoSuchElementException; + +/** + * Visit a R23 report. + */ +@Slf4j +@EqualsAndHashCode(callSuper = true) +public class R23Visitor extends AbstractStaticTemplateMapConstructor implements IReportVisitor { + private static final long serialVersionUID = 3013480234676995245L; + + private static final String NULL = ""; + private static final String EMPTY = ""; + + protected final R23BOMLineHolderVisitor r23BOMLineHolderVisitor = new R23BOMLineHolderVisitor(); + private final int unitNumber; + + /** + * Constructor. + */ + public R23Visitor(final int unitNumber) { + this.unitNumber = unitNumber; + } + + private static String check(final Object anInput) { + return anInput == null ? NULL : anInput.toString(); + } + + /** + * Translate the specific result of the visitor into something the printer can understand. + */ + private List> translate(final List> visitorMaps) { + // Add empty fields in the first line + Map firstLine = visitorMaps.get(0); + // Empty receptor + firstLine.put(R23VisitorKeys.UNIT_NUM, String.valueOf(unitNumber)); + firstLine.put(R23VisitorKeys.IDENTIFIANT_RECEPTEUR, EMPTY); + firstLine.put(R23VisitorKeys.REVISION_RECEPTEUR, EMPTY); + firstLine.put(R23VisitorKeys.NOM_RECEPTEUR, EMPTY); + // Empty RF + firstLine.put(R23VisitorKeys.REPERE_FONCTIONNEL, EMPTY); + firstLine.put(R23VisitorKeys.REVISION_REPERE_FONCTIONNEL, EMPTY); + firstLine.put(R23VisitorKeys.IDENTIFIANT_REPERE_FONCTIONNEL, EMPTY); + firstLine.put(R23VisitorKeys.MAQUETTE, EMPTY); + firstLine.put(R23VisitorKeys.TRANSFERT_LIEN_LOGISTIQUE, EMPTY); + firstLine.put(R23VisitorKeys.TRANSFERT_LIEN_MONTAGE, EMPTY); + firstLine.put(R23VisitorKeys.UIN, EMPTY); + firstLine.put(R23VisitorKeys.EQUIVALENT_SNSSIN, EMPTY); + firstLine.put(R23VisitorKeys.RESPONSABLE_REPERE, EMPTY); + firstLine.put(R23VisitorKeys.SUIVI_MONTAGE, EMPTY); + firstLine.put(R23VisitorKeys.IDENTIFIANT_RF_ADMIN, EMPTY); + firstLine.put(R23VisitorKeys.REVISION_RF_ADMIN, EMPTY); + firstLine.put(R23VisitorKeys.IDENTIFIANT_RF_ADMIN_AP, EMPTY); + firstLine.put(R23VisitorKeys.REVISION_RF_ADMIN_AP, EMPTY); + firstLine.put(R23VisitorKeys.FRONTIERE_AVION, EMPTY); + firstLine.put(R23VisitorKeys.FRONTIERE_COOPERANT, EMPTY); + firstLine.put(R23VisitorKeys.GEOMETRIE_PIECE_RIGIDE, EMPTY); + firstLine.put(R23VisitorKeys.GEOMETRIE_SIMPLIFIE_RIGIDE, EMPTY); + firstLine.put(R23VisitorKeys.ENVELOPPE_DE_CINEMATIQUE, EMPTY); + firstLine.put(R23VisitorKeys.ENVELOPPE_DE_MAINTENANCE, EMPTY); + firstLine.put(R23VisitorKeys.ENVELOPPE_DE_MONTAGE_DEMONTAGE, EMPTY); + firstLine.put(R23VisitorKeys.TRACE_AXIALE, EMPTY); + firstLine.put(R23VisitorKeys.INTERFACE, EMPTY); + firstLine.put(R23VisitorKeys.PROJECT_MOTEUR, EMPTY); + firstLine.put(R23VisitorKeys.MAQUETTE_ECHANGEABLE, EMPTY); + firstLine.put(R23VisitorKeys.WORKPACKAGE, EMPTY); + // Empty BOM + firstLine.put(R23VisitorKeys.ALT, EMPTY); + firstLine.put(R23VisitorKeys.SB, EMPTY); + firstLine.put(R23VisitorKeys.QUANTITE_CUMULEE, EMPTY); + firstLine.put(R23VisitorKeys.PANACHE, EMPTY); + firstLine.put(R23VisitorKeys.QUANTITE, EMPTY); + + // Construct the map list expected by the printer + List> printerMaps = new ArrayList<>(); + for (Map visitorMap : visitorMaps) { + Map printerMap = new HashMap<>(); + for (R23VisitorKeys key : R23VisitorKeys.values()) { + printerMap.put(key.toString(), check(visitorMap.get(key))); + } + printerMaps.add(printerMap); + } + + return printerMaps; + } + + @Override + public List> visitReport(final BOMLineHolder holder) { + List> visitorMaps = r23BOMLineHolderVisitor.visitTopReceptorBom(holder); + return translate(visitorMaps); + } + + @Override + public void constructDataMaps(TcSession session, final PrintParameters printParameters, final BOMLineHolder data) throws KurtException { + long start = System.currentTimeMillis(); + if (data == null) { + throw new NoSuchElementException("No Product structure found"); + } + + // Parse all the snecma objects... + List> printerMaps = this.visitReport(data); + printParameters.addReportData(printerMaps); + log.info("Filtering time : {} ms", System.currentTimeMillis() - start); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r23report/visitors/R23VisitorKeys.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r23report/visitors/R23VisitorKeys.java new file mode 100644 index 0000000..99fd70a --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r23report/visitors/R23VisitorKeys.java @@ -0,0 +1,63 @@ +package com.capgemini.reports.definition.r23report.visitors; + +/** + * Enumeration of all the columns of the R23 report. + */ +public enum R23VisitorKeys { + IDENTIFIANT_RECEPTEUR, + REVISION_RECEPTEUR, + NOM_RECEPTEUR, + REPERE_FONCTIONNEL, + REVISION_REPERE_FONCTIONNEL, + UIN, + EQUIVALENT_SNSSIN, + RESPONSABLE_REPERE, + SUIVI_MONTAGE, + ALT, + SB, + QUANTITE_CUMULEE, + PANACHE, + QUANTITE, + REF_FABRICANT_REF_SNECMA, + REVISION_REFERENCE, + REFERENCE_CONCEPTEUR, + TYPE_REFERENCE, + NOM_REFERENCE, + DESIGNATION_EN, + REFERENCE_TRANSPOSEE, + RESPONSABLE_CONCEPTION, + ALTERNATIVE, + CLASSEMENT, + SUIVI_UTILISATION, + SUIVI_DUREE_VIE, + MASSE_INDICATIVE, + UNITE_DE_MASSE, + IDENTIFIANT_REPERE_FONCTIONNEL, + MAQUETTE, + TRANSFERT_LIEN_LOGISTIQUE, + TRANSFERT_LIEN_MONTAGE, + STATUT_REFERENCE_ARTICLE, + SUIVI_DEVELOPPEMENT, + TYPE_PRODUIT, + DOCUMENT_CONTROLE, + OBTURATION, + IDENTIFIANT_RF_ADMIN, + REVISION_RF_ADMIN, + IDENTIFIANT_RF_ADMIN_AP, + REVISION_RF_ADMIN_AP, + FRONTIERE_AVION, + FRONTIERE_COOPERANT, + GEOMETRIE_PIECE_RIGIDE, + GEOMETRIE_SIMPLIFIE_RIGIDE, + ENVELOPPE_DE_CINEMATIQUE, + ENVELOPPE_DE_MAINTENANCE, + ENVELOPPE_DE_MONTAGE_DEMONTAGE, + TRACE_AXIALE, + INTERFACE, + PROJECT_MOTEUR, + MAQUETTE_ECHANGEABLE, + WORKPACKAGE, + UNIT_NUM, + CR, + CN +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r23report/visitors/bomlineholder/R23AltOrDetBehaviour.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r23report/visitors/bomlineholder/R23AltOrDetBehaviour.java new file mode 100644 index 0000000..489aab7 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r23report/visitors/bomlineholder/R23AltOrDetBehaviour.java @@ -0,0 +1,77 @@ +package com.capgemini.reports.definition.r23report.visitors.bomlineholder; + +import com.capgemini.reports.bomlineholder.processor.AltOrDetBehaviour; +import com.capgemini.reports.definition.r23report.visitors.R23VisitorKeys; +import com.capgemini.reports.snecmaobjects.part.AlternateRevision; +import com.capgemini.reports.snecmaobjects.part.DETRevision; + +import java.util.Map; + +/** + * This class visits Parts that are below an {@link AlternateRevision} or a {@link DETRevision}.
    + * It puts "Oui" in the ALTERNATIVE field of a map. + */ +public class R23AltOrDetBehaviour implements AltOrDetBehaviour { + private static final long serialVersionUID = -7332694328622575681L; + + private static final String OUI = "Oui"; + private static final String EMPTY_STRING = ""; + + @Override + public boolean shouldVisitPartsInPseudoFolder() { + return true; + } + + @Override + public boolean shouldVisitPartsBelowAlt() { + return true; + } + + @Override + public void treatPartsInPseudoFolder(final Map map) { + treatAnyPartBelowThisAltOrDet(map); + } + + @Override + public void treatAlternateOrDETAsReceptor(final Map map) { + treatAnyPartBelowThisAltOrDet(map); + } + + private void treatAnyPartBelowThisAltOrDet(final Map map) { + // Empty fields + map.put(R23VisitorKeys.REPERE_FONCTIONNEL, EMPTY_STRING); + map.put(R23VisitorKeys.IDENTIFIANT_REPERE_FONCTIONNEL, EMPTY_STRING); + map.put(R23VisitorKeys.REVISION_REPERE_FONCTIONNEL, EMPTY_STRING); + map.put(R23VisitorKeys.MAQUETTE, EMPTY_STRING); + map.put(R23VisitorKeys.UIN, EMPTY_STRING); + map.put(R23VisitorKeys.EQUIVALENT_SNSSIN, EMPTY_STRING); + map.put(R23VisitorKeys.RESPONSABLE_REPERE, EMPTY_STRING); + map.put(R23VisitorKeys.TRANSFERT_LIEN_LOGISTIQUE, EMPTY_STRING); + map.put(R23VisitorKeys.TRANSFERT_LIEN_MONTAGE, EMPTY_STRING); + map.put(R23VisitorKeys.SUIVI_MONTAGE, EMPTY_STRING); + map.put(R23VisitorKeys.IDENTIFIANT_RF_ADMIN, EMPTY_STRING); + map.put(R23VisitorKeys.REVISION_RF_ADMIN, EMPTY_STRING); + map.put(R23VisitorKeys.IDENTIFIANT_RF_ADMIN_AP, EMPTY_STRING); + map.put(R23VisitorKeys.REVISION_RF_ADMIN_AP, EMPTY_STRING); + map.put(R23VisitorKeys.FRONTIERE_AVION, EMPTY_STRING); + map.put(R23VisitorKeys.FRONTIERE_COOPERANT, EMPTY_STRING); + map.put(R23VisitorKeys.GEOMETRIE_PIECE_RIGIDE, EMPTY_STRING); + map.put(R23VisitorKeys.GEOMETRIE_SIMPLIFIE_RIGIDE, EMPTY_STRING); + map.put(R23VisitorKeys.ENVELOPPE_DE_CINEMATIQUE, EMPTY_STRING); + map.put(R23VisitorKeys.ENVELOPPE_DE_MAINTENANCE, EMPTY_STRING); + map.put(R23VisitorKeys.ENVELOPPE_DE_MONTAGE_DEMONTAGE, EMPTY_STRING); + map.put(R23VisitorKeys.TRACE_AXIALE, EMPTY_STRING); + map.put(R23VisitorKeys.INTERFACE, EMPTY_STRING); + map.put(R23VisitorKeys.PROJECT_MOTEUR, EMPTY_STRING); + map.put(R23VisitorKeys.MAQUETTE_ECHANGEABLE, EMPTY_STRING); + map.put(R23VisitorKeys.WORKPACKAGE, EMPTY_STRING); + map.put(R23VisitorKeys.ALT, EMPTY_STRING); + map.put(R23VisitorKeys.SB, EMPTY_STRING); + map.put(R23VisitorKeys.QUANTITE_CUMULEE, EMPTY_STRING); + map.put(R23VisitorKeys.PANACHE, EMPTY_STRING); + map.put(R23VisitorKeys.QUANTITE, EMPTY_STRING); + + // Mention that these parts are alternatives to each other + map.put(R23VisitorKeys.ALTERNATIVE, OUI); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r23report/visitors/bomlineholder/R23BOMLineHolderVisitor.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r23report/visitors/bomlineholder/R23BOMLineHolderVisitor.java new file mode 100644 index 0000000..5834594 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r23report/visitors/bomlineholder/R23BOMLineHolderVisitor.java @@ -0,0 +1,83 @@ +package com.capgemini.reports.definition.r23report.visitors.bomlineholder; + +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.bomlineholder.visitor.AbstractBOMLineHolderVisitor; +import com.capgemini.reports.definition.r23report.visitors.R23VisitorKeys; +import com.capgemini.reports.definition.r23report.visitors.snecmaobject.R23ComponentVisitor; +import com.capgemini.reports.definition.r23report.visitors.snecmaobject.R23ReceptorVisitor; +import com.capgemini.reports.releasestatus.EffectivityBehaviourHelper; +import lombok.EqualsAndHashCode; +import lombok.extern.slf4j.Slf4j; + +import java.util.Map; + +/** + * Visitor of an expansion of BOMLineHolder for the R23 report. + */ +@Slf4j +@EqualsAndHashCode(callSuper = true) +public class R23BOMLineHolderVisitor extends AbstractBOMLineHolderVisitor { + private static final long serialVersionUID = -3036778839181191276L; + + public R23BOMLineHolderVisitor() { + super(new R23ReceptorVisitor(), new R23ComponentVisitor(), EffectivityBehaviourHelper.visitOnlyUnitManagedParts(), + new R23AltOrDetBehaviour(), false, true, false); + } + + @Override + protected Map visitThisReceptor(final BOMLineHolder aBomLine) { + return aBomLine.getSnecmaObject().accept(receptorVisitor); + } + + @Override + protected Map visitThisComponent(final BOMLineHolder aBomLine) { + Map aMap = aBomLine.getSnecmaObject().accept(componentVisitor); + + // Put the BOMLine properties into the map + if ((aBomLine.getSnecmaObject().isGeneric()) || (aBomLine.getSnecmaObject().isPart() || (aBomLine.getSnecmaObject().isSuperModel()))) { + aMap.put(R23VisitorKeys.ALT, aBomLine.getBomAlt()); + aMap.put(R23VisitorKeys.SB, aBomLine.getBomSb()); + aMap.put(R23VisitorKeys.QUANTITE_CUMULEE, aBomLine.getBomQtyCumul()); + aMap.put(R23VisitorKeys.PANACHE, aBomLine.getBomPanache()); + aMap.put(R23VisitorKeys.QUANTITE, aBomLine.getBomQty()); + aMap.put(R23VisitorKeys.UIN, aBomLine.getUin()); + } + return aMap; + } + + @Override + protected void visitSpecificFirstLine(final BOMLineHolder aTopBomLine) { + Map theFirstLine = aTopBomLine.getSnecmaObject().accept(getComponentVisitor()); + theReportTable.add(theFirstLine); + } + + @Override + protected void mergeReceptorAndRepereReceptor(final Map aReceptor, final Map aRepereReceptor) { + aReceptor.putAll(aRepereReceptor); + } + + @Override + protected void mergeComponentAndRepereComponent(final Map aComponent, final Map aRepereComponent) { + aComponent.putAll(aRepereComponent); + } + + @Override + protected void mergeRepereReceptorandAdmin(final Map aRepereReceptor, final Map anAdmin) { + aRepereReceptor.putAll(anAdmin); + } + + @Override + protected void mergeRepereComponentandAdmin(final Map aRepereComponent, final Map anAdmin) { + aRepereComponent.putAll(anAdmin); + } + + @Override + protected void addToReport(final Map aReceptor, final Map aComponent) { + // Put the Receptor and Repere Receptor in the Component and modify the Component + // Do not modify the receptor + aComponent.putAll(aReceptor); + + // Add to the R21 report + theReportTable.add(aComponent); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r23report/visitors/snecmaobject/R23ComponentVisitor.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r23report/visitors/snecmaobject/R23ComponentVisitor.java new file mode 100644 index 0000000..2cd599a --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r23report/visitors/snecmaobject/R23ComponentVisitor.java @@ -0,0 +1,407 @@ +package com.capgemini.reports.definition.r23report.visitors.snecmaobject; + +import com.capgemini.framework.common.DoubleFormatter; +import com.capgemini.framework.common.LanguageHelper; +import com.capgemini.framework.teamcenter.object.pom.status.TcReleaseStatus; +import com.capgemini.reports.definition.r23report.visitors.R23VisitorKeys; +import com.capgemini.reports.snecmaobjects.AbstractSnecmaObject; +import com.capgemini.reports.snecmaobjects.admin.RFAdminAGRevision; +import com.capgemini.reports.snecmaobjects.admin.RFAdminAPRevision; +import com.capgemini.reports.snecmaobjects.admin.RFAdminARevision; +import com.capgemini.reports.snecmaobjects.admin.RFAdminRevision; +import com.capgemini.reports.snecmaobjects.descriptif.DescriptifRevision; +import com.capgemini.reports.snecmaobjects.generic.AbstractGenericRevision; +import com.capgemini.reports.snecmaobjects.generic.GenericAssembRevision; +import com.capgemini.reports.snecmaobjects.generic.GenericRevision; +import com.capgemini.reports.snecmaobjects.mockup.MockupRevision; +import com.capgemini.reports.snecmaobjects.part.*; +import com.capgemini.reports.snecmaobjects.product.ProductRevision; +import com.capgemini.reports.snecmaobjects.rf.AbstractRF; +import com.capgemini.reports.snecmaobjects.rf.RFGenericRevision; +import com.capgemini.reports.snecmaobjects.rf.RFPartAssembRevision; +import com.capgemini.reports.snecmaobjects.rf.RFPartRevision; +import com.capgemini.reports.snecmaobjects.supermodel.AbstractSuperModelRevision; +import com.capgemini.reports.snecmaobjects.supermodel.SuperModelRevision; +import com.capgemini.reports.snecmaobjects.visitor.IComponentVisitor; + +import java.util.EnumMap; +import java.util.List; +import java.util.Map; + +/** + * Visit a Component SnecmaObject to make a R23 report. + */ +public class R23ComponentVisitor implements IComponentVisitor> { + private static final long serialVersionUID = 7703811551227059716L; + + private static final int MASS_SIGNIFICANT_DIGITS = 15; + private static final String EMPTY_STRING = ""; + private static final String PART_MAT = "PartMat"; + private static final String SEPARATOR = " / "; + private static final String VALUE_MATIERE = "matière"; + private static final String PRODUIT = "Produit"; + private static final String GENERIQUE_MONTAGE = "Générique Montage"; + private static final String GENERIQUE = "Générique"; + private static final String SUPERMODEL = "Super Model"; + private static final String PARAM_NON = "Non"; + private static final String PARAM_OUI = "Oui"; + + private static String french(final String string) { + return LanguageHelper.french(string); + } + + @Override + public Map visitComponent(final ProductRevision aProductRev) { + Map theMap = getAbstractSnecmaObjectProperties(aProductRev); + theMap.put(R23VisitorKeys.DESIGNATION_EN, aProductRev.getDesignationEN()); + theMap.put(R23VisitorKeys.TYPE_PRODUIT, aProductRev.getTypeProduit()); + theMap.put(R23VisitorKeys.TYPE_REFERENCE, PRODUIT); + theMap.put(R23VisitorKeys.SUIVI_UTILISATION, PARAM_NON); + theMap.put(R23VisitorKeys.SUIVI_DUREE_VIE, PARAM_NON); + theMap.put(R23VisitorKeys.REFERENCE_CONCEPTEUR, EMPTY_STRING); + theMap.put(R23VisitorKeys.REFERENCE_TRANSPOSEE, EMPTY_STRING); + theMap.put(R23VisitorKeys.RESPONSABLE_CONCEPTION, EMPTY_STRING); + theMap.put(R23VisitorKeys.MASSE_INDICATIVE, EMPTY_STRING); + theMap.put(R23VisitorKeys.UNITE_DE_MASSE, EMPTY_STRING); + theMap.put(R23VisitorKeys.STATUT_REFERENCE_ARTICLE, statutReferenceArticle(aProductRev.getStatusList())); + theMap.put(R23VisitorKeys.CLASSEMENT, "-"); + theMap.put(R23VisitorKeys.ALTERNATIVE, EMPTY_STRING); + theMap.put(R23VisitorKeys.SUIVI_DEVELOPPEMENT, EMPTY_STRING); + theMap.put(R23VisitorKeys.DOCUMENT_CONTROLE, EMPTY_STRING); + theMap.put(R23VisitorKeys.OBTURATION, EMPTY_STRING); + + return theMap; + } + + private String statutReferenceArticle(final List statuses) { + StringBuilder builder = new StringBuilder(); + int size = statuses.size(); + for (int i = 0; i < size; i++) { + builder.append(statuses.get(i).getDisplayableName()); + if (i != size - 1) { + builder.append(", "); + } + } + return builder.toString(); + } + + @Override + public Map visitComponent(final GenericRevision aGenericRev) { + Map theMap = getAbstractSnecmaObjectProperties(aGenericRev); + theMap.put(R23VisitorKeys.TYPE_REFERENCE, GENERIQUE); + putGenericProperties(theMap, aGenericRev); + return theMap; + } + + @Override + public Map visitComponent(final GenericAssembRevision aGenericAssembRev) { + Map theMap = getAbstractSnecmaObjectProperties(aGenericAssembRev); + theMap.put(R23VisitorKeys.TYPE_REFERENCE, GENERIQUE_MONTAGE); + putGenericProperties(theMap, aGenericAssembRev); + return theMap; + } + + @Override + public Map visitComponent(final SuperModelRevision aSuperModelRev) { + Map theMap = getAbstractSnecmaObjectProperties(aSuperModelRev); + theMap.put(R23VisitorKeys.TYPE_REFERENCE, GENERIQUE); + putSuperModelProperties(theMap, aSuperModelRev); + return theMap; + } + + @Override + public Map visitComponent(final AlternateRevision anAlternateRev) { + Map theMap = getAbstractSnecmaObjectProperties(anAlternateRev); + putPartProperties(theMap, anAlternateRev); + theMap.put(R23VisitorKeys.TYPE_REFERENCE, french(anAlternateRev.getTypeAlt1()) + SEPARATOR + french(anAlternateRev.getTypeAlt2())); + theMap.put(R23VisitorKeys.SUIVI_DEVELOPPEMENT, french(anAlternateRev.getSuiviDeveloppement())); + theMap.put(R23VisitorKeys.DOCUMENT_CONTROLE, french(anAlternateRev.getDocumentControle())); + theMap.put(R23VisitorKeys.OBTURATION, french(anAlternateRev.getObturation())); + return theMap; + } + + @Override + public Map visitComponent(final DETRevision aDetRev) { + Map theMap = getAbstractSnecmaObjectProperties(aDetRev); + putPartProperties(theMap, aDetRev); + theMap.put(R23VisitorKeys.TYPE_REFERENCE, french(aDetRev.getTypeDet1()) + SEPARATOR + french(aDetRev.getTypeDet2())); + theMap.put(R23VisitorKeys.SUIVI_DEVELOPPEMENT, french(aDetRev.getSuiviDeveloppement())); + theMap.put(R23VisitorKeys.DOCUMENT_CONTROLE, french(aDetRev.getDocumentControle())); + theMap.put(R23VisitorKeys.OBTURATION, french(aDetRev.getObturation())); + return theMap; + } + + @Override + public Map visitComponent(final PartAeroRevision aPartAeroRev) { + Map theMap = getAbstractSnecmaObjectProperties(aPartAeroRev); + putPartProperties(theMap, aPartAeroRev); + theMap.put(R23VisitorKeys.TYPE_REFERENCE, french(aPartAeroRev.getTypeAero1()) + SEPARATOR + french(aPartAeroRev.getTypeAero2()) + SEPARATOR + french(aPartAeroRev.getTypeAero3())); + theMap.put(R23VisitorKeys.SUIVI_DEVELOPPEMENT, french(aPartAeroRev.getSuiviDeveloppement())); + theMap.put(R23VisitorKeys.DOCUMENT_CONTROLE, french(aPartAeroRev.getDocumentControle())); + theMap.put(R23VisitorKeys.OBTURATION, french(aPartAeroRev.getObturation())); + return theMap; + } + + @Override + public Map visitComponent(final PartNoAeroRevision aPartNoAeroRev) { + Map theMap = getAbstractSnecmaObjectProperties(aPartNoAeroRev); + putPartProperties(theMap, aPartNoAeroRev); + theMap.put(R23VisitorKeys.TYPE_REFERENCE, french(aPartNoAeroRev.getTypeNoAero())); + theMap.put(R23VisitorKeys.SUIVI_DEVELOPPEMENT, french(aPartNoAeroRev.getSuiviDeveloppement())); + theMap.put(R23VisitorKeys.DOCUMENT_CONTROLE, french(aPartNoAeroRev.getDocumentControle())); + theMap.put(R23VisitorKeys.OBTURATION, EMPTY_STRING); + return theMap; + } + + @Override + public Map visitComponent(final PartAssembRevision aPartAssembRev) { + Map theMap = getAbstractSnecmaObjectProperties(aPartAssembRev); + putPartProperties(theMap, aPartAssembRev); + theMap.put(R23VisitorKeys.TYPE_REFERENCE, french(aPartAssembRev.getTypePartMontage1()) + SEPARATOR + french(aPartAssembRev.getTypePartMontage2())); + theMap.put(R23VisitorKeys.SUIVI_DEVELOPPEMENT, EMPTY_STRING); + theMap.put(R23VisitorKeys.DOCUMENT_CONTROLE, french(aPartAssembRev.getDocumentControle())); + theMap.put(R23VisitorKeys.OBTURATION, EMPTY_STRING); + return theMap; + } + + @Override + public Map visitComponent(final PartMatRevision aPartMatRev) { + Map theMap = getAbstractSnecmaObjectProperties(aPartMatRev); + putPartProperties(theMap, aPartMatRev); + theMap.put(R23VisitorKeys.TYPE_REFERENCE, VALUE_MATIERE); + theMap.put(R23VisitorKeys.CLASSEMENT, aPartMatRev.getClassementMat()); + theMap.put(R23VisitorKeys.SUIVI_UTILISATION, PARAM_NON); + theMap.put(R23VisitorKeys.SUIVI_DUREE_VIE, PARAM_NON); + theMap.put(R23VisitorKeys.SUIVI_DEVELOPPEMENT, EMPTY_STRING); + theMap.put(R23VisitorKeys.DOCUMENT_CONTROLE, EMPTY_STRING); + theMap.put(R23VisitorKeys.OBTURATION, EMPTY_STRING); + return theMap; + } + + @Override + public Map visitComponent(final StandardRevision aStandardRev) { + Map theMap = getAbstractSnecmaObjectProperties(aStandardRev); + putPartProperties(theMap, aStandardRev); + theMap.put(R23VisitorKeys.TYPE_REFERENCE, french(aStandardRev.getTypeStandard())); + theMap.put(R23VisitorKeys.SUIVI_DEVELOPPEMENT, french(aStandardRev.getSuiviDeveloppement())); + theMap.put(R23VisitorKeys.DOCUMENT_CONTROLE, french(aStandardRev.getDocumentControle())); + theMap.put(R23VisitorKeys.OBTURATION, EMPTY_STRING); + return theMap; + } + + /** + * Get Component properties to make a R23 report. + * + * @param anAbstractSnecmaObject AbstractSnecmaObject + * @return theMap Map + */ + private Map getAbstractSnecmaObjectProperties(final AbstractSnecmaObject anAbstractSnecmaObject) { + Map theMap = new EnumMap<>(R23VisitorKeys.class); + theMap.put(R23VisitorKeys.REF_FABRICANT_REF_SNECMA, anAbstractSnecmaObject.getItemId()); + theMap.put(R23VisitorKeys.NOM_REFERENCE, anAbstractSnecmaObject.getName()); + theMap.put(R23VisitorKeys.REVISION_REFERENCE, anAbstractSnecmaObject.getRevisionId()); + theMap.put(R23VisitorKeys.ALTERNATIVE, EMPTY_STRING); + theMap.put(R23VisitorKeys.CR, anAbstractSnecmaObject.getCRPseudoFolderContentAsString()); + theMap.put(R23VisitorKeys.CN, anAbstractSnecmaObject.getCNPseudoFolderContentAsString()); + return theMap; + } + + /** + * Put the Generic properties into aMap. + * + * @param aMap Map + * @param anAbstractGenericRevision AbstractGenericRevision + */ + private void putGenericProperties(final Map aMap, final AbstractGenericRevision anAbstractGenericRevision) { + aMap.put(R23VisitorKeys.DESIGNATION_EN, anAbstractGenericRevision.getDesignationEN()); + aMap.put(R23VisitorKeys.RESPONSABLE_CONCEPTION, anAbstractGenericRevision.getResponsableConception()); + aMap.put(R23VisitorKeys.SUIVI_UTILISATION, PARAM_OUI); + aMap.put(R23VisitorKeys.SUIVI_DUREE_VIE, PARAM_NON); + aMap.put(R23VisitorKeys.REFERENCE_CONCEPTEUR, EMPTY_STRING); + aMap.put(R23VisitorKeys.REFERENCE_TRANSPOSEE, EMPTY_STRING); + aMap.put(R23VisitorKeys.MASSE_INDICATIVE, EMPTY_STRING); + aMap.put(R23VisitorKeys.UNITE_DE_MASSE, EMPTY_STRING); + aMap.put(R23VisitorKeys.STATUT_REFERENCE_ARTICLE, statutReferenceArticle(anAbstractGenericRevision.getStatusList())); + aMap.put(R23VisitorKeys.ALTERNATIVE, EMPTY_STRING); + aMap.put(R23VisitorKeys.CLASSEMENT, "-"); + aMap.put(R23VisitorKeys.TYPE_PRODUIT, EMPTY_STRING); + aMap.put(R23VisitorKeys.SUIVI_DEVELOPPEMENT, EMPTY_STRING); + aMap.put(R23VisitorKeys.DOCUMENT_CONTROLE, EMPTY_STRING); + aMap.put(R23VisitorKeys.OBTURATION, EMPTY_STRING); + } + + + /** + * Put the Super Model properties into aMap. + * + * @param aMap Map + * @param anAbstractSuperModelRevision AbstractSuperModelRevision + */ + private void putSuperModelProperties(final Map aMap, final AbstractSuperModelRevision anAbstractSuperModelRevision) { + aMap.put(R23VisitorKeys.SUIVI_UTILISATION, EMPTY_STRING); + aMap.put(R23VisitorKeys.SUIVI_DUREE_VIE, EMPTY_STRING); + aMap.put(R23VisitorKeys.REFERENCE_CONCEPTEUR, EMPTY_STRING); + aMap.put(R23VisitorKeys.REFERENCE_TRANSPOSEE, EMPTY_STRING); + aMap.put(R23VisitorKeys.MASSE_INDICATIVE, EMPTY_STRING); + aMap.put(R23VisitorKeys.UNITE_DE_MASSE, EMPTY_STRING); + aMap.put(R23VisitorKeys.TYPE_REFERENCE, french(anAbstractSuperModelRevision.getType())); + aMap.put(R23VisitorKeys.STATUT_REFERENCE_ARTICLE, statutReferenceArticle(anAbstractSuperModelRevision.getStatusList())); + aMap.put(R23VisitorKeys.ALTERNATIVE, EMPTY_STRING); + aMap.put(R23VisitorKeys.CLASSEMENT, "-"); + aMap.put(R23VisitorKeys.TYPE_PRODUIT, EMPTY_STRING); + aMap.put(R23VisitorKeys.SUIVI_DEVELOPPEMENT, EMPTY_STRING); + aMap.put(R23VisitorKeys.DOCUMENT_CONTROLE, EMPTY_STRING); + aMap.put(R23VisitorKeys.OBTURATION, EMPTY_STRING); + aMap.put(R23VisitorKeys.DESIGNATION_EN, EMPTY_STRING); + aMap.put(R23VisitorKeys.RESPONSABLE_CONCEPTION, EMPTY_STRING); + + } + + + + + + + + + /** + * Put the Part properties into aMap. + * + * @param aMap Map + * @param anAbstractPart AbstractPart + */ + private void putPartProperties(final Map aMap, final AbstractPart anAbstractPart) { + aMap.put(R23VisitorKeys.DESIGNATION_EN, anAbstractPart.getDesignationEN()); + aMap.put(R23VisitorKeys.REFERENCE_CONCEPTEUR, anAbstractPart.getRefCompleteConcepteur()); + aMap.put(R23VisitorKeys.REFERENCE_TRANSPOSEE, anAbstractPart.getRefTransposeeSnecma()); + aMap.put(R23VisitorKeys.RESPONSABLE_CONCEPTION, anAbstractPart.getResponsableConception()); + if (!PART_MAT.equals(anAbstractPart.getType())) { + aMap.put(R23VisitorKeys.CLASSEMENT, anAbstractPart.getClassement()); + aMap.put(R23VisitorKeys.SUIVI_UTILISATION, french(anAbstractPart.getSuiviUtilisation())); + aMap.put(R23VisitorKeys.SUIVI_DUREE_VIE, french(anAbstractPart.getSuiviDureeVie())); + } + aMap.put(R23VisitorKeys.MASSE_INDICATIVE, DoubleFormatter.toSignificantDigits(anAbstractPart.getMass(), MASS_SIGNIFICANT_DIGITS)); + aMap.put(R23VisitorKeys.UNITE_DE_MASSE, anAbstractPart.getMassUnit()); + aMap.put(R23VisitorKeys.STATUT_REFERENCE_ARTICLE, statutReferenceArticle(anAbstractPart.getStatusList())); + aMap.put(R23VisitorKeys.TYPE_PRODUIT, anAbstractPart.getTypeProduit()); + } + + @Override + public Map visitComponent(final RFGenericRevision aRfGenericRev) { + Map theMap = getRfProperties(aRfGenericRev); + theMap.put(R23VisitorKeys.SUIVI_MONTAGE, PARAM_NON); + return theMap; + } + + @Override + public Map visitComponent(final RFPartAssembRevision aRfPartAssembRev) { + Map theMap = new EnumMap<>(R23VisitorKeys.class); + theMap.put(R23VisitorKeys.REPERE_FONCTIONNEL, aRfPartAssembRev.getName()); + theMap.put(R23VisitorKeys.REVISION_REPERE_FONCTIONNEL, aRfPartAssembRev.getRevisionId()); + theMap.put(R23VisitorKeys.IDENTIFIANT_REPERE_FONCTIONNEL, aRfPartAssembRev.getItemId()); + theMap.put(R23VisitorKeys.EQUIVALENT_SNSSIN, EMPTY_STRING); + return theMap; + } + + @Override + public Map visitComponent(final RFPartRevision aRfPartRev) { + return getRfProperties(aRfPartRev); + } + + @Override + public Map visitComponent(final RFAdminRevision aRfAdminRev) { + Map theMap = new EnumMap<>(R23VisitorKeys.class); + theMap.put(R23VisitorKeys.MAQUETTE, french(aRfAdminRev.getMaqIntExt())); + theMap.put(R23VisitorKeys.IDENTIFIANT_RF_ADMIN, aRfAdminRev.getItemId()); + theMap.put(R23VisitorKeys.REVISION_RF_ADMIN, aRfAdminRev.getRevisionId()); + theMap.put(R23VisitorKeys.RESPONSABLE_REPERE, aRfAdminRev.getResponsableRepere()); + theMap.put(R23VisitorKeys.FRONTIERE_AVION, french(aRfAdminRev.getFrontiereAvion())); + theMap.put(R23VisitorKeys.FRONTIERE_COOPERANT, french(aRfAdminRev.getFrontiereCooperant())); + theMap.put(R23VisitorKeys.GEOMETRIE_PIECE_RIGIDE, french(aRfAdminRev.getGeometriePieceRigide())); + theMap.put(R23VisitorKeys.GEOMETRIE_SIMPLIFIE_RIGIDE, french(aRfAdminRev.getGeometrieSimplifiee())); + theMap.put(R23VisitorKeys.ENVELOPPE_DE_CINEMATIQUE, french(aRfAdminRev.getEnveloppeCinematique())); + theMap.put(R23VisitorKeys.ENVELOPPE_DE_MAINTENANCE, french(aRfAdminRev.getEnveloppeMaintenance())); + theMap.put(R23VisitorKeys.ENVELOPPE_DE_MONTAGE_DEMONTAGE, french(aRfAdminRev.getEnveloppeMontage())); + theMap.put(R23VisitorKeys.TRACE_AXIALE, french(aRfAdminRev.getTraceAxiale())); + theMap.put(R23VisitorKeys.INTERFACE, french(aRfAdminRev.getInterfaceRfAdmin())); + theMap.put(R23VisitorKeys.PROJECT_MOTEUR, aRfAdminRev.getProjetMoteur()); + theMap.put(R23VisitorKeys.MAQUETTE_ECHANGEABLE, aRfAdminRev.getMaqEchangeable()); + theMap.put(R23VisitorKeys.WORKPACKAGE, aRfAdminRev.getWorkpackage()); + return theMap; + } + + @Override + public Map visitComponent(final RFAdminARevision aRfAdminARev) { + Map theMap = new EnumMap<>(R23VisitorKeys.class); + theMap.put(R23VisitorKeys.SUIVI_MONTAGE, french(aRfAdminARev.getSuiviMontage())); + theMap.put(R23VisitorKeys.RESPONSABLE_REPERE, aRfAdminARev.getResponsableRepere()); + theMap.put(R23VisitorKeys.MAQUETTE, french(aRfAdminARev.getMaqIntExt())); + theMap.put(R23VisitorKeys.IDENTIFIANT_RF_ADMIN, EMPTY_STRING); + theMap.put(R23VisitorKeys.REVISION_RF_ADMIN, EMPTY_STRING); + theMap.put(R23VisitorKeys.IDENTIFIANT_RF_ADMIN_AP, EMPTY_STRING); + theMap.put(R23VisitorKeys.REVISION_RF_ADMIN_AP, EMPTY_STRING); + theMap.put(R23VisitorKeys.FRONTIERE_AVION, EMPTY_STRING); + theMap.put(R23VisitorKeys.FRONTIERE_COOPERANT, EMPTY_STRING); + theMap.put(R23VisitorKeys.GEOMETRIE_PIECE_RIGIDE, EMPTY_STRING); + theMap.put(R23VisitorKeys.GEOMETRIE_SIMPLIFIE_RIGIDE, EMPTY_STRING); + theMap.put(R23VisitorKeys.ENVELOPPE_DE_CINEMATIQUE, EMPTY_STRING); + theMap.put(R23VisitorKeys.ENVELOPPE_DE_MAINTENANCE, EMPTY_STRING); + theMap.put(R23VisitorKeys.ENVELOPPE_DE_MONTAGE_DEMONTAGE, EMPTY_STRING); + theMap.put(R23VisitorKeys.TRACE_AXIALE, EMPTY_STRING); + theMap.put(R23VisitorKeys.INTERFACE, EMPTY_STRING); + theMap.put(R23VisitorKeys.PROJECT_MOTEUR, EMPTY_STRING); + theMap.put(R23VisitorKeys.MAQUETTE_ECHANGEABLE, EMPTY_STRING); + theMap.put(R23VisitorKeys.WORKPACKAGE, EMPTY_STRING); + theMap.put(R23VisitorKeys.TRANSFERT_LIEN_LOGISTIQUE, french(aRfAdminARev.getTransfertLienLogisti())); + theMap.put(R23VisitorKeys.TRANSFERT_LIEN_MONTAGE, french(aRfAdminARev.getTransfertLienMontage())); + return theMap; + } + + @Override + public Map visitComponent(final RFAdminAPRevision aRfAdminAPRev) { + Map theMap = new EnumMap<>(R23VisitorKeys.class); + theMap.put(R23VisitorKeys.IDENTIFIANT_RF_ADMIN_AP, aRfAdminAPRev.getItemId()); + theMap.put(R23VisitorKeys.REVISION_RF_ADMIN_AP, aRfAdminAPRev.getRevisionId()); + theMap.put(R23VisitorKeys.SUIVI_MONTAGE, french(aRfAdminAPRev.getSuiviMontage())); + theMap.put(R23VisitorKeys.TRANSFERT_LIEN_LOGISTIQUE, french(aRfAdminAPRev.getTransfertLienLogisti())); + theMap.put(R23VisitorKeys.TRANSFERT_LIEN_MONTAGE, french(aRfAdminAPRev.getTransfertLienMontage())); + return theMap; + } + + @Override + public Map visitComponent(final RFAdminAGRevision aRfAdminAGRev) { + Map theMap = new EnumMap<>(R23VisitorKeys.class); + theMap.put(R23VisitorKeys.IDENTIFIANT_RF_ADMIN_AP, EMPTY_STRING); + theMap.put(R23VisitorKeys.REVISION_RF_ADMIN_AP, EMPTY_STRING); + theMap.put(R23VisitorKeys.TRANSFERT_LIEN_LOGISTIQUE, french(aRfAdminAGRev.getTransfertLienLogisti())); + theMap.put(R23VisitorKeys.TRANSFERT_LIEN_MONTAGE, french(aRfAdminAGRev.getTransfertLienMontage())); + return theMap; + } + + /** + * Get the Repere Component properties to make a R23 report. + * + * @param anAbstractRF AbstractRF + * @return theMap Map + */ + private Map getRfProperties(final AbstractRF anAbstractRF) { + Map theMap = new EnumMap<>(R23VisitorKeys.class); + theMap.put(R23VisitorKeys.REPERE_FONCTIONNEL, anAbstractRF.getName()); + theMap.put(R23VisitorKeys.IDENTIFIANT_REPERE_FONCTIONNEL, anAbstractRF.getItemId()); + theMap.put(R23VisitorKeys.REVISION_REPERE_FONCTIONNEL, anAbstractRF.getRevisionId()); + theMap.put(R23VisitorKeys.EQUIVALENT_SNSSIN, anAbstractRF.getEquivalentSnsSin()); + return theMap; + } + + @Override + public Map visitComponent(final MockupRevision aMockupRev) { + // This object is not use in this report + return null; + } + + @Override + public Map visitComponent(final DescriptifRevision aDescriptifRev) { + // This object is not use in this report + return null; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r23report/visitors/snecmaobject/R23ReceptorVisitor.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r23report/visitors/snecmaobject/R23ReceptorVisitor.java new file mode 100644 index 0000000..eaa34f9 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r23report/visitors/snecmaobject/R23ReceptorVisitor.java @@ -0,0 +1,154 @@ +package com.capgemini.reports.definition.r23report.visitors.snecmaobject; + +import com.capgemini.reports.definition.r23report.visitors.R23VisitorKeys; +import com.capgemini.reports.snecmaobjects.ISnecmaObject; +import com.capgemini.reports.snecmaobjects.admin.RFAdminAGRevision; +import com.capgemini.reports.snecmaobjects.admin.RFAdminAPRevision; +import com.capgemini.reports.snecmaobjects.admin.RFAdminARevision; +import com.capgemini.reports.snecmaobjects.admin.RFAdminRevision; +import com.capgemini.reports.snecmaobjects.descriptif.DescriptifRevision; +import com.capgemini.reports.snecmaobjects.generic.GenericAssembRevision; +import com.capgemini.reports.snecmaobjects.generic.GenericRevision; +import com.capgemini.reports.snecmaobjects.mockup.MockupRevision; +import com.capgemini.reports.snecmaobjects.part.*; +import com.capgemini.reports.snecmaobjects.product.ProductRevision; +import com.capgemini.reports.snecmaobjects.rf.RFGenericRevision; +import com.capgemini.reports.snecmaobjects.rf.RFPartAssembRevision; +import com.capgemini.reports.snecmaobjects.rf.RFPartRevision; +import com.capgemini.reports.snecmaobjects.supermodel.SuperModelRevision; +import com.capgemini.reports.snecmaobjects.visitor.IReceptorVisitor; + +import java.util.EnumMap; +import java.util.Map; + +/** + * Visit a Receptor SnecmaObject to make a R23 report. + */ +public class R23ReceptorVisitor implements IReceptorVisitor> { + private static final long serialVersionUID = 390235455677826754L; + + @Override + public Map visitReceptor(final ProductRevision aProductRev) { + return getReceptorProperties(aProductRev); + } + + @Override + public Map visitReceptor(final GenericRevision aGenericRev) { + return getReceptorProperties(aGenericRev); + } + + @Override + public Map visitReceptor(final SuperModelRevision aSuperModelRev) { + return getReceptorProperties(aSuperModelRev); + } + + @Override + public Map visitReceptor(final GenericAssembRevision aGenericAssembRev) { + return getReceptorProperties(aGenericAssembRev); + } + + @Override + public Map visitReceptor(final AlternateRevision anAlternateRev) { + return getReceptorProperties(anAlternateRev); + } + + @Override + public Map visitReceptor(final DETRevision aDetRev) { + return getReceptorProperties(aDetRev); + } + + @Override + public Map visitReceptor(final PartAeroRevision aPartAeroRev) { + return getReceptorProperties(aPartAeroRev); + } + + @Override + public Map visitReceptor(final PartNoAeroRevision aPartNoAeroRev) { + return getReceptorProperties(aPartNoAeroRev); + } + + @Override + public Map visitReceptor(final PartAssembRevision aPartAssembRev) { + return getReceptorProperties(aPartAssembRev); + } + + @Override + public Map visitReceptor(final PartMatRevision aPartMatRev) { + return getReceptorProperties(aPartMatRev); + } + + @Override + public Map visitReceptor(final StandardRevision aStandardRev) { + return getReceptorProperties(aStandardRev); + } + + @Override + public Map visitReceptor(final RFGenericRevision aRfGenericRev) { + // No use in R23 report + return new EnumMap<>(R23VisitorKeys.class); + } + + @Override + public Map visitReceptor(final RFPartAssembRevision aRfPartAssembRev) { + // No use in R23 report + return new EnumMap<>(R23VisitorKeys.class); + } + + @Override + public Map visitReceptor(final RFPartRevision aRfPartRev) { + // No use in R23 report + return new EnumMap<>(R23VisitorKeys.class); + } + + @Override + public Map visitReceptor(final RFAdminRevision aRfAdminRev) { + // No use in R23 report + return new EnumMap<>(R23VisitorKeys.class); + } + + @Override + public Map visitReceptor(final RFAdminARevision aRfAdminARev) { + // No use in R23 report + return new EnumMap<>(R23VisitorKeys.class); + } + + @Override + public Map visitReceptor(final RFAdminAPRevision aRfAdminAPRev) { + // No use in R23 report + return new EnumMap<>(R23VisitorKeys.class); + } + + @Override + public Map visitReceptor(final RFAdminAGRevision aRfAdminAGRev) { + // No use in R23 report + return new EnumMap<>(R23VisitorKeys.class); + } + + /** + * Get the Receptor properties. + */ + private Map getReceptorProperties(final ISnecmaObject iSnecmaObject) { + Map theMap = new EnumMap<>(R23VisitorKeys.class); + theMap.put(R23VisitorKeys.IDENTIFIANT_RECEPTEUR, iSnecmaObject.getItemId()); + theMap.put(R23VisitorKeys.NOM_RECEPTEUR, iSnecmaObject.getName()); + theMap.put(R23VisitorKeys.REVISION_RECEPTEUR, iSnecmaObject.getRevisionId()); + return theMap; + } + + @Override + public Map visitReceptor(final MockupRevision aMockupRev) { + // This object is not use in this report + return null; + } + + @Override + public Map visitReceptor(final DescriptifRevision aDescriptifRev) { + // This object is not use in this report + return null; + } + + @Override + public Map emptyRf() { + return new EnumMap<>(R23VisitorKeys.class); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r24report/DataReportPreparatorR24.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r24report/DataReportPreparatorR24.java new file mode 100644 index 0000000..810b23d --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r24report/DataReportPreparatorR24.java @@ -0,0 +1,270 @@ +package com.capgemini.reports.definition.r24report; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.EmptyNomenclatureException; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.object.pom.status.StatusEnum; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcRevisionRule; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcRevisionRuleProperties; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.generic.TcGeneric; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.generic.TcGenericPv; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.product.TcProduct; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.product.TcProductRevision; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.unit.TcUnitRevision; +import com.capgemini.framework.teamcenter.object.runtime.TcBomWindow; +import com.capgemini.framework.teamcenter.object.runtime.TcBomWindowConfiguration; +import com.capgemini.framework.teamcenter.object.runtime.TcRevisionRulesConfiguration; +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.capgemini.framework.teamcenter.queries.saved.modelobject.ItemRevisionQuery; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.documentationobjects.DocNorm; +import com.capgemini.reports.documentationobjects.DocNormStandard; +import com.capgemini.reports.documentationobjects.DocTechnic; +import com.capgemini.reports.exceptions.InvalidUserInputException; +import com.capgemini.reports.exceptions.NoConfChangesException; +import com.capgemini.reports.exceptions.UserInputErrorEnum; +import com.capgemini.reports.execution.IDataReportPreparator; +import com.capgemini.reports.execution.strategies.IExecutionStrategy; +import com.capgemini.reports.optimized.r24report.OptimizedR24Folder; +import com.capgemini.reports.printing.PrintParameters; +import com.capgemini.reports.releasestatus.RevisionStatusAndDate; +import com.capgemini.reports.reports.parameters.ProductUnit; +import com.capgemini.reports.snecmaobjects.admin.RFAdminRevision; +import com.capgemini.reports.snecmaobjects.generic.GenericRevision; +import com.capgemini.reports.snecmaobjects.part.AbstractPart; +import com.capgemini.reports.snecmaobjects.part.PartAeroRevision; +import com.capgemini.reports.snecmaobjects.rf.RFGenericRevision; +import com.capgemini.reports.teamcenter.ObjectInfoHelper; +import com.capgemini.reports.teamcenter.ObjectInfoLoader; +import com.capgemini.reports.teamcenter.resolution.structureservice.SingleStructureServiceCaller; +import com.google.common.base.Optional; +import com.google.common.collect.FluentIterable; +import com.teamcenter.soa.client.model.strong.Item; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import lombok.EqualsAndHashCode; +import lombok.extern.slf4j.Slf4j; +import net.lingala.zip4j.exception.ZipException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; + +/** + * This class will allow to prepare data and findAll back data for making report R24. + */ +@Slf4j +@EqualsAndHashCode +public class DataReportPreparatorR24 implements IDataReportPreparator { + private static final long serialVersionUID = 3714231249482402544L; + + private static final Logger LOGGER = LoggerFactory.getLogger(DataReportPreparatorR24.class); + + private static final String REC_DEFINITION = "REC-Définition de récupération / Recovery design"; + private static final String MCI_MASSE_CENTRE_DE_GRAVITE = "MCI-Masse, Centre de gravité et inertie / Mass, gravity center and inertia"; + private static final String REALISATION_ACHIEVEMENT = "Réalisation / Achievement"; + + @Override + public String print(TcSession session, ExecutionR24 execution, IExecutionStrategy executionStrategy) throws KurtException, ZipException { + ProductUnit productUnit = execution.getProductUnit(); + TcProduct tcProduct = new TcProduct(session, productUnit.getProduct(session)); + TcProductRevision tcProductRevision = tcProduct.revisions().get(0); + execution.setProductLine(tcProductRevision.ligneProduit()); + String typeProduit = tcProductRevision.productType(); + PrintParameters printParameters = execution.reportParameters(); + + if (new OptimizedR24Folder().configurationHasNotChanged(productUnit)) { + throw new NoConfChangesException(UserInputErrorEnum.NO_CONFIGURATION_CHANGES.getMsgEn()); + } + + int unitNumber = productUnit.getUnit(); + Optional tcUnitRevision = tcProductRevision.unitRevision(unitNumber); + if (!tcUnitRevision.isPresent()) { + throw new InvalidUserInputException(UserInputErrorEnum.PRODUCT_AND_UNIT_DOES_NOT_EXIST); + } + TcRevisionRulesConfiguration revisionRulesConfiguration = revisionRulesConfiguration(session, execution, tcProduct, unitNumber); + + session.setObjectPropPolicy(execution.getFullPolicy()); + + List tcGenericPvs = tcUnitRevision.get().genericPvs(); + List tcGenerics = FluentIterable.from(tcGenericPvs).filter(TcGeneric.class).toList(); + int genericsDontExistForPU = 0; + for (TcGeneric generic : tcGenerics) { + try { + ExecutionR24 subExecution = new ExecutionR24(execution.getProductUnit(), generic.getItem(), execution.getTypeImpression(), execution.getFrenchInput()); + subExecution.setProductLine(tcProductRevision.ligneProduit()); + subExecution.setTypeProduit(typeProduit); + subExecution.setClausePropriete(ObjectInfoLoader.getClausePropriete(typeProduit, session)); + printParameters.addSubReport("R24-" + generic.getItem().get_item_id(), prepareData(session, subExecution, generic, revisionRulesConfiguration)); + } + catch (EmptyNomenclatureException e) { + genericsDontExistForPU++; + log.warn("No Bom for generic:" + generic.getItem().get_item_id() + " for PU:" + productUnit.getProductID() + "/" + productUnit.getUnitStr()); + } + } + if (genericsDontExistForPU == tcGenerics.size()) { + throw new InvalidUserInputException(UserInputErrorEnum.NO_GENERIC_FOUND_FOR_THIS_PU); + } + + executionStrategy.print(printParameters, execution); + return executionStrategy.getReportFileName(execution) + printParameters.getOuputFileExtension(); + } + + private TcRevisionRulesConfiguration revisionRulesConfiguration(final TcSession session, final ExecutionR24 report, final TcProduct productObject, int unit) throws KurtException { + TcRevisionRuleProperties revisionRuleProperties = new TcRevisionRuleProperties(productObject, unit); + TcRevisionRule revisionRule = session.findRevRule(report.getRevisionRule()); + return new TcRevisionRulesConfiguration(revisionRule, revisionRuleProperties); + } + + private PrintParameters prepareData(final TcSession session, final ExecutionR24 report, final TcGeneric tcGeneric, final TcRevisionRulesConfiguration revisionRulesConfiguration) throws KurtException { + LOGGER.debug("PrepareData started on: {}", report.getReportIdentifier().getReportTitle()); + TcBomWindowConfiguration bomWindowConfiguration = new TcBomWindowConfiguration(tcGeneric, revisionRulesConfiguration); + try (TcBomWindow bomWindow = session.createBomWindow(bomWindowConfiguration)) { + BOMLineHolder rfGenericBom = new SingleStructureServiceCaller(session).resolve(bomWindow.topLine(), new R24BOMLineExplorer()); + + // Treatment of the RFGenericBom + ItemRevision rfGeneric = rfGenericBom.getItemRevision(); + report.setRfGenericRev(new RFGenericRevision(session, rfGeneric)); + + for (BOMLineHolder currentChild : rfGenericBom.getBomChilds()) { + ItemRevision itemRevChild = currentChild.getItemRevision(); + String childType = itemRevChild.getTypeObject().getName(); + if (SnecmaObjectTypes.PART_AERO_REVISION.equals(childType)) { + report.getPartNumberRevList().add(new PartAeroRevision(session, itemRevChild)); + } + else if (SnecmaObjectTypes.DESCRIPTIF_REVISION.equals(childType)) { + retrieveDocNormAndDocNormStandardLists(session, itemRevChild, report); + retrieveDocTechnicList(session, itemRevChild, report); + } + else if (SnecmaObjectTypes.RF_ADMIN_REVISION.equals(childType)) { + report.setRfAdminRev(new RFAdminRevision(session, itemRevChild)); + report.setFrontiereAvion(report.getRfAdminRev().getFrontiereAvion()); + report.setFrontiereCooperant(report.getRfAdminRev().getFrontiereCooperant()); + } + } + + ItemRevision generivRev = (ItemRevision) bomWindow.topLine().get_bl_line_object(); + String typeGeneric = generivRev.getTypeObject().getName(); + if (SnecmaObjectTypes.GENERIC_REVISION.equals(typeGeneric)) { + report.setGenericRev(new GenericRevision(session, generivRev)); + } + else { + throw new KurtException("Object should be a Generic but is a: " + typeGeneric); + } + + // Specific treatment of DocTechnic + filterDocTechnic(report); + filterForDefinitionCertifiee(report); + PrintParameters printParameters = report.subReportParameters(); + new R24Printer().constructDataMaps(session, printParameters, report); + LOGGER.debug("PrepareData ended on: {}", report.getReportIdentifier().getReportTitle()); + return printParameters; + } + } + + private void filterForDefinitionCertifiee(final ExecutionR24 report) { + if (report.isDefCertifiee()) { + List transitList = new ArrayList<>(); + for (DocTechnic docTechnic : report.getDocTechnicList()) { + // These values are forbidden + if ("Définition / Design".equals(docTechnic.getTypeDocTechnic1())) { + transitList.add(docTechnic); + } + } + report.getDocTechnicList().clear(); + report.getDocTechnicList().addAll(transitList); + } + } + + /** + * Returns true if this report execution generated an empty table of documents (no doc found). + * + * @param report - the execution report which provide all informations for the report + * @return true if the table of documents is empty + */ + public boolean isEmptyTable(final ExecutionR24 report) { + return report.getDocNormList().isEmpty() && report.getDocNormStandardList().isEmpty() && report.getDocTechnicList().isEmpty(); + } + + /** + * Retrieve the {@link DocNorm} and the {@link DocNormStandard} in their respective {@link List}s. + * + * @param session {@link TcSession} - the tc session + * @param itemRevision {@link ItemRevision} - the object which possess all the documents + * @param report - the execution report which provide all informations for the report + */ + private void retrieveDocNormAndDocNormStandardLists(final TcSession session, + final ItemRevision itemRevision, final ExecutionR24 report) { + List referenceDoclist = AbstractPart.returnReferenceDocuments(session, itemRevision); + if (!referenceDoclist.isEmpty()) { + for (Item docItem : referenceDoclist) { + if (docItem == null) { + continue; + } + String docType = docItem.getTypeObject().getName(); + String docId = docItem.get_item_id(); + if (SnecmaObjectTypes.DOC_NORM.equals(docType)) { + ItemRevision selectedDocRev = getDocNormAndDocNormStandardRevisions(session, docId); + report.docNormList.add(new DocNorm(session, selectedDocRev)); + } + else if (SnecmaObjectTypes.DOC_NORM_STANDARD.equals(docType)) { + ItemRevision selectedDocRev = getDocNormAndDocNormStandardRevisions(session, docId); + report.docNormStandardList.add(new DocNormStandard(session, selectedDocRev)); + } + } + } + } + + private ItemRevision getDocNormAndDocNormStandardRevisions(final TcSession session, final String docId) { + // Retrieve the revisions + List listOfDocNormRev = new ItemRevisionQuery(session).searchID(docId).findAll(); + // Try to obtain the revision with the latest release date... + Optional selectedDocRev; + selectedDocRev = ObjectInfoHelper.getRevisionFromStatusWithMostRecentReleaseDate(session, listOfDocNormRev, Calendar.getInstance(), + StatusEnum.PUBLISHED, StatusEnum.FROZEN); + if (selectedDocRev.isPresent()) { + return selectedDocRev.get(); + } + else { + // No release date found, now obtain the revision with latest modification date + RevisionStatusAndDate revAndStatus = + ObjectInfoHelper.getRevisionAndStatusWithMostRecentModificationDate(listOfDocNormRev, Calendar.getInstance()); + return revAndStatus.getItemRevision(); + } + } + + /** + * Retrieve the {@link DocTechnic} in a {@link List}. + */ + private void retrieveDocTechnicList(final TcSession session, final ItemRevision partItemRevision, final ExecutionR24 report) { + List technicDocObjects = AbstractPart.returnDefinitionDocuments(session, partItemRevision); + if (!technicDocObjects.isEmpty()) { + for (ItemRevision docTechnicRev : technicDocObjects) { + if (docTechnicRev != null) { + report.docTechnicList.add(new DocTechnic(session, docTechnicRev)); + } + } + } + } + + /** + * Filter the DocTechnic with specific values on the type_doc_technic_1 and type_doc_technic_2 properties. + * + * @param report - the execution report which provide all informations for the report + */ + private void filterDocTechnic(final ExecutionR24 report) { + List transitList = new ArrayList<>(); + for (DocTechnic docTechnic : report.docTechnicList) { + // These values are forbidden + String typeDocTechnic1 = docTechnic.getTypeDocTechnic1(); + String typeDocTechnic2 = docTechnic.getTypeDocTechnic2(); + if (!(REALISATION_ACHIEVEMENT.equals(typeDocTechnic1) + && (MCI_MASSE_CENTRE_DE_GRAVITE.equals(typeDocTechnic2) || REC_DEFINITION.equals(typeDocTechnic2)))) { + transitList.add(docTechnic); + } + } + report.docTechnicList.clear(); + report.docTechnicList.addAll(transitList); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r24report/ExecutionR24.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r24report/ExecutionR24.java new file mode 100644 index 0000000..61ace27 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r24report/ExecutionR24.java @@ -0,0 +1,232 @@ +package com.capgemini.reports.definition.r24report; + +import com.capgemini.framework.common.*; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.reports.JasperTemplate; +import com.capgemini.reports.ReportEnum; +import com.capgemini.reports.ReportLaunchTypeEnum; +import com.capgemini.reports.builder.R24Builder; +import com.capgemini.reports.builder.ReportBuilder; +import com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum; +import com.capgemini.reports.database.manager.MngCriteriaVal; +import com.capgemini.reports.definition.r23report.ExecutionR23; +import com.capgemini.reports.documentationobjects.DocNorm; +import com.capgemini.reports.documentationobjects.DocNormStandard; +import com.capgemini.reports.documentationobjects.DocTechnic; +import com.capgemini.reports.exceptions.FileLoadingException; +import com.capgemini.reports.exceptions.ReportPrintException; +import com.capgemini.reports.execution.AbstractExecutionReport; +import com.capgemini.reports.execution.IDataReportPreparator; +import com.capgemini.reports.printing.PrintParameters; +import com.capgemini.reports.printing.Printer; +import com.capgemini.reports.reports.parameters.IChecker; +import com.capgemini.reports.reports.parameters.ProductUnit; +import com.capgemini.reports.reports.parameters.checker.ProductChecker; +import com.capgemini.reports.reports.parameters.checker.ProductUnitChecker; +import com.capgemini.reports.snecmaobjects.admin.RFAdminRevision; +import com.capgemini.reports.snecmaobjects.generic.AbstractGenericRevision; +import com.capgemini.reports.snecmaobjects.part.PartAeroRevision; +import com.capgemini.reports.snecmaobjects.rf.RFGenericRevision; +import com.teamcenter.soa.client.model.strong.Item; +import lombok.AccessLevel; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; + +/** + * This class controls the execution of a R24 report. + */ +@Getter +@Setter(value = AccessLevel.PROTECTED) +@EqualsAndHashCode(callSuper = true) +public class ExecutionR24 extends AbstractExecutionReport { + protected static final String FRENCH_LANGUAGE = "Francais"; + private static final long serialVersionUID = -5076506178171189943L; + private static final Logger LOGGER = LoggerFactory.getLogger(ExecutionR23.class); + // Policies + private static final PolicyLocation R24_POLICY_XML_FULL = PolicyLocation.make("R24_policy_full", "/xml/policies/r24report/R24_policy_full.xml"); + private static final PolicyLocation R24_POLICY_XML_LIGHT = PolicyLocation.make("R24_policy_light", "/xml/policies/r24report/R24_policy_light.xml"); + // Priority parameter + private static final int REPORT_PRIORITY = SettingsHelper.getPriority(ReportEnum.REPORT_R24); + // Revision rule parameter + private static final String REPORT_REVISION_RULE = SettingsHelper.getPropertyWithDefaultValue("common.bom.revisionRule.REPORT_R24", DEFAULT_REVISION_RULE); + // Launch type parameter + private static final ReportLaunchTypeEnum REPORT_LAUNCH_TYPE = ReportLaunchTypeEnum.getReportLaunchType("common.launch.launchType.REPORT_R24"); + // Configuration + private static final String FILE_SEPARATOR = "_"; + private static final String PATTERN_DATE = "dd-MM-yyyy"; + // Report parameters + protected final boolean french; + protected final String frenchInput; + // Documents gathered + protected final List docNormList = new ArrayList<>(); + protected final List docNormStandardList = new ArrayList<>(); + protected final List docTechnicList = new ArrayList<>(); + // Raw input parameters + protected final ProductUnit productUnit; + protected final Item genericItem; + // Internal working data + protected final String typeImpression; + protected final boolean isDefCertifiee; + // Data gathered + protected String dateReleased = ""; + protected String revisionArticle = ""; + protected String typeProduit; + protected String clausePropriete; + protected RFGenericRevision rfGenericRev; + // Data gathered + protected AbstractGenericRevision genericRev; + protected List partNumberRevList = new ArrayList<>(); + protected RFAdminRevision rfAdminRev; + protected String frontiereAvion = ""; + protected String frontiereCooperant = ""; + private String productLine; + + /** + * Constructor. + * + * @param produitUnit {@link ProductUnit} - the Product id and the Unit range. + * @param typeImpression {@link String} - the type of impression of the report + * @param langage {@link String} - the language selected by the user + */ + public ExecutionR24(final ProductUnit produitUnit, final String typeImpression, final String langage) { + this(produitUnit, null, typeImpression, langage); + } + + public ExecutionR24(final ProductUnit produitUnit, final Item generic, final String typeImpression, final String langage) { + super(REPORT_PRIORITY, REPORT_REVISION_RULE, REPORT_LAUNCH_TYPE); + this.genericItem = generic; + this.frenchInput = langage; + this.french = isFrench(langage); + this.productUnit = produitUnit; + this.isDefCertifiee = "Def_certifiee".equals(typeImpression); + this.typeImpression = typeImpression; + } + + protected static boolean isFrench(final String language) { + return FRENCH_LANGUAGE.equals(language); + } + + @Override + public List getLaunchData() { + List theCriteria = new ArrayList<>(); + theCriteria.add(new MngCriteriaVal.CriteriaValue(ReportCriteriaEnum.PRODUCT, productUnit.getProductID())); + theCriteria.add(new MngCriteriaVal.CriteriaValue(ReportCriteriaEnum.UNIT, productUnit.getUnitStr())); + theCriteria.add(new MngCriteriaVal.CriteriaValue(ReportCriteriaEnum.TYPE_IMPRESSION, typeImpression)); + theCriteria.add(new MngCriteriaVal.CriteriaValue(ReportCriteriaEnum.LANGUAGE, frenchInput)); + return theCriteria; + } + + @Override + public List getQuickChecks() { + ArrayList quickChecks = new ArrayList<>(); + quickChecks.add(new ProductChecker(productUnit.getProductID())); + quickChecks.add(new ProductUnitChecker(productUnit)); + return quickChecks; + } + + @Override + public String getTemplateLocation() { + return JasperTemplate.TEMPLATE_R24.getFilepath(); + } + + @Override + public PolicyLocation getPropertyPolicyForLongChecks() { + return R24_POLICY_XML_LIGHT; + } + + @Override + public PolicyLocation getFullPolicy() { + return R24_POLICY_XML_FULL; + } + + @Override + public List getLongChecks() { + return new ArrayList<>(); + } + + @Override + public ReportEnum getReportIdentifier() { + return ReportEnum.REPORT_R24; + } + + /** + * Format file expected : R24_"Critère produit"_"Ligne produit"_"Critère Unit"_"générique traité"_"date_système".XLSX + */ + private String getSubReportFileName() { + return setFileName(true).toString(); + } + + /** + * Format file expected : R24_"Critère produit"_"Ligne produit"_"Critère Unit"_"date_système".zip + * + * @return zip filename + */ + @Override + public String getSpecifiedFileName() { + return setFileName(false).toString(); + } + + private StringBuilder setFileName(Boolean addItemId) { + StringBuilder filename = new StringBuilder("R24").append(FILE_SEPARATOR); + filename.append(productUnit.getProductID()).append(FILE_SEPARATOR); + filename.append(productLine.replaceAll(StringHelper.REGEXP_ALPHANUM, " ")).append(FILE_SEPARATOR); + filename.append(productUnit.getUnitStr()).append(FILE_SEPARATOR); + if (addItemId) { + filename.append(genericItem.get_item_id()).append(FILE_SEPARATOR); + } + filename.append(TeamcenterDateFormatter.formatCalendarToPattern(Calendar.getInstance(), PATTERN_DATE)); + + return filename; + } + + @Override + public Printer getPrinter() { + return new Printer(Printer.AvailablePrinter.ZIP); + } + + @Override + public Printer.PrintFormat getPrintingFormat() { + return Printer.PrintFormat.XLSX; + } + + @Override + public IDataReportPreparator getDataPreparator() { + return new DataReportPreparatorR24(); + } + + @Override + public AbstractExecutionReport cloneTemplateToExecution() { + return new ExecutionR24(productUnit, typeImpression, frenchInput); + } + + @Override + public Class getReportBuilderClass() { + return R24Builder.class; + } + + public PrintParameters reportParameters() { + return new PrintParameters(Printer.PrintFormat.ZIP, getFileNameOnDisc(), ReportFolderOutputHelper.getStorageFolderLocation(getLaunchType())); + } + + public PrintParameters subReportParameters() throws ReportPrintException, FileLoadingException { + String storageFolder = ReportFolderOutputHelper.getStorageFolderLocation(getLaunchType()); + String templateLocation = getTemplateLocation(); + try (InputStream templateStream = ResourceHelper.getResourceAsStream(templateLocation)) { + PrintParameters printParameters = PrintParameters.createMainReport(getPrintingFormat(), getSubReportFileName(), storageFolder, templateStream); + printParameters.setReportTitle(getReportIdentifier().getReportTitle()); + return printParameters; + } catch (IOException e) { + LOGGER.error("Unable to close the template file properly from " + templateLocation, e); + return null; // IOException is only thrown by close() which, if it ever fails, means you have much bigger problems! + } + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r24report/R24BOMLineExplorer.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r24report/R24BOMLineExplorer.java new file mode 100644 index 0000000..bf00409 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r24report/R24BOMLineExplorer.java @@ -0,0 +1,33 @@ +package com.capgemini.reports.definition.r24report; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.EmptyNomenclatureException; +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.capgemini.framework.teamcenter.resolution.filtering.ITcTypeFilter; +import com.capgemini.framework.teamcenter.resolution.filtering.TcTypeInclusionFilter; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.bomlineholder.BOMLineHolderHelper; +import com.capgemini.reports.exceptions.InvalidInputException; +import com.capgemini.reports.exceptions.MalformedNomenclatureException; +import com.capgemini.reports.teamcenter.resolution.IBOMLineExplorer; +import com.capgemini.reports.teamcenter.resolution.structureservice.SingleStructureServiceCaller; + +/** + * Explorer of {@link BOMLineHolder}s used in {@link SingleStructureServiceCaller} for R24 report.
    + * Thanks to this class, the SINGLE resolution structure could carry on and the Part Number could be taken.
    + * The Rf Generic is returned, and its children Part Aero / RF Admin and Descriptif are loaded + */ +public class R24BOMLineExplorer implements IBOMLineExplorer { + + private static final ITcTypeFilter FILTER_PART_ADMIN_DESCRIPTION = new TcTypeInclusionFilter(SnecmaObjectTypes.PART_AERO_REVISION, SnecmaObjectTypes.RF_ADMIN_REVISION, SnecmaObjectTypes.DESCRIPTIF_REVISION); + private static final ITcTypeFilter FILTER_RF_GENERIC_REVISION = new TcTypeInclusionFilter(SnecmaObjectTypes.RF_GENERIC_REVISION); + + @Override + public BOMLineHolder explore(TcSession session, final SingleStructureServiceCaller.SingleLevelExpander expander, final BOMLineHolder genericBom) throws EmptyNomenclatureException, + InvalidInputException, MalformedNomenclatureException { + BOMLineHolder expandedGenericBom = expander.expand(genericBom, FILTER_RF_GENERIC_REVISION); + BOMLineHolder rfGeneric = BOMLineHolderHelper.findRfGenericBL(expandedGenericBom); + return expander.expand(rfGeneric, FILTER_PART_ADMIN_DESCRIPTION); + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r24report/R24Printer.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r24report/R24Printer.java new file mode 100644 index 0000000..f74df34 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r24report/R24Printer.java @@ -0,0 +1,192 @@ +package com.capgemini.reports.definition.r24report; + +import com.capgemini.framework.common.LanguageHelper; +import com.capgemini.framework.common.StringHelper; +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.reports.definition.r15r16r17reports.AbstractExecutionR15R16R17; +import com.capgemini.reports.definition.r15r16r17reports.CommunR15R16R17ComponentVisitor; +import com.capgemini.reports.definition.r15r16r17reports.R15R16R17R24R25Keys; +import com.capgemini.reports.definition.r15r16r17reports.R15R16R17R24R25Keys.Page2; +import com.capgemini.reports.documentationobjects.DocNorm; +import com.capgemini.reports.documentationobjects.DocNormStandard; +import com.capgemini.reports.documentationobjects.DocTechnic; +import com.capgemini.reports.execution.mapconstructor.AbstractStaticTemplateMapConstructor; +import com.capgemini.reports.execution.mapconstructor.IMapConstructor; +import com.capgemini.reports.printing.PrintParameters; +import com.capgemini.reports.snecmaobjects.part.PartAeroRevision; +import com.capgemini.reports.snecmaobjects.visitor.IComponentVisitor; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.EnumMap; +import java.util.List; +import java.util.Map; + +/** + * This class is able to put the data gathered by an {@link ExecutionR24} into some {@link PrintParameters} for printing. + */ +@Slf4j +public class R24Printer extends AbstractStaticTemplateMapConstructor implements IMapConstructor { + private static final long serialVersionUID = -789205459094400840L; + + private static final String N_A = "N/A"; + + private static final String EMPTY_STRING = StringHelper.EMPTY; + private static final String UNKNOWN_STR = "???"; + private static final String SANS_OBJET = "Sans objet"; + private static final String NOT_APPLICABLE = "Not applicable "; + + private static String french(final String string) { + return LanguageHelper.french(string); + } + + private static String english(final String string) { + return LanguageHelper.english(string); + } + + /** + * Puts the data gathered by an {@link AbstractExecutionR15R16R17} into some {@link PrintParameters} for printing. + * + * @param execution the data-bearing {@link AbstractExecutionR15R16R17} + * @param mainReport the {@link PrintParameters} + */ + private void print(final ExecutionR24 execution, final PrintParameters mainReport) { + // first put generic data + DataReportPreparatorR24 preparator = (DataReportPreparatorR24) execution.getDataPreparator(); + mainReport.addReportParameters(setupStringParameters(execution)); + mainReport.addReportParameter(R15R16R17R24R25Keys.EMPTY_TABLE.toString(), preparator.isEmptyTable(execution)); + mainReport.addReportDataFromEnum(setupData(execution)); + + // Now add the specific stuff + addOptionalParameters(execution, mainReport); + } + + private Map setupStringParameters(final ExecutionR24 execution) { + Map params = new EnumMap<>(R15R16R17R24R25Keys.class); + params.put(R15R16R17R24R25Keys.CLAUSE_PROPRIETE, execution.getClausePropriete()); + params.put(R15R16R17R24R25Keys.PRODUCT_TYPE, execution.getTypeProduit()); + params.put(R15R16R17R24R25Keys.REPORT_TITLE, getTitle()); + params.put(R15R16R17R24R25Keys.ITEM_REVISION_ID, execution.getRevisionArticle()); + String dateReleased = execution.getDateReleased(); + params.put(R15R16R17R24R25Keys.RELEASE_DATE, execution.isFrench() ? french(dateReleased) : english(dateReleased)); + return params; + } + + private List> setupData(final ExecutionR24 execution) { + List> dataTable = new ArrayList<>(); + boolean isFrench = execution.isFrench(); + for (DocNorm norm : execution.getDocNormList()) { + dataTable.add(getDocNormLine(norm, isFrench)); + } + for (DocNormStandard normStd : execution.getDocNormStandardList()) { + dataTable.add(getDocNormStandardLine(normStd, isFrench)); + } + for (DocTechnic technic : execution.getDocTechnicList()) { + dataTable.add(getDocTechnicLine(technic, isFrench)); + } + + // If there are no documents, add an empty line to provoke band printing + if (dataTable.isEmpty()) { + Map line = new EnumMap<>(Page2.class); + line.put(Page2.DOC_NUMBER, "(No document found)"); + line.put(Page2.ISSUE, N_A); + line.put(Page2.DOC_TYPE, N_A); + line.put(Page2.DOC_TITLE, N_A); + dataTable.add(line); + } + return dataTable; + } + + private Map getDocNormLine(final DocNorm docNorm, final boolean isFrench) { + String idOrigine = docNorm.getIdOrigine(); + Map line = new EnumMap<>(Page2.class); + line.put(Page2.DOC_NUMBER, (idOrigine == null || idOrigine.isEmpty()) ? docNorm.getDocId() : idOrigine); + line.put(Page2.ISSUE, "-"); + String typeDocNorm = docNorm.getTypeDocNorm(); + line.put(Page2.DOC_TYPE, isFrench ? french(typeDocNorm) : english(typeDocNorm)); + line.put(Page2.DOC_TITLE, isFrench ? docNorm.getItemName() : docNorm.getDesignationEn()); + return line; + } + + private Map getDocNormStandardLine(final DocNormStandard normStd, final boolean isFrench) { + Map line = new EnumMap<>(Page2.class); + String idOrigine = normStd.getIdOrigine(); + line.put(Page2.DOC_NUMBER, (idOrigine == null || idOrigine.isEmpty()) ? normStd.getDocId() : idOrigine); + line.put(Page2.ISSUE, "-"); + line.put(Page2.DOC_TYPE, isFrench ? "Norme pour articles standards" : "Norm for standards items"); + line.put(Page2.DOC_TITLE, isFrench ? normStd.getItemName() : normStd.getDesignationEn()); + return line; + } + + private Map getDocTechnicLine(final DocTechnic technic, final boolean isFrench) { + Map line = new EnumMap<>(Page2.class); + String idOrigine = technic.getIdOrigine(); + line.put(Page2.DOC_NUMBER, (idOrigine == null || idOrigine.isEmpty()) ? technic.getDocId() : idOrigine); + line.put(Page2.ISSUE, technic.getIndice()); + + String typeDocTechnic1 = technic.getTypeDocTechnic1(); + String type1 = isFrench ? french(typeDocTechnic1) : english(typeDocTechnic1); + String typeDocTechnic2 = technic.getTypeDocTechnic2(); + String type2 = isFrench ? french(typeDocTechnic2) : english(typeDocTechnic2); + line.put(Page2.DOC_TYPE, type1 + " / " + type2); + + line.put(Page2.DOC_TITLE, isFrench ? technic.getName() : technic.getDesignationEn()); + return line; + } + + private void addOptionalParameters(final ExecutionR24 execution, final PrintParameters mainReport) { + Map params = new EnumMap<>(R15R16R17R24R25Keys.class); + List partNumberRevList = execution.getPartNumberRevList(); + if (partNumberRevList != null && !partNumberRevList.isEmpty()) { + Map map = new EnumMap<>(R15R16R17R24R25Keys.class); + if (partNumberRevList.size() == 1) { + map = partNumberRevList.get(0).accept(getVisitor(execution.isFrench())); + map.remove(R15R16R17R24R25Keys.PART_VERSION); + } else { + map.put(R15R16R17R24R25Keys.ITEM_ID, UNKNOWN_STR); + map.put(R15R16R17R24R25Keys.PART_NUMBER, UNKNOWN_STR); + map.put(R15R16R17R24R25Keys.MANUFACTURER_CODE, UNKNOWN_STR); + map.put(R15R16R17R24R25Keys.FRENCH_DESIGNATION, UNKNOWN_STR); + map.put(R15R16R17R24R25Keys.ENGLISH_DESIGNATION, UNKNOWN_STR); + map.put(R15R16R17R24R25Keys.OBTURATION, execution.isFrench() ? SANS_OBJET : NOT_APPLICABLE); + map.put(R15R16R17R24R25Keys.CLASSIFICATION, "-"); + map.put(R15R16R17R24R25Keys.FIELD_OPN_SERIALISATION, UNKNOWN_STR); + map.put(R15R16R17R24R25Keys.LOG_DOCUMENT, execution.isFrench() ? SANS_OBJET : NOT_APPLICABLE); + } + map.put(R15R16R17R24R25Keys.PART_VERSION, EMPTY_STRING); + params.putAll(map); + } else { + params.putAll(execution.getGenericRev().accept(getVisitor(execution.isFrench()))); + } + params.put(R15R16R17R24R25Keys.MT_NUMBER, EMPTY_STRING); + params.put(R15R16R17R24R25Keys.PREVIOUS_RELEASE_DATE, EMPTY_STRING); + params.put(R15R16R17R24R25Keys.ITEM_ID, execution.getGenericItem().get_item_id()); + mainReport.addReportParameters(params); + + Map map = new EnumMap<>(R15R16R17R24R25Keys.SpecificR15R16.class); + boolean isFrench = execution.isFrench(); + String frontiereAvion = execution.getFrontiereAvion(); + map.put(R15R16R17R24R25Keys.SpecificR15R16.INSTALLATION_INTERFACE, isFrench ? french(frontiereAvion) : english(frontiereAvion)); + String frontiereCooperant = execution.getFrontiereCooperant(); + map.put(R15R16R17R24R25Keys.SpecificR15R16.PARTNER_INTERFACE, isFrench ? french(frontiereCooperant) : english(frontiereCooperant)); + map.put(R15R16R17R24R25Keys.SpecificR15R16.PRODUCT_UNIT, execution.getProductUnit().toString()); + mainReport.addReportParameters(map); + mainReport.addReportParameter(R15R16R17R24R25Keys.SpecificR15R16.IS_PREVIOUS_DEF.toString(), false); + } + + private String getTitle() { + return StringHelper.EMPTY; + } + + private IComponentVisitor> getVisitor(final boolean isFrench) { + return new CommunR15R16R17ComponentVisitor(isFrench); + } + + @Override + public void constructDataMaps(TcSession session, final PrintParameters printParameters, final ExecutionR24 data) throws KurtException { + long start = System.currentTimeMillis(); + this.print(data, printParameters); + log.trace("Execution time : {} ms for {}", System.currentTimeMillis() - start, "data filtering"); + } +} \ No newline at end of file diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r25report/DataReportPreparatorR25.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r25report/DataReportPreparatorR25.java new file mode 100644 index 0000000..d1a89e9 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r25report/DataReportPreparatorR25.java @@ -0,0 +1,298 @@ +package com.capgemini.reports.definition.r25report; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.EmptyNomenclatureException; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.object.pom.status.StatusEnum; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcRevisionRule; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcRevisionRuleProperties; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.generic.TcGeneric; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.generic.TcGenericPv; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.product.TcProduct; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.product.TcProductRevision; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.unit.TcUnitRevision; +import com.capgemini.framework.teamcenter.object.runtime.TcBomWindow; +import com.capgemini.framework.teamcenter.object.runtime.TcBomWindowConfiguration; +import com.capgemini.framework.teamcenter.object.runtime.TcRevisionRulesConfiguration; +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.capgemini.framework.teamcenter.queries.saved.modelobject.ItemRevisionQuery; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.documentationobjects.DocNorm; +import com.capgemini.reports.documentationobjects.DocNormStandard; +import com.capgemini.reports.documentationobjects.DocTechnic; +import com.capgemini.reports.exceptions.InvalidUserInputException; +import com.capgemini.reports.exceptions.UserInputErrorEnum; +import com.capgemini.reports.execution.IDataReportPreparator; +import com.capgemini.reports.execution.strategies.IExecutionStrategy; +import com.capgemini.reports.printing.PrintParameters; +import com.capgemini.reports.releasestatus.RevisionStatusAndDate; +import com.capgemini.reports.reports.parameters.ProductUnit; +import com.capgemini.reports.snecmaobjects.admin.RFAdminRevision; +import com.capgemini.reports.snecmaobjects.descriptif.DescriptifRevision; +import com.capgemini.reports.snecmaobjects.generic.GenericRevision; +import com.capgemini.reports.snecmaobjects.part.AbstractPart; +import com.capgemini.reports.snecmaobjects.part.PartAeroRevision; +import com.capgemini.reports.snecmaobjects.rf.RFGenericRevision; +import com.capgemini.reports.teamcenter.ObjectInfoHelper; +import com.capgemini.reports.teamcenter.ObjectInfoLoader; +import com.capgemini.reports.teamcenter.resolution.structureservice.SingleStructureServiceCaller; +import com.google.common.base.Optional; +import com.google.common.collect.FluentIterable; +import com.teamcenter.soa.client.model.strong.Item; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import net.lingala.zip4j.exception.ZipException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; + +import static com.capgemini.framework.teamcenter.object.pom.status.StatusEnum.OPEN; + +/** + * This class will allow to prepare data and findAll back data for making report R25. + */ +public class DataReportPreparatorR25 implements IDataReportPreparator { + private static final long serialVersionUID = 3714231249482402544L; + + private static final Logger LOGGER = LoggerFactory.getLogger(DataReportPreparatorR25.class); + + private static final String REC_DEFINITION = "REC-Définition de récupération / Recovery design"; + private static final String MCI_MASSE_CENTRE_DE_GRAVITE = "MCI-Masse, Centre de gravité et inertie / Mass, gravity center and inertia"; + private static final String REALISATION_ACHIEVEMENT = "Réalisation / Achievement"; + + @Override + public String print(TcSession session, ExecutionR25 execution, IExecutionStrategy executionStrategy) throws KurtException, ZipException { + ProductUnit productUnit = execution.getProductUnit(); + TcProduct tcProduct = new TcProduct(session, productUnit.getProduct(session)); + TcProductRevision tcProductRevision = tcProduct.revisions().get(0); + execution.setProductLine(tcProductRevision.ligneProduit()); + String typeProduit = tcProductRevision.productType(); + session.setObjectPropPolicy(execution.getFullPolicy()); + PrintParameters printParameters = execution.reportParameters(); + + // Si l'utilisateur n'a pas saisi le Unit + if (productUnit.getUnitStr().isEmpty()) { + for (TcUnitRevision unitRevision : unitToProcess(tcProductRevision)) { + int unitNumber = unitRevision.unitNumber(); + ProductUnit subProductUnit = new ProductUnit(productUnit.getProductID(), unitNumber); + ExecutionR25 subExecution = new ExecutionR25(subProductUnit, execution.getTypeImpression(), execution.getFrenchInput()); + subExecution.setProductLine(tcProductRevision.ligneProduit()); + printParameters + .addSubReport("R25-" + subProductUnit.getProductID() + "-" + unitNumber, + collectData(session, subExecution, subExecution.reportSubZipParameters(), typeProduit, subProductUnit, tcProduct, unitNumber, tcProductRevision, tcProductRevision.openUnitRevision(unitNumber))); + } + } + else { + productUnit.parseUserUnit(); + int unitNumber = productUnit.getUnit(); + Optional tcUnitRevision = tcProductRevision.notCancelledRevision(unitNumber); + if (!tcUnitRevision.isPresent()) { + throw new InvalidUserInputException(UserInputErrorEnum.PRODUCT_AND_UNIT_DOES_NOT_EXIST); + } + collectData(session, execution, printParameters, typeProduit, productUnit, tcProduct, unitNumber, tcProductRevision, tcUnitRevision); + } + + executionStrategy.print(printParameters, execution); + return executionStrategy.getReportFileName(execution) + printParameters.getOuputFileExtension(); + + } + + private List unitToProcess(final TcProductRevision tcProductRevision) throws InvalidUserInputException { + List unitsToProcess = new ArrayList<>(); + unitsToProcess.addAll(tcProductRevision.unitRevisionsWithStatus(OPEN)); + if (unitsToProcess.isEmpty()) { + throw new InvalidUserInputException(UserInputErrorEnum.NO_DATA_COULD_BE_EXTRACTED_NO_OPEN_UNIT_TO_THE_PRODUCT); + } + return unitsToProcess; + } + + private PrintParameters collectData(final TcSession session, final ExecutionR25 execution, final PrintParameters subReportParameters, String typeProduit, ProductUnit productUnit, TcProduct tcProduct, int unitNumber, TcProductRevision tcProductRevision, Optional tcUnitRevision) throws KurtException { + List tcGenericPvs = tcUnitRevision.get().genericPvs(); + List tcGenerics = FluentIterable.from(tcGenericPvs).filter(TcGeneric.class).toList(); + int genericsDontExistForPU = 0; + + for (TcGeneric generic : tcGenerics) { + try { + TcRevisionRulesConfiguration revisionRulesConfiguration = revisionRulesConfiguration(session, execution, tcProduct, unitNumber); + ExecutionR25 subExecution = new ExecutionR25(productUnit, generic.getItem(), execution.getTypeImpression(), execution.getFrenchInput()); + subExecution.setProductLine(tcProductRevision.ligneProduit()); + subExecution.setTypeProduit(typeProduit); + subExecution.setClausePropriete(ObjectInfoLoader.getClausePropriete(typeProduit, session)); + subReportParameters.addSubReport("R25-" + generic.getItem().get_item_id(), prepareData(session, subExecution, generic, revisionRulesConfiguration)); + } + catch (EmptyNomenclatureException e) { + genericsDontExistForPU++; + LOGGER.warn("No Bom for generic:" + generic.getItem().get_item_id() + " for PU:" + productUnit.getProductID() + "/" + productUnit.getUnitStr()); + } + } + + if (genericsDontExistForPU == tcGenerics.size()) { + throw new InvalidUserInputException(UserInputErrorEnum.NO_GENERIC_FOUND_FOR_THIS_PU); + } + + return subReportParameters; + } + + private TcRevisionRulesConfiguration revisionRulesConfiguration(final TcSession session, final ExecutionR25 report, final TcProduct productObject, int unit) throws KurtException { + TcRevisionRuleProperties revisionRuleProperties = new TcRevisionRuleProperties(productObject, unit); + TcRevisionRule revisionRule = session.findRevRule(report.getRevisionRule()); + return new TcRevisionRulesConfiguration(revisionRule, revisionRuleProperties); + } + + private PrintParameters prepareData(final TcSession session, final ExecutionR25 report, final TcGeneric tcGeneric, final TcRevisionRulesConfiguration revisionRulesConfiguration) throws KurtException { + LOGGER.debug("PrepareData started on: {}", report.getReportIdentifier().getReportTitle()); + TcBomWindowConfiguration bomWindowConfiguration = new TcBomWindowConfiguration(tcGeneric, revisionRulesConfiguration); + try (TcBomWindow bomWindow = session.createBomWindow(bomWindowConfiguration)) { + BOMLineHolder rfGenericBom = new SingleStructureServiceCaller(session).resolve(bomWindow.topLine(), new R25BOMLineExplorer()); + + // Treatment of the RFGenericBom + ItemRevision rfGeneric = rfGenericBom.getItemRevision(); + report.setRfGenericRev(new RFGenericRevision(session, rfGeneric)); + + for (BOMLineHolder currentChild : rfGenericBom.getBomChilds()) { + ItemRevision itemRevChild = currentChild.getItemRevision(); + String childType = itemRevChild.getTypeObject().getName(); + if (SnecmaObjectTypes.PART_AERO_REVISION.equals(childType)) { + report.getPartNumberRevList().add(new PartAeroRevision(session, itemRevChild)); + } + else if (SnecmaObjectTypes.DESCRIPTIF_REVISION.equals(childType)) { + report.setDescriptifRev(new DescriptifRevision(session, itemRevChild)); + retrieveDocNormAndDocNormStandardLists(session, itemRevChild, report); + retrieveDocTechnicList(session, itemRevChild, report); + } + else if (SnecmaObjectTypes.RF_ADMIN_REVISION.equals(childType)) { + report.setRfAdminRev(new RFAdminRevision(session, itemRevChild)); + report.setFrontiereAvion(report.getRfAdminRev().getFrontiereAvion()); + report.setFrontiereCooperant(report.getRfAdminRev().getFrontiereCooperant()); + } + } + + ItemRevision generivRev = (ItemRevision) bomWindow.topLine().get_bl_line_object(); + String typeGeneric = generivRev.getTypeObject().getName(); + if (SnecmaObjectTypes.GENERIC_REVISION.equals(typeGeneric)) { + report.setGenericRev(new GenericRevision(session, generivRev)); + } + else { + throw new KurtException("Object should be a Generic but is a: " + typeGeneric); + } + + // Specific treatment of DocTechnic + filterDocTechnic(report); + filterForDefinitionCertifiee(report); + PrintParameters printParameters = report.subReportParameters(); + new R25Printer().constructDataMaps(session, printParameters, report); + LOGGER.debug("PrepareData ended on: {}", report.getReportIdentifier().getReportTitle()); + return printParameters; + } + } + + /** + * Returns true if this report execution generated an empty table of documents (no doc found). + * + * @param report - the execution report which provide all informations for the report + * @return true if the table of documents is empty + */ + public boolean isEmptyTable(final ExecutionR25 report) { + return report.getDocNormList().isEmpty() && report.getDocNormStandardList().isEmpty() && report.getDocTechnicList().isEmpty(); + } + + /** + * Retrieve the {@link DocNorm} and the {@link DocNormStandard} in their respective {@link List}s. + * + * @param session {@link TcSession} - the tc session + * @param itemRevision {@link ItemRevision} - the object which possess all the documents + * @param report - the execution report which provide all informations for the report + */ + private void retrieveDocNormAndDocNormStandardLists(final TcSession session, + final ItemRevision itemRevision, final ExecutionR25 report) { + List referenceDoclist = AbstractPart.returnReferenceDocuments(session, itemRevision); + if (!referenceDoclist.isEmpty()) { + for (Item docItem : referenceDoclist) { + if (docItem == null) { + continue; + } + String docType = docItem.getTypeObject().getName(); + String docId = docItem.get_item_id(); + if (SnecmaObjectTypes.DOC_NORM.equals(docType)) { + ItemRevision selectedDocRev = retrieveDocNormAndDocNormStandardRevisions(session, docId); + report.docNormList.add(new DocNorm(session, selectedDocRev)); + } + else if (SnecmaObjectTypes.DOC_NORM_STANDARD.equals(docType)) { + ItemRevision selectedDocRev = retrieveDocNormAndDocNormStandardRevisions(session, docId); + report.docNormStandardList.add(new DocNormStandard(session, selectedDocRev)); + } + } + } + } + + private ItemRevision retrieveDocNormAndDocNormStandardRevisions(final TcSession session, final String docId) { + // Retrieve the revisions + List listOfDocNormRev = new ItemRevisionQuery(session).searchID(docId).findAll(); + // Try to obtain the revision with the latest release date... + Optional selectedDocRev; + selectedDocRev = ObjectInfoHelper.getRevisionFromStatusWithMostRecentReleaseDate(session, listOfDocNormRev, Calendar.getInstance(), + StatusEnum.PUBLISHED, StatusEnum.FROZEN); + if (selectedDocRev.isPresent()) { + return selectedDocRev.get(); + } + else { + // No release date found, now obtain the revision with latest modification date + RevisionStatusAndDate revAndStatus = + ObjectInfoHelper.getRevisionAndStatusWithMostRecentModificationDate(listOfDocNormRev, Calendar.getInstance()); + return revAndStatus.getItemRevision(); + } + } + + /** + * Retrieve the {@link DocTechnic} in a {@link List}. + */ + private void retrieveDocTechnicList(final TcSession session, final ItemRevision partItemRevision, final ExecutionR25 report) { + List technicDocObjects = AbstractPart.returnDefinitionDocuments(session, partItemRevision); + if (!technicDocObjects.isEmpty()) { + for (ItemRevision docTechnicRev : technicDocObjects) { + if (docTechnicRev != null) { + report.docTechnicList.add(new DocTechnic(session, docTechnicRev)); + } + } + } + } + + /** + * Filter the DocTechnic with specific values on the type_doc_technic_1 and type_doc_technic_2 properties. + * + * @param report - the execution report which provide all informations for the report + */ + private void filterDocTechnic(final ExecutionR25 report) { + List transitList = new ArrayList<>(); + for (DocTechnic docTechnic : report.docTechnicList) { + // These values are forbidden + String typeDocTechnic1 = docTechnic.getTypeDocTechnic1(); + String typeDocTechnic2 = docTechnic.getTypeDocTechnic2(); + if (!(REALISATION_ACHIEVEMENT.equals(typeDocTechnic1) + && (MCI_MASSE_CENTRE_DE_GRAVITE.equals(typeDocTechnic2) || REC_DEFINITION.equals(typeDocTechnic2)))) { + transitList.add(docTechnic); + } + } + report.docTechnicList.clear(); + report.docTechnicList.addAll(transitList); + } + + private void filterForDefinitionCertifiee(final ExecutionR25 report) { + if (report.isDefCertifiee()) { + List transitList = new ArrayList<>(); + for (DocTechnic docTechnic : report.getDocTechnicList()) { + // These values are forbidden + if ("Définition / Design".equals(docTechnic.getTypeDocTechnic1())) { + transitList.add(docTechnic); + } + } + report.getDocTechnicList().clear(); + report.getDocTechnicList().addAll(transitList); + } + } +} + + + diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r25report/ExecutionR25.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r25report/ExecutionR25.java new file mode 100644 index 0000000..532ca96 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r25report/ExecutionR25.java @@ -0,0 +1,241 @@ +package com.capgemini.reports.definition.r25report; + +import com.capgemini.framework.common.*; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.reports.JasperTemplate; +import com.capgemini.reports.ReportEnum; +import com.capgemini.reports.ReportLaunchTypeEnum; +import com.capgemini.reports.builder.R25Builder; +import com.capgemini.reports.builder.ReportBuilder; +import com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum; +import com.capgemini.reports.database.manager.MngCriteriaVal; +import com.capgemini.reports.documentationobjects.DocNorm; +import com.capgemini.reports.documentationobjects.DocNormStandard; +import com.capgemini.reports.documentationobjects.DocTechnic; +import com.capgemini.reports.exceptions.FileLoadingException; +import com.capgemini.reports.exceptions.ReportPrintException; +import com.capgemini.reports.execution.AbstractExecutionReport; +import com.capgemini.reports.execution.IDataReportPreparator; +import com.capgemini.reports.printing.PrintParameters; +import com.capgemini.reports.printing.Printer; +import com.capgemini.reports.reports.parameters.IChecker; +import com.capgemini.reports.reports.parameters.ProductUnit; +import com.capgemini.reports.reports.parameters.checker.ProductChecker; +import com.capgemini.reports.reports.parameters.checker.ProductUnitChecker; +import com.capgemini.reports.snecmaobjects.admin.RFAdminRevision; +import com.capgemini.reports.snecmaobjects.descriptif.DescriptifRevision; +import com.capgemini.reports.snecmaobjects.generic.AbstractGenericRevision; +import com.capgemini.reports.snecmaobjects.part.PartAeroRevision; +import com.capgemini.reports.snecmaobjects.rf.RFGenericRevision; +import com.teamcenter.soa.client.model.strong.Item; +import lombok.AccessLevel; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; + +/** + * This class controls the execution of a R25 report. + */ +@Getter +@Setter(value = AccessLevel.PROTECTED) +@EqualsAndHashCode(callSuper = true) +public class ExecutionR25 extends AbstractExecutionReport { + protected static final String FRENCH_LANGUAGE = "Francais"; + private static final long serialVersionUID = -5076506178171189943L; + private static final Logger LOGGER = LoggerFactory.getLogger(ExecutionR25.class); + // Policies + private static final PolicyLocation R25_POLICY_XML_FULL = PolicyLocation.make("R25_policy_full", "/xml/policies/r25report/R25_policy_full.xml"); + private static final PolicyLocation R25_POLICY_XML_LIGHT = PolicyLocation.make("R25_policy_light", "/xml/policies/r25report/R25_policy_light.xml"); + // Priority parameter + private static final int REPORT_PRIORITY = SettingsHelper.getPriority(ReportEnum.REPORT_R25); + // Revision rule parameter + private static final String REPORT_REVISION_RULE = SettingsHelper.getPropertyWithDefaultValue("common.bom.revisionRule.REPORT_R25", DEFAULT_REVISION_RULE); + // Launch type parameter + private static final ReportLaunchTypeEnum REPORT_LAUNCH_TYPE = ReportLaunchTypeEnum.getReportLaunchType("common.launch.launchType.REPORT_R25"); + // Configuration + private static final String FILE_SEPARATOR = "_"; + private static final String PATTERN_DATE = "dd-MM-yyyy"; + // Report parameters + protected final boolean french; + protected final String frenchInput; + // Documents gathered + protected final List docNormList = new ArrayList<>(); + protected final List docNormStandardList = new ArrayList<>(); + protected final List docTechnicList = new ArrayList<>(); + // Raw input parameters + protected final ProductUnit productUnit; + protected final Item genericItem; + // Internal working data + protected final String typeImpression; + protected final boolean isDefCertifiee; + // Data gathered + protected String dateReleased = ""; + protected String revisionArticle = ""; + protected String typeProduit; + protected String clausePropriete; + protected RFGenericRevision rfGenericRev; + // Data gathered + protected AbstractGenericRevision genericRev; + protected List partNumberRevList = new ArrayList<>(); + protected RFAdminRevision rfAdminRev; + protected DescriptifRevision descriptifRev; + protected String frontiereAvion = ""; + protected String frontiereCooperant = ""; + private String productLine; + + /** + * Constructor. + * + * @param produitUnit {@link ProductUnit} - the Product id and the Unit range. + * @param typeImpression {@link String} - the type of impression of the report + * @param langage {@link String} - the language selected by the user + */ + public ExecutionR25(final ProductUnit produitUnit, final String typeImpression, final String langage) { + this(produitUnit, null, typeImpression, langage); + } + + public ExecutionR25(final ProductUnit produitUnit, final Item generic, final String typeImpression, final String langage) { + super(REPORT_PRIORITY, REPORT_REVISION_RULE, REPORT_LAUNCH_TYPE); + this.genericItem = generic; + this.frenchInput = langage; + this.french = isFrench(langage); + this.productUnit = produitUnit; + this.isDefCertifiee = "Def_certifiee".equals(typeImpression); + this.typeImpression = typeImpression; + } + + protected static boolean isFrench(final String language) { + return FRENCH_LANGUAGE.equals(language); + } + + @Override + public List getLaunchData() { + List theCriteria = new ArrayList<>(); + theCriteria.add(new MngCriteriaVal.CriteriaValue(ReportCriteriaEnum.PRODUCT, productUnit.getProductID())); + theCriteria.add(new MngCriteriaVal.CriteriaValue(ReportCriteriaEnum.UNIT, productUnit.getUnitStr())); + theCriteria.add(new MngCriteriaVal.CriteriaValue(ReportCriteriaEnum.TYPE_IMPRESSION, typeImpression)); + theCriteria.add(new MngCriteriaVal.CriteriaValue(ReportCriteriaEnum.LANGUAGE, frenchInput)); + return theCriteria; + } + + @Override + public List getQuickChecks() { + ArrayList quickChecks = new ArrayList<>(); + quickChecks.add(new ProductChecker(productUnit.getProductID())); + if (!productUnit.getUnitStr().isEmpty()) { + quickChecks.add(new ProductUnitChecker(productUnit)); + } + return quickChecks; + } + + @Override + public String getTemplateLocation() { + return JasperTemplate.TEMPLATE_R25.getFilepath(); + } + + @Override + public PolicyLocation getPropertyPolicyForLongChecks() { + return R25_POLICY_XML_LIGHT; + } + + @Override + public PolicyLocation getFullPolicy() { + return R25_POLICY_XML_FULL; + } + + @Override + public List getLongChecks() { + return new ArrayList<>(); + } + + @Override + public ReportEnum getReportIdentifier() { + return ReportEnum.REPORT_R25; + } + + /** + * Format file expected : R25_"Critère produit"_"Ligne produit"_"Critère Unit"_"générique traité"_"date_système".XLSX + */ + private String getSubReportFileName() { + return setFileName(true).toString(); + } + + /** + * Format file expected : R25_"Critère produit"_"Ligne produit"_"Critère Unit"_"date_système".zip + * + * @return zip filename + */ + @Override + public String getSpecifiedFileName() { + return setFileName(false).toString(); + } + + private StringBuilder setFileName(Boolean addItemId) { + StringBuilder filename = new StringBuilder("R25").append(FILE_SEPARATOR); + filename.append(productUnit.getProductID()).append(FILE_SEPARATOR); + filename.append(productLine.replaceAll(StringHelper.REGEXP_ALPHANUM, " ")).append(FILE_SEPARATOR); + if (!productUnit.getUnitStr().isEmpty()) { + filename.append(productUnit.getUnitStr()).append(FILE_SEPARATOR); + } + if (addItemId) { + filename.append(genericItem.get_item_id()).append(FILE_SEPARATOR); + } + filename.append(TeamcenterDateFormatter.formatCalendarToPattern(Calendar.getInstance(), PATTERN_DATE)); + + return filename; + } + + @Override + public Printer getPrinter() { + return new Printer(Printer.AvailablePrinter.ZIP); + } + + @Override + public Printer.PrintFormat getPrintingFormat() { + return Printer.PrintFormat.XLSX; + } + + @Override + public IDataReportPreparator getDataPreparator() { + return new DataReportPreparatorR25(); + } + + @Override + public AbstractExecutionReport cloneTemplateToExecution() { + return new ExecutionR25(productUnit, typeImpression, frenchInput); + } + + @Override + public Class getReportBuilderClass() { + return R25Builder.class; + } + + public PrintParameters reportParameters() { + return new PrintParameters(Printer.PrintFormat.ZIP, getFileNameOnDisc(), ReportFolderOutputHelper.getStorageFolderLocation(getLaunchType())); + } + + public PrintParameters reportSubZipParameters() { + return new PrintParameters(Printer.PrintFormat.ZIP, getSpecifiedFileName(), ReportFolderOutputHelper.getStorageFolderLocation(getLaunchType())); + } + + public PrintParameters subReportParameters() throws ReportPrintException, FileLoadingException { + String storageFolder = ReportFolderOutputHelper.getStorageFolderLocation(getLaunchType()); + String templateLocation = getTemplateLocation(); + try (InputStream templateStream = ResourceHelper.getResourceAsStream(templateLocation)) { + PrintParameters printParameters = PrintParameters.createMainReport(getPrintingFormat(), getSubReportFileName(), storageFolder, templateStream); + printParameters.setReportTitle(getReportIdentifier().getReportTitle()); + return printParameters; + } catch (IOException e) { + LOGGER.error("Unable to close the template file properly from " + templateLocation, e); + return null; // IOException is only thrown by close() which, if it ever fails, means you have much bigger problems! + } + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r25report/R25BOMLineExplorer.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r25report/R25BOMLineExplorer.java new file mode 100644 index 0000000..20d5ef5 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r25report/R25BOMLineExplorer.java @@ -0,0 +1,33 @@ +package com.capgemini.reports.definition.r25report; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.EmptyNomenclatureException; +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.capgemini.framework.teamcenter.resolution.filtering.ITcTypeFilter; +import com.capgemini.framework.teamcenter.resolution.filtering.TcTypeInclusionFilter; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.bomlineholder.BOMLineHolderHelper; +import com.capgemini.reports.exceptions.InvalidInputException; +import com.capgemini.reports.exceptions.MalformedNomenclatureException; +import com.capgemini.reports.teamcenter.resolution.IBOMLineExplorer; +import com.capgemini.reports.teamcenter.resolution.structureservice.SingleStructureServiceCaller; + +/** + * Explorer of {@link BOMLineHolder}s used in {@link SingleStructureServiceCaller} for R24 report.
    + * Thanks to this class, the SINGLE resolution structure could carry on and the Part Number could be taken.
    + * The Rf Generic is returned, and its children Part Aero / RF Admin and Descriptif are loaded + */ +public class R25BOMLineExplorer implements IBOMLineExplorer { + + private static final ITcTypeFilter FILTER_PART_ADMIN_DESCRIPTION = new TcTypeInclusionFilter(SnecmaObjectTypes.PART_AERO_REVISION, SnecmaObjectTypes.RF_ADMIN_REVISION, SnecmaObjectTypes.DESCRIPTIF_REVISION); + private static final ITcTypeFilter FILTER_RF_GENERIC_REVISION = new TcTypeInclusionFilter(SnecmaObjectTypes.RF_GENERIC_REVISION); + + @Override + public BOMLineHolder explore(TcSession session, final SingleStructureServiceCaller.SingleLevelExpander expander, final BOMLineHolder genericBom) throws EmptyNomenclatureException, + InvalidInputException, MalformedNomenclatureException { + BOMLineHolder expandedGenericBom = expander.expand(genericBom, FILTER_RF_GENERIC_REVISION); + BOMLineHolder rfGeneric = BOMLineHolderHelper.findRfGenericBL(expandedGenericBom); + return expander.expand(rfGeneric, FILTER_PART_ADMIN_DESCRIPTION); + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r25report/R25Printer.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r25report/R25Printer.java new file mode 100644 index 0000000..423b748 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r25report/R25Printer.java @@ -0,0 +1,230 @@ +package com.capgemini.reports.definition.r25report; + +import com.capgemini.framework.common.LanguageHelper; +import com.capgemini.framework.common.StringHelper; +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.object.pom.status.StatusEnum; +import com.capgemini.reports.definition.r15r16r17reports.AbstractExecutionR15R16R17; +import com.capgemini.reports.definition.r15r16r17reports.CommunR15R16R17ComponentVisitor; +import com.capgemini.reports.definition.r15r16r17reports.R15R16R17R24R25Keys; +import com.capgemini.reports.definition.r15r16r17reports.R15R16R17R24R25Keys.Page2; +import com.capgemini.reports.documentationobjects.DocNorm; +import com.capgemini.reports.documentationobjects.DocNormStandard; +import com.capgemini.reports.documentationobjects.DocTechnic; +import com.capgemini.reports.execution.mapconstructor.AbstractStaticTemplateMapConstructor; +import com.capgemini.reports.execution.mapconstructor.IMapConstructor; +import com.capgemini.reports.printing.PrintParameters; +import com.capgemini.reports.snecmaobjects.part.PartAeroRevision; +import com.capgemini.reports.snecmaobjects.visitor.IComponentVisitor; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.EnumMap; +import java.util.List; +import java.util.Map; + +/** + * This class is able to put the data gathered by an {@link ExecutionR25} into some {@link PrintParameters} for printing. + */ +@Slf4j +public class R25Printer extends AbstractStaticTemplateMapConstructor implements IMapConstructor { + private static final long serialVersionUID = -789205459094400840L; + + private static final String N_A = "N/A"; + + private static final String EMPTY_STRING = StringHelper.EMPTY; + private static final String UNKNOWN_STR = "???"; + private static final String SANS_OBJET = "Sans objet"; + private static final String NOT_APPLICABLE = "Not applicable "; + + private static String french(final String string) { + return LanguageHelper.french(string); + } + + private static String english(final String string) { + return LanguageHelper.english(string); + } + + /** + * Puts the data gathered by an {@link AbstractExecutionR15R16R17} into some {@link PrintParameters} for printing. + * + * @param execution the data-bearing {@link AbstractExecutionR15R16R17} + * @param mainReport the {@link PrintParameters} + */ + private void print(final ExecutionR25 execution, final PrintParameters mainReport) { + // first put generic data + DataReportPreparatorR25 preparator = (DataReportPreparatorR25) execution.getDataPreparator(); + mainReport.addReportParameters(setupStringParameters(execution)); + mainReport.addReportParameter(R15R16R17R24R25Keys.EMPTY_TABLE.toString(), preparator.isEmptyTable(execution)); + mainReport.addReportParameters(addDescriptifParameters(execution)); + mainReport.addReportDataFromEnum(setupData(execution)); + + // Now add the specific stuff + addOptionalParameters(execution, mainReport); + } + + private Map addDescriptifParameters(final ExecutionR25 execution) { + Map params = new EnumMap<>(Page2.class); + if (execution.descriptifRev != null) { + params.put(Page2.REF_DESCRIPTIF, execution.descriptifRev.getItemId()); + params.put(Page2.REV_DESCRIPTIF, execution.descriptifRev.getRevisionId()); + if (execution.descriptifRev.hasStatus(StatusEnum.J3B)) { + params.put(Page2.STATUS, StatusEnum.J3B.getIdentifier()); + } + else { + params.put(Page2.STATUS, StatusEnum.EFFECTIVITY.getIdentifier()); + } + if (execution.descriptifRev.hasStatus(StatusEnum.CREATED)) { + params.put(Page2.MATURITY_STATUS, StatusEnum.CREATED.getIdentifier()); + } + else if (execution.descriptifRev.hasStatus(StatusEnum.DEF_READY)) { + params.put(Page2.MATURITY_STATUS, StatusEnum.DEF_READY.getIdentifier()); + } + else if (execution.descriptifRev.hasStatus(StatusEnum.DEF_APPROVED)) { + params.put(Page2.MATURITY_STATUS, StatusEnum.DEF_APPROVED.getIdentifier()); + } + else { + params.put(Page2.MATURITY_STATUS, EMPTY_STRING); + } + } + else { + params.put(Page2.REF_DESCRIPTIF, EMPTY_STRING); + params.put(Page2.REV_DESCRIPTIF, EMPTY_STRING); + params.put(Page2.STATUS, EMPTY_STRING); + params.put(Page2.MATURITY_STATUS, EMPTY_STRING); + } + return params; + } + + private Map setupStringParameters(final ExecutionR25 execution) { + Map params = new EnumMap<>(R15R16R17R24R25Keys.class); + params.put(R15R16R17R24R25Keys.CLAUSE_PROPRIETE, execution.getClausePropriete()); + params.put(R15R16R17R24R25Keys.PRODUCT_TYPE, execution.getTypeProduit()); + params.put(R15R16R17R24R25Keys.REPORT_TITLE, getTitle()); + params.put(R15R16R17R24R25Keys.ITEM_REVISION_ID, execution.getRevisionArticle()); + String dateReleased = execution.getDateReleased(); + params.put(R15R16R17R24R25Keys.RELEASE_DATE, execution.isFrench() ? french(dateReleased) : english(dateReleased)); + return params; + } + + private List> setupData(final ExecutionR25 execution) { + List> dataTable = new ArrayList<>(); + boolean isFrench = execution.isFrench(); + for (DocNorm norm : execution.getDocNormList()) { + dataTable.add(getDocNormLine(norm, isFrench)); + + } + for (DocNormStandard normStd : execution.getDocNormStandardList()) { + dataTable.add(getDocNormStandardLine(normStd, isFrench)); + } + for (DocTechnic technic : execution.getDocTechnicList()) { + dataTable.add(getDocTechnicLine(technic, isFrench)); + } + + // If there are no documents, add an empty line to provoke band printing + if (dataTable.isEmpty()) { + Map line = new EnumMap<>(Page2.class); + line.put(Page2.DOC_NUMBER, "(No document found)"); + line.put(Page2.ISSUE, N_A); + line.put(Page2.DOC_TYPE, N_A); + line.put(Page2.DOC_TITLE, N_A); + dataTable.add(line); + } + return dataTable; + } + + private Map getDocNormLine(final DocNorm docNorm, final boolean isFrench) { + String idOrigine = docNorm.getIdOrigine(); + Map line = new EnumMap<>(Page2.class); + line.put(Page2.DOC_NUMBER, (idOrigine == null || idOrigine.isEmpty()) ? docNorm.getDocId() : idOrigine); + line.put(Page2.ISSUE, "-"); + String typeDocNorm = docNorm.getTypeDocNorm(); + line.put(Page2.DOC_TYPE, isFrench ? french(typeDocNorm) : english(typeDocNorm)); + line.put(Page2.DOC_TITLE, isFrench ? docNorm.getItemName() : docNorm.getDesignationEn()); + return line; + } + + private Map getDocNormStandardLine(final DocNormStandard normStd, final boolean isFrench) { + Map line = new EnumMap<>(Page2.class); + String idOrigine = normStd.getIdOrigine(); + line.put(Page2.DOC_NUMBER, (idOrigine == null || idOrigine.isEmpty()) ? normStd.getDocId() : idOrigine); + line.put(Page2.ISSUE, "-"); + line.put(Page2.DOC_TYPE, isFrench ? "Norme pour articles standards" : "Norm for standards items"); + line.put(Page2.DOC_TITLE, isFrench ? normStd.getItemName() : normStd.getDesignationEn()); + return line; + } + + private Map getDocTechnicLine(final DocTechnic technic, final boolean isFrench) { + Map line = new EnumMap<>(Page2.class); + String idOrigine = technic.getIdOrigine(); + line.put(Page2.DOC_NUMBER, (idOrigine == null || idOrigine.isEmpty()) ? technic.getDocId() : idOrigine); + line.put(Page2.ISSUE, technic.getIndice()); + + String typeDocTechnic1 = technic.getTypeDocTechnic1(); + String type1 = isFrench ? french(typeDocTechnic1) : english(typeDocTechnic1); + String typeDocTechnic2 = technic.getTypeDocTechnic2(); + String type2 = isFrench ? french(typeDocTechnic2) : english(typeDocTechnic2); + line.put(Page2.DOC_TYPE, type1 + " / " + type2); + + line.put(Page2.DOC_TITLE, isFrench ? technic.getName() : technic.getDesignationEn()); + return line; + } + + private void addOptionalParameters(final ExecutionR25 execution, final PrintParameters mainReport) { + Map params = new EnumMap<>(R15R16R17R24R25Keys.class); + List partNumberRevList = execution.getPartNumberRevList(); + if (partNumberRevList != null && !partNumberRevList.isEmpty()) { + Map map = new EnumMap<>(R15R16R17R24R25Keys.class); + if (partNumberRevList.size() == 1) { + map = partNumberRevList.get(0).accept(getVisitor(execution.isFrench())); + map.remove(R15R16R17R24R25Keys.PART_VERSION); + } + else { + map.put(R15R16R17R24R25Keys.ITEM_ID, UNKNOWN_STR); + map.put(R15R16R17R24R25Keys.PART_NUMBER, UNKNOWN_STR); + map.put(R15R16R17R24R25Keys.MANUFACTURER_CODE, UNKNOWN_STR); + map.put(R15R16R17R24R25Keys.FRENCH_DESIGNATION, UNKNOWN_STR); + map.put(R15R16R17R24R25Keys.ENGLISH_DESIGNATION, UNKNOWN_STR); + map.put(R15R16R17R24R25Keys.OBTURATION, execution.isFrench() ? SANS_OBJET : NOT_APPLICABLE); + map.put(R15R16R17R24R25Keys.CLASSIFICATION, "-"); + map.put(R15R16R17R24R25Keys.FIELD_OPN_SERIALISATION, UNKNOWN_STR); + map.put(R15R16R17R24R25Keys.LOG_DOCUMENT, execution.isFrench() ? SANS_OBJET : NOT_APPLICABLE); + } + map.put(R15R16R17R24R25Keys.PART_VERSION, EMPTY_STRING); + params.putAll(map); + } + else { + params.putAll(execution.getGenericRev().accept(getVisitor(execution.isFrench()))); + } + params.put(R15R16R17R24R25Keys.MT_NUMBER, EMPTY_STRING); + params.put(R15R16R17R24R25Keys.PREVIOUS_RELEASE_DATE, EMPTY_STRING); + params.put(R15R16R17R24R25Keys.ITEM_ID, execution.getGenericItem().get_item_id()); + mainReport.addReportParameters(params); + + Map map = new EnumMap<>(R15R16R17R24R25Keys.SpecificR15R16.class); + boolean isFrench = execution.isFrench(); + String frontiereAvion = execution.getFrontiereAvion(); + map.put(R15R16R17R24R25Keys.SpecificR15R16.INSTALLATION_INTERFACE, isFrench ? french(frontiereAvion) : english(frontiereAvion)); + String frontiereCooperant = execution.getFrontiereCooperant(); + map.put(R15R16R17R24R25Keys.SpecificR15R16.PARTNER_INTERFACE, isFrench ? french(frontiereCooperant) : english(frontiereCooperant)); + map.put(R15R16R17R24R25Keys.SpecificR15R16.PRODUCT_UNIT, execution.getProductUnit().toString()); + mainReport.addReportParameters(map); + mainReport.addReportParameter(R15R16R17R24R25Keys.SpecificR15R16.IS_PREVIOUS_DEF.toString(), false); + } + + private String getTitle() { + return StringHelper.EMPTY; + } + + private IComponentVisitor> getVisitor(final boolean isFrench) { + return new CommunR15R16R17ComponentVisitor(isFrench); + } + + @Override + public void constructDataMaps(TcSession session, final PrintParameters printParameters, final ExecutionR25 data) throws KurtException { + long start = System.currentTimeMillis(); + this.print(data, printParameters); + log.trace("Execution time : {} ms for {}", System.currentTimeMillis() - start, "data filtering"); + } +} \ No newline at end of file diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r26report/DataReportPreparatorR26.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r26report/DataReportPreparatorR26.java new file mode 100644 index 0000000..24d0868 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r26report/DataReportPreparatorR26.java @@ -0,0 +1,232 @@ +package com.capgemini.reports.definition.r26report; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.object.SnecmaObjectProperties; +import com.capgemini.framework.teamcenter.object.pom.status.TcEffectivity; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcBomObject; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcBomObjectFactory; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcRevisionRule; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcRevisionRuleProperties; +import com.capgemini.framework.teamcenter.object.runtime.TcBomWindow; +import com.capgemini.framework.teamcenter.object.runtime.TcBomWindowConfiguration; +import com.capgemini.framework.teamcenter.object.runtime.TcRevisionRulesConfiguration; +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.capgemini.framework.teamcenter.queries.saved.modelobject.ItemQuery; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.definition.r26report.ExecutionR26.ReportDataR26; +import com.capgemini.reports.exceptions.InvalidUserInputException; +import com.capgemini.reports.exceptions.UserInputErrorEnum; +import com.capgemini.reports.execution.IDataReportPreparator; +import com.capgemini.reports.execution.strategies.IExecutionStrategy; +import com.capgemini.reports.filter.AllIsGoodFilter; +import com.capgemini.reports.printing.PrintParameters; +import com.capgemini.reports.reports.parameters.EffectivityDate; +import com.capgemini.reports.snecmaobjects.product.ProductRevision; +import com.capgemini.reports.teamcenter.queries.TypeQuery; +import com.capgemini.reports.teamcenter.resolution.structureservice.SingleStructureServiceCaller; +import com.teamcenter.soa.client.model.strong.Item; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import com.teamcenter.soa.client.model.strong.RevisionRule; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * This class will allow to prepare data and findAll back data for making report R26. + */ +public class DataReportPreparatorR26 implements IDataReportPreparator { + + private static final long serialVersionUID = -8429205549743626211L; + + private static final Logger LOGGER = LoggerFactory.getLogger(DataReportPreparatorR26.class); + + @Override + public String print(TcSession session, ExecutionR26 execution, IExecutionStrategy executionStrategy) throws KurtException { + PrintParameters printParameters = prepareData(session, execution); + executionStrategy.print(printParameters, execution); + return executionStrategy.getReportFileName(execution) + printParameters.getOuputFileExtension(); + } + + private PrintParameters prepareData(final TcSession session, final ExecutionR26 report) throws KurtException { + LOGGER.debug("PrepareData started on: {}", report.getReportIdentifier().getReportTitle()); + + String componentId = report.getComponent(); + + List items = new ItemQuery(session).searchID(componentId).findAll(); + if(items.isEmpty()){ + throw new InvalidUserInputException(UserInputErrorEnum.OBJECT_DOES_NOT_EXIST); + } + + Item item = null; + + // Depuis qu'il est possible d'avoir le meme item id sur une part et un document il faut parcourir la liste pour + // ne récuperer que l'objet part. + for(Item currentItem : items) { + if(SnecmaObjectTypes.isPart(currentItem.getTypeObject().getName())) { + item = currentItem; + break; + } + } + + if(item == null) { + throw new InvalidUserInputException(UserInputErrorEnum.THE_SELECTED_OBJECT_IS_NOT_PERMITTED_ON_THIS_REPORT); + } + + session.loadProperties(item, SnecmaObjectProperties.OBJECT_TYPE); + + List list = TypeQuery.getRevisionRule(session, report.getRevisionRule()); + RevisionRule reportRevisionRule = list.get(0); + + String revisionRuleNameForThisR26 = "R26_" + componentId + "_" + report.getReportTechnicalUid(); + try { + RevisionRuleManager revisionRuleManager = new RevisionRuleManager(session, reportRevisionRule, revisionRuleNameForThisR26); + LineManager lineManager = new LineManager(session, report, revisionRuleManager); + + session.setObjectPropPolicy(report.getFullPolicy()); + + EffectivityDate effectivityDate = report.getEffectivityDate(); + TcRevisionRuleProperties revisionRuleProperties = new TcRevisionRuleProperties(effectivityDate.isNow() ? null : effectivityDate.getDateTime()); + TcRevisionRule revisionRule = session.findRevRule(report.getRevisionRule()); + TcRevisionRulesConfiguration revRulesConfiguration = new TcRevisionRulesConfiguration(revisionRule, revisionRuleProperties); + List firstLevelParents = session.whereUsed(resolveGoodRevision(session, report, item, revRulesConfiguration), 1, reportRevisionRule); + + for (ItemRevision firstLevelParentRev : firstLevelParents) { + session.loadProperties(firstLevelParentRev, "object_name","item_revision_id","item_revision"); + LOGGER.info("=== Treating object at level 1: {}/{} ===",firstLevelParentRev.get_item_id(),firstLevelParentRev.get_item_revision_id()); + List secondLevelParents = session.whereUsed(firstLevelParentRev, 1, reportRevisionRule); + if (secondLevelParents.isEmpty()) { + LOGGER.debug("Second Level empty"); + if (SnecmaObjectTypes.isPartRevision(firstLevelParentRev.getTypeObject().getName())) { + // si il n'y a pas de second level alors pas d'effectivité, ni produit, ni module + // cf: SFD:5.8.3 Remontée de nomenclature + if (lineManager.bomLineExists(firstLevelParentRev, componentId)) { + // cas où plusieurs révisions disponibles: une seule est valide avec la règle de révision du R26 + lineManager.addLines(firstLevelParentRev, null, null, null, "", + false, false); + } + } + else { + // Le composant n'est pas lié à un RF à Date valide (donc lié à un RF à Date obsolète) -> la ligne de nomenclature n'est pas traitée + // Ou il est lié à un RF en PU -> la ligne de nomenclature est traitée + + Map tcEffectivities = EffectivityHelper.getEffectivitiesWithUnitRange(session, + firstLevelParentRev); + + // récupérer les effectivitées + for (Map.Entry currentTcEff : tcEffectivities.entrySet()) { + + int[] units = currentTcEff.getKey().unitNumbers(); + Item product = currentTcEff.getKey().endItem(); + String productItemId = product.get_item_id(); + + session.loadProperties(product, "revision_list", "item_revision"); + ProductRevision productRev = new ProductRevision(session, (ItemRevision) (product.get_revision_list()[0])); + + // remonter au Generic avec DMA Configuration Interface Product Unit + revisionRuleManager.setProductUnitRevisionRuleProperties(product.getUid(), units[0]); + secondLevelParents = session.whereUsed(firstLevelParentRev, 1, revisionRuleManager.getRevisionRule()); + + LOGGER.info("=== Launching DMA Configuration Interface Product Unit on part {}/{} with Product {}/{} Unit {} ",firstLevelParentRev.get_item_id(),firstLevelParentRev.get_item_revision(),product.get_item_id(),product.get_item_revision(),units[0]); + + LOGGER.info("We found {} parents", secondLevelParents.size()); + + Map> itemRangeMap = new HashMap<>(); + + for (ItemRevision currentParent : secondLevelParents) { + + LOGGER.info("checking parent {}/{}",currentParent.get_item_id(),currentParent.get_item_revision_id()); + + if (SnecmaObjectTypes.isGenericRevision(currentParent.getTypeObject().getName())) { + LOGGER.debug("Currently on generic {}/{} ",currentParent.get_item_id(),currentParent.get_item_revision_id()); + // récupère les effectivités valide + String effectivityRangeUnit = EffectivityHelper.calculateEffectivity(session, firstLevelParentRev, product, itemRangeMap); + + if (EffectivityHelper.isEffectivityMatches(session, currentTcEff.getKey(), currentParent)) { + // tester si le composant est non standard + if (!item.get_object_type().equals(SnecmaObjectTypes.STANDARD)) { + LOGGER.debug("Effectivity matches {} {} ", currentTcEff.getKey().endItem(), currentTcEff.getKey().unitNumbers()); + boolean productFound = lineManager.findProduct(revisionRuleManager.getRevisionRule(), productItemId, currentParent); + lineManager.addLines(currentParent, firstLevelParentRev, productRev, currentParent, + effectivityRangeUnit, productFound, true); + } else { + // The Component is a standard. We will not check that the product consume the component. + lineManager.addLines(currentParent, firstLevelParentRev, productRev, currentParent, + effectivityRangeUnit, false, true); + } + } else { + LOGGER.debug("Effectivity doesn't matches {} ", currentTcEff.getKey().unitNumbers()); + } + } else if(!SnecmaObjectTypes.isSuperModelRevision(currentParent.getTypeObject().getName())){ + // remonter au dernier Generic trouvé + Map generics = new HashMap<>(); + lineManager.addGenerics(generics, currentParent, currentTcEff.getKey(), productItemId, item); + + // récupère les effectivités valide + String effectivityRangeUnit = EffectivityHelper.calculateEffectivity(session, firstLevelParentRev, product, itemRangeMap); + + lineManager.manageGenerics(generics, firstLevelParentRev, currentParent, productRev, + effectivityRangeUnit, true); + } + } + } + } + } + else { + LOGGER.debug("Navigate second level"); + for (ItemRevision secondLevelParentRev : secondLevelParents) { + + List rfPUs = RfPUManager.getRfPURevisions(session, reportRevisionRule, secondLevelParentRev); + for (ItemRevision currentRfPU : rfPUs) { + lineManager.manageRfPU(firstLevelParentRev, secondLevelParentRev, currentRfPU, item); + } + + if (rfPUs.isEmpty() && SnecmaObjectTypes.isPartRevision(secondLevelParentRev.getTypeObject().getName()) + && lineManager.bomLineExists(secondLevelParentRev, firstLevelParentRev.get_item_id())) { + + if (SnecmaObjectTypes.isPartRevision(firstLevelParentRev.getTypeObject().getName())) { + // Pas de RF, le Récepteur est une Part + lineManager.addLines(firstLevelParentRev, null, null, null, + report.getEffectivityDate().formatAsInputCriteria(), false, false); + } + else { + // Le récepteur est une part et le RF est à date + lineManager.addLines(secondLevelParentRev, firstLevelParentRev, null, null, + report.getEffectivityDate().formatAsInputCriteria(), false, false); + } + } + } + } + } + + ReportDataR26 reportDataR26 = new ReportDataR26(lineManager.getR26BomLines()); + reportDataR26.setStandard(item.get_object_type().equals(SnecmaObjectTypes.STANDARD)); + LOGGER.debug("The component is a standard = {}", reportDataR26.isStandard()); + R26Printer printer = new R26Printer(); + PrintParameters printParameters = printer.makeMasterTemplate(report, reportDataR26); + printer.constructDataMaps(session, printParameters, reportDataR26); + LOGGER.debug("PrepareData ended on: {}", report.getReportIdentifier().getReportTitle()); + return printParameters; + } + finally { + // Suppression de la règle de révision créée pour ce Rapport R26 + List revisionRuleList = TypeQuery.getRevisionRule(session, revisionRuleNameForThisR26); + if (!revisionRuleList.isEmpty()) { + session.deleteObjects(revisionRuleList.get(0)); + } + } + } + + private ItemRevision resolveGoodRevision(TcSession session, ExecutionR26 report, Item item, TcRevisionRulesConfiguration revRulesConfiguration) throws KurtException { + TcBomObject topLineObject = new TcBomObjectFactory(session, item).create(); + TcBomWindowConfiguration tcBomWindowConfiguration = new TcBomWindowConfiguration(topLineObject, revRulesConfiguration); + try (TcBomWindow bomWindow = session.createBomWindow(tcBomWindowConfiguration)) { + session.setObjectPropPolicy(report.getFullPolicy()); + BOMLineHolder unbuiltTopLine = new SingleStructureServiceCaller(session).resolve(bomWindow.topLine(), new AllIsGoodFilter()); + return unbuiltTopLine.getItemRevision(); + } + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r26report/EffectivityHelper.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r26report/EffectivityHelper.java new file mode 100644 index 0000000..63f88e7 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r26report/EffectivityHelper.java @@ -0,0 +1,205 @@ +package com.capgemini.reports.definition.r26report; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.object.pom.status.TcEffectivity; +import com.teamcenter.soa.client.model.ModelObject; +import com.teamcenter.soa.client.model.strong.Effectivity; +import com.teamcenter.soa.client.model.strong.Item; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import com.teamcenter.soa.client.model.strong.ReleaseStatus; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Helper for Effectivity for making report R26. + */ +class EffectivityHelper { + private static final int BORNE_SUP = 2147483646; + + private static final Logger LOGGER = LoggerFactory.getLogger(EffectivityHelper.class); + + /** + * Retourne true si l'effectivité "tcEffectivity" est comprise dans une des effectivités de l'item revision. + */ + static boolean isEffectivityMatches(TcSession session, TcEffectivity tcEffectivity, ItemRevision itemRevision) { + boolean effectivityMatches = false; + + Map tcEffectivities = getEffectivitiesWithUnitRange(session, itemRevision); + for (Map.Entry currentEff : tcEffectivities.entrySet()) { + int[] currentEffUnits = currentEff.getKey().unitNumbers(); + + LOGGER.debug(" Checking effectivity {} of {}",currentEffUnits ,itemRevision.get_item_id()); + + if (tcEffectivity.endItem().equals(currentEff.getKey().endItem())) { + int[] tcEffUnits = tcEffectivity.unitNumbers(); + if ((currentEffUnits.length == 1 && currentEffUnits[0] <= tcEffUnits[0]) + || + (currentEffUnits.length == 2 + && currentEffUnits[0] <= tcEffUnits[0] + && tcEffUnits[0] <= currentEffUnits[1])) { + effectivityMatches = true; + break; + } + } + } + + return effectivityMatches; + } + + /** + * Retourne la liste des effectivités trouvées sur les statuts avec les units concernés. + */ + static Map getEffectivitiesWithUnitRange(TcSession session, ItemRevision itemRevision) { + Map tcEffectivities = new HashMap<>(); + + // récuperer les effectivitées + Map statuses = getReleaseStatuses(session, itemRevision); + for (Map.Entry currentStatus : statuses.entrySet()) { + for (ModelObject currentEff : currentStatus.getKey().get_effectivities()) { + // pour chacune récupérer l'object tcEffectivity + TcEffectivity tcEffectivity = new TcEffectivity(session, (Effectivity) currentEff); + if (!tcEffectivity.unitRange().isEmpty()) { + tcEffectivities.put(tcEffectivity, currentStatus.getValue()); + } + } + } + return tcEffectivities; + } + + /** + * Retourne les status Effectivity de toutes les révisions de l'objet parent de la révision passée en paramètre. + * + * @param session, la session courante + * @param itemRevision, l'item révision courant + */ + private static Map getReleaseStatuses(TcSession session, ItemRevision itemRevision) { + Map statuses = new HashMap<>(); + + getReleaseStatus(session, itemRevision, statuses); + + return statuses; + } + + private static void getReleaseStatus(TcSession session, ItemRevision itemRevision, Map statuses) { + + session.loadProperties(itemRevision, "release_status_list"); + for (ReleaseStatus status : itemRevision.get_release_status_list()) { + + session.loadProperties(status, "name"); + if (status.get_name().equals("Effectivity")) { + statuses.put(status, itemRevision); + } + } + } + + /** + * Retourne true si au moins une des effectivités est en Produit-Unit, false sinon. + * + * @param session, session courante + * @param statuses, status + */ + static boolean isEffectivityWithUnitRange(TcSession session, ReleaseStatus[] statuses) { + // récuperer les effectivitées + for (ReleaseStatus currentStatus : statuses) { + for (ModelObject currentEff : currentStatus.get_effectivities()) { + // pour chacune récupérer le produit et la page de unit + Effectivity effectivity = (Effectivity) currentEff; + session.loadProperties(effectivity, "unit_range_text"); + String unitRange = effectivity.get_unit_range_text(); + + if (!unitRange.isEmpty()) { + return true; + } + } + } + return false; + } + + /** + * Retourne les effectivités des statuts Effectivity. + * + * @param statuses, status + */ + static ModelObject[] getEffectivities(ReleaseStatus[] statuses) { + for (ReleaseStatus releaseStatus : statuses) { + if (releaseStatus.get_name().equals("Effectivity")) { + return releaseStatus.get_effectivities(); + } + } + return new ModelObject[0]; + } + + private static List getEffectivitiesOfAllItemRev(TcSession session, ItemRevision itemRevision, Item product) { + List rangeList = new ArrayList<>(); + + // récuperer les effectivitées + for (ModelObject currentModelObject : itemRevision.get_revision_list()) { + ItemRevision currentItemRev = (ItemRevision) currentModelObject; + session.loadProperties(currentItemRev, "release_status_list"); + for (ReleaseStatus status : currentItemRev.get_release_status_list()) { + + for (ModelObject currentEff : status.get_effectivities()) { + // pour chacune récupérer l'object tcEffectivity + TcEffectivity tcEffectivity = new TcEffectivity(session, (Effectivity) currentEff); + + if (!tcEffectivity.unitRange().isEmpty() && tcEffectivity.endItem().equals(product)) { + int[] unitNumbers = tcEffectivity.unitNumbers(); + int end = (unitNumbers.length == 2) ? unitNumbers[1] : BORNE_SUP; + rangeList.add(new Range(currentItemRev, unitNumbers[0], end)); + } + } + } + } + + List newRangeList = new ArrayList<>(); + boolean found = false; + for (Range range_1 : rangeList) { + for (Range range_2 : rangeList) { + if (range_1 != range_2 && range_1.borneInf() == range_2.borneInf() && range_1.borneSup() == range_2.borneSup()) { + if (!RfPUManager.isLastReleasedRfPURev(session, range_1.getItemRevion())) { + found = true; + break; + } + } + } + if (!found) { + newRangeList.add(range_1); + } + found = false; + } + + return newRangeList; + } + + static String calculateEffectivity(TcSession session, ItemRevision itemRevision, Item product, Map> itemRangeMap) { + + List rangeList = itemRangeMap.get(itemRevision.get_item_id()); + if(rangeList == null) { + rangeList = new ArrayList<>(); + LOGGER.debug("Effectivities ranges: "); + for (Range eff : getEffectivitiesOfAllItemRev(session, itemRevision, product)) { + rangeList.add(new Range(eff.getItemRevion().get_item_revision_id(), eff.borneInf(), eff.borneSup())); + LOGGER.debug("range {}/{} {} {}",eff.getItemRevion().get_item_id(),eff.getItemRevion().get_item_revision_id(), eff.borneInf(), eff.borneSup()); + } + + Collections.sort(rangeList, new Comparator() { + public int compare(Range r1, Range r2) { + return Integer.compare(r1.borneInf(), r2.borneInf()); + } + }); + + itemRangeMap.put(itemRevision.get_item_id(),rangeList); + } + + + + return new Ranges(rangeList).toString(itemRevision.get_item_revision_id()); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r26report/ExecutionR26.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r26report/ExecutionR26.java new file mode 100644 index 0000000..cb4c4d4 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r26report/ExecutionR26.java @@ -0,0 +1,167 @@ +package com.capgemini.reports.definition.r26report; + +import com.capgemini.framework.common.SettingsHelper; +import com.capgemini.framework.common.TeamcenterDateFormatter; +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.reports.JasperTemplate; +import com.capgemini.reports.ReportEnum; +import com.capgemini.reports.ReportLaunchTypeEnum; +import com.capgemini.reports.builder.R26Builder; +import com.capgemini.reports.builder.ReportBuilder; +import com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum; +import com.capgemini.reports.database.manager.MngCriteriaVal.CriteriaValue; +import com.capgemini.reports.definition.r26report.ExecutionR26.ReportDataR26; +import com.capgemini.reports.execution.AbstractExecutionReport; +import com.capgemini.reports.execution.IDataReportPreparator; +import com.capgemini.reports.printing.Printer.PrintFormat; +import com.capgemini.reports.reports.parameters.EffectivityDate; +import com.capgemini.reports.reports.parameters.IChecker; +import com.capgemini.reports.reports.parameters.checker.ObjectTypeChecker; +import lombok.Getter; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; + +/** + * Class responsible for executing a R26 report. + */ +@Getter +public class ExecutionR26 extends AbstractExecutionReport { + + private static final long serialVersionUID = -8662335546561586221L; + + // Policies parameters + private static final PolicyLocation R26_POLICY_XML_LIGHT = PolicyLocation.make("R26_policy_light", "/xml/policies/r26report/R26_policy_light.xml"); + private static final PolicyLocation R26_POLICY_XML_FULL = PolicyLocation.make("R26_policy_full", "/xml/policies/r26report/R26_policy_full.xml"); + + // Priority parameter + private static final int REPORT_PRIORITY = SettingsHelper.getPriority(ReportEnum.REPORT_R26); + + // Revision rule parameter + private static final String REPORT_REVISION_RULE = SettingsHelper.getPropertyWithDefaultValue("common.bom.revisionRule.REPORT_R26", DEFAULT_REVISION_RULE); + + // Launch type parameter + private static final ReportLaunchTypeEnum REPORT_LAUNCH_TYPE = ReportLaunchTypeEnum.getReportLaunchType("common.launch.launchType.REPORT_R26"); + + // Configuration + private static final String SEPARATOR = "-"; + private static final String PATTERN_DATE = "yyyy-MM-dd"; + + // Raw input parameters + private final String component; + private final EffectivityDate effectivityDate; + + /** + * Constructor. + * + * @param component {@link String} - the component + * @param effectivityDate {@link EffectivityDate} - the effectivity + */ + public ExecutionR26(final String component, final EffectivityDate effectivityDate) { + super(REPORT_PRIORITY, REPORT_REVISION_RULE, REPORT_LAUNCH_TYPE); + this.component = component; + this.effectivityDate = effectivityDate; + } + + @Override + public List getLaunchData() { + List theCriteria = new ArrayList<>(); + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.PART_ID, component)); + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.EFFECTIVITY_DATE, effectivityDate.formatAsInputCriteria())); + theCriteria.add(new CriteriaValue(ReportCriteriaEnum.REVISION_RULE, this.revisionRule)); + return theCriteria; + } + + @Override + public List getQuickChecks() { + ArrayList quickChecks = new ArrayList<>(); + quickChecks.add(new ObjectTypeChecker(component, SnecmaObjectTypes.ALTERNATE, SnecmaObjectTypes.DET, + SnecmaObjectTypes.PART_AERO, SnecmaObjectTypes.PART_ASSEMB, SnecmaObjectTypes.PART_MAT, + SnecmaObjectTypes.PART_NO_AERO, SnecmaObjectTypes.STANDARD)); + return quickChecks; + } + + @Override + public String getTemplateLocation() { + return JasperTemplate.TEMPLATE_R26_MASTER.getFilepath(); + } + + @Override + public PolicyLocation getPropertyPolicyForLongChecks() { + return R26_POLICY_XML_LIGHT; + } + + @Override + public PolicyLocation getFullPolicy() { + return R26_POLICY_XML_FULL; + } + + @Override + public List getLongChecks() { + return new ArrayList<>(); + } + + @Override + public ReportEnum getReportIdentifier() { + return ReportEnum.REPORT_R26; + } + + /** + * Format file expected : R26-"Composant"-"Date effectivté".XLSX + */ + @Override + public String getSpecifiedFileName() { + StringBuilder filename = new StringBuilder("R26-"); + filename.append(component).append(SEPARATOR); + filename.append(TeamcenterDateFormatter.formatCalendarToPattern(Calendar.getInstance(), PATTERN_DATE)); + return filename.toString(); + } + + @Override + public PrintFormat getPrintingFormat() { + return PrintFormat.XLSX; + } + + @Override + public IDataReportPreparator getDataPreparator() { + return new DataReportPreparatorR26(); + } + + @Override + public AbstractExecutionReport cloneTemplateToExecution() { + return new ExecutionR26(component, effectivityDate); + } + + @Override + public Class getReportBuilderClass() { + return R26Builder.class; + } + + + /** + * POJO container of all data required for this report. + */ + public static class ReportDataR26 { + private final List r26BomLines; + + private boolean isStandard = false; + + public boolean isStandard() { + return isStandard; + } + + public void setStandard(boolean standard) { + isStandard = standard; + } + + protected ReportDataR26(final List r26BomLines) { + this.r26BomLines = r26BomLines; + } + + public List getR26BomLines() { + return r26BomLines; + } + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r26report/LineManager.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r26report/LineManager.java new file mode 100644 index 0000000..8eb6e0b --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r26report/LineManager.java @@ -0,0 +1,272 @@ +package com.capgemini.reports.definition.r26report; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.EmptyNomenclatureException; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.object.pom.status.TcEffectivity; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcBomObject; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcBomObjectFactory; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcRevisionRule; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcRevisionRuleProperties; +import com.capgemini.framework.teamcenter.object.runtime.TcBomWindow; +import com.capgemini.framework.teamcenter.object.runtime.TcBomWindowConfiguration; +import com.capgemini.framework.teamcenter.object.runtime.TcRevisionRulesConfiguration; +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.bomlineholder.BOMLineHolderFactory; +import com.capgemini.reports.bomlineholder.processor.DefaultAltOrDetBehaviour; +import com.capgemini.reports.filter.AllIsGoodFilter; +import com.capgemini.reports.reports.parameters.EffectivityDate; +import com.capgemini.reports.snecmaobjects.product.ProductRevision; +import com.capgemini.reports.teamcenter.resolution.structureservice.SingleStructureServiceCaller; +import com.teamcenter.soa.client.model.ModelObject; +import com.teamcenter.soa.client.model.strong.BOMLine; +import com.teamcenter.soa.client.model.strong.Form; +import com.teamcenter.soa.client.model.strong.Item; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import com.teamcenter.soa.client.model.strong.RevisionRule; +import com.teamcenter.soa.client.model.strong.WorkspaceObject; +import lombok.Getter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Manager for making lines in report R26. + */ +@Getter +class LineManager { + + private static final AllIsGoodFilter ACCEPT_ALL = new AllIsGoodFilter(); + + private static final Logger LOGGER = LoggerFactory.getLogger(LineManager.class); + + private TcSession session; + private ExecutionR26 report; + private String componentId; + private RevisionRule revisionRuleR26; + private EffectivityDate effectivityDate; + private List r26BomLines; + private TcRevisionRulesConfiguration revRulesConfiguration; + private RevisionRuleManager revisionRuleManager; + + LineManager(TcSession session, ExecutionR26 report, RevisionRuleManager revisionRuleManager) throws KurtException { + this.session = session; + this.report = report; + this.componentId = report.getComponent(); + this.r26BomLines = new ArrayList<>(); + this.revisionRuleR26 = revisionRuleManager.getRevisionRule(); + this.effectivityDate = report.getEffectivityDate(); + this.revisionRuleManager = revisionRuleManager; + + TcRevisionRuleProperties revisionRuleProperties = new TcRevisionRuleProperties(effectivityDate.getDateTime()); + TcRevisionRule revisionRule = session.findRevRule(report.getRevisionRule()); + revRulesConfiguration = new TcRevisionRulesConfiguration(revisionRule, revisionRuleProperties); + } + + /** + * Ajoute les lignes de nomenclature au rapport R26. + */ + void addLines(ItemRevision receptor, ItemRevision rf, ProductRevision product, ItemRevision module, String effectivity, + Boolean consumedByProduct, Boolean effectivityUnit) throws KurtException { + BOMLineHolder unBuiltTopLine = getBomLineHolder(rf == null ? receptor : rf); + if (unBuiltTopLine != null) { + for (BOMLineHolder currentChild : unBuiltTopLine.getBomChilds()) { + ItemRevision itemRev = currentChild.getItemRevision(); + if (currentChild.getBomChilds().isEmpty() && componentId.equals(itemRev.get_item_id())) { + addLineToR26(currentChild.getBomLineObject(), receptor, rf, product, module, + effectivity, consumedByProduct, effectivityUnit); + } + } + } + } + + /** + * Retourne la bom line générée avec l'objet topWo ou null si elle n'existe pas. + */ + private BOMLineHolder getBomLineHolder(WorkspaceObject topWo) throws KurtException { + BOMLineHolder unBuiltTopLine; + TcBomObject topLineObject = new TcBomObjectFactory(session, topWo).create(); + + try (TcBomWindow bomWindow = session.createBomWindow(new TcBomWindowConfiguration(topLineObject, revRulesConfiguration))) { + // Perform the job + try { + unBuiltTopLine = new SingleStructureServiceCaller(session).resolve(bomWindow.topLine(), new R26BOMLineExplorer()); + + List itemRevMaster = unBuiltTopLine.getAllItemRevMasters(); + session.loadProperties(itemRevMaster.toArray(new ModelObject[0])); + + BOMLineHolderFactory.buildTopBom(session, unBuiltTopLine, ACCEPT_ALL); + DefaultAltOrDetBehaviour aBOMLineHolderProcessor = new DefaultAltOrDetBehaviour<>(session, + effectivityDate.isNow() ? null : effectivityDate.getDateTime()); + unBuiltTopLine.process(aBOMLineHolderProcessor); + unBuiltTopLine.freeze(); + } + catch (EmptyNomenclatureException e) { + unBuiltTopLine = null; + } + } + return unBuiltTopLine; + } + + /** + * Ajoute la ligne de nomenclature aux lignes du rapport R26 si elle n'existe pas déjà. + */ + private void addLineToR26(BOMLine line, ItemRevision receptor, ItemRevision rf, ProductRevision product, ItemRevision module, + String effectivity, Boolean consumedByProduct, Boolean effectivityUnit) { + if (line != null) { + R26BomLine r26BomLine = new R26BomLine(line.get_bl_quantity(), line.get_bl_item_uom_tag(), + receptor, rf, product, module, effectivity, consumedByProduct, effectivityUnit); + consolidateR26BomLines(r26BomLine); + if (!isLineAlreadyAdded(r26BomLine)) { + r26BomLines.add(r26BomLine); + } + } + } + + /** + * Retourne true si la ligne existe déjà dans le rapport (toutes les valeurs sont identiques). + * Sinon si seule l'effectivté est différente et en Produit/Unit alors la ligne existante sera supprimée + * et une nouvelle ligne avec les effectivités cumulées sera ajoutée. + */ + private boolean isLineAlreadyAdded(R26BomLine r26BomLine) { + for (R26BomLine currentLine : r26BomLines) { + if (r26BomLine.equals(currentLine)) { + return true; + } + } + return false; + } + + private void consolidateR26BomLines(R26BomLine r26BomLine) { + List r26BomLinesToDelete = new ArrayList<>(); + for (R26BomLine currentLine : r26BomLines) { + if (r26BomLine.equals(currentLine) && r26BomLine.getConsumedByProduct() && !currentLine.getConsumedByProduct()) { + r26BomLinesToDelete.add(currentLine); + } + if (r26BomLine.equals(currentLine) && r26BomLine.equalsExceptEffectivity(currentLine) && r26BomLine.isEffectivityUnit()) { + // cumulate effectivities + String eff1 = currentLine.getEffectivity(); + String eff2 = r26BomLine.getEffectivity(); + r26BomLine.setEffectivity(eff1 + ";" + eff2); + r26BomLinesToDelete.add(currentLine); + } + } + for (R26BomLine r26BomLineToDelete : r26BomLinesToDelete) { + r26BomLines.remove(r26BomLineToDelete); + } + } + + /** + * Traitement des Generic/Generic Assemb. + * Pour chacun: ajout de la ligne de nomenclatures trouvée au rapport R26. + * Si aucun Generic/Generic Assemb: la ligne est ajoutée sans Module et sera visible en rouge car non consommée par un produit. + */ + void manageGenerics(Map generics, ItemRevision firstLevelParentRev, ItemRevision secondLevelParentRev, + ProductRevision productRev, String effectivity, Boolean effectivityUnit) throws KurtException { + + for (Map.Entry currentGenerics : generics.entrySet()) { + LOGGER.info("=== Treating Generic: {} ===",currentGenerics.getKey().get_item_revision_id()); + if (SnecmaObjectTypes.isPartRevision(firstLevelParentRev.getTypeObject().getName())) { + addLines(firstLevelParentRev, null, productRev, currentGenerics.getKey(), "", currentGenerics.getValue(), effectivityUnit); + } + else { + addLines(secondLevelParentRev, firstLevelParentRev, productRev, currentGenerics.getKey(), effectivity, + currentGenerics.getValue(), effectivityUnit); + } + } + + // produit à noté en rouge, le composant de la ligne n'est pas consommé + if (generics.isEmpty() && !SnecmaObjectTypes.isPartRevision(firstLevelParentRev.getTypeObject().getName())) { + addLines(secondLevelParentRev, firstLevelParentRev, productRev, null, effectivity, false, effectivityUnit); + } + } + + /** + * Récupère tous les Generic/Generic Assemb lors de la remontée via where used + */ + void addGenerics(Map generics, ItemRevision itemRev, TcEffectivity tcEffectivity, String productItemId, Item item) { + List parents = session.whereUsed(itemRev, 1, revisionRuleR26); + for (ItemRevision currentParent : parents) { + if (SnecmaObjectTypes.isGenericRevision(currentParent.getTypeObject().getName())) { + if (EffectivityHelper.isEffectivityMatches(session, tcEffectivity, currentParent)) { + // tester si le composant est non standard + if (!item.get_object_type().equals(SnecmaObjectTypes.STANDARD)) { + boolean productFound = findProduct(revisionRuleR26, productItemId, currentParent); + generics.put(currentParent, productFound); + } else { + generics.put(currentParent, false); + } + } + } else { + addGenerics(generics, currentParent, tcEffectivity, productItemId, item); + } + } + } + + /** + * Manage le RF en Produit/Unit (currentRfPU): + * Pour chaque effectivité trouvée sur le statut Effectivity: + * La règle de révision du rapport est mise à jour avec le produit et les units du statut + * Tous les Generic/Generic Assemb trouvés sont ensuite gérés + */ + void manageRfPU(ItemRevision firstLevelParentRev, ItemRevision secondLevelParentRev, ItemRevision currentRfPU, Item item) throws KurtException { + Map tcEffectivities = EffectivityHelper.getEffectivitiesWithUnitRange(session, currentRfPU); + // récuperer les effectivitées + for (Map.Entry currentEff : tcEffectivities.entrySet()) { + int[] units = currentEff.getKey().unitNumbers(); + Item product = currentEff.getKey().endItem(); + + revisionRuleManager.setProductUnitRevisionRuleProperties(product.getUid(), units[0]); + + // récupérer tous les Generic/Generic Assemb trouvés via le where used. + Map generics = new HashMap<>(); + addGenerics(generics, currentRfPU, currentEff.getKey(), product.get_item_id(), item); + + session.loadProperties(product, "revision_list"); + ProductRevision productRev = new ProductRevision(session, (ItemRevision) (product.get_revision_list()[0])); + + manageGenerics(generics, firstLevelParentRev, secondLevelParentRev, productRev, + effectivityDate.formatAsInputCriteria(), false); + } + } + + /** + * Retourne true si la ligne de nomenclature entre parentRev et childRev existe, false sinon. + */ + boolean bomLineExists(ItemRevision parentRev, String childRevId) throws KurtException { + session.loadProperties(parentRev, "items_tag"); + BOMLineHolder unBuiltTopLine = getBomLineHolder(parentRev.get_items_tag()); + if (unBuiltTopLine != null && unBuiltTopLine.getItemRevision().get_item_revision_id().equals(parentRev.get_item_revision_id())) { + for (BOMLineHolder currentChild : unBuiltTopLine.getBomChilds()) { + ItemRevision itemRev = currentChild.getItemRevision(); + if (childRevId.equals(itemRev.get_item_id())) { + return true; + } + } + } + return false; + } + + /** + * Retourne true si l'itemRev est consommé par un produit, false sinon. + */ + boolean findProduct(RevisionRule revRule, String productItemId, ItemRevision itemRev) { + List parents = session.whereUsed(itemRev, 1, revRule); + boolean productFound = false; + // remonter au produit: si trouvé alors true, false sinon + for (ItemRevision currentParent : parents) { + if (SnecmaObjectTypes.isProductRevision(currentParent.getTypeObject().getName()) && productItemId.equals(currentParent.get_item_id())) { + return true; + } + else { + productFound = productFound || findProduct(revRule, productItemId, currentParent); + } + } + return productFound; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r26report/R26BOMLineExplorer.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r26report/R26BOMLineExplorer.java new file mode 100644 index 0000000..c0d987e --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r26report/R26BOMLineExplorer.java @@ -0,0 +1,29 @@ +package com.capgemini.reports.definition.r26report; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.EmptyNomenclatureException; +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.capgemini.framework.teamcenter.resolution.filtering.ITcTypeFilter; +import com.capgemini.framework.teamcenter.resolution.filtering.TcTypeInclusionFilter; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.teamcenter.resolution.IBOMLineExplorer; +import com.capgemini.reports.teamcenter.resolution.structureservice.SingleStructureServiceCaller; + +/** + * Explorer of {@link BOMLineHolder}s used in {@link SingleStructureServiceCaller} for R26report.
    + * Thanks to this class, the SINGLE resolution structure could carry on and the Part Number could be taken.
    + * The Rf Generic is returned, and its children Part Aero / RF Admin and Descriptif are loaded + */ +public class R26BOMLineExplorer implements IBOMLineExplorer { + + private static final ITcTypeFilter FILTER_DESCRIPTION = new TcTypeInclusionFilter(SnecmaObjectTypes.PART_AERO_REVISION, + SnecmaObjectTypes.PART_NO_AERO_REVISION, SnecmaObjectTypes.PART_ASSEMB_REVISION, SnecmaObjectTypes.PART_MAT_REVISION, + SnecmaObjectTypes.DET_REVISION, SnecmaObjectTypes.STANDARD_REVISION, SnecmaObjectTypes.ALTERNATE_REVISION, + SnecmaObjectTypes.RF_GENERIC_REVISION, SnecmaObjectTypes.RF_PART_ASSEMB_REVISION, SnecmaObjectTypes.RF_ADMIN_REVISION, + SnecmaObjectTypes.RF_PART_REVISION, SnecmaObjectTypes.RF_ADMIN_AG_REVISION, SnecmaObjectTypes.RF_ADMIN_AP_REVISION); + + public BOMLineHolder explore(TcSession session, final SingleStructureServiceCaller.SingleLevelExpander expander, + final BOMLineHolder genericBom) throws EmptyNomenclatureException { + return expander.expand(genericBom, FILTER_DESCRIPTION); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r26report/R26BomLine.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r26report/R26BomLine.java new file mode 100644 index 0000000..968c2dd --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r26report/R26BomLine.java @@ -0,0 +1,78 @@ +package com.capgemini.reports.definition.r26report; + +import com.capgemini.reports.snecmaobjects.product.ProductRevision; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import lombok.Getter; + +@Getter +public class R26BomLine { + private String quantity; + private String unitOfMeasure; + private ItemRevision receptor; + private ItemRevision rf; + private ProductRevision productRev; + private ItemRevision module; + private String effectivity; + private Boolean consumedByProduct; + private Boolean effectivityUnit; + + R26BomLine(final String quantity, final String unitOfMeasure, final ItemRevision receptor, final ItemRevision rf, + final ProductRevision productRev, final ItemRevision module, final String effectivity, + final Boolean consumedByProduct, Boolean effectivityUnit) { + this.quantity = quantity; + this.unitOfMeasure = unitOfMeasure; + this.receptor = receptor; + this.rf = rf; + this.productRev = productRev; + this.module = module; + this.effectivity = effectivity; + this.consumedByProduct = consumedByProduct; + this.effectivityUnit = effectivityUnit; + } + + public boolean equals(R26BomLine r26BomLine) { + return ( + this.quantity.equals(r26BomLine.getQuantity()) + && this.unitOfMeasure.equals(r26BomLine.getUnitOfMeasure()) + && this.receptor == r26BomLine.getReceptor() + && this.rf == r26BomLine.getRf() + && isProductEquals(r26BomLine.getProductRev()) + && (this.module == null && r26BomLine.getModule() == null + || (this.module != null && r26BomLine.getModule() != null + && this.module.get_item_id().equals(r26BomLine.getModule().get_item_id()))) + && this.effectivity.contentEquals(r26BomLine.getEffectivity())); + } + + private boolean isProductEquals(ProductRevision productRev) { + boolean productEquals = false; + if (this.productRev == null && productRev == null) { + productEquals = true; + } + else if (this.productRev == null || productRev == null) { + productEquals = false; + } + else if (this.productRev.getItemId().equals(productRev.getItemId())) { + productEquals = true; + } + return productEquals; + } + + boolean equalsExceptEffectivity(R26BomLine r26BomLine) { + return ( + this.quantity.equals(r26BomLine.getQuantity()) + && this.unitOfMeasure.equals(r26BomLine.getUnitOfMeasure()) + && this.receptor == r26BomLine.getReceptor() + && this.rf == r26BomLine.getRf() + && isProductEquals(r26BomLine.getProductRev()) + && this.module == r26BomLine.getModule() + && !this.effectivity.contentEquals(r26BomLine.getEffectivity())); + } + + public void setEffectivity(String effectivity) { + this.effectivity = effectivity; + } + + Boolean isEffectivityUnit() { + return effectivityUnit; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r26report/R26Keys.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r26report/R26Keys.java new file mode 100644 index 0000000..b90c81a --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r26report/R26Keys.java @@ -0,0 +1,28 @@ +package com.capgemini.reports.definition.r26report; + +/** + * Key attributes to the Jasper report content. + */ +public enum R26Keys { + SUBREPORT_P1, + SUBREPORT_P2, + MESSAGE_1, + MESSAGE_2, + MESSAGE_3, + MESSAGE_4, + RECEPTOR_ID, + RECEPTOR_REVISION, + RECEPTOR_NAME, + REPERE_ID, + REPERE_REVISION, + REPERE_NAME, + QUANTITY, + UNIT_OF_MEASURE, + PRODUCT, + PRODUCT_LINE, + EFFECTIVITY_UNIT, + MODULE_ID, + MODULE_NAME, + CONSUMED_BY_PRODUCT, + TYPE_STANDARD +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r26report/R26Printer.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r26report/R26Printer.java new file mode 100644 index 0000000..d3d9c1f --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r26report/R26Printer.java @@ -0,0 +1,165 @@ +package com.capgemini.reports.definition.r26report; + +import com.capgemini.framework.common.ResourceHelper; +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.capgemini.reports.JasperTemplate; +import com.capgemini.reports.definition.r26report.ExecutionR26.ReportDataR26; +import com.capgemini.reports.execution.mapconstructor.AbstractStaticTemplateMapConstructor; +import com.capgemini.reports.execution.mapconstructor.IMapConstructor; +import com.capgemini.reports.printing.PrintParameters; +import lombok.extern.slf4j.Slf4j; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.EnumMap; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Extracts the relevant data obtained from TC into the expected List of Maps for Jasper. + */ +@Slf4j +public class R26Printer extends AbstractStaticTemplateMapConstructor implements IMapConstructor { + + private static final long serialVersionUID = 4281716591716247163L; + + private static final String SUBREPORT_P1 = "SUBREPORT_P1"; + private static final String SUBREPORT_P2 = "SUBREPORT_P2"; + private static final String MESSAGE_PRODUIT_NON_CONSOMME = "Les produits notés en rouge ne consomment pas le composant de la ligne de nomenclature"; + private static final String MESSAGE_PRODUIT_COMPOSANT_STANDARD = "Pour le composant de type standard, il n'est pas vérifié que les produits en violet consomment le composant."; + private static final String MESSAGE_AUCUNE_DONNEE = "Aucune donnée n’a pu être extraite, aucune ligne de nomenclature trouvée pour le composant"; + private static final String MESSAGE_AUCUNE_DONNEE_ETUDE = "Aucune donnée Etude n’a pu être extraite, aucune ligne de nomenclature trouvée pour le composant"; + private static final String MESSAGE_AUCUNE_DONNEE_MONTAGE = "Aucune donnée Montage n’a pu être extraite, aucune ligne de nomenclature trouvée pour le composant"; + + /** + * Puts the data gathered by an {@link ExecutionR26} into some {@link PrintParameters} for printing. + * + * @param reportData the data-bearing {@link ReportDataR26} + * @param mainReport the {@link PrintParameters} + */ + private void print(final ReportDataR26 reportData, final PrintParameters mainReport) throws KurtException { + + boolean vueEtudeEmpty = setupPage1(reportData, mainReport); + boolean vueMontageEmpty = setupPage2(reportData, mainReport); + + Map map = new EnumMap<>(R26Keys.class); + if (vueEtudeEmpty && vueMontageEmpty) { + map.put(R26Keys.MESSAGE_1, MESSAGE_AUCUNE_DONNEE); + } + else { + map.put(R26Keys.MESSAGE_1, vueEtudeEmpty ? MESSAGE_AUCUNE_DONNEE_ETUDE : MESSAGE_PRODUIT_NON_CONSOMME); + map.put(R26Keys.MESSAGE_2, vueMontageEmpty ? MESSAGE_AUCUNE_DONNEE_MONTAGE : MESSAGE_PRODUIT_NON_CONSOMME); + map.put(R26Keys.MESSAGE_3, vueEtudeEmpty ? "" : MESSAGE_PRODUIT_COMPOSANT_STANDARD); + map.put(R26Keys.MESSAGE_4, vueMontageEmpty ? "" : MESSAGE_PRODUIT_COMPOSANT_STANDARD); + } + List> test = new ArrayList<>(); + test.add(map); + mainReport.addReportDataFromEnum(test); + + // Setup main report + mainReport.addReportData(setupEmptyData()); + } + + private static List> setupEmptyData() { + List> list = new ArrayList<>(); + list.add(new HashMap()); + return list; + } + + private static boolean setupPage1(final ReportDataR26 reportData, final PrintParameters mainReport) + throws KurtException { + boolean emptySubReport = true; + try (InputStream page1Stream = ResourceHelper.getResourceAsStream(JasperTemplate.TEMPLATE_R26_SUBREPORT.getFilepath())) { + List> vueEtudeList = setupPage1Data(reportData); + + if (!vueEtudeList.isEmpty()) { + emptySubReport = false; + } + + mainReport.addSubReport(SUBREPORT_P1, page1Stream, vueEtudeList, new EnumMap<>(R26Keys.class)); + } + catch (IOException e) { + log.error("Unable to close template of the R26 report", e); + } + return emptySubReport; + } + + private static boolean setupPage2(final ReportDataR26 reportData, final PrintParameters mainReport) + throws KurtException { + boolean emptySubReport = true; + try (InputStream page2Stream = ResourceHelper.getResourceAsStream(JasperTemplate.TEMPLATE_R26_SUBREPORT.getFilepath())) { + List> vueMontageList = setupPage2Data(reportData); + + if (!vueMontageList.isEmpty()) { + emptySubReport = false; + } + + mainReport.addSubReport(SUBREPORT_P2, page2Stream, vueMontageList, new EnumMap<>(R26Keys.class)); + } + catch (IOException e) { + log.error("Unable to close template of the R26 report", e); + } + return emptySubReport; + } + + private static List> setupPage1Data(ReportDataR26 reportData) { + List> vueEtudeList = new ArrayList<>(); + for (R26BomLine currentLine : reportData.getR26BomLines()) { + if (currentLine.getModule() == null || currentLine.getModule().getTypeObject().getName().equals(SnecmaObjectTypes.GENERIC_REVISION)) { + Map map = getR26KeysStringMap(currentLine, reportData.isStandard()); + vueEtudeList.add(map); + } + } + return vueEtudeList; + } + + private static List> setupPage2Data(ReportDataR26 reportData) { + List> vueMontageList = new ArrayList<>(); + for (R26BomLine currentLine : reportData.getR26BomLines()) { + if (currentLine.getModule() != null && currentLine.getModule().getTypeObject().getName().equals(SnecmaObjectTypes.GENERIC_ASSEMB_REVISION)) { + Map map = getR26KeysStringMap(currentLine, reportData.isStandard()); + vueMontageList.add(map); + } + } + return vueMontageList; + } + + private static Map getR26KeysStringMap(R26BomLine currentLine, boolean isStandard) { + Map map = new EnumMap<>(R26Keys.class); + + map.put(R26Keys.RECEPTOR_ID, currentLine.getReceptor() == null ? "" : currentLine.getReceptor().get_item_id()); + map.put(R26Keys.RECEPTOR_REVISION, currentLine.getReceptor() == null ? "" : currentLine.getReceptor().get_item_revision_id()); + map.put(R26Keys.RECEPTOR_NAME, currentLine.getReceptor() == null ? "" : currentLine.getReceptor().get_object_name()); + + map.put(R26Keys.REPERE_ID, currentLine.getRf() == null ? "" : currentLine.getRf().get_item_id()); + map.put(R26Keys.REPERE_REVISION, currentLine.getRf() == null ? "" : currentLine.getRf().get_item_revision_id()); + map.put(R26Keys.REPERE_NAME, currentLine.getRf() == null ? "" : currentLine.getRf().get_object_name()); + + map.put(R26Keys.QUANTITY, currentLine.getQuantity()); + map.put(R26Keys.UNIT_OF_MEASURE, currentLine.getUnitOfMeasure()); + + map.put(R26Keys.PRODUCT, currentLine.getProductRev() == null ? "" : currentLine.getProductRev().getItemId()); + map.put(R26Keys.PRODUCT_LINE, currentLine.getProductRev() == null ? "" : currentLine.getProductRev().getProductLine()); + map.put(R26Keys.EFFECTIVITY_UNIT, currentLine.getEffectivity() == null ? "" : currentLine.getEffectivity()); + + map.put(R26Keys.MODULE_ID, currentLine.getModule() == null ? "" : currentLine.getModule().get_item_id()); + map.put(R26Keys.MODULE_NAME, currentLine.getModule() == null ? "" : currentLine.getModule().get_object_name()); + + map.put(R26Keys.CONSUMED_BY_PRODUCT, String.valueOf(currentLine.getConsumedByProduct())); + map.put(R26Keys.TYPE_STANDARD, String.valueOf(isStandard)); + return map; + } + + @Override + public void constructDataMaps(final TcSession session, final PrintParameters printParameters, final ReportDataR26 reportData) throws KurtException { + long start = System.currentTimeMillis(); + print(reportData, printParameters); + log.trace("Execution time : {} ms for {}", System.currentTimeMillis() - start, "data filtering"); + + log.info("Browsing the Snecma Objects"); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r26report/Range.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r26report/Range.java new file mode 100644 index 0000000..fb62ea0 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r26report/Range.java @@ -0,0 +1,59 @@ +package com.capgemini.reports.definition.r26report; + +import com.google.common.base.Joiner; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +public class Range { + private int borneInf; + private int borneSup; + private ItemRevision itemRevion; + private String revision; + + Range(ItemRevision revision, int borneInf, int borneSup) { + this.itemRevion = revision; + this.revision = revision.get_item_revision_id(); + this.borneInf = borneInf; + this.borneSup = borneSup; + } + + Range(String revision, int borneInf, int borneSup) { + this.itemRevion = null; + this.revision = revision; + this.borneInf = borneInf; + this.borneSup = borneSup; + } + + @Override + public String toString() { + if (borneInf == borneSup) { + return Integer.toString(borneInf); + } + else { + return Joiner.on("-").join(Integer.toString(borneInf), Integer.toString(borneSup)); + } + } + + ItemRevision getItemRevion() { + return itemRevion; + } + + public String getRevision() { + return revision; + } + + public void setRevision(String revision) { + this.revision = revision; + } + + int borneSup() { + return borneSup; + } + + int borneInf() { + return borneInf; + } + + public boolean isUp() { + return borneSup == 2147483646; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r26report/Ranges.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r26report/Ranges.java new file mode 100644 index 0000000..cd5e163 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r26report/Ranges.java @@ -0,0 +1,190 @@ +package com.capgemini.reports.definition.r26report; + +import com.google.common.base.Joiner; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + +public class Ranges { + + private final List ranges; + + Ranges(List ranges) { + this.ranges = ranges; + } + + public String toString(final String revId) { + List newRanges = new LinkedList<>(); + for (int index = 0; index < ranges.size(); index++) { + Range currentRange = ranges.get(index); + if (index == 0) { + newRanges.add(currentRange); + } + else { + int borneInfIndex = indexForIncludedBorne(newRanges, currentRange.borneInf()); + int borneSupIndex = indexForIncludedBorne(newRanges, currentRange.borneSup()); + + if (borneInfIndex == -1 && borneSupIndex == -1) { + int excludedBorneInfIndex = indexForExcludedBorne(newRanges, currentRange.borneInf()); + int excludedBorneSupIndex = indexForExcludedBorne(newRanges, currentRange.borneSup()); + + if (excludedBorneInfIndex == excludedBorneSupIndex) { + newRanges.add(excludedBorneInfIndex, new Range(currentRange.getRevision(), currentRange.borneInf(), currentRange.borneSup())); + } + else { + newRanges.set(excludedBorneInfIndex, new Range(currentRange.getRevision(), currentRange.borneInf(), currentRange.borneSup())); + } + } + else if (borneInfIndex <= newRanges.size() && borneSupIndex == -1) { + Range previousRange = newRanges.get(borneInfIndex); + newRanges.set(borneInfIndex, new Range(previousRange.getRevision(), previousRange.borneInf(), currentRange.borneInf() - 1)); + newRanges.add(new Range(currentRange.getRevision(), currentRange.borneInf(), currentRange.borneSup())); + } + else if (borneInfIndex == borneSupIndex) { + Range previousRange = newRanges.get(borneInfIndex); + if (currentRange.borneInf() == previousRange.borneInf() && currentRange.borneSup() == previousRange.borneSup()) { + newRanges.set(borneInfIndex, new Range(currentRange.getRevision(), currentRange.borneInf(), currentRange.borneSup())); + } + else if (currentRange.borneInf() == previousRange.borneInf()) { + newRanges.set(borneInfIndex, new Range(previousRange.getRevision(), currentRange.borneInf(), currentRange.borneSup())); + newRanges.add(borneInfIndex + 1, new Range(previousRange.getRevision(), currentRange.borneSup() + 1, previousRange.borneSup())); + } + else if (currentRange.borneSup() == previousRange.borneSup()) { + newRanges.set(borneInfIndex, new Range(previousRange.getRevision(), previousRange.borneInf(), currentRange.borneInf() - 1)); + newRanges.add(borneInfIndex + 1, new Range(currentRange.getRevision(), currentRange.borneInf(), currentRange.borneSup())); + } + else { + newRanges.set(borneInfIndex, new Range(previousRange.getRevision(), previousRange.borneInf(), currentRange.borneInf() - 1)); + newRanges.add(borneInfIndex + 1, new Range(currentRange.getRevision(), currentRange.borneInf(), currentRange.borneSup())); + newRanges.add(borneInfIndex + 2, new Range(previousRange.getRevision(), currentRange.borneSup() + 1, previousRange.borneSup())); + } + } + else { + for (int i = borneInfIndex; i <= borneSupIndex; i = i + 2) { + Range nextRange = newRanges.get(i); + if (i == borneInfIndex) { + if (currentRange.borneInf() == nextRange.borneInf()) { + newRanges.set(i, new Range(nextRange.getRevision(), nextRange.borneInf(), currentRange.borneInf())); + newRanges.add(i + 1, new Range(currentRange.getRevision(), currentRange.borneInf() + 1, nextRange.borneSup())); + } + else { + newRanges.set(i, new Range(nextRange.getRevision(), nextRange.borneInf(), currentRange.borneInf() - 1)); + newRanges.add(i + 1, new Range(currentRange.getRevision(), currentRange.borneInf(), nextRange.borneSup())); + } + borneSupIndex = borneSupIndex + 1; + } + else { + if (!currentRange.isUp()) { + newRanges.set(i, new Range(nextRange.getRevision(), nextRange.borneInf(), currentRange.borneSup())); + newRanges.add(i + 1, new Range(currentRange.getRevision(), currentRange.borneSup() + 1, nextRange.borneSup())); + borneSupIndex = borneSupIndex + 1; + } + else { + newRanges.set(i, new Range(currentRange.getRevision(), nextRange.borneInf(), currentRange.borneSup())); + } + } + } + } + } + } + + List validRevs = filterValidRevs(revId, newRanges); + return Joiner.on(";").join(consolidateRevs(validRevs)).replace("2147483646", "UP"); + } + + private List filterValidRevs(String revId, List newRanges) { + List validRevs = new ArrayList<>(); + for (Range range : newRanges) { + if (revId.equals(range.getRevision())) { + validRevs.add(range); + } + } + return validRevs; + } + + private List consolidateRevs(List validRevs) { + List consolidatedRanges = new ArrayList<>(); + if (validRevs.size() == 1) { + consolidatedRanges.add(validRevs.get(0)); + } + else if (validRevs.size() == 2) { + Range previousRange = validRevs.get(0); + Range currentRange = validRevs.get(1); + if (previousRange.borneSup() + 1 == currentRange.borneInf()) { + Range consolidatedRange = new Range(currentRange.getRevision(), previousRange.borneInf(), currentRange.borneSup()); + consolidatedRanges.add(consolidatedRange); + } + else { + consolidatedRanges.addAll(validRevs); + } + } + else { + for (int i = 0; i < validRevs.size(); i++) { + int indexToConsolidate = indexToConsolidate(validRevs, i); + if (indexToConsolidate != -1) { + Range previousRange = validRevs.get(i); + Range nextRange = validRevs.get(indexToConsolidate); + Range consolidatedRange = new Range(nextRange.getRevision(), previousRange.borneInf(), nextRange.borneSup()); + consolidatedRanges.add(consolidatedRange); + i = indexToConsolidate; + } + else { + consolidatedRanges.add(validRevs.get(i)); + } + } + } + return consolidatedRanges; + } + + private int indexForExcludedBorne(List newRanges, int borne) { + if (borne < newRanges.get(0).borneInf()) { + return 0; + } + if (borne > newRanges.get(newRanges.size() - 1).borneSup()) { + return newRanges.size(); + } + + for (int i = 1; i < newRanges.size(); i++) { + Range previousRange = newRanges.get(i - 1); + Range range = newRanges.get(i); + if (borne >= previousRange.borneSup() && borne <= range.borneInf()) { + return i; + } + } + return -1; + } + + private int indexForIncludedBorne(List newRanges, int borne) { + for (int i = 0; i < newRanges.size(); i++) { + Range range = newRanges.get(i); + if (borne >= range.borneInf() && borne <= range.borneSup()) { + return i; + } + } + return -1; + } + + private int indexToConsolidate(List newRanges, int startIndex) { + for (int i = startIndex; i < newRanges.size(); i++) { + Range currentRange = newRanges.get(i); + if (i == 0 && i < newRanges.size() - 1) { + Range nextRange = newRanges.get(i + 1); + if (currentRange.borneSup() + 1 != nextRange.borneInf()) { + return -1; + } + } + else if (i > 0 && i < newRanges.size() - 1) { + Range previousRange = newRanges.get(i - 1); + Range nextRange = newRanges.get(i + 1); + if (previousRange.borneSup() + 1 == currentRange.borneInf() && currentRange.borneSup() + 1 != nextRange.borneInf()) { + return i; + } + else if (currentRange.borneSup() + 1 == nextRange.borneInf() && nextRange.isUp()) { + return i + 1; + } + } + } + return -1; // not found + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r26report/RevisionRuleManager.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r26report/RevisionRuleManager.java new file mode 100644 index 0000000..9d8c9c3 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r26report/RevisionRuleManager.java @@ -0,0 +1,57 @@ +package com.capgemini.reports.definition.r26report; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcRevisionRule; +import com.capgemini.reports.exceptions.InvalidUserInputException; +import com.capgemini.reports.exceptions.UserInputErrorEnum; +import com.capgemini.reports.teamcenter.queries.TypeQuery; +import com.teamcenter.soa.client.model.strong.RevisionRule; +import lombok.Getter; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Manager for Revision Rule for making report R26. + */ +@Getter +class RevisionRuleManager { + + private RevisionRule revisionRule; + private String revisionRuleName; + private TcRevisionRule tcRevisionRule; + + RevisionRuleManager(TcSession session, RevisionRule reportRevRule, String newRevRuleName) throws InvalidUserInputException { + try { + session.cloneRevisionRule(reportRevRule, newRevRuleName); + } + catch (Exception e) { + throw new InvalidUserInputException(UserInputErrorEnum.UNABLE_TO_USE_REVISION_RULE); + } + + List list = TypeQuery.getRevisionRule(session, newRevRuleName); + + if (list.isEmpty()) { + throw new InvalidUserInputException(UserInputErrorEnum.UNABLE_TO_USE_REVISION_RULE); + } + else { + revisionRule = list.get(0); + tcRevisionRule = new TcRevisionRule(session, revisionRule); + session.loadProperties(revisionRule, "object_name"); + revisionRuleName = revisionRule.get_object_name(); + } + } + + /** + * Mise à jour des valeurs Article et Produit de la règle de révision du rapport R26. + */ + void setProductUnitRevisionRuleProperties(String productUid, int unit) { + Map map = new HashMap<>(); + map.put("rule_unit", String.valueOf(unit)); + map.put("rule_end_item", productUid); + + tcRevisionRule.setProperties(map); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r26report/RfPUManager.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r26report/RfPUManager.java new file mode 100644 index 0000000..2be5d67 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r26report/RfPUManager.java @@ -0,0 +1,108 @@ +package com.capgemini.reports.definition.r26report; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.teamcenter.soa.client.model.ModelObject; +import com.teamcenter.soa.client.model.strong.*; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; + +/** + * Manager for RF PU for making report R26. + */ +public class RfPUManager { + + /** + * A partir de l'item revision passé en paramètre, retourne tous les RF en Produit/Unit trouvés via where used. + */ + static List getRfPUs(TcSession session, RevisionRule revRule, ItemRevision itemRev) { + List rfPUs = new ArrayList<>(); + List parents = session.whereUsed(itemRev, 1, revRule); + if (parents.isEmpty() && isRfPU(session, itemRev) && isLastReleasedRfPURev(session, itemRev)) { + rfPUs.add(itemRev); + } + for (ItemRevision parent : parents) { + addRfPUs(session, revRule, parent, rfPUs); + } + return rfPUs; + } + + /** + * Récupère tous les RF en PU trouvé récursivement. + */ + private static void addRfPUs(TcSession session, RevisionRule revRule, ItemRevision itemRev, List rfPUs) { + List parents = session.whereUsed(itemRev, 1, revRule); + + if (parents.isEmpty() && isRfPU(session, itemRev) && isLastReleasedRfPURev(session, itemRev)) { + rfPUs.add(itemRev); + return; + } + for (ItemRevision currentParent : parents) { + addRfPUs(session, revRule, currentParent, rfPUs); + } + } + + /** + * Récupère tous les RF en PU. + */ + static List getRfPURevisions(TcSession session, RevisionRule reportRevisionRule, ItemRevision secondLevelParentRev) { + List rfPUs = new ArrayList<>(); + if (isRfPU(session, secondLevelParentRev)) { + // si l'object courant est un RF et a une effectivité en PU + rfPUs.add(secondLevelParentRev); + } else { + rfPUs.addAll(getRfPUs(session, reportRevisionRule, secondLevelParentRev)); + } + return rfPUs; + } + + /** + * Retourne true si l'itemRev est un RF en PU. + */ + static boolean isRfPU(TcSession session, ItemRevision itemRev) { + return SnecmaObjectTypes.isRFRevision(itemRev.getTypeObject().getName()) + && EffectivityHelper.isEffectivityWithUnitRange(session, itemRev.get_release_status_list()); + } + + /** + * Si une autre révision de l'objet courant possède la même effectivité, seule la révision la plus récente (last released) sera traitée. + * Retourne true si c'est la révision la plus récente, false sinon. + */ + static boolean isLastReleasedRfPURev(TcSession session, ItemRevision rfRev) { + ReleaseStatus[] statuses = rfRev.get_release_status_list(); + + session.loadProperties(rfRev, "items_tag"); + Item item = rfRev.get_items_tag(); + session.loadProperties(item, "revision_list"); + ModelObject[] revisions = item.get_revision_list(); + + Calendar releaseDate1 = rfRev.get_date_released(); + + for (ModelObject currentEffectivity : EffectivityHelper.getEffectivities(statuses)) { + Effectivity effectivity = (Effectivity) currentEffectivity; + session.loadProperties(effectivity, "unit_range_text"); + String effText1 = effectivity.get_unit_range_text(); + + for (ModelObject currentRev: revisions) { + ItemRevision itemRev = (ItemRevision) currentRev; + if (!rfRev.equals(itemRev)) { + Calendar releaseDate2 = itemRev.get_date_released(); + ReleaseStatus[] statuses2 = itemRev.get_release_status_list(); + + for (ModelObject currentEffectivity2 : EffectivityHelper.getEffectivities(statuses2)) { + Effectivity effectivity2 = (Effectivity) currentEffectivity2; + session.loadProperties(effectivity2, "unit_range_text"); + String effText2 = effectivity2.get_unit_range_text(); + + if (effText1.equals(effText2) && releaseDate1.before(releaseDate2)) { + return false; + } + } + } + } + } + return true; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r27report/DataReportPreparatorR27.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r27report/DataReportPreparatorR27.java new file mode 100644 index 0000000..16d0642 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r27report/DataReportPreparatorR27.java @@ -0,0 +1,53 @@ +package com.capgemini.reports.definition.r27report; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.queries.saved.modelobject.ItemQuery; +import com.capgemini.reports.execution.IDataReportPreparator; +import com.capgemini.reports.execution.strategies.IExecutionStrategy; +import com.capgemini.reports.printing.PrintParameters; +import com.teamcenter.soa.client.model.strong.Item; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +/** + * This class will allow to prepare data and findAll back data for making report R27. + */ +class DataReportPreparatorR27 implements IDataReportPreparator { + private static final long serialVersionUID = 1758410914529352674L; + private static final Logger LOGGER = LoggerFactory.getLogger(DataReportPreparatorR27.class); + + + @Override + public String print(final TcSession session, ExecutionR27 execution, IExecutionStrategy executionStrategy) throws KurtException { + PrintParameters printParameters = prepareData(session, execution); + executionStrategy.print(printParameters, execution); + return executionStrategy.getReportFileName(execution) + printParameters.getOuputFileExtension(); + } + + + private PrintParameters prepareData(final TcSession session, final ExecutionR27 report) throws KurtException { + LOGGER.debug("PrepareData started on: {}", report.getReportIdentifier().getReportTitle()); + + session.setObjectPropPolicy(report.getFullPolicy()); + ItemQuery query = new ItemQuery(session); + query.searchType("Alternate;DET;Part Aero;Part Mat;Part No Aero;Standard"); + List results = query.findAll(); + session.loadObjects(); + + ExecutionR27.ReportDataR27 reportDataR27 = new ExecutionR27.ReportDataR27(results); + R27Printer r27Printer = new R27Printer(); + PrintParameters printParameters = r27Printer.makeMasterTemplate(report, reportDataR27); + r27Printer.constructDataMaps(session, printParameters, reportDataR27); + LOGGER.debug("PrepareData ended on: {}", report.getReportIdentifier().getReportTitle()); + return printParameters; + } + +} + + + + + diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r27report/ExecutionR27.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r27report/ExecutionR27.java new file mode 100644 index 0000000..ae27b92 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r27report/ExecutionR27.java @@ -0,0 +1,151 @@ +package com.capgemini.reports.definition.r27report; + +import com.capgemini.framework.common.ReportFolderOutputHelper; +import com.capgemini.framework.common.SettingsHelper; +import com.capgemini.framework.common.TeamcenterDateFormatter; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.reports.JasperTemplate; +import com.capgemini.reports.ReportEnum; +import com.capgemini.reports.ReportLaunchTypeEnum; +import com.capgemini.reports.builder.R27Builder; +import com.capgemini.reports.builder.ReportBuilder; +import com.capgemini.reports.database.manager.MngCriteriaVal.CriteriaValue; +import com.capgemini.reports.execution.AbstractExecutionReport; +import com.capgemini.reports.execution.IDataReportPreparator; +import com.capgemini.reports.printing.PrintParameters; +import com.capgemini.reports.printing.Printer; +import com.capgemini.reports.printing.Printer.PrintFormat; +import com.capgemini.reports.reports.parameters.IChecker; +import com.teamcenter.soa.client.model.strong.Item; +import lombok.EqualsAndHashCode; +import lombok.Getter; + +import java.util.Calendar; +import java.util.Collections; +import java.util.List; + +/** + * Obtain data for report R27.
    + * Contain {@link IChecker} for a report's construction + */ +@Getter +@EqualsAndHashCode(callSuper = true) +public class ExecutionR27 extends AbstractExecutionReport { + /** + * Policy for inspecting Alternates and DETs more closely (i.e. looking into their pseudo-folders for alternative parts). + */ + public static final PolicyLocation R27_POLICY_XML_ALT = PolicyLocation.make("R27_policy_alt", "/xml/policies/r27report/R27_policy_alt.xml"); + private static final long serialVersionUID = 2659767774930642547L; + private static final IDataReportPreparator DATA_REPORT_PREPARATOR_R27 = new DataReportPreparatorR27(); + // Policies parameters + private static final PolicyLocation R27_POLICY_XML_LIGHT = PolicyLocation.make("R27_policy_light", "/xml/policies/r27report/R27_policy_light.xml"); + private static final PolicyLocation R27_POLICY_XML_FULL = PolicyLocation.make("R27_policy_full", "/xml/policies/r27report/R27_policy_full.xml"); + // Launch type parameter + private static final ReportLaunchTypeEnum REPORT_LAUNCH_TYPE = ReportLaunchTypeEnum.getReportLaunchType("common.launch.launchType.REPORT_R27"); + + // Priority parameter + private static final int REPORT_PRIORITY = SettingsHelper.getPriority(ReportEnum.REPORT_R27); + + private static final String FILE_SEPARATOR = "_"; + private static final String TITLE = "Export_Articles"; + private static final String PATTERN_DATE = "dd-MM-yyyy"; + + /** + * Constructor. + */ + public ExecutionR27(List queryObjects) { + super(REPORT_PRIORITY, REPORT_LAUNCH_TYPE); + } + + + /** + * Empty constructor. + */ + public ExecutionR27() { + super(REPORT_PRIORITY, REPORT_LAUNCH_TYPE); + } + + + @Override + public String getSpecifiedFileName() { + StringBuilder builder = new StringBuilder("R27").append(FILE_SEPARATOR).append(TITLE).append(FILE_SEPARATOR); + builder.append(TeamcenterDateFormatter.formatCalendarToPattern(Calendar.getInstance(), PATTERN_DATE)); + return builder.toString(); + } + + @Override + public PrintFormat getPrintingFormat() { + return PrintFormat.CSV; + } + + @Override + public List getLaunchData() { + return Collections.emptyList(); + } + + @Override + public ReportEnum getReportIdentifier() { + return ReportEnum.REPORT_R27; + } + + + @Override + public PolicyLocation getPropertyPolicyForLongChecks() { + return R27_POLICY_XML_LIGHT; + } + + @Override + public PolicyLocation getFullPolicy() { + return R27_POLICY_XML_FULL; + } + + @Override + public List getLongChecks() { + return Collections.emptyList(); + } + + @Override + public String getTemplateLocation() { + return JasperTemplate.TEMPLATE_R27.getFilepath(); + } + + @Override + public IDataReportPreparator getDataPreparator() { + return DATA_REPORT_PREPARATOR_R27; + } + + @Override + public List getQuickChecks() { + return Collections.emptyList(); + } + + @Override + public Class getReportBuilderClass() { + return R27Builder.class; + } + + @Override + public AbstractExecutionReport cloneTemplateToExecution() { + return null; + } + + public PrintParameters reportParameters() { + return new PrintParameters(PrintFormat.CSV, getFileNameOnDisc(), ReportFolderOutputHelper.getStorageFolderLocation(getLaunchType())); + } + + /** + * POJO container of all data required for this report. + */ + static class ReportDataR27 { + private final List parts; + + public ReportDataR27(List parts) { + this.parts = parts; + } + + public List getParts() { + return parts; + } + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r27report/R27Keys.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r27report/R27Keys.java new file mode 100644 index 0000000..7285e8e --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r27report/R27Keys.java @@ -0,0 +1,8 @@ +package com.capgemini.reports.definition.r27report; + +/** + * Enumeration of all the columns of the R27 report. + */ +public enum R27Keys { + ITEM_ID, +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r27report/R27Printer.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r27report/R27Printer.java new file mode 100644 index 0000000..e07b7e4 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r27report/R27Printer.java @@ -0,0 +1,57 @@ +package com.capgemini.reports.definition.r27report; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.reports.definition.r27report.ExecutionR27.ReportDataR27; +import com.capgemini.reports.execution.mapconstructor.AbstractStaticTemplateMapConstructor; +import com.capgemini.reports.execution.mapconstructor.IMapConstructor; +import com.capgemini.reports.printing.PrintParameters; +import com.teamcenter.soa.client.model.strong.Item; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.EnumMap; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Extracts the relevant data obtained from TC into the expected List of Maps for Jasper. + */ +@Slf4j +public class R27Printer extends AbstractStaticTemplateMapConstructor implements IMapConstructor { + + private static final long serialVersionUID = 4281716591716247163L; + + /** + * Puts the data gathered by an {@link ExecutionR27} into some {@link PrintParameters} for printing. + * + * @param reportData the data-bearing {@link ReportDataR27} + * @param mainReport the {@link PrintParameters} + */ + private void print(final ReportDataR27 reportData, final PrintParameters mainReport) { + List parts = reportData.getParts(); + if (parts.isEmpty()) { + mainReport.addReportData(setupEmptyData()); + } + else { + List> reportDataMap = new ArrayList<>(); + for (Item part : parts) { + Map map = new EnumMap<>(R27Keys.class); + map.put(R27Keys.ITEM_ID, part.get_item_id()); + reportDataMap.add(map); + } + mainReport.addReportDataFromEnum(reportDataMap); + } + } + + private static List> setupEmptyData() { + List> list = new ArrayList<>(); + list.add(new HashMap()); + return list; + } + + @Override + public void constructDataMaps(TcSession session, PrintParameters printParameters, ReportDataR27 reportData) { + print(reportData, printParameters); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r28report/DataReportPreparatorR28.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r28report/DataReportPreparatorR28.java new file mode 100644 index 0000000..1985d5d --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r28report/DataReportPreparatorR28.java @@ -0,0 +1,53 @@ +package com.capgemini.reports.definition.r28report; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.queries.saved.modelobject.ItemQuery; +import com.capgemini.reports.execution.IDataReportPreparator; +import com.capgemini.reports.execution.strategies.IExecutionStrategy; +import com.capgemini.reports.printing.PrintParameters; +import com.teamcenter.soa.client.model.strong.Item; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +/** + * This class will allow to prepare data and findAll back data for making report R28. + */ +class DataReportPreparatorR28 implements IDataReportPreparator { + private static final long serialVersionUID = 1758410914529352674L; + private static final Logger LOGGER = LoggerFactory.getLogger(DataReportPreparatorR28.class); + + + @Override + public String print(final TcSession session, ExecutionR28 execution, IExecutionStrategy executionStrategy) throws KurtException { + PrintParameters printParameters = prepareData(session, execution); + executionStrategy.print(printParameters, execution); + return executionStrategy.getReportFileName(execution) + printParameters.getOuputFileExtension(); + } + + + private PrintParameters prepareData(final TcSession session, final ExecutionR28 report) throws KurtException { + LOGGER.debug("PrepareData started on: {}", report.getReportIdentifier().getReportTitle()); + + session.setObjectPropPolicy(report.getFullPolicy()); + ItemQuery query = new ItemQuery(session); + query.searchType("RF Part"); + List results = query.findAll(); + session.loadObjects(); + + ExecutionR28.ReportDataR28 reportDataR28 = new ExecutionR28.ReportDataR28(results); + R28Printer r28Printer = new R28Printer(); + PrintParameters printParameters = r28Printer.makeMasterTemplate(report, reportDataR28); + r28Printer.constructDataMaps(session, printParameters, reportDataR28); + LOGGER.debug("PrepareData ended on: {}", report.getReportIdentifier().getReportTitle()); + return printParameters; + } + +} + + + + + diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r28report/ExecutionR28.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r28report/ExecutionR28.java new file mode 100644 index 0000000..de27fdc --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r28report/ExecutionR28.java @@ -0,0 +1,151 @@ +package com.capgemini.reports.definition.r28report; + +import com.capgemini.framework.common.ReportFolderOutputHelper; +import com.capgemini.framework.common.SettingsHelper; +import com.capgemini.framework.common.TeamcenterDateFormatter; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.reports.JasperTemplate; +import com.capgemini.reports.ReportEnum; +import com.capgemini.reports.ReportLaunchTypeEnum; +import com.capgemini.reports.builder.R28Builder; +import com.capgemini.reports.builder.ReportBuilder; +import com.capgemini.reports.database.manager.MngCriteriaVal.CriteriaValue; +import com.capgemini.reports.execution.AbstractExecutionReport; +import com.capgemini.reports.execution.IDataReportPreparator; +import com.capgemini.reports.printing.PrintParameters; +import com.capgemini.reports.printing.Printer; +import com.capgemini.reports.printing.Printer.PrintFormat; +import com.capgemini.reports.reports.parameters.IChecker; +import com.teamcenter.soa.client.model.strong.Item; +import lombok.EqualsAndHashCode; +import lombok.Getter; + +import java.util.Calendar; +import java.util.Collections; +import java.util.List; + +/** + * Obtain data for report R28.
    + * Contain {@link IChecker} for a report's construction + */ +@Getter +@EqualsAndHashCode(callSuper = true) +public class ExecutionR28 extends AbstractExecutionReport { + /** + * Policy for inspecting Alternates and DETs more closely (i.e. looking into their pseudo-folders for alternative parts). + */ + public static final PolicyLocation R28_POLICY_XML_ALT = PolicyLocation.make("R28_policy_alt", "/xml/policies/r28report/R28_policy_alt.xml"); + private static final long serialVersionUID = -5027358935089122516L; + private static final IDataReportPreparator DATA_REPORT_PREPARATOR_R28 = new DataReportPreparatorR28(); + // Policies parameters + private static final PolicyLocation R28_POLICY_XML_LIGHT = PolicyLocation.make("R28_policy_light", "/xml/policies/r28report/R28_policy_light.xml"); + private static final PolicyLocation R28_POLICY_XML_FULL = PolicyLocation.make("R28_policy_full", "/xml/policies/r28report/R28_policy_full.xml"); + // Launch type parameter + private static final ReportLaunchTypeEnum REPORT_LAUNCH_TYPE = ReportLaunchTypeEnum.getReportLaunchType("common.launch.launchType.REPORT_R28"); + + // Priority parameter + private static final int REPORT_PRIORITY = SettingsHelper.getPriority(ReportEnum.REPORT_R28); + + private static final String FILE_SEPARATOR = "_"; + private static final String TITLE = "Export_Repere_fonctionnel"; + private static final String PATTERN_DATE = "dd-MM-yyyy"; + + /** + * Constructor. + */ + public ExecutionR28(List queryObjects) { + super(REPORT_PRIORITY, REPORT_LAUNCH_TYPE); + } + + + /** + * Empty constructor. + */ + public ExecutionR28() { + super(REPORT_PRIORITY, REPORT_LAUNCH_TYPE); + } + + + @Override + public String getSpecifiedFileName() { + StringBuilder builder = new StringBuilder("R28").append(FILE_SEPARATOR).append(TITLE).append(FILE_SEPARATOR); + builder.append(TeamcenterDateFormatter.formatCalendarToPattern(Calendar.getInstance(), PATTERN_DATE)); + return builder.toString(); + } + + @Override + public PrintFormat getPrintingFormat() { + return PrintFormat.CSV; + } + + @Override + public List getLaunchData() { + return Collections.emptyList(); + } + + @Override + public ReportEnum getReportIdentifier() { + return ReportEnum.REPORT_R28; + } + + + @Override + public PolicyLocation getPropertyPolicyForLongChecks() { + return R28_POLICY_XML_LIGHT; + } + + @Override + public PolicyLocation getFullPolicy() { + return R28_POLICY_XML_FULL; + } + + @Override + public List getLongChecks() { + return Collections.emptyList(); + } + + @Override + public String getTemplateLocation() { + return JasperTemplate.TEMPLATE_R28.getFilepath(); + } + + @Override + public IDataReportPreparator getDataPreparator() { + return DATA_REPORT_PREPARATOR_R28; + } + + @Override + public List getQuickChecks() { + return Collections.emptyList(); + } + + @Override + public Class getReportBuilderClass() { + return R28Builder.class; + } + + @Override + public AbstractExecutionReport cloneTemplateToExecution() { + return null; + } + + public PrintParameters reportParameters() { + return new PrintParameters(PrintFormat.CSV, getFileNameOnDisc(), ReportFolderOutputHelper.getStorageFolderLocation(getLaunchType())); + } + + /** + * POJO container of all data required for this report. + */ + static class ReportDataR28 { + private final List parts; + + public ReportDataR28(List parts) { + this.parts = parts; + } + + public List getParts() { + return parts; + } + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r28report/R28Keys.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r28report/R28Keys.java new file mode 100644 index 0000000..5e6918a --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r28report/R28Keys.java @@ -0,0 +1,10 @@ +package com.capgemini.reports.definition.r28report; + +/** + * Enumeration of all the columns of the R27 report. + */ +public enum R28Keys { + ITEM_ID, + ITEM_NAME, + ITEM_EFFECTIVITY, +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/definition/r28report/R28Printer.java b/kurt-utility/src/main/java/com/capgemini/reports/definition/r28report/R28Printer.java new file mode 100644 index 0000000..640355c --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/definition/r28report/R28Printer.java @@ -0,0 +1,79 @@ +package com.capgemini.reports.definition.r28report; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.reports.definition.r28report.ExecutionR28.ReportDataR28; +import com.capgemini.reports.execution.mapconstructor.AbstractStaticTemplateMapConstructor; +import com.capgemini.reports.execution.mapconstructor.IMapConstructor; +import com.capgemini.reports.printing.PrintParameters; +import com.teamcenter.soa.client.model.strong.Item; +import lombok.extern.slf4j.Slf4j; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.EnumMap; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static com.capgemini.framework.teamcenter.object.SnecmaObjectProperties.PV4_TYPE_EFFECTIVITY; +import static com.capgemini.framework.teamcenter.object.SnecmaObjectProperties.PV4_TYPE_MODIFICATION; + +/** + * Extracts the relevant data obtained from TC into the expected List of Maps for Jasper. + */ +@Slf4j +public class R28Printer extends AbstractStaticTemplateMapConstructor implements IMapConstructor { + + private static final long serialVersionUID = 4281716591716247163L; + private static final Logger LOGGER = LoggerFactory.getLogger(TcSession.class); + + /** + * Puts the data gathered by an {@link ExecutionR28} into some {@link PrintParameters} for printing. + * + * @param reportData the data-bearing {@link ReportDataR28} + * @param mainReport the {@link PrintParameters} + */ + private void print(final ReportDataR28 reportData, final PrintParameters mainReport, final TcSession session) { + List parts = reportData.getParts(); + if (parts.isEmpty()) { + mainReport.addReportData(setupEmptyData()); + } + else { + + List> reportDataMap = new ArrayList<>(); + for (Item part : parts) { + Map map = new EnumMap<>(R28Keys.class); + map.put(R28Keys.ITEM_ID, part.get_item_id()); + map.put(R28Keys.ITEM_NAME, part.get_object_name()); + // if (part.get_IMAN_master_form()[0].) + if (part.get_IMAN_master_form().length != 0){ + session.loadProperties(part.get_IMAN_master_form()[0], PV4_TYPE_EFFECTIVITY); + // LOGGER.trace("Property is ", part.get_IMAN_master_form()[0].getPropertyObject(PV4_TYPE_EFFECTIVITY).getDisplayableValue()); + if (part.get_IMAN_master_form()[0].getPropertyObject(PV4_TYPE_EFFECTIVITY).getDisplayableValue() == "") { + LOGGER.trace("Object ID " + part.get_item_id() + " does not have any effectivity type"); + map.put(R28Keys.ITEM_EFFECTIVITY, ""); + } else { + map.put(R28Keys.ITEM_EFFECTIVITY, part.get_IMAN_master_form()[0].getPropertyObject(PV4_TYPE_EFFECTIVITY).getDisplayableValue()); + } + } else { + LOGGER.trace("Object ID " + part.get_item_id() + " does not have any form"); + map.put(R28Keys.ITEM_EFFECTIVITY, ""); + } + reportDataMap.add(map); + } + mainReport.addReportDataFromEnum(reportDataMap); + } + } + + private static List> setupEmptyData() { + List> list = new ArrayList<>(); + list.add(new HashMap()); + return list; + } + + @Override + public void constructDataMaps(TcSession session, PrintParameters printParameters, ReportDataR28 reportData) { + print(reportData, printParameters, session); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/emailing/templates/AbstractEmailTemplate.java b/kurt-utility/src/main/java/com/capgemini/reports/emailing/templates/AbstractEmailTemplate.java new file mode 100644 index 0000000..2b7ca9a --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/emailing/templates/AbstractEmailTemplate.java @@ -0,0 +1,133 @@ +package com.capgemini.reports.emailing.templates; + +import com.capgemini.framework.common.FileTemplate; +import com.capgemini.framework.common.MailHelper; +import com.capgemini.framework.common.ResourceHelper; +import com.capgemini.reports.database.javabean.DbUser; +import com.capgemini.reports.exceptions.FileLoadingException; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.List; + +/** + * Template class for generating email content when a report has been scheduled, posted in the queue, has failed or is completed.
    + * This class provides a way to replace tags (found in the email template) by some provided content. + */ +@Slf4j +public abstract class AbstractEmailTemplate extends FileTemplate { + + @Getter + private final String subject; + + /** + * Constructor. + * + * @param subject the email's Subject + */ + public AbstractEmailTemplate(final String subject) { + super(); + this.subject = subject; + try { + // Select the corresponding template content + String theTemplateContent = ResourceHelper.getResourceContent("/html/email/" + getEmailTemplate()); + // Assign the expected template + setTemplateContent(theTemplateContent); + } + catch (FileLoadingException e) { + log.warn("Could not load the email template file", e); + } + } + + protected abstract String getEmailTemplate(); + + /** + * Assign a tag value in the template. + * + * @param aTag Tag identifier + * @param aTagValue Tag value + */ + protected void setTagValue(final EmailTagEnum aTag, final String aTagValue) { + setTagValue(aTag.toString(), aTagValue); + } + + /** + * Sends this mail to the provided list of users. + * + * @param users a list of users, each of them having potentially several comma-separated email addresses + */ + public void send(final List users) { + List validEmails = new ArrayList<>(); + List invalidUsers = new ArrayList<>(); + for (DbUser user : users) { + String email = user.getEmail(); + if (email == null || email.isEmpty() || user.isGuest()) { + invalidUsers.add(user); + } + else { + validEmails.add(email); + } + } + + sendToAdresses(validEmails); + if (users.isEmpty() || !invalidUsers.isEmpty()) { // no users, or at least one invalid user --> send to admins + log.debug("Some User(s) do not have an email address in ActiveDirectory."); + } + } + + /** + * Sends this mail to this user. + * + * @param user the user + */ + public void send(final DbUser user) { + String email = user.getEmail(); + if (email == null || email.isEmpty() || user.isGuest()) { + log.debug("User {} does not have an email address in ActiveDirectory. Sending email to default address(es).", user.getLogin()); + } + else { + List asList = new ArrayList<>(); + asList.add(email); + sendToAdresses(asList); + } + } + + /** + * Sends this mail to the users that required the report. + * + * @param destinators the email addresses for all receivers + */ + public void sendToAdresses(final List destinators) { + // Generate content using parameters and template + String content = this.generateCode(); + + // Send the email + MailHelper.sendAll(destinators, subject, content); + } + + /** + * This Enum contains specific tags constants.
    + * These tags exist whithin the eMail template files, and can be replaced by any String thanks to the {@link AbstractEmailTemplate} class. + */ + protected enum EmailTagEnum { + // Common tag + REPORT_NAME, + + // Required when report state is: SCHEDULED + QUEUE_NAME, + ESTIMATED_COMPLETION_TIME, + + // Required when report state is: BAD PARAMETERS | FINISHED | FAILED + POSTING_TIME, + START_TIME, + END_TIME, + + // Required when report state is FINISHED + REPORT_LOCATION, + + // Required when report state is: BAD PARAMETERS | FAILED + ERROR_MESSAGE + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/emailing/templates/BadParamEmailTemplate.java b/kurt-utility/src/main/java/com/capgemini/reports/emailing/templates/BadParamEmailTemplate.java new file mode 100644 index 0000000..44a7439 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/emailing/templates/BadParamEmailTemplate.java @@ -0,0 +1,39 @@ +package com.capgemini.reports.emailing.templates; + +import com.capgemini.reports.exceptions.InvalidInputException; + +/** + * Represents a mail to warn the destinator that the report has some invalid parameters and will not be executed.
    + */ +public class BadParamEmailTemplate extends AbstractEmailTemplate { + + private static final String SUCCESSFUL_FR = " terminé avec succès"; + private static final String TEMPLATE_LOCATION = "template_email_bad_parameters.html"; + + /** + * Represents a mail to warn the destinator that the report has some invalid parameters and will not be executed.
    + * + * @param completeReportName the name of the report (e.g. R01 report "BOM Assemblage PU") + * @param postingTime a String describing he time at which this report was posted in the queues + * @param startTime a String describing he time at which this report's execution has started + * @param failureTime a String describing he time at which this report failed + * @param iie the specific Exception that contains the explanation + */ + public BadParamEmailTemplate(final String completeReportName, final String postingTime, final String startTime, final String failureTime, + final InvalidInputException iie) { + super(completeReportName + SUCCESSFUL_FR); + + // Assign parameters + this.setTagValue(EmailTagEnum.REPORT_NAME, completeReportName); + this.setTagValue(EmailTagEnum.POSTING_TIME, postingTime); + this.setTagValue(EmailTagEnum.START_TIME, startTime); + this.setTagValue(EmailTagEnum.END_TIME, failureTime); + this.setTagValue(EmailTagEnum.ERROR_MESSAGE, iie.getErrorMessageForUser()); + } + + @Override + protected String getEmailTemplate() { + return TEMPLATE_LOCATION; + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/emailing/templates/EmailReportHelper.java b/kurt-utility/src/main/java/com/capgemini/reports/emailing/templates/EmailReportHelper.java new file mode 100644 index 0000000..d5c57f7 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/emailing/templates/EmailReportHelper.java @@ -0,0 +1,146 @@ +package com.capgemini.reports.emailing.templates; + +import com.capgemini.framework.common.TeamcenterDateFormatter; +import com.capgemini.framework.common.activedirectory.ActiveDirectory; +import com.capgemini.reports.database.javabean.DbUser; +import com.capgemini.reports.execution.AbstractExecutionReport; +import lombok.extern.slf4j.Slf4j; + +import java.util.List; + +/** + * This class will allow to send different types of mail to the user. + */ +@Slf4j +public final class EmailReportHelper { + + private EmailReportHelper() { + // Cannot be called + } + + /** + * Sends a mail to warn the user that his report has successfully completed and may be retrieved. + * + * @param downloadLink the Location where the file has been stored + * @param aAbstractExecutionReport will provide the report concerned + * @param users the {@link List} of {@link DbUser} that have subscribed to this report + */ + public static void sendEndEmail(final String downloadLink, final AbstractExecutionReport aAbstractExecutionReport, + final List users) { + // Register current time as the posting time + aAbstractExecutionReport.setEndTime(TeamcenterDateFormatter.getCurrentTime()); + String completeReportName = aAbstractExecutionReport.getReportIdentifier().buildCompleteReportName().toString(); + new SuccessfulEmailTemplate(completeReportName, aAbstractExecutionReport.getPostingTime(), aAbstractExecutionReport.getStartTime(), + aAbstractExecutionReport.getEndTime(), downloadLink).send(users); + } + + /** + * Sends a mail to warn the user that his SCHEDULED report has successfully completed and may be retrieved. + * + * @param downloadLink the Location where the file has been stored + * @param aAbstractExecutionReport will provide the report concerned + * @param users the {@link List} of {@link DbUser} that have subscribed to this report + * @param schedulingName String - the scheduling name of the SCHEDULED report + */ + public static void sendScheduledEndEmail(final String downloadLink, final AbstractExecutionReport aAbstractExecutionReport, + final List users, final String schedulingName) { + // Register current time as the posting time + aAbstractExecutionReport.setEndTime(TeamcenterDateFormatter.getCurrentTime()); + String completeReportName = aAbstractExecutionReport.getReportIdentifier().buildCompleteReportName().toString(); + new SuccessfulEmailTemplate(completeReportName, aAbstractExecutionReport.getPostingTime(), aAbstractExecutionReport.getStartTime(), + aAbstractExecutionReport.getEndTime(), downloadLink, schedulingName).send(users); + } + + /** + * Sends a mail to warn the user that his report has failed to complete. + * + * @param errorMessage the error message to include for the user + * @param aAbstractExecutionReport will provide the report concerned + * @param users the {@link List} of {@link DbUser} that have subscribed to this report + */ + public static void sendErrorEmail(final String errorMessage, final AbstractExecutionReport aAbstractExecutionReport, + final List users) { + // Register current time as the error time + aAbstractExecutionReport.setFailureTime(TeamcenterDateFormatter.getCurrentTime()); + String completeReportName = aAbstractExecutionReport.getReportIdentifier().buildCompleteReportName().toString(); + new FailedEmailTemplate(completeReportName, aAbstractExecutionReport.getPostingTime(), aAbstractExecutionReport.getStartTime(), + aAbstractExecutionReport.getFailureTime(), errorMessage).send(users); + } + + /** + * Sends a mail to warn to the report admins that his report has failed to complete. + * + * @param errorMessage the error message to include for the admin report + * @param aAbstractExecutionReport will provide the report concerned + */ + public static void sendErrorEmailToAdminsReport(final String errorMessage, final AbstractExecutionReport aAbstractExecutionReport) { + // Register current time as the error time + aAbstractExecutionReport.setFailureTime(TeamcenterDateFormatter.getCurrentTime()); + String completeReportName = aAbstractExecutionReport.getReportIdentifier().buildCompleteReportName().toString(); + List adminsReport = ActiveDirectory.getAdminsReportUpdateDatabase(); + if (adminsReport.isEmpty()) { + log.error("The request for recovery of the admins report from active directory of SNECMA has returned nothing, on fail {} ", + aAbstractExecutionReport.getReportIdentifier()); + } else { + new FailedEmailTemplateAdmin(completeReportName, aAbstractExecutionReport.getPostingTime(), aAbstractExecutionReport.getStartTime(), + aAbstractExecutionReport.getFailureTime(), errorMessage).send(adminsReport); + } + } + + /** + * Sends a mail to warn the user that his report, launched by a workflow, has failed to complete. + * + * @param errorMessage the error message to include for the user + * @param aAbstractExecutionReport will provide the report concerned + * @param users the {@link List} of {@link DbUser} that have subscribed to this report + * @param relaunchURL the URL to launch this report again + */ + public static void sendWorkflowErrorEmail(final String errorMessage, final AbstractExecutionReport aAbstractExecutionReport, + final List users, final String relaunchURL) { + String reportName = aAbstractExecutionReport.getReportIdentifier().buildCompleteReportName().toString(); + String postingTime = aAbstractExecutionReport.getPostingTime(); + String startTime = aAbstractExecutionReport.getStartTime(); + String failureTime = aAbstractExecutionReport.getFailureTime(); + new FailedWorkflowEmailTemplate(reportName, postingTime, startTime, failureTime, errorMessage, relaunchURL).send(users); + } + + /** + * Sends a mail to warn to the report admin that his report (launched by workflow) has failed to complete. + * + * @param errorMessage the error message to include for the admin report + * @param aAbstractExecutionReport will provide the report concerned + * @param adminsReport the {@link List} of {@link DbUser} that have subscribed to this report + * @param relaunchURL the URL to use to re-launch the report + */ + public static void sendWorkflowErrorEmailToAdminsReport(final String errorMessage, final AbstractExecutionReport aAbstractExecutionReport, + final List adminsReport, final String relaunchURL) { + String reportName = aAbstractExecutionReport.getReportIdentifier().buildCompleteReportName().toString(); + String postingTime = aAbstractExecutionReport.getPostingTime(); + String startTime = aAbstractExecutionReport.getStartTime(); + String failureTime = aAbstractExecutionReport.getFailureTime(); + FailedWorkflowEmailTemplateAdmin emailTemplate = new FailedWorkflowEmailTemplateAdmin(reportName, postingTime, startTime, failureTime, errorMessage, relaunchURL); + emailTemplate.send(adminsReport); + } + + public static void sendScheduledErrorEmailToAdminsReport(String errorMessage, AbstractExecutionReport aAbstractExecutionReport) { + // Register current time as the error time + aAbstractExecutionReport.setFailureTime(TeamcenterDateFormatter.getCurrentTime()); + String completeReportName = aAbstractExecutionReport.getReportIdentifier().buildCompleteReportName().toString(); + List adminsReport = ActiveDirectory.getAdminsReportUpdateDatabase(); + if (adminsReport.isEmpty()) { + log.error("The request for recovery of the admins report from active directory of SNECMA has returned nothing, on fail {} ", + aAbstractExecutionReport.getReportIdentifier()); + } else { + new FailedEmailTemplateAdmin(completeReportName, aAbstractExecutionReport.getPostingTime(), aAbstractExecutionReport.getStartTime(), + aAbstractExecutionReport.getFailureTime(), errorMessage, aAbstractExecutionReport.getSchedulingName()).send(adminsReport); + } + } + + public static void sendScheduledErrorEmail(String errorMessage, AbstractExecutionReport aAbstractExecutionReport, List users) { + // Register current time as the error time + aAbstractExecutionReport.setFailureTime(TeamcenterDateFormatter.getCurrentTime()); + String completeReportName = aAbstractExecutionReport.getReportIdentifier().buildCompleteReportName().toString(); + new FailedEmailTemplate(completeReportName, aAbstractExecutionReport.getPostingTime(), aAbstractExecutionReport.getStartTime(), + aAbstractExecutionReport.getFailureTime(), errorMessage, aAbstractExecutionReport.getSchedulingName()).send(users); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/emailing/templates/FailedEmailTemplate.java b/kurt-utility/src/main/java/com/capgemini/reports/emailing/templates/FailedEmailTemplate.java new file mode 100644 index 0000000..7144bfd --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/emailing/templates/FailedEmailTemplate.java @@ -0,0 +1,54 @@ +package com.capgemini.reports.emailing.templates; + +import lombok.extern.slf4j.Slf4j; + +/** Represents a mail to warn the user that his report has failed. */ +@Slf4j +public class FailedEmailTemplate extends AbstractEmailTemplate { + + private static final String FAILED_FR = " terminé en erreur"; + private static final String TEMPLATE_LOCATION = "template_email_failed.html"; + + /** + * Represents a mail to warn the user that his report has failed. + * @param completeReportName the name of the report (e.g. R01 report "BOM Assemblage PU") + * @param postingTime a String describing he time at which this report was posted in the queues + * @param startTime a String describing he time at which this report's execution has started + * @param failureTime a String describing he time at which this report caused an error + * @param errorMessage the error message to include for the user + * @param schedulingName + */ + public FailedEmailTemplate(final String completeReportName, final String postingTime, final String startTime, final String failureTime, + final String errorMessage, final String schedulingName) { + super(completeReportName + " - planification " + schedulingName + FAILED_FR); + this.setTagValue(EmailTagEnum.POSTING_TIME, postingTime); + this.setTagValue(EmailTagEnum.REPORT_NAME, completeReportName); + this.setTagValue(EmailTagEnum.START_TIME, startTime); + this.setTagValue(EmailTagEnum.END_TIME, failureTime); + this.setTagValue(EmailTagEnum.ERROR_MESSAGE, errorMessage); + } + + /** + * Represents a mail to warn the user that his report has failed. + * @param completeReportName the name of the report (e.g. R01 report "BOM Assemblage PU") + * @param postingTime a String describing he time at which this report was posted in the queues + * @param startTime a String describing he time at which this report's execution has started + * @param failureTime a String describing he time at which this report caused an error + * @param errorMessage the error message to include for the user + */ + public FailedEmailTemplate(final String completeReportName, final String postingTime, final String startTime, final String failureTime, + final String errorMessage) { + super(completeReportName + FAILED_FR); + this.setTagValue(EmailTagEnum.POSTING_TIME, postingTime); + this.setTagValue(EmailTagEnum.REPORT_NAME, completeReportName); + this.setTagValue(EmailTagEnum.START_TIME, startTime); + this.setTagValue(EmailTagEnum.END_TIME, failureTime); + this.setTagValue(EmailTagEnum.ERROR_MESSAGE, errorMessage); + } + + @Override + protected String getEmailTemplate() { + return TEMPLATE_LOCATION; + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/emailing/templates/FailedEmailTemplateAdmin.java b/kurt-utility/src/main/java/com/capgemini/reports/emailing/templates/FailedEmailTemplateAdmin.java new file mode 100644 index 0000000..94fcd1d --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/emailing/templates/FailedEmailTemplateAdmin.java @@ -0,0 +1,35 @@ +package com.capgemini.reports.emailing.templates; + +/** + * Email template when a report execution has failed (with a TECHNICAL ERROR) and an email must be sent to the admin. + */ +public class FailedEmailTemplateAdmin extends FailedEmailTemplate { + + private static final String TEMPLATE_LOCATION = "template_email_failed_admin.html"; + + /** + * Prepares an email to be sent to the admins, if a report failed (with a TECHNICAL ERROR). + * + * @param completeReportName the full report's name + * @param postingTime the time at which the report has been posted + * @param startTime the time at which the report qstarted to execute + * @param failureTime the time at which the report execution failed + * @param errorMessage the error message for the user + * @param schedulingName + */ + public FailedEmailTemplateAdmin(final String completeReportName, final String postingTime, final String startTime, final String failureTime, + final String errorMessage, final String schedulingName) { + super(completeReportName, postingTime, startTime, failureTime, errorMessage, schedulingName); + } + + public FailedEmailTemplateAdmin(final String completeReportName, final String postingTime, final String startTime, final String failureTime, + final String errorMessage) { + super(completeReportName, postingTime, startTime, failureTime, errorMessage); + } + + @Override + protected String getEmailTemplate() { + return TEMPLATE_LOCATION; + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/emailing/templates/FailedWorkflowEmailTemplate.java b/kurt-utility/src/main/java/com/capgemini/reports/emailing/templates/FailedWorkflowEmailTemplate.java new file mode 100644 index 0000000..ef8d1d0 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/emailing/templates/FailedWorkflowEmailTemplate.java @@ -0,0 +1,27 @@ +package com.capgemini.reports.emailing.templates; + +/** + * Represents a mail to warn the user that this report, launched by a Workflow, has failed. + */ +public class FailedWorkflowEmailTemplate extends FailedEmailTemplate { + + /** + * Represents a mail to warn the user that this report, launched by a Workflow, has failed. + * + * @param completeReportName the name of the report (e.g. R01 report "BOM Assemblage PU") + * @param postingTime a String describing he time at which this report was posted in the queues + * @param startTime a String describing he time at which this report's execution has started + * @param failureTime a String describing he time at which this report caused an error + * @param errorMessage the error message to include for the user + * @param relaunchURL an URL that can be used to re-launch this report + */ + public FailedWorkflowEmailTemplate(final String completeReportName, final String postingTime, final String startTime, final String failureTime, + final String errorMessage, final String relaunchURL) { + super(completeReportName, postingTime, startTime, failureTime, makeErrorMessageFromFailure(errorMessage, relaunchURL)); + } + + private static String makeErrorMessageFromFailure(final String errorMessage, final String relaunchURL) { + return "Description de l'erreur : " + errorMessage + "

    " + "Lien de relance : " + relaunchURL + ""; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/emailing/templates/SuccessfulEmailTemplate.java b/kurt-utility/src/main/java/com/capgemini/reports/emailing/templates/SuccessfulEmailTemplate.java new file mode 100644 index 0000000..56f86a6 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/emailing/templates/SuccessfulEmailTemplate.java @@ -0,0 +1,59 @@ +package com.capgemini.reports.emailing.templates; + + +/** + * Represents a mail to warn the user that his report has successfully completed and may be retrieved. + */ +public class SuccessfulEmailTemplate extends AbstractEmailTemplate { + + private static final String SUCCESSFUL_FR = " terminé avec succès"; + private static final String TEMPLATE_LOCATION = "template_email_finished.html"; + + /** + * Represents a mail to warn the user that his report has successfully completed and may be retrieved. + * + * @param completeReportName String - the name of the report (e.g. R01 report "BOM Assemblage PU") + * @param postingTime String - the time at which this report was posted in the queues + * @param startTime String - the time at which this report's execution has started + * @param endTime String - the time at which this report was completed + * @param reportLocation String - the location at which the user may retrieve this report + */ + public SuccessfulEmailTemplate(final String completeReportName, final String postingTime, final String startTime, final String endTime, + final String reportLocation) { + super(completeReportName + SUCCESSFUL_FR); + assignParameters(completeReportName, postingTime, startTime, endTime, reportLocation); + } + + /** + * Represents a mail to warn the user that his SCHEDULED report has successfully completed and may be retrieved. + * + * @param completeReportName String - the name of the report (e.g. R01 report "BOM Assemblage PU") + * @param postingTime String - the time at which this report was posted in the queues + * @param startTime String - the time at which this report's execution has started + * @param endTime String - the time at which this report was completed + * @param reportLocation String - the location at which the user may retrieve this report + * @param schedulingName String - the scheduling mane of the SCHEDULED report + */ + public SuccessfulEmailTemplate(final String completeReportName, final String postingTime, final String startTime, final String endTime, + final String reportLocation, final String schedulingName) { + super(completeReportName + " - planification " + schedulingName + SUCCESSFUL_FR); + assignParameters(completeReportName, postingTime, startTime, endTime, reportLocation); + } + + private void assignParameters(final String completeReportName, final String postingTime, final String startTime, final String endTime, + final String reportLocation) { + String hyperLink = "" + reportLocation + ""; + + this.setTagValue(EmailTagEnum.POSTING_TIME, postingTime); + this.setTagValue(EmailTagEnum.REPORT_NAME, completeReportName); + this.setTagValue(EmailTagEnum.START_TIME, startTime); + this.setTagValue(EmailTagEnum.END_TIME, endTime); + this.setTagValue(EmailTagEnum.REPORT_LOCATION, hyperLink); + } + + @Override + protected String getEmailTemplate() { + return TEMPLATE_LOCATION; + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/exceptions/DuplicateReportEntryFound.java b/kurt-utility/src/main/java/com/capgemini/reports/exceptions/DuplicateReportEntryFound.java new file mode 100644 index 0000000..6ed193a --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/exceptions/DuplicateReportEntryFound.java @@ -0,0 +1,28 @@ +package com.capgemini.reports.exceptions; + +/** + * Exception used in the event of a report request received, that matches an already-waiting report.
    + * The former report is in this case not executed, and the user is directed to the latter report execution. + */ +public class DuplicateReportEntryFound extends InvalidUserInputException { + + private static final long serialVersionUID = -7724360531026615817L; + + /** + * Exception used in the event of a report request received, that matches an already-waiting report.
    + * Throw this exception if the user himself owns an identical execution request that predates this request. + */ + public DuplicateReportEntryFound() { + super(UserInputErrorEnum.DUPLICATE_REPORT_LAUNCHED_RECENTLY_BY_SELF); + } + + /** + * Exception used in the event of a report request received, that matches an already-waiting report.
    + * Throw this exception if an other user owns an identical execution request that predates this request. + * + * @param userName the user name of the person who requested the report again. + */ + public DuplicateReportEntryFound(final String userName) { + super(UserInputErrorEnum.DUPLICATE_REPORT_LAUNCHED_RECENTLY, userName); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/exceptions/DuplicateSchedulingEntryFound.java b/kurt-utility/src/main/java/com/capgemini/reports/exceptions/DuplicateSchedulingEntryFound.java new file mode 100644 index 0000000..efb2248 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/exceptions/DuplicateSchedulingEntryFound.java @@ -0,0 +1,33 @@ +package com.capgemini.reports.exceptions; + +/** + * Exception Thrown if two schedulings with the same name exist. + */ +public class DuplicateSchedulingEntryFound extends InvalidInputException { + + private static final long serialVersionUID = -7724360531026615817L; + + private final String messageToUser; + + /** + * Simple constructor. + * + * @param messageToUser a message for the user + */ + public DuplicateSchedulingEntryFound(final String messageToUser) { + super(UserInputErrorEnum.DUPLICATE_REPORT_LAUNCHED_RECENTLY_BY_SELF); + this.messageToUser = messageToUser; + } + + /** + * Returns the message to be sent to the user. + * + * @return the message + */ + @Override + public String getErrorMessageForUser() { + return messageToUser; + } + + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/exceptions/FileLoadingException.java b/kurt-utility/src/main/java/com/capgemini/reports/exceptions/FileLoadingException.java new file mode 100644 index 0000000..eefdc32 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/exceptions/FileLoadingException.java @@ -0,0 +1,32 @@ +package com.capgemini.reports.exceptions; + +import com.capgemini.framework.teamcenter.exceptions.KurtException; + +/** + * Exception générée lors d'une erreur d'ouverture / lecture de fichier. + * + */ +public class FileLoadingException extends KurtException { + + private static final long serialVersionUID = 5516185489090268051L; + + /** + * Constructor. + * + * @param aMessage Error message + */ + public FileLoadingException(String aMessage) { + super(aMessage); + } + + /** + * Constructor. + * + * @param aMessage Error message + * @param anException Original exception + */ + public FileLoadingException(String aMessage, Throwable anException) { + super(aMessage, anException); + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/exceptions/InsufficientParametersException.java b/kurt-utility/src/main/java/com/capgemini/reports/exceptions/InsufficientParametersException.java new file mode 100644 index 0000000..6370490 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/exceptions/InsufficientParametersException.java @@ -0,0 +1,32 @@ +package com.capgemini.reports.exceptions; + +import com.capgemini.framework.teamcenter.exceptions.KurtException; + +/** + * Exception générée lorsqu'il manque des paramètres à une requète. + * + */ +public class InsufficientParametersException extends KurtException { + + private static final long serialVersionUID = 148136358620949560L; + + /** + * Constructor. + * + * @param aMessage Error message + */ + public InsufficientParametersException(String aMessage) { + super(aMessage); + } + + /** + * Constructor. + * + * @param aMessage Error message + * @param anException Original exception + */ + public InsufficientParametersException(String aMessage, Throwable anException) { + super(aMessage, anException); + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/exceptions/InvalidActiveDirectoryInputException.java b/kurt-utility/src/main/java/com/capgemini/reports/exceptions/InvalidActiveDirectoryInputException.java new file mode 100644 index 0000000..850b08c --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/exceptions/InvalidActiveDirectoryInputException.java @@ -0,0 +1,19 @@ +package com.capgemini.reports.exceptions; + +import com.capgemini.framework.teamcenter.exceptions.KurtException; + +/** Custom error occurring when the search is rejected by the ActiveDirectory (search might be ill-formed). */ +public class InvalidActiveDirectoryInputException extends KurtException { + + private static final long serialVersionUID = -1697080676771636361L; + + /** + * Creates a custom {@link InvalidActiveDirectoryInputException} wrapper around an exception thrown by the ActiveDirectory. + * + * @param aMessage custom error message + * @param anException original exception + */ + public InvalidActiveDirectoryInputException(final String aMessage, final Throwable anException) { + super(aMessage, anException); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/exceptions/InvalidActiveDirectorySearchException.java b/kurt-utility/src/main/java/com/capgemini/reports/exceptions/InvalidActiveDirectorySearchException.java new file mode 100644 index 0000000..4dc2f94 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/exceptions/InvalidActiveDirectorySearchException.java @@ -0,0 +1,19 @@ +package com.capgemini.reports.exceptions; + +import com.capgemini.framework.teamcenter.exceptions.KurtException; + +/** Custom error occurring when the search is rejected by the ActiveDirectory (search might be ill-formed). */ +public class InvalidActiveDirectorySearchException extends KurtException { + + private static final long serialVersionUID = -1697080676771636361L; + + /** + * Creates a custom {@link InvalidActiveDirectorySearchException} wrapper around an exception thrown by the ActiveDirectory. + * + * @param aMessage custom error message + * @param anException original exception + */ + public InvalidActiveDirectorySearchException(final String aMessage, final Throwable anException) { + super(aMessage, anException); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/exceptions/InvalidCredentialsException.java b/kurt-utility/src/main/java/com/capgemini/reports/exceptions/InvalidCredentialsException.java new file mode 100644 index 0000000..e35d66b --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/exceptions/InvalidCredentialsException.java @@ -0,0 +1,32 @@ +package com.capgemini.reports.exceptions; + +import com.capgemini.framework.teamcenter.exceptions.KurtException; + +/** + * Représente les erreurs de login (username / mot de passe). + * + */ +public class InvalidCredentialsException extends KurtException { + + private static final long serialVersionUID = 1364013468727766676L; + + /** + * Constructor. + * + * @param aMessage Error message + */ + public InvalidCredentialsException(String aMessage) { + super(aMessage); + } + + /** + * Constructor. + * + * @param aMessage Error message + * @param anException Original exception + */ + public InvalidCredentialsException(String aMessage, Throwable anException) { + super(aMessage, anException); + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/exceptions/InvalidDatasetException.java b/kurt-utility/src/main/java/com/capgemini/reports/exceptions/InvalidDatasetException.java new file mode 100644 index 0000000..8c4e7db --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/exceptions/InvalidDatasetException.java @@ -0,0 +1,30 @@ +package com.capgemini.reports.exceptions; + +import com.capgemini.framework.teamcenter.exceptions.KurtException; + +/** Exception obtained when a Dataset could not be created because of invalid parameters. */ +public class InvalidDatasetException extends KurtException { + + private static final long serialVersionUID = 6936261014709390652L; + + /** + * Constructor. + * + * @param aMessage Error message + */ + public InvalidDatasetException(String aMessage) { + super(aMessage); + } + + /** + * Constructor. + * + * @param aMessage Error message + * @param anException Original exception + */ + public InvalidDatasetException(String aMessage, Throwable anException) { + super(aMessage, anException); + } + + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/exceptions/NoConnectionToActiveDirectoryException.java b/kurt-utility/src/main/java/com/capgemini/reports/exceptions/NoConnectionToActiveDirectoryException.java new file mode 100644 index 0000000..c451b82 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/exceptions/NoConnectionToActiveDirectoryException.java @@ -0,0 +1,29 @@ +package com.capgemini.reports.exceptions; + +import com.capgemini.framework.teamcenter.exceptions.KurtException; + +/** Custom error occurring when no connection could be set up to the ActiveDirectory (appli might not be in the same domain as AD?). */ +public class NoConnectionToActiveDirectoryException extends KurtException { + + private static final long serialVersionUID = 8900355250902392135L; + + /** + * Creates a custom {@link NoConnectionToActiveDirectoryException} wrapper around an exception thrown by the ActiveDirectory. + * + * @param aMessage custom error message + * @param anException original exception + */ + public NoConnectionToActiveDirectoryException(final String aMessage, final Throwable anException) { + super(aMessage, anException); + } + + + /** + * Creates a custom {@link NoConnectionToActiveDirectoryException} exception when Active Directory connection could not be made. + * + * @param aMessage custom error message + */ + public NoConnectionToActiveDirectoryException(final String aMessage) { + super(aMessage); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/exceptions/NothingToBeShownException.java b/kurt-utility/src/main/java/com/capgemini/reports/exceptions/NothingToBeShownException.java new file mode 100644 index 0000000..0202f88 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/exceptions/NothingToBeShownException.java @@ -0,0 +1,24 @@ +package com.capgemini.reports.exceptions; + +/** Exception thrown in HMI when there is no data to be shown. */ +public class NothingToBeShownException extends InvalidInputException { + + private static final long serialVersionUID = 6401523061302777316L; + + final String niceMessageForUser; + + /** + * Creates an instance. + * @param aTechnicalErrorMessage a technical error message for debugging + * @param userMessage a friendly user message for displaying + */ + public NothingToBeShownException(String aTechnicalErrorMessage, String userMessage) { + super(aTechnicalErrorMessage, UserInputErrorEnum.NOTHING_TO_BE_SHOWN); + this.niceMessageForUser = userMessage; + } + + public String getErrorMessageForUser() { + return niceMessageForUser; + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/exceptions/ReportPrintException.java b/kurt-utility/src/main/java/com/capgemini/reports/exceptions/ReportPrintException.java new file mode 100644 index 0000000..a94c8b6 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/exceptions/ReportPrintException.java @@ -0,0 +1,32 @@ +package com.capgemini.reports.exceptions; + +import com.capgemini.framework.teamcenter.exceptions.KurtException; + +/** + * Générée lorsqu'une impression ne s'est pas deroulee correctement. + * + */ +public class ReportPrintException extends KurtException { + + private static final long serialVersionUID = 1499768115472984402L; + + /** + * Constructor. + * + * @param aMessage Error message + */ + public ReportPrintException(String aMessage) { + super(aMessage); + } + + /** + * Constructor. + * + * @param aMessage Error message + * @param anException Original exception + */ + public ReportPrintException(String aMessage, Throwable anException) { + super(aMessage, anException); + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/execution/AbstractExecutionReport.java b/kurt-utility/src/main/java/com/capgemini/reports/execution/AbstractExecutionReport.java new file mode 100644 index 0000000..8a2b86f --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/execution/AbstractExecutionReport.java @@ -0,0 +1,348 @@ +package com.capgemini.reports.execution; + +import com.capgemini.framework.common.SettingsHelper; +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.reports.ReportEnum; +import com.capgemini.reports.ReportLaunchTypeEnum; +import com.capgemini.reports.builder.ReportBuilder; +import com.capgemini.reports.database.manager.MngCriteriaVal.CriteriaValue; +import com.capgemini.reports.execution.mapconstructor.IMapConstructor; +import com.capgemini.reports.execution.strategies.DelayedExecutionStrategy; +import com.capgemini.reports.execution.strategies.IExecutionStrategy; +import com.capgemini.reports.execution.strategies.ImmediateExecutionStrategy; +import com.capgemini.reports.execution.strategies.ScheduledExecutionStrategy; +import com.capgemini.reports.printing.PrintParameters; +import com.capgemini.reports.printing.Printer; +import com.capgemini.reports.printing.Printer.AvailablePrinter; +import com.capgemini.reports.printing.Printer.PrintFormat; +import com.capgemini.reports.queuing.ReportPriority; +import com.capgemini.reports.reports.parameters.IChecker; +import lombok.AccessLevel; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; +import net.lingala.zip4j.exception.ZipException; + +import java.io.Serializable; +import java.util.List; +import java.util.UUID; + +/** + * Abstract class for the execution of each report.
    + * The main method, {@link #doStart(TcSession)}, is called by the queuing system and executes (and prints) a report.
    + * It uses in that order the following objects for processing: + *

      + *
    1. Obtain the data from the Tc servers
    2. + *
    3. Create the template
    4. + *
    5. Printing
    6. + *
    + *

    + * If any of these steps fail, then a mail is Sent. + * + * @param Generic object about type of report + * @param A custom (POJO) object to carry data from the data preparator to the printer + */ +@Slf4j +@Getter +@Setter +@EqualsAndHashCode +public abstract class AbstractExecutionReport, U> implements Serializable { + // Configuration + protected static final String DEFAULT_REVISION_RULE = SettingsHelper.getDefaultRevisionRule(); + private static final long serialVersionUID = 5813503218626640137L; + private static final String LINE_BREAKER = "==========================================="; + protected final int priorityCode; + protected final String revisionRule; + protected String reportTechnicalUid = UUID.randomUUID().toString(); + // Scheduling parameters (default null if it is not a scheduling and it shoudn't be called). Setter is specifically added for both values + @Setter(value = AccessLevel.NONE) + protected String schedulingName; + @Setter(value = AccessLevel.NONE) + protected Long schedulingId; + @Getter(value = AccessLevel.NONE) + protected Boolean wkf = Boolean.FALSE; // By default, not launched by a WKF + // Times parameters + private String postingTime; + private String startTime; + @Setter(value = AccessLevel.NONE) + private String endTime; + @Setter(value = AccessLevel.NONE) + private String failureTime; + /** + * The strategy which defines immediate, delayed or scheduled behaviors during the execution of a report. Set up during constructor, but can be overwritten by scheduling servlet to force scheduling behaviour. + */ + private IExecutionStrategy executionStrategy; + + /** + * Constructor for DELAYEd / IMMEDIATE / SCHEDULED launches. + * + * @param priorityCode int - the priority code found in the reporting.properties file associated to a report. + * @param reportLaunchType the type of launch required.ccan be {@link ReportLaunchTypeEnum#IMMEDIATE} or {@link ReportLaunchTypeEnum#DELAYED} + */ + protected AbstractExecutionReport(final int priorityCode, final String revisionRule, final ReportLaunchTypeEnum reportLaunchType) { + this.priorityCode = priorityCode; + this.revisionRule = revisionRule; + switch (reportLaunchType) { + case DELAYED: + this.executionStrategy = new DelayedExecutionStrategy(); + break; + case IMMEDIATE: + this.executionStrategy = new ImmediateExecutionStrategy(); + break; + case SCHEDULED: + this.executionStrategy = new ScheduledExecutionStrategy(); + break; + default: + break; + } + } + + + /** + * Constructor for DELAYEd / IMMEDIATE / SCHEDULED launches. + * + * @param priorityCode int - the priority code found in the reporting.properties file associated to a report. + * @param reportLaunchType the type of launch required.ccan be {@link ReportLaunchTypeEnum#IMMEDIATE} or {@link ReportLaunchTypeEnum#DELAYED} + */ + + public AbstractExecutionReport (final int priorityCode, ReportLaunchTypeEnum reportLaunchType) { + this.priorityCode = priorityCode; + this.revisionRule = null; + switch (reportLaunchType) { + case DELAYED: + this.executionStrategy = new DelayedExecutionStrategy(); + break; + case IMMEDIATE: + this.executionStrategy = new ImmediateExecutionStrategy(); + break; + case SCHEDULED: + this.executionStrategy = new ScheduledExecutionStrategy(); + break; + default: + break; + } + } + + /* ******************************************/ + /* *************** EXECUTION ****************/ + /* ******************************************/ + + /** + * Defines the backbone of report creation.
    + *

      + * In order of execution: + *
    1. : Extracts all the raw data from Teamcenter
    2. + *
    3. {@link IMapConstructor#makeMasterTemplate(AbstractExecutionReport, Object) constructDataMaps}: Creates a {@link PrintParameters} objec
    4. + *
    5. {@link IMapConstructor#constructDataMaps(TcSession, PrintParameters, Object) constructDataMaps}: Filters and maps the data to some tokens from the report template
    6. + *
    7. Gives {@link PrintParameters} to that {@link Printer}
    8. + *
    9. {@link Printer#print(PrintParameters) Print}s the report
    10. + *
    + * Also, whenever any {@link KurtException} generated is caught here and will send an error email to the user. + *

    + * + * @param session the Teamcenter {@link com.capgemini.framework.teamcenter.authent.TcSession} used to perform the work. + * @throws KurtException something goes wrong internally (database not in line, problems in TC communication, problems in repor generation, etc.) + */ + public void doStart(final TcSession session) throws KurtException, ZipException { + @SuppressWarnings("unchecked") + T thisReport = (T) this; + + // Register the start of the report + log.info("Job started on: " + getReportIdentifier().buildCompleteReportName()); + + // Perform pre-execution steps + executionStrategy.preExecutionStep(thisReport, session); + + String fileNameWithExtension = getDataPreparator().print(session, thisReport, executionStrategy); + + // All the users who requested this report, at this time of the execution: END + executionStrategy.postExecutionStep(thisReport, fileNameWithExtension, session); + + log.info("Execution complete on: {}", this.getReportIdentifier().getReportTitle()); + } + + /** + * Fills the scheduling data in case this report was created from a scheduling template. + * + * @param schedulingId the Identifier of the scheduling + * @param schedulingName the name of the scheduling + */ + public void setScheduling(final Long schedulingId, final String schedulingName) { + this.schedulingId = schedulingId; + this.schedulingName = schedulingName; + } + + /** + * Get the data preparator.
    + * This object is responsible for recovering TC data and trnsforming it into report data. + * + * @return the {@link IDataReportPreparator} corresponding to the report + */ + public abstract IDataReportPreparator getDataPreparator(); + + /** + * Returns a list containing every {@link IChecker} used to verify report parameters BEFORE posting it to the queues. + * + * @return a {@link List}<{@link IChecker}> + */ + public abstract List getQuickChecks(); + + /** + * This method provides the {@link PolicyLocation} of the property policy to be used during the long checks. + * + * @return the location of the file as a String + */ + public abstract PolicyLocation getPropertyPolicyForLongChecks(); + + /** + * The identifier of the {@link PolicyLocation} for the resolution of nomenclature. + * + * @return identifier of the xml file + */ + public abstract PolicyLocation getFullPolicy(); + + /** + * Returns a list containing every {@link IChecker} used for to verify report parameters AFTER posting it to the queues, but BEFORE the full execution begins. + * + * @return a {@link List}<{@link IChecker}> + */ + public abstract List getLongChecks(); + + /* ******************************************/ + /* **************** PRINTING ****************/ + /* ******************************************/ + + /** + * Returns some Printer. + * + * @return the available printer + */ + public Printer getPrinter() { + return new Printer(AvailablePrinter.JASPER); + } + + /** + * Returns the report priority (to know which queue to join). + * + * @return a {@link ReportPriority} + */ + public ReportPriority getReportPriority() { + return ReportPriority.getReportPriority(priorityCode); + } + + /** + * Returns the location to the JASPER template file to be used. + * + * @return the path (within src/main/resources) + */ + public abstract String getTemplateLocation(); + + /* ======================================== */ + /* = REPORT IDENTIFIERS, NAMES AND TITLES = */ + /* ======================================== */ + + /** + * Returns the report identifier.
    + * Exemple with Report R01: "REPORT_R01". + * + * @return the report code + */ + public abstract ReportEnum getReportIdentifier(); + + /** + * Set true if this report has been launched by a workflow. + */ + public void isWkf() { + this.wkf = Boolean.TRUE; + } + + /* ================ */ + /* = PRINT PARAMS = */ + /* ================ */ + + /** + * Returns the file name required to save this report, as per the specifications. + * + * @return the file name + */ + public abstract String getSpecifiedFileName(); + + /** + * Returns the file name as it will be saved to disc locally. + * + * @return the file name + */ + public String getFileNameOnDisc() { + return getSpecifiedFileName() + "_" + reportTechnicalUid; + } + + /** + * Returns a structure of print parameters, initialised with the required output format for the report (xlsx, .pdf etc). + * + * @return some {@link PrintParameters} + */ + public abstract PrintFormat getPrintingFormat(); + + /** + * Prepare criteria values list of report. + * + * @return a {@link List} of every {@link CriteriaValue}. + */ + public abstract List getLaunchData(); + + /** + * Returns the name of a {@link ReportBuilder} implementation that is able to instantiate a report of the right type. + * + * @return the full class name + */ + public final String getReportBuilderClassName() { + Class builderClass = getReportBuilderClass(); + return builderClass.getName(); + } + + /** + * Returns the {@link Class} of a {@link ReportBuilder} implementation that is able to instantiate a report of the right type. + * + * @return the Class object. Must have a no-args constructor + */ + public abstract Class getReportBuilderClass(); + + /** + * Sets the time at which this report execution failed. + * + * @param aFailure the Time at which it failed as a String + */ + public void setFailureTime(final String aFailure) { + this.failureTime = aFailure; + } + + /** + * Sets the time at which this report execution completed. + * + * @param aEndtime the Time at which it failed as a String + */ + public void setEndTime(final String aEndtime) { + this.endTime = aEndtime; + } + + /** + * Clone a report execution from a scheduling template.
    + * Give him all the same criteria but a different uid. Also, reset the default launch type. + * + * @return the cloned report + */ + public abstract AbstractExecutionReport cloneTemplateToExecution(); + + /** + * Returns the {@link ReportLaunchTypeEnum} planned for this report. + * + * @return the {@link ReportLaunchTypeEnum} + */ + public final ReportLaunchTypeEnum getLaunchType() { + return getExecutionStrategy().getLaunchType(); + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/execution/IDataReportPreparator.java b/kurt-utility/src/main/java/com/capgemini/reports/execution/IDataReportPreparator.java new file mode 100644 index 0000000..9b1ed01 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/execution/IDataReportPreparator.java @@ -0,0 +1,31 @@ +package com.capgemini.reports.execution; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.reports.execution.strategies.IExecutionStrategy; +import net.lingala.zip4j.exception.ZipException; + +import java.io.Serializable; + +/** + * This interface will allow to prepare data for the reports. + * + * @param The type of the report this is preparing data for + */ +public interface IDataReportPreparator extends Serializable { + + /** + * Message to display execution time. + */ + String EXECUTION_TIME_XXX_MS_FOR_YYY = "Execution time : {} ms for {}"; + + /** + * Print the data by extracting it from Teamcenter. + * + * @param session + * @param execution will provide the report which is executing + * @param executionStrategy + * @throws KurtException when an internal error occurred + */ + String print(TcSession session, T execution, IExecutionStrategy executionStrategy) throws KurtException, ZipException; +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/AbstractPostExecutionStep.java b/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/AbstractPostExecutionStep.java new file mode 100644 index 0000000..d6e9f69 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/AbstractPostExecutionStep.java @@ -0,0 +1,57 @@ +package com.capgemini.reports.execution.actions; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.reports.database.javabean.DbReport; +import com.capgemini.reports.exceptions.InvalidUserInputException; +import com.capgemini.reports.execution.AbstractExecutionReport; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; +import lombok.Getter; + +/** + * This abstract class makes it easy do define a report-specific action, with strong typing.
    + * Intercepts the default (weakly-typed)
    + * {@link IPostExecutionStep#performPostAction(TcSession, AbstractExecutionReport, DbReport, String) performPostAction}
    + * And forwards it to this class's (strongly-typed)
    + * {@link AbstractPostExecutionStep#performPostActionOnReport(TcSession, AbstractExecutionReport, DbReport, String)} + * + * @param the exact report type + * @param Return type. Use {@link Void} for nothing. + */ +@AllArgsConstructor +@EqualsAndHashCode +public abstract class AbstractPostExecutionStep, R> implements IPostExecutionStep { + private static final long serialVersionUID = -1817048657143927445L; + + @Getter(value = AccessLevel.PROTECTED) + private final Class reportClass; + + @Override + public > void performPostAction(TcSession session, K reportRaw, DbReport theExecutingReport, + String fileNameWithExtension) throws KurtException { + try { + T report = reportClass.cast(reportRaw); + performPostActionOnReport(session, report, theExecutingReport, fileNameWithExtension); + } catch (ClassCastException e) { + throw new KurtException( + "Unable to perform Specialized action because input report is not of the right type, UID=" + reportRaw.getReportTechnicalUid(), + e); + } + } + + /** + * Performs a specific action on a particular report type to perform after the report execution. + * + * @param session a Teamcenter session (active) + * @param reportRaw the report which has just finished printing + * @param dbReport the Db object + * @param fileNameWithExtension the filename of the report (includes extension) + * @throws KurtException anything that happens must be a {@link KurtException} so it can be caught and dealt with appropriately.
    + * Particularly, if the error is a functional error, do throw an {@link InvalidUserInputException} + */ + protected abstract R performPostActionOnReport(TcSession session, T reportRaw, DbReport dbReport, + String fileNameWithExtension) throws KurtException; + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/AbstractPreExecutionStep.java b/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/AbstractPreExecutionStep.java new file mode 100644 index 0000000..de56da3 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/AbstractPreExecutionStep.java @@ -0,0 +1,53 @@ +package com.capgemini.reports.execution.actions; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.reports.database.javabean.DbReport; +import com.capgemini.reports.exceptions.InvalidUserInputException; +import com.capgemini.reports.execution.AbstractExecutionReport; +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; + +/** + * This abstract class makes it easy do define a report-specific action, with strong typing.
    + * Intercepts the default (weakly-typed)
    + * {@link IPreExecutionStep#performPreAction(AbstractExecutionReport, DbReport, TcSession) performPreAction}
    + * And forwards it to this class's (strongly-typed)
    + * {@link AbstractPreExecutionStep#performPreActionOnReport(AbstractExecutionReport, DbReport, TcSession) performPreActionOnReport} + * @param the exact report type + */ +@AllArgsConstructor +@EqualsAndHashCode +public abstract class AbstractPreExecutionStep> implements IPreExecutionStep { + + private static final long serialVersionUID = -1516821856454786852L; + + private final Class reportClass; + + @Override + public > void performPreAction(K reportRaw, DbReport dbReport, TcSession session) + throws KurtException { + try { + T report = reportClass.cast(reportRaw); + performPreActionOnReport(report, dbReport, session); + } catch (ClassCastException e) { + throw new KurtException( + "Unable to perform Specialized action because input report is not of the right type, UID=" + reportRaw.getReportTechnicalUid(), + e); + } + } + + /** + * Performs a specific action on a particular report type before the report execution. + * + * @param reportRaw + * @param dbReport the report which has just finished printing + * @param session + * + * @throws KurtException anything that happens must be a {@link KurtException} so it can be caught and dealt with appropriately.
    + * Particularly, if the error is a functional error, do throw an {@link InvalidUserInputException} + */ + protected abstract void performPreActionOnReport(T reportRaw, DbReport dbReport, TcSession session) throws KurtException; + +} + diff --git a/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/CompositeErrorAction.java b/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/CompositeErrorAction.java new file mode 100644 index 0000000..88be028 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/CompositeErrorAction.java @@ -0,0 +1,53 @@ +package com.capgemini.reports.execution.actions; + +import com.capgemini.reports.database.javabean.DbUser; +import com.capgemini.reports.exceptions.InvalidInputException; +import com.capgemini.reports.exceptions.NoConfChangesException; +import com.capgemini.reports.execution.AbstractExecutionReport; +import lombok.EqualsAndHashCode; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * If you need to perform several {@link IErrorExecutionStep}s, use this class to execute them orderly. + */ +@EqualsAndHashCode +public class CompositeErrorAction implements IErrorExecutionStep { + + private static final long serialVersionUID = -7228217924123134048L; + + private final List actions = new ArrayList<>(); + + /** + * Creates a composite error handler, capable of executing several actions in series. + * + * @param inputActions the actions to be carried out sequentially. + */ + public CompositeErrorAction(IErrorExecutionStep... inputActions) { + Collections.addAll(this.actions, inputActions); + } + + @Override + public void performFunctionalErrorAction(AbstractExecutionReport report, List owners, NoConfChangesException theOrginalException) { + for (IErrorExecutionStep action : actions) { + action.performFunctionalErrorAction(report, owners, theOrginalException); + } + } + + @Override + public void performFunctionalErrorAction(AbstractExecutionReport report, List owners, InvalidInputException theOrginalException) { + for (IErrorExecutionStep action : actions) { + action.performFunctionalErrorAction(report, owners, theOrginalException); + } + } + + @Override + public void performTechnicalErrorAction(AbstractExecutionReport report, List owners, Throwable theOrginalException) { + for (IErrorExecutionStep action : actions) { + action.performTechnicalErrorAction(report, owners, theOrginalException); + } + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/CompositePostAction.java b/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/CompositePostAction.java new file mode 100644 index 0000000..f23ecbb --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/CompositePostAction.java @@ -0,0 +1,40 @@ +package com.capgemini.reports.execution.actions; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.reports.database.javabean.DbReport; +import com.capgemini.reports.execution.AbstractExecutionReport; +import lombok.EqualsAndHashCode; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * If you need to perform several {@link IPostExecutionStep}s, use this class to execute them orderly. + */ +@EqualsAndHashCode +public class CompositePostAction implements IPostExecutionStep { + + private static final long serialVersionUID = -7228217924123134048L; + + private final List actions; + + /** + * Creates a composite post execution action, capable of executing several actions in series. + * + * @param inputActions the actions to be carried out sequentially. + */ + public CompositePostAction(IPostExecutionStep... inputActions) { + this.actions = new ArrayList<>(); + Collections.addAll(this.actions, inputActions); + } + + @Override + public > void performPostAction(TcSession session, T report, DbReport theExecutingReport, + String fileNameWithExtension) throws KurtException { + for (IPostExecutionStep iPostExecutionStep : actions) { + iPostExecutionStep.performPostAction(session, report, theExecutingReport, fileNameWithExtension); + } + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/CompositePreAction.java b/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/CompositePreAction.java new file mode 100644 index 0000000..7669937 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/CompositePreAction.java @@ -0,0 +1,38 @@ +package com.capgemini.reports.execution.actions; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.reports.database.javabean.DbReport; +import com.capgemini.reports.execution.AbstractExecutionReport; +import lombok.EqualsAndHashCode; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** If you need to perform several {@link IPreExecutionStep}s, use this class to execute them orderly. */ +@EqualsAndHashCode +public class CompositePreAction implements IPreExecutionStep { + + private static final long serialVersionUID = -7228217924123134048L; + + private final List actions; + + /** + * Creates a composite pre execution action, capable of executing several actions in series. + * + * @param inputActions the actions to be carried out sequentially. + */ + public CompositePreAction(IPreExecutionStep... inputActions) { + this.actions = new ArrayList<>(); + Collections.addAll(this.actions, inputActions); + } + + @Override + public > void performPreAction(T abstractExecutionReport, DbReport dbReport, TcSession session) + throws KurtException { + for (IPreExecutionStep iPostExecutionStep : actions) { + iPostExecutionStep.performPreAction(abstractExecutionReport, dbReport, session); + } + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/DoNothingAction.java b/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/DoNothingAction.java new file mode 100644 index 0000000..15d6fd8 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/DoNothingAction.java @@ -0,0 +1,48 @@ +package com.capgemini.reports.execution.actions; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.reports.database.javabean.DbReport; +import com.capgemini.reports.database.javabean.DbUser; +import com.capgemini.reports.exceptions.InvalidDatasetException; +import com.capgemini.reports.exceptions.InvalidInputException; +import com.capgemini.reports.exceptions.NoConfChangesException; +import com.capgemini.reports.exceptions.NotFoundException; +import com.capgemini.reports.execution.AbstractExecutionReport; +import lombok.EqualsAndHashCode; + +import java.util.List; + +/** + * This action does nothing. Useful if an action Object is required by an API, but nothing needs to be done.
    + * Can be used as a {@link IPreExecutionStep}, a {@link IPostExecutionStep}, and/or a {@link IErrorExecutionStep}. + */ +@EqualsAndHashCode +public class DoNothingAction implements IPreExecutionStep, IPostExecutionStep, IErrorExecutionStep { + private static final long serialVersionUID = 8222229264738863306L; + + @Override + public > void performPreAction(T abstractExecutionReport, DbReport dbReport, TcSession session) { + // Let's happily do nothing at all, here. Yay! + } + + @Override + public > void performPostAction(TcSession session, T report, DbReport theExecutingReport, + String fileNameWithExtension) throws NotFoundException, InvalidDatasetException { + // Let's happily do nothing at all, here. Yay! + } + + @Override + public void performTechnicalErrorAction(AbstractExecutionReport report, List owners, Throwable theOrginalException) { + // Let's happily do nothing at all, here. Yay! + } + + @Override + public void performFunctionalErrorAction(AbstractExecutionReport report, List owners, NoConfChangesException theOriginalException) { + // Let's happily do nothing at all, here. Yay! + } + + @Override + public void performFunctionalErrorAction(AbstractExecutionReport report, List owners, InvalidInputException theOriginalException) { + // Let's happily do nothing at all, here. Yay! + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/IErrorExecutionStep.java b/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/IErrorExecutionStep.java new file mode 100644 index 0000000..5a7e5d8 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/IErrorExecutionStep.java @@ -0,0 +1,41 @@ +package com.capgemini.reports.execution.actions; + +import com.capgemini.reports.database.javabean.DbUser; +import com.capgemini.reports.exceptions.InvalidInputException; +import com.capgemini.reports.exceptions.NoConfChangesException; +import com.capgemini.reports.execution.AbstractExecutionReport; + +import java.io.Serializable; +import java.util.List; + +/** Interface for ations to be taken in case of functional/technical error encountered during a report execution. */ +public interface IErrorExecutionStep extends Serializable { + + /** + * Action to be performed in case of Technical error.
    + * Note these actions may never fail, please do catch and handle any exception. + * + * @param report the report whose execution failed + * @param owners the owners of the failed report + */ + void performTechnicalErrorAction(AbstractExecutionReport report, List owners, Throwable theOriginalException); + + /** + * Action to be performed in case of Functional error.
    + * Note these actions may never fail, please do catch and handle any exception. + * + * @param report the report whose execution failed + * @param owners the owners of the failed report + * @param theOriginalException the exception that cause mayhem + */ + void performFunctionalErrorAction(AbstractExecutionReport report, List owners, NoConfChangesException theOriginalException); + + /** + * Action to be performed in case of Functional error.
    + * Note these actions may never fail, please do catch and handle any exception. + * @param report the report whose execution failed + * @param owners the owners of the failed report + * @param theOriginalException the exception that cause mayhem + */ + void performFunctionalErrorAction(AbstractExecutionReport report, List owners, InvalidInputException theOriginalException); +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/IPostExecutionStep.java b/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/IPostExecutionStep.java new file mode 100644 index 0000000..c558442 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/IPostExecutionStep.java @@ -0,0 +1,30 @@ +package com.capgemini.reports.execution.actions; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.reports.database.javabean.DbReport; +import com.capgemini.reports.exceptions.InvalidUserInputException; +import com.capgemini.reports.execution.AbstractExecutionReport; + +import java.io.Serializable; + +/** + * Interface for an action to be taken after a report has been printed. + */ +public interface IPostExecutionStep extends Serializable { + + /** + * The action to perform after the report execution. + * + * @param the type of report which failed + * @param session a Teamcenter session (active) + * @param report the report which has just finished printing + * @param dbReport the Db object + * @param fileNameWithExtension the filename of the report (includes extension) + * @throws KurtException anything that happens must be a {@link KurtException} so it can be caught and dealt with appropriately.
    + * Particularly, if the error is a functional error, do throw an {@link InvalidUserInputException} + */ + > void performPostAction(TcSession session, T report, DbReport dbReport, + String fileNameWithExtension) throws KurtException; + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/IPreExecutionStep.java b/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/IPreExecutionStep.java new file mode 100644 index 0000000..3b899b2 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/IPreExecutionStep.java @@ -0,0 +1,26 @@ +package com.capgemini.reports.execution.actions; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.reports.database.javabean.DbReport; +import com.capgemini.reports.exceptions.InvalidUserInputException; +import com.capgemini.reports.execution.AbstractExecutionReport; + +import java.io.Serializable; + +/** Interface for an action to be taken right before a report begins its execution. */ +public interface IPreExecutionStep extends Serializable { + + /** + * The action to perform before the report execution. + * + * @param session a Teamcenter session (active) + * @param report the report which has just finished printing + * @param dbReport the Db object + * @param the type of report which failed + * @throws KurtException anything that happens must be a {@link KurtException} so it can be caught and dealt with appropriately.
    + * Particularly, if the error is a functional error, do throw an {@link InvalidUserInputException} + */ + > void performPreAction(T report, DbReport dbReport, TcSession session) throws KurtException; + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/InteractiveEmailAction.java b/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/InteractiveEmailAction.java new file mode 100644 index 0000000..11d5eab --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/InteractiveEmailAction.java @@ -0,0 +1,58 @@ +package com.capgemini.reports.execution.actions; + +import com.capgemini.framework.common.SettingsHelper; +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.reports.database.HibernateUtil; +import com.capgemini.reports.database.javabean.DbReport; +import com.capgemini.reports.database.javabean.DbUser; +import com.capgemini.reports.database.manager.MngUser; +import com.capgemini.reports.emailing.templates.EmailReportHelper; +import com.capgemini.reports.exceptions.InvalidInputException; +import com.capgemini.reports.exceptions.NoConfChangesException; +import com.capgemini.reports.exceptions.NotFoundException; +import com.capgemini.reports.execution.AbstractExecutionReport; +import org.hibernate.Session; +import org.hibernate.SessionFactory; + +import java.util.List; + +/** + * This action sends the typical email when normal reports begin execution, end their execution, or fail. + */ +public class InteractiveEmailAction implements IPostExecutionStep, IErrorExecutionStep { + private static final long serialVersionUID = -2216273173886557249L; + + private static final String DOWNLOAD_URL_SERVLET = "kurt-web/downloadServlet?reportUid="; + private static final String DOWNLOAD_URL_ROOT = SettingsHelper.getDownloadUrlRoot(); + private static final String INTERNAL_ERROR_MESSAGE = "An internal error occurred while performing the report
    "; + + @Override + public > void performPostAction(TcSession tcSession, T report, DbReport dbReport, String fileNameWithExtension) throws NotFoundException { + // All the users who requested this report, at this time of the execution: END + SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); + Session session = sessionFactory.openSession(); + try { + List ownersAtReportEnd = new MngUser().searchReportOwners(session, dbReport); + EmailReportHelper.sendEndEmail(DOWNLOAD_URL_ROOT + DOWNLOAD_URL_SERVLET + dbReport.getReportUid(), report, ownersAtReportEnd); + } + finally { + session.close(); + } + } + + @Override + public void performTechnicalErrorAction(AbstractExecutionReport report, List owners, Throwable theOriginalException) { + EmailReportHelper.sendErrorEmail(INTERNAL_ERROR_MESSAGE, report, owners); + EmailReportHelper.sendErrorEmailToAdminsReport(INTERNAL_ERROR_MESSAGE, report); + } + + @Override + public void performFunctionalErrorAction(AbstractExecutionReport report, List owners, NoConfChangesException theOriginalException) { + // Nothing to do in this case + } + + @Override + public void performFunctionalErrorAction(AbstractExecutionReport report, List owners, InvalidInputException theOriginalException) { + EmailReportHelper.sendErrorEmail(theOriginalException.getErrorMessageForUser(), report, owners); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/LoggingAction.java b/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/LoggingAction.java new file mode 100644 index 0000000..5e778e2 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/LoggingAction.java @@ -0,0 +1,48 @@ +package com.capgemini.reports.execution.actions; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.reports.database.javabean.DbReport; +import com.capgemini.reports.database.javabean.DbUser; +import com.capgemini.reports.exceptions.InvalidInputException; +import com.capgemini.reports.exceptions.NoConfChangesException; +import com.capgemini.reports.execution.AbstractExecutionReport; +import com.capgemini.reports.logging.ReportLoggerHelper; +import lombok.EqualsAndHashCode; + +import java.util.List; + +/** + * Logs typical report events (begin/end/error) to a special Logger setup in JBoss (using {@link ReportLoggerHelper}). + */ +@EqualsAndHashCode +public class LoggingAction implements IPostExecutionStep, IPreExecutionStep, IErrorExecutionStep { + + private static final long serialVersionUID = -2216273173886557249L; + + @Override + public > void performPreAction(T report, DbReport dbReport, TcSession session) { + // Log this event in the events log + ReportLoggerHelper.logStart(dbReport, report); + } + + @Override + public > void performPostAction(TcSession session, T report, DbReport dbReport, + String fileNameWithExtension) { + ReportLoggerHelper.logCompletion(dbReport, fileNameWithExtension, report); + } + + @Override + public void performTechnicalErrorAction(AbstractExecutionReport report, List owners, Throwable theOrginalException) { + ReportLoggerHelper.logError(theOrginalException.getMessage(), theOrginalException, report); + } + + @Override + public void performFunctionalErrorAction(AbstractExecutionReport report, List owners, NoConfChangesException theOrginalException) { + ReportLoggerHelper.logError(theOrginalException.getMessage(), theOrginalException, report); + } + + @Override + public void performFunctionalErrorAction(AbstractExecutionReport report, List owners, InvalidInputException theOrginalException) { + ReportLoggerHelper.logError(theOrginalException.getMessage(), theOrginalException, report); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/QuickCheckAction.java b/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/QuickCheckAction.java new file mode 100644 index 0000000..9286461 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/QuickCheckAction.java @@ -0,0 +1,28 @@ +package com.capgemini.reports.execution.actions; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.reports.checkdata.CheckingDataHelper; +import com.capgemini.reports.database.javabean.DbReport; +import com.capgemini.reports.exceptions.FileLoadingException; +import com.capgemini.reports.exceptions.InvalidUserInputException; +import com.capgemini.reports.execution.AbstractExecutionReport; +import lombok.EqualsAndHashCode; +import lombok.extern.slf4j.Slf4j; + +/** This class is an {@link IPreExecutionStep} which performs 'quick checks' on a report. */ +@Slf4j +@EqualsAndHashCode +public class QuickCheckAction implements IPreExecutionStep { + + private static final long serialVersionUID = 8658242340621050777L; + + @Override + public > void performPreAction(T report, DbReport dbReport, TcSession session) + throws InvalidUserInputException, FileLoadingException { + // Do a quick Check. If it fails, the exception thrown will interrupt this execution + log.debug("Beggining quick checks of the scheduled {} report {}.", report.getReportIdentifier().getReportCode(), + report.getReportTechnicalUid()); + CheckingDataHelper.doQuickCheck(session, report); + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/ReLaunchEmailAction.java b/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/ReLaunchEmailAction.java new file mode 100644 index 0000000..b9e04d7 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/ReLaunchEmailAction.java @@ -0,0 +1,55 @@ +package com.capgemini.reports.execution.actions; + +import com.capgemini.framework.common.activedirectory.ActiveDirectory; +import com.capgemini.reports.database.javabean.DbUser; +import com.capgemini.reports.emailing.templates.EmailReportHelper; +import com.capgemini.reports.exceptions.InvalidInputException; +import com.capgemini.reports.exceptions.NoConfChangesException; +import com.capgemini.reports.execution.AbstractExecutionReport; +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; +import lombok.extern.slf4j.Slf4j; + +import java.util.List; + +/** An {@link IErrorExecutionStep} that sends an email containing a link for re-launching the report. */ +@Slf4j +@AllArgsConstructor +@EqualsAndHashCode +public class ReLaunchEmailAction implements IErrorExecutionStep { + + private static final long serialVersionUID = 4317516668621824636L; + + private static final String INTERNAL_ERROR_MESSAGE = "An internal error occurred while performing the report
    "; + + private final String requestURL; + + @Override + public void performTechnicalErrorAction(final AbstractExecutionReport report, List owners, Throwable theOrginalException) { + EmailReportHelper.sendWorkflowErrorEmail(INTERNAL_ERROR_MESSAGE, report, owners, requestURL); + + // Send email to all admins report + List adminReports = ActiveDirectory.getAdminsReportUpdateDatabase(); + + if (adminReports == null || adminReports.isEmpty()) { + log.error("The request for recovery of the admins report from active directory of SNECMA has returned nothing, on fail {} ", + report.getReportIdentifier()); + } else { + EmailReportHelper.sendWorkflowErrorEmailToAdminsReport(INTERNAL_ERROR_MESSAGE, report, adminReports, requestURL); + } + } + + @Override + public void performFunctionalErrorAction(AbstractExecutionReport report, List owners, NoConfChangesException theOriginalException) { + // This is a workflow execution, there are no 'functional' errors. + // Forward email handling to Technical error handler: + performTechnicalErrorAction(report, owners, theOriginalException); + } + + @Override + public void performFunctionalErrorAction(AbstractExecutionReport report, List owners, InvalidInputException theOriginalException) { + // This is a workflow execution, there are no 'functional' errors. + // Forward email handling to Technical error handler: + performTechnicalErrorAction(report, owners, theOriginalException); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/ScheduledEmailAction.java b/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/ScheduledEmailAction.java new file mode 100644 index 0000000..943dcc9 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/ScheduledEmailAction.java @@ -0,0 +1,49 @@ +package com.capgemini.reports.execution.actions; + +import com.capgemini.framework.common.SettingsHelper; +import com.capgemini.framework.common.activedirectory.ActiveDirectory; +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.reports.database.javabean.DbReport; +import com.capgemini.reports.database.javabean.DbUser; +import com.capgemini.reports.emailing.templates.EmailReportHelper; +import com.capgemini.reports.exceptions.InvalidInputException; +import com.capgemini.reports.exceptions.NoConfChangesException; +import com.capgemini.reports.execution.AbstractExecutionReport; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +/** + * This action is similar to {@link InteractiveEmailAction}, but for scheduled reports, where mail title etc. are slightly different.
    + * PArticularly, owners of a report are not considered, the emails are sent to the administrators. + */ +public class ScheduledEmailAction implements IPostExecutionStep, IErrorExecutionStep { + private static final long serialVersionUID = -2216273173886557249L; + + private static final Logger LOGGER = LoggerFactory.getLogger(ScheduledEmailAction.class); + private static final String INTERNAL_ERROR_MESSAGE = "An internal error occurred while performing the report
    "; + + @Override + public > void performPostAction(TcSession session, T report, DbReport dbReport, String fileNameWithExtension) { + String downloadURLroot = SettingsHelper.getDownloadUrlRoot(); + List ownersAtReportEnd = ActiveDirectory.getAdminsReportUpdateDatabase(); + EmailReportHelper.sendScheduledEndEmail(downloadURLroot + "kurt-web/downloadServlet?reportUid=" + report.getReportTechnicalUid(), report, ownersAtReportEnd, report.getSchedulingName()); + } + + @Override + public void performTechnicalErrorAction(AbstractExecutionReport report, List owners, Throwable theOriginalException) { + LOGGER.error("A Technical error occured", theOriginalException); + EmailReportHelper.sendScheduledErrorEmailToAdminsReport(INTERNAL_ERROR_MESSAGE, report); + } + + @Override + public void performFunctionalErrorAction(AbstractExecutionReport report, List owners, NoConfChangesException theOriginalException) { + // Nothing to do in this case + } + + @Override + public void performFunctionalErrorAction(AbstractExecutionReport report, List owners, InvalidInputException theOriginalException) { + EmailReportHelper.sendScheduledErrorEmail(theOriginalException.getErrorMessageForUser(), report, owners); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/UpdateReportAction.java b/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/UpdateReportAction.java new file mode 100644 index 0000000..836b815 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/UpdateReportAction.java @@ -0,0 +1,52 @@ +package com.capgemini.reports.execution.actions; + +import com.capgemini.framework.common.TeamcenterDateFormatter; +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.reports.database.javabean.DbReport; +import com.capgemini.reports.database.javabean.DbUser; +import com.capgemini.reports.exceptions.InvalidInputException; +import com.capgemini.reports.exceptions.NoConfChangesException; +import com.capgemini.reports.execution.AbstractExecutionReport; +import lombok.EqualsAndHashCode; + +import java.util.List; + +/** + * This action updates the {@link AbstractExecutionReport}'s internal state (primarily event times) according to events on the report lifecycle. + */ +@EqualsAndHashCode +public class UpdateReportAction implements IPreExecutionStep, IPostExecutionStep, IErrorExecutionStep { + + private static final long serialVersionUID = -5967051491832029054L; + + @Override + public > void performPreAction(T abstractExecutionReport, DbReport dbReport, TcSession session) { + // Register current time as the posting time + abstractExecutionReport.setStartTime(TeamcenterDateFormatter.getCurrentTime()); + } + + @Override + public > void performPostAction(TcSession session, T report, DbReport theExecutingReport, + String fileNameWithExtension) { + // Register current time as the end time + report.setEndTime(TeamcenterDateFormatter.getCurrentTime()); + } + + @Override + public void performTechnicalErrorAction(AbstractExecutionReport report, List owners, Throwable theOriginalException) { + // Register current time as the failure time + report.setFailureTime(TeamcenterDateFormatter.getCurrentTime()); + } + + @Override + public void performFunctionalErrorAction(AbstractExecutionReport report, List owners, NoConfChangesException theOriginalException) { + // Register current time as the failure time + report.setFailureTime(TeamcenterDateFormatter.getCurrentTime()); + } + + @Override + public void performFunctionalErrorAction(AbstractExecutionReport report, List owners, InvalidInputException theOriginalException) { + // Register current time as the failure time + report.setFailureTime(TeamcenterDateFormatter.getCurrentTime()); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/UpdateReportInDbAction.java b/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/UpdateReportInDbAction.java new file mode 100644 index 0000000..7cb9065 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/UpdateReportInDbAction.java @@ -0,0 +1,59 @@ +package com.capgemini.reports.execution.actions; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.reports.database.DataBaseReportHelper; +import com.capgemini.reports.database.javabean.DbReport; +import com.capgemini.reports.database.javabean.DbUser; +import com.capgemini.reports.database.javabean.enumeration.ReportErrorTypeEnum; +import com.capgemini.reports.database.manager.MngReport; +import com.capgemini.reports.exceptions.InvalidInputException; +import com.capgemini.reports.exceptions.NoConfChangesException; +import com.capgemini.reports.exceptions.NotFoundException; +import com.capgemini.reports.execution.AbstractExecutionReport; +import lombok.EqualsAndHashCode; + +import java.util.List; + +/** + * This class manages typical interaction with DB during a report lifecycle.
    + * Can be used for: + *

      + *
    • Before executing the report: set the state as STARTED & register the report start generation date in DB
    • + *
    • After executing the report: set the state as FINISHED & register the report end generation date in DB, as well as its filename
    • + *
    • When an error occurs during execution: set the state as FAILED & register the report failure date in DB, as well as failure message
    • + *
    + */ +@EqualsAndHashCode +public class UpdateReportInDbAction implements IPreExecutionStep, IPostExecutionStep, IErrorExecutionStep { + + private static final long serialVersionUID = -5967051491832029054L; + + @Override + public > void performPreAction(T report, DbReport dbReport, TcSession session) + throws NotFoundException { + DataBaseReportHelper.registerStart(new MngReport(), report.getReportTechnicalUid()); + } + + @Override + public > void performPostAction(TcSession session, T report, DbReport theExecutingReport, + String fileNameWithExtension) throws KurtException { + MngReport theReportManager = new MngReport(); + DataBaseReportHelper.registerCompletion(theExecutingReport, fileNameWithExtension, theReportManager); + } + + @Override + public void performTechnicalErrorAction(AbstractExecutionReport report, List owners, Throwable theOriginalException) { + DataBaseReportHelper.registerError(theOriginalException.getMessage(), ReportErrorTypeEnum.TECHNICAL, report.getReportTechnicalUid()); + } + + @Override + public void performFunctionalErrorAction(AbstractExecutionReport report, List owners, NoConfChangesException theOriginalException) { + DataBaseReportHelper.registerError(theOriginalException.getMessage(), ReportErrorTypeEnum.FUNCTIONAL, report.getReportTechnicalUid()); + } + + @Override + public void performFunctionalErrorAction(AbstractExecutionReport report, List owners, InvalidInputException theOriginalException) { + DataBaseReportHelper.registerError(theOriginalException.getMessage(), ReportErrorTypeEnum.FUNCTIONAL, report.getReportTechnicalUid()); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/ondataset/CreateDatasetAction.java b/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/ondataset/CreateDatasetAction.java new file mode 100644 index 0000000..39dc8e8 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/ondataset/CreateDatasetAction.java @@ -0,0 +1,92 @@ +package com.capgemini.reports.execution.actions.ondataset; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.ConnectionMisconguredException; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.exceptions.MalformedDataSetException; +import com.capgemini.framework.teamcenter.files.FileManagement; +import com.capgemini.framework.teamcenter.files.FileManagement.FileType; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.reports.database.javabean.DbReport; +import com.capgemini.reports.exceptions.InvalidDatasetException; +import com.capgemini.reports.execution.AbstractExecutionReport; +import com.capgemini.reports.execution.actions.AbstractPostExecutionStep; +import com.teamcenter.services.loose.core._2006_03.FileManagement.GetDatasetWriteTicketsInputData; +import lombok.EqualsAndHashCode; +import lombok.extern.slf4j.Slf4j; + +import javax.inject.Provider; +import java.io.File; +import java.io.Serializable; + +/** + * This class is an action of creating a dataset, and can be performed automatically upon a report execution completion. + * + * @param the Class of the caller report + */ +@Slf4j +@EqualsAndHashCode(callSuper = true) +public class CreateDatasetAction> extends AbstractPostExecutionStep { + + private static final long serialVersionUID = -1516821856454786852L; + + private static final PolicyLocation POLICY_XML_DATASET = PolicyLocation.make("policy_dataset", "xml/policies/common/policy_dataset.xml"); + + private final SerializableProvider fileProvider; + private final SerializableProvider datasetNameProvider; + + /** + * Creates a {@link CreateDatasetAction} to be executed when a report completes. + * + * @param Name Provider class. Must be both {@link Serializable} and a {@link String} {@link Provider}. + * @param File Provider class. Must be both {@link Serializable} and a {@link File} {@link Provider}. + * @param reportClass the caller report Class + * @param datasetNameProvider a {@link Provider} which will eventually {@link Provider#get() provide} a dataset name + * @param fileProvider a {@link Provider} which will eventually {@link Provider#get() provide} a file + */ + public & Serializable, FP extends Provider & Serializable> CreateDatasetAction(final Class reportClass, + final NP datasetNameProvider, FP fileProvider) { + super(reportClass); + // Cast is OK, because the cast interface extends both input classes + this.datasetNameProvider = (SerializableProvider) datasetNameProvider; + this.fileProvider = (SerializableProvider) fileProvider; + } + + /** + * Creates a dataset, with a file in it. + * + * @param session an active tc session + * @param datasetName the desired dataset name + * @param file the file to add to the dataset + * @param report the requesting report + * @return a Token registering the dataset request data + * @throws InvalidDatasetException if something occurred + */ + public static GetDatasetWriteTicketsInputData createDataset(final TcSession session, final String datasetName, final File file, + final AbstractExecutionReport report) throws InvalidDatasetException { + String dataSetDescription = report.getReportIdentifier().getReportTitle(); + + // Perform the upload + GetDatasetWriteTicketsInputData data; + try { + data = FileManagement.addSingleDataSet(session, datasetName, dataSetDescription, file, FileType.FICHE_ARTICLE); + } catch (MalformedDataSetException | ConnectionMisconguredException e) { + throw new InvalidDatasetException("Unable to create the dataset for the report " + report.getReportIdentifier().getReportCode() + " UID=" + report.getReportTechnicalUid(), e); + } + return data; + } + + @Override + public GetDatasetWriteTicketsInputData performPostActionOnReport(final TcSession session, final T report, + final DbReport theExecutingReport, final String fileNameWithExtension) throws KurtException { + session.setObjectPropPolicy(POLICY_XML_DATASET); + + String datasetName = datasetNameProvider.get(); + + // Create a new dataset + log.debug("Wokflow launch: Creating dataset {}", datasetName); + return createDataset(session, datasetName, fileProvider.get(), report); + } + +} + diff --git a/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/ondataset/DestroyRelationshipsAction.java b/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/ondataset/DestroyRelationshipsAction.java new file mode 100644 index 0000000..8733a1e --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/ondataset/DestroyRelationshipsAction.java @@ -0,0 +1,81 @@ +package com.capgemini.reports.execution.actions.ondataset; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.FailedRelationshipActionException; +import com.capgemini.framework.teamcenter.queries.saved.modelobject.IMANRelationQuery; +import com.capgemini.reports.database.javabean.DbReport; +import com.capgemini.reports.execution.AbstractExecutionReport; +import com.capgemini.reports.execution.actions.AbstractPostExecutionStep; +import com.teamcenter.soa.client.model.ModelObject; +import com.teamcenter.soa.client.model.strong.ImanRelation; +import lombok.EqualsAndHashCode; +import lombok.extern.slf4j.Slf4j; + +import javax.inject.Provider; +import java.io.Serializable; +import java.util.List; + +/** + * This {@link AbstractPostExecutionStep} can destroy a Relationship between a Part and some of its datasets. + * + * @param the report class + */ +@Slf4j +@EqualsAndHashCode(callSuper = true) +public class DestroyRelationshipsAction> extends AbstractPostExecutionStep { + + private static final long serialVersionUID = -3343435909197113891L; + + private final SerializableProvider targetIdProvider; + private final SerializableProvider datasetNameProvider; + + /** + * Constructs an action to be executed after the report generation is done. + * + * @param a name provider class. Must be both {@link Serializable} and a {@link String} {@link Provider}. + * @param reportClass the report {@link Class} + * @param targetIdProvider a {@link Provider} which will eventually {@link Provider#get() provide} the partId (target) + * @param datasetNameProvider a {@link Provider} which will eventually {@link Provider#get() provide} the dataset name + */ + public & Serializable> DestroyRelationshipsAction(Class reportClass, NP targetIdProvider, + NP datasetNameProvider) { + super(reportClass); + // Both casts are safe because a SerializableProvider is both Serializable... and a Provider + this.targetIdProvider = (SerializableProvider) targetIdProvider; + this.datasetNameProvider = (SerializableProvider) datasetNameProvider; + } + + /** + * Destroys all relationship between a part and all dataset with specific name. + * + * @param session an active Tc session + * @param datasetName the name of the dataset + * @param targetID the name of the part which holds the dataset + * @throws FailedRelationshipActionException in case the relationship could not be destroyed + */ + public static void destroyConflictingDatasets(final TcSession session, final String datasetName, final String targetID) + throws FailedRelationshipActionException { + List existingRelations = new IMANRelationQuery(session).find(targetID, datasetName); + log.debug("Wokflow launch: destroying conflicting datasets: {} relations found", existingRelations.size()); + // Let's browse all conflicting datasets + for (ImanRelation relation : existingRelations) { + ModelObject datasetMO = relation.get_secondary_object(); + + // Let's destroy the relation first + log.debug(" - Wokflow launch: destroying relation between Item {} and dataset {}", targetID, datasetMO.getUid()); + session.deleteObjects(relation); + + // Let's destroy the Dataset now that it is free from relationships + log.debug(" - Wokflow launch: destroying dataset {}", datasetMO.getUid()); + session.deleteObjects(datasetMO); + } + } + + @Override + protected Void performPostActionOnReport(final TcSession session, T reportRaw, DbReport theExecutingReport, + String fileNameWithExtension) throws FailedRelationshipActionException { + destroyConflictingDatasets(session, targetIdProvider.get(), datasetNameProvider.get()); + return null; + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/ondataset/LinkFicheArticleAction.java b/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/ondataset/LinkFicheArticleAction.java new file mode 100644 index 0000000..0423314 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/ondataset/LinkFicheArticleAction.java @@ -0,0 +1,75 @@ +package com.capgemini.reports.execution.actions.ondataset; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.FailedRelationshipActionException; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.reports.database.javabean.DbReport; +import com.capgemini.reports.execution.AbstractExecutionReport; +import com.capgemini.reports.execution.actions.AbstractPostExecutionStep; +import com.teamcenter.soa.client.model.ModelObject; +import com.teamcenter.soa.client.model.strong.Item; +import lombok.EqualsAndHashCode; + +import javax.inject.Provider; +import java.io.Serializable; + +import static com.capgemini.framework.teamcenter.TeamcenterObjectTypes.IMAN_REFERENCE; + +/** + * This class is an action that may be performed after a report execution has completed. + * + * @param the class of the calling report + */ +@EqualsAndHashCode(callSuper = true) +public class LinkFicheArticleAction> extends AbstractPostExecutionStep { + + private static final long serialVersionUID = 2717496737388126196L; + + private final SerializableProvider partProvider; + private final SerializableProvider datasetProvider; + + /** + * Create a {@link LinkFicheArticleAction} that can be triggered after a report has completed its execution. + * + * @param class of the part provider. Must be both {@link Serializable} and an {@link Item} {@link Provider} + * @param class of the dataset provider. Must be both {@link Serializable} and an {@link ModelObject} {@link Provider} + * @param reportClass the Class of the report. + * @param partProvider an {@link Item} {@link Provider} which can eventually {@link Provider#get() provide} a part + * @param datasetProvider a {@link ModelObject} {@link Provider} which can eventually {@link Provider#get() provide} a dataset + */ + public & Serializable, DSP extends Provider & Serializable> LinkFicheArticleAction( + Class reportClass, PP partProvider, final DSP datasetProvider) { + super(reportClass); + // Both casts are safe because a Serializable Provider is both Serializable... and a Provider + this.partProvider = (SerializableProvider) partProvider; + this.datasetProvider = (SerializableProvider) datasetProvider; + } + + /** + * Links a Part to a dataset.
    + * If successful, a Relationship is created between the Part and the Dataset.
    + * If unsuccessful, the provided dataset will be deleted, to make sure it is not left orphaned (attached to nothing) + * + * @param session an active session + * @param thePart the target part + * @param dataset the dataset to attach + * @throws FailedRelationshipActionException whenever something fails (in which case the provided dataset is destroyed) + */ + public static void linkDatasetToPart(final TcSession session, final Item thePart, final ModelObject dataset) + throws FailedRelationshipActionException { + try { + session.createRelation(thePart, dataset, IMAN_REFERENCE); + } catch (FailedRelationshipActionException e) { + // Unable to link back the dataset to the part. Let's cleanup behind us and destroy that orphan dataset! + session.deleteObjects(dataset); + throw e; + } + } + + @Override + protected Void performPostActionOnReport(TcSession session, T reportRaw, DbReport theExecutingReport, + String fileNameWithExtension) throws KurtException { + linkDatasetToPart(session, partProvider.get(), datasetProvider.get()); + return null; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/ondataset/SerializableProvider.java b/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/ondataset/SerializableProvider.java new file mode 100644 index 0000000..5049a97 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/ondataset/SerializableProvider.java @@ -0,0 +1,8 @@ +package com.capgemini.reports.execution.actions.ondataset; + +import javax.inject.Provider; +import java.io.Serializable; + +interface SerializableProvider extends Provider, Serializable { + // Nothing special to add, this is just an interface fusion +} \ No newline at end of file diff --git a/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/ondataset/SetStatusAction.java b/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/ondataset/SetStatusAction.java new file mode 100644 index 0000000..b3b7996 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/execution/actions/ondataset/SetStatusAction.java @@ -0,0 +1,75 @@ +package com.capgemini.reports.execution.actions.ondataset; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.UnableToCreateStatusException; +import com.capgemini.framework.teamcenter.statuating.StatusSetter; +import com.capgemini.reports.database.javabean.DbReport; +import com.capgemini.reports.execution.AbstractExecutionReport; +import com.capgemini.reports.execution.actions.AbstractPostExecutionStep; +import com.teamcenter.soa.client.model.ModelObject; +import com.teamcenter.soa.client.model.strong.ReleaseStatus; +import com.teamcenter.soa.client.model.strong.WorkspaceObject; +import lombok.EqualsAndHashCode; +import lombok.extern.slf4j.Slf4j; + +import javax.inject.Provider; +import java.io.Serializable; + +/** + * This class is an action that can be used to set a {@link ReleaseStatus} on a {@link ModelObject} with a given name. + * + * @param the class of the calling report + */ +@Slf4j +@EqualsAndHashCode(callSuper = true) +public class SetStatusAction> extends AbstractPostExecutionStep { + + private static final long serialVersionUID = -1516821856454786852L; + + private final SerializableProvider targetProvider; + private final SerializableProvider statusNameProvider; + + /** + * Creates a {@link SetStatusAction} to be executed when the report has completed its execution. + * + * @param the class of the target provider. Must be both {@link Serializable} and a {@link ModelObject} {@link Provider}. + * @param the class of the name provider. Must be both {@link Serializable} and a {@link String} {@link Provider}. + * @param targetProvider a {@link Provider} which will eventually {@link Provider#get() provide} a target {@link ModelObject}. + * @param nameProvider a {@link Provider} which will eventually {@link Provider#get() provide} a status name. + * @param reportClass the Class of the calling report. + */ + public & Serializable, NP extends Provider & Serializable> SetStatusAction(TP targetProvider, + NP nameProvider, Class reportClass) { + super(reportClass); + // Both casts are safe because a Serializable Provider is both Serializable... and a Provider + this.targetProvider = (SerializableProvider) targetProvider; + this.statusNameProvider = (SerializableProvider) nameProvider; + } + + /** + * Sets a status on a {@link ModelObject}. + * + * @param session an active Tc session + * @param target the target ModelObject + * @param statusName the desired status name + * @return the newly created status + * @throws UnableToCreateStatusException thrown if unable to create the status. + */ + public static ReleaseStatus setStatus(final TcSession session, final ModelObject target, String statusName) + throws UnableToCreateStatusException { + return new StatusSetter(session).putStatus((WorkspaceObject) target, statusName); + } + + @Override + public Void performPostActionOnReport(final TcSession session, final T report, final DbReport theExecutingReport, + final String fileNameWithExtension) throws UnableToCreateStatusException { + // Get the target + ModelObject target = targetProvider.get(); + + // Set the TcReleaseStatus on the dataset + log.debug("Wokflow launch: Adding 'Frozen' status to the object {}", target.getUid()); + setStatus(session, target, statusNameProvider.get()); + return null; + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/execution/mapconstructor/AbstractStaticTemplateMapConstructor.java b/kurt-utility/src/main/java/com/capgemini/reports/execution/mapconstructor/AbstractStaticTemplateMapConstructor.java new file mode 100644 index 0000000..73fcb78 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/execution/mapconstructor/AbstractStaticTemplateMapConstructor.java @@ -0,0 +1,40 @@ +package com.capgemini.reports.execution.mapconstructor; + +import com.capgemini.framework.common.ReportFolderOutputHelper; +import com.capgemini.framework.common.ResourceHelper; +import com.capgemini.reports.exceptions.FileLoadingException; +import com.capgemini.reports.exceptions.ReportPrintException; +import com.capgemini.reports.execution.AbstractExecutionReport; +import com.capgemini.reports.printing.PrintParameters; +import com.capgemini.reports.printing.PrintReportHelper; +import lombok.EqualsAndHashCode; +import lombok.extern.slf4j.Slf4j; + +import java.io.IOException; +import java.io.InputStream; + +/** + * Simple class that will generate a {@link PrintParameters} using a fixed template file. + * + * @param the report Type + * @param the type that holds the relevant report data between the data preparator and the printer + */ +@Slf4j +@EqualsAndHashCode +public abstract class AbstractStaticTemplateMapConstructor, U> implements IMapConstructor { + + private static final long serialVersionUID = 2006289510760058068L; + + @Override + public PrintParameters makeMasterTemplate(final T report, final U optionalData) throws ReportPrintException, FileLoadingException { + String storageFolder = ReportFolderOutputHelper.getStorageFolderLocation(report.getLaunchType()); + String fileName = report.getFileNameOnDisc(); + String templateLocation = report.getTemplateLocation(); + try (InputStream templateStream = ResourceHelper.getResourceAsStream(templateLocation)) { + return PrintReportHelper.setupPrintParameters(templateStream, storageFolder, fileName, report); + } catch (IOException e) { + log.error("Unable to close the template file properly from " + templateLocation, e); + return null; // IOException is only thrown by close() which, if it ever fails, means you have much bigger problems! + } + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/execution/mapconstructor/IMapConstructor.java b/kurt-utility/src/main/java/com/capgemini/reports/execution/mapconstructor/IMapConstructor.java new file mode 100644 index 0000000..c06be56 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/execution/mapconstructor/IMapConstructor.java @@ -0,0 +1,53 @@ +package com.capgemini.reports.execution.mapconstructor; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.reports.exceptions.FileLoadingException; +import com.capgemini.reports.exceptions.InvalidInputException; +import com.capgemini.reports.exceptions.ReportPrintException; +import com.capgemini.reports.execution.AbstractExecutionReport; +import com.capgemini.reports.printing.PrintParameters; +import net.sf.jasperreports.engine.JRException; + +import java.io.IOException; +import java.io.Serializable; +import java.util.Map; + +/** + * This interface will allow to construct data map for the reports. + * + * @param generic object for reports + * @param An intermediate Type object that contains all generated data + */ +public interface IMapConstructor, U> extends Serializable { + + /** Message to display execution time. */ + String EXECUTION_TIME_XXX_MS_FOR_YYY = "Execution time : {} ms for {}"; + + /** + * Creates the main report template.
    + * If a simple template should be loaded from the disc, use {@link AbstractStaticTemplateMapConstructor}. + * + * @param report the report to build the template for + * @param optionalData optionally, some additonal data might be required + * @return the {@link PrintParameters} with the template on board + * @throws ReportPrintException + * @throws FileLoadingException + * @throws InvalidInputException + */ + PrintParameters makeMasterTemplate(final T report, final U optionalData) throws ReportPrintException, FileLoadingException, InvalidInputException; + + /** + * Constructs some data {@link Map}s from the Tc data, and puts them into the provided PrintParameters. + * + * + * @param session + * @param printParameters the {@link PrintParameters} that must be set up + * @param reportdata will provide informations for the report which is executing + * @throws KurtException + * @throws IOException + * @throws JRException + */ + void constructDataMaps(TcSession session, final PrintParameters printParameters, final U reportdata) throws KurtException, JRException, IOException; + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/execution/strategies/AbstractExecutionStrategy.java b/kurt-utility/src/main/java/com/capgemini/reports/execution/strategies/AbstractExecutionStrategy.java new file mode 100644 index 0000000..87f6365 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/execution/strategies/AbstractExecutionStrategy.java @@ -0,0 +1,212 @@ +package com.capgemini.reports.execution.strategies; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.reports.database.HibernateUtil; +import com.capgemini.reports.database.javabean.DbReport; +import com.capgemini.reports.database.javabean.DbUser; +import com.capgemini.reports.database.manager.MngReport; +import com.capgemini.reports.database.manager.MngUser; +import com.capgemini.reports.exceptions.InvalidUserInputException; +import com.capgemini.reports.exceptions.NoConfChangesException; +import com.capgemini.reports.exceptions.NotFoundException; +import com.capgemini.reports.exceptions.ReportPrintException; +import com.capgemini.reports.execution.AbstractExecutionReport; +import com.capgemini.reports.execution.actions.*; +import com.capgemini.reports.printing.PrintParameters; +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +/** + * This class is an abstract class which is used to manage execution behaviors to reports.
    + * There are two different behaviors for now :
    + *
      + *
    • The immediate or delayed strategy. + *
    • The scheduled strategy. + *
    + */ +@AllArgsConstructor +@EqualsAndHashCode +public abstract class AbstractExecutionStrategy implements IExecutionStrategy, Serializable { + private static final long serialVersionUID = -4156807152530226260L; + private static final Logger LOGGER = LoggerFactory.getLogger(AbstractExecutionStrategy.class); + + private final IPreExecutionStep preAction; + private final IPostExecutionStep postAction; + private final IErrorExecutionStep errorAction; + + /** + * Constructs a default strategy, with default pre/post/error actions. + */ + AbstractExecutionStrategy() { + this.preAction = defaultPreAction(); + this.postAction = defaultPostAction(); + this.errorAction = defaultErrorAction(); + } + + /** + * Default pre-execution action. + *
      + *
    1. Update AbstractExecutionReport state (start generation date).
    2. + *
    3. Register report execution start in the DB.
    4. + *
    5. Send start email to report owners
    6. + *
    7. Log report Start event in special log file
    8. + *
    9. log effective start in technical log
    10. + *
    + */ + private static CompositePreAction defaultPreAction() { + return new CompositePreAction(new UpdateReportAction(), new UpdateReportInDbAction(), new LoggingAction()); + } + + /** + * Default post-execution action. + *
      + *
    1. Update AbstractExecutionReport state (end generation date).
    2. + *
    3. Register report execution end in the DB.
    4. + *
    5. Send end email to report owners (include the location where the report can be retrieved as a download link)
    6. + *
    7. Log report End event in special log file
    8. + *
    9. log effective end in technical log
    10. + *
    + */ + private static CompositePostAction defaultPostAction() { + return new CompositePostAction(new UpdateReportAction(), new UpdateReportInDbAction(), new InteractiveEmailAction(), new LoggingAction()); + } + + /** + * Default Error action. + *
      + *
    1. Update AbstractExecutionReport state (error date).
    2. + *
    3. Register report execution failure in the DB.
    4. + *
    5. Send end email to report owners and administrators
    6. + *
    7. Log report Failure event in special log file
    8. + *
    9. log effective end in technical log
    10. + *
    + */ + private static CompositeErrorAction defaultErrorAction() { + return new CompositeErrorAction(new UpdateReportAction(), new UpdateReportInDbAction(), new InteractiveEmailAction(), new LoggingAction()); + } + + @Override + public > void preExecutionStep(T report, TcSession tcSession) throws KurtException { + SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); + Session session = sessionFactory.openSession(); + try { + MngReport mngReport = new MngReport(); + DbReport dbReport = mngReport.searchByUid(report.getReportTechnicalUid(), session); + preAction.performPreAction(report, dbReport, tcSession); + } + finally { + session.close(); + } + } + + @Override + public > void postExecutionStep(final T report, final String fileNameWithExtension, + TcSession tcSession) throws KurtException { + SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); + Session session = sessionFactory.openSession(); + try { + MngReport mngReport = new MngReport(); + DbReport dbReport = mngReport.searchByUid(report.getReportTechnicalUid(), session); + postAction.performPostAction(tcSession, report, dbReport, fileNameWithExtension); + } + finally { + session.close(); + } + } + + @Override + public File print(final PrintParameters printParameters, final AbstractExecutionReport report) throws KurtException { + // Only print the report + // No need to add specific behaviors contrary to ScheduledStrategy + return printReport(printParameters, report); + } + + @Override + public String getReportFileName(final AbstractExecutionReport report) { + return report.getSpecifiedFileName(); + } + + File printReport(final PrintParameters printParameters, final AbstractExecutionReport report) throws KurtException { + try { + return report.getPrinter().print(printParameters); + } + catch (ReportPrintException e) { + throw new KurtException("JASPER print failed ", e); + } + } + + /** + * Takes care of any technical (unexpected) error.
    + * Searches the DB for report owners, then lets the on-board {@link IErrorExecutionStep} deal with it. + * + * @param report the report which just crashed + * @param theThrowable the exception that caused all the turmoil + */ + @Override + public void handleTechnicalError(final AbstractExecutionReport report, final Throwable theThrowable) { + SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); + Session session = sessionFactory.openSession(); + try { + DbReport dbReport = new MngReport().searchByUid(report.getReportTechnicalUid(), session); + List owners = new MngUser().searchReportOwners(session, dbReport); + errorAction.performTechnicalErrorAction(report, owners, theThrowable); + } + catch (NotFoundException e) { + LOGGER.warn("Handling a prior technical error, could not find the original owners UID=" + report.getReportTechnicalUid(), e); + } + finally { + session.close(); + } + } + + /** + * Takes care of any functional (unexpected) error.
    + * Searches the DB for report owners, then lets the on-board {@link IErrorExecutionStep} deal with it. + * + * @param report the report which just crashed + * @param error the exception that caused all the turmoil + */ + @Override + public void handleFunctionalError(final AbstractExecutionReport report, final NoConfChangesException error) { + LOGGER.info(error.getMessage()); + errorAction.performFunctionalErrorAction(report, owners(report), error); + } + + /** + * Takes care of any functional (unexpected) error.
    + * Searches the DB for report owners, then lets the on-board {@link IErrorExecutionStep} deal with it. + * + * @param report the report which just crashed + * @param error the exception that caused all the turmoil + */ + @Override + public void handleFunctionalError(final AbstractExecutionReport report, final InvalidUserInputException error) { + errorAction.performFunctionalErrorAction(report, owners(report), error); + } + + protected List owners(AbstractExecutionReport report) { + SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); + Session session = sessionFactory.openSession(); + try { + DbReport dbReport = new MngReport().searchByUid(report.getReportTechnicalUid(), session); + return new MngUser().searchReportOwners(session, dbReport); + } + catch (NotFoundException e) { + LOGGER.warn("Handling a prior technical error, could not find the original owners of report with UID=" + report.getReportTechnicalUid(), e); + return new ArrayList<>(); + } + finally { + session.close(); + } + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/execution/strategies/AutomaticExecutionStrategy.java b/kurt-utility/src/main/java/com/capgemini/reports/execution/strategies/AutomaticExecutionStrategy.java new file mode 100644 index 0000000..eac1981 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/execution/strategies/AutomaticExecutionStrategy.java @@ -0,0 +1,76 @@ +package com.capgemini.reports.execution.strategies; + +import com.capgemini.reports.ReportLaunchTypeEnum; +import com.capgemini.reports.execution.actions.*; +import lombok.EqualsAndHashCode; + +/** + * Strategy for reports launched automatically, via a workflow.
    + * In this strategy, no email are sent except on error cases, in which case a re-launch URL is provided. + */ +@EqualsAndHashCode(callSuper = true) +public class AutomaticExecutionStrategy extends AbstractExecutionStrategy { + + private static final long serialVersionUID = -476263626956824427L; + + /** + * Prepares a strategy for automatic execution. + * @param requestURL a URL that allows the process to be executed again in case of an error + */ + public AutomaticExecutionStrategy(String requestURL) { + super(makePreAction(new DoNothingAction()), makePostAction(new DoNothingAction()), makeErrorActionPlan(requestURL)); + } + + /** + * Prepares a strategy for automatic execution. + * @param requestURL a URL that allows the process to be executed again in case of an error + * @param specializedPreAction a special action to perform before anything is done on this report + * @param specializedPostAction a special action to perform right after the report has been generated + */ + public AutomaticExecutionStrategy(String requestURL, final IPreExecutionStep specializedPreAction, + final IPostExecutionStep specializedPostAction) { + super(makePreAction(specializedPreAction), makePostAction(specializedPostAction), makeErrorActionPlan(requestURL)); + } + + /** + * Pre-execution action for reports launched automatically by workflow. + *
      + *
    1. Update AbstractExecutionReport state (startDate).
    2. + *
    3. Register report execution start in the DB.
    4. + *
    5. Log report Start event i special log file
    6. + *
    7. log effective start in technical log
    8. + *
    + * Note: no email sent in normal execution flow + */ + private static CompositePreAction makePreAction(final IPreExecutionStep specializedPreAction) { + // Be sure to NOT include mails of any kind in normal report execution actions + return new CompositePreAction(specializedPreAction, new UpdateReportAction(), new UpdateReportInDbAction(), new LoggingAction()); + } + + /** + * post-execution action for reports launched automatically by workflow. + *
      + *
    1. Update AbstractExecutionReport state (endDate).
    2. + *
    3. Register report execution end in the DB.
    4. + *
    5. Send end email to report owners (include the location where the report can be retrieved as a download link)
    6. + *
    7. log effective end in technical log
    8. + *
    + * + * @param report the report which has been completed + */ + private static CompositePostAction makePostAction(final IPostExecutionStep specializedPostAction) { + // Be sure to NOT include mails of any kind in normal report execution actions + return new CompositePostAction(specializedPostAction, new UpdateReportAction(), new UpdateReportInDbAction(), new LoggingAction()); + } + + private static IErrorExecutionStep makeErrorActionPlan(String requestURL) { + return new CompositeErrorAction(new UpdateReportAction(), new UpdateReportInDbAction(), new LoggingAction(), + new ReLaunchEmailAction(requestURL)); + } + + @Override + public ReportLaunchTypeEnum getLaunchType() { + return ReportLaunchTypeEnum.AUTOMATIC; + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/execution/strategies/DelayedExecutionStrategy.java b/kurt-utility/src/main/java/com/capgemini/reports/execution/strategies/DelayedExecutionStrategy.java new file mode 100644 index 0000000..f3c0968 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/execution/strategies/DelayedExecutionStrategy.java @@ -0,0 +1,16 @@ +package com.capgemini.reports.execution.strategies; + +import com.capgemini.reports.ReportLaunchTypeEnum; +import lombok.EqualsAndHashCode; + +/** Execution flow for report that is requested but must be postponed until later this day. */ +@EqualsAndHashCode(callSuper = true) +public class DelayedExecutionStrategy extends AbstractExecutionStrategy { + + private static final long serialVersionUID = -7625339402185787331L; + + @Override + public final ReportLaunchTypeEnum getLaunchType() { + return ReportLaunchTypeEnum.DELAYED; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/execution/strategies/IExecutionStrategy.java b/kurt-utility/src/main/java/com/capgemini/reports/execution/strategies/IExecutionStrategy.java new file mode 100644 index 0000000..36f657a --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/execution/strategies/IExecutionStrategy.java @@ -0,0 +1,102 @@ +package com.capgemini.reports.execution.strategies; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.reports.ReportLaunchTypeEnum; +import com.capgemini.reports.exceptions.InvalidUserInputException; +import com.capgemini.reports.exceptions.NoConfChangesException; +import com.capgemini.reports.execution.AbstractExecutionReport; +import com.capgemini.reports.printing.PrintParameters; + +import java.io.File; +import java.io.Serializable; + +/** + * This interface represents a strategy of report's execution.
    + * According to the launch type, we have different strategies :
    + *
      + *
    • A strategy for immediate reports. + *
    • A strategy for delayed reports. + *
    • A strategy for scheduled report. + *
    + */ +public interface IExecutionStrategy extends Serializable { + + /** + * Perform the printing step of a report : the generation of the file and the folders output.
    + *
      + *
    • An IMMEDIATE or DELAYED report just print its report. + *
    • A SCHEDULED report must manage its two output folders and print the report inside both of them.
      + * There is one folder of output an another of history.
      + * In the history folder, we can find all the generated scheduled report.
      + * In the scheduled output folder, we just find the last generated report of each scheduling. + *
    + * + * @param printParameters {@link PrintParameters} - the parameters used in the template Jasper to do a report + * @param report {@link AbstractExecutionReport} - the report with his own specificities + * @return the printed {@link File} + * @throws KurtException + */ + File print(final PrintParameters printParameters, final AbstractExecutionReport report) throws KurtException; + + /** + * Defines what is to be done before the report starts to execute. + * + * @param report the report instance + * @param the exact report type + * @throws KurtException + */ + > void preExecutionStep(final T report, TcSession session) throws KurtException; + + /** + * Defines what is to be done after the report has completed its execution. + * + * @param the exact report type + * @param report the report instance + * @param fileNameWithExtension the file name + * @throws KurtException + */ + > void postExecutionStep(final T report, final String fileNameWithExtension, + TcSession session) throws KurtException; + + /** + * Construct the name of the file.
    + * For IMMEDIATE or DELAYED report, each report has its own name.
    + * For SCHEDULED report, the name is specific to the report code, the scheduling and the execution date. + * + * @param report {@link AbstractExecutionReport} - the report which his specificities (code, file name,...) + * @return the file name + */ + String getReportFileName(final AbstractExecutionReport report); + + /** + * The type of launch (as a {@link ReportLaunchTypeEnum}). + * + * @return DELAYED, SCHEDULED, IMMEDIATE, AUTOMATIC + */ + ReportLaunchTypeEnum getLaunchType(); + + /** + * Handles a functional error by the user. + * + * @param report the report which failed + * @param error the exception that was encountered (an {@link NoConfChangesException}) + */ + void handleFunctionalError(AbstractExecutionReport report, NoConfChangesException error); + + /** + * Handles a functional error by the user. + * + * @param report the report which failed + * @param error the exception that was encountered (an {@link InvalidUserInputException}) + */ + void handleFunctionalError(AbstractExecutionReport report, InvalidUserInputException error); + + /** + * Handles a technical error. + * + * @param report the report which failed + * @param theThrowable the exception that was encountered + */ + void handleTechnicalError(AbstractExecutionReport report, Throwable theThrowable); +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/execution/strategies/ImmediateExecutionStrategy.java b/kurt-utility/src/main/java/com/capgemini/reports/execution/strategies/ImmediateExecutionStrategy.java new file mode 100644 index 0000000..470d375 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/execution/strategies/ImmediateExecutionStrategy.java @@ -0,0 +1,16 @@ +package com.capgemini.reports.execution.strategies; + +import com.capgemini.reports.ReportLaunchTypeEnum; +import lombok.EqualsAndHashCode; + +/** Execution flow for report that is requested and must be executed immediately. */ +@EqualsAndHashCode(callSuper = true) +public class ImmediateExecutionStrategy extends AbstractExecutionStrategy { + + private static final long serialVersionUID = -4519380941500076374L; + + @Override + public final ReportLaunchTypeEnum getLaunchType() { + return ReportLaunchTypeEnum.IMMEDIATE; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/execution/strategies/ScheduledExecutionStrategy.java b/kurt-utility/src/main/java/com/capgemini/reports/execution/strategies/ScheduledExecutionStrategy.java new file mode 100644 index 0000000..24b1143 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/execution/strategies/ScheduledExecutionStrategy.java @@ -0,0 +1,143 @@ +package com.capgemini.reports.execution.strategies; + +import com.capgemini.framework.common.DateHelper; +import com.capgemini.framework.common.ReportFolderOutputHelper; +import com.capgemini.framework.common.SettingsHelper; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.reports.ReportLaunchTypeEnum; +import com.capgemini.reports.database.HibernateUtil; +import com.capgemini.reports.database.javabean.DbReport; +import com.capgemini.reports.database.javabean.DbReportOwner; +import com.capgemini.reports.database.manager.MngReport; +import com.capgemini.reports.database.manager.MngReportOwner; +import com.capgemini.reports.exceptions.NotFoundException; +import com.capgemini.reports.execution.AbstractExecutionReport; +import com.capgemini.reports.execution.actions.*; +import com.capgemini.reports.printing.PrintParameters; +import com.google.common.io.Files; +import lombok.EqualsAndHashCode; +import lombok.extern.slf4j.Slf4j; +import org.hibernate.Session; +import org.hibernate.SessionFactory; + +import java.io.File; +import java.io.IOException; +import java.sql.Timestamp; +import java.text.SimpleDateFormat; +import java.util.List; + +/** + * Class representing the strategy to execute for scheduled reports. + */ +@Slf4j +@EqualsAndHashCode(callSuper = true) +public class ScheduledExecutionStrategy extends AbstractExecutionStrategy { + private static final long serialVersionUID = -1874201095083131827L; + /** + * Location in HD of the folder where the latest version of scheduled reports are kept. + */ + private static final String SCHEDULING_LOCATION_OUTPUT = SettingsHelper.getSchedulingLocation(); + + /** + * PRepares an execution strategy for scheduled reports. + */ + public ScheduledExecutionStrategy() { + super(new CompositePreAction(new UpdateReportAction(), new QuickCheckAction(), new UpdateReportInDbAction(), new LoggingAction()), + new CompositePostAction(new UpdateReportAction(), new UpdateReportInDbAction(), new ScheduledEmailAction(), new LoggingAction()), makeSchedulingDefaultErrorAction()); + } + + + private static IErrorExecutionStep makeSchedulingDefaultErrorAction() { + UpdateReportAction updateReportAction = new UpdateReportAction(); + UpdateReportInDbAction updateReportInDbAction = new UpdateReportInDbAction(); + ScheduledEmailAction scheduledEmailAction = new ScheduledEmailAction(); + LoggingAction loggingAction = new LoggingAction(); + return new CompositeErrorAction(updateReportAction, updateReportInDbAction, scheduledEmailAction, loggingAction); + } + + @Override + public final ReportLaunchTypeEnum getLaunchType() { + return ReportLaunchTypeEnum.SCHEDULED; + } + + + @Override + public File print(final PrintParameters printParameters, final AbstractExecutionReport report) throws KurtException { + String fileNameShort = fileNameShort(report) + printParameters.getOuputFileExtension(); + if (ReportFolderOutputHelper.checkIfAlreadyLaunched(report.getSchedulingId())) { + // It has already launched so we have to delete the precedent file in the scheduled output folder + // But the history folder doesn't change + try { + ReportFolderOutputHelper.deleteScheduledReportFile(fileNameShort); + } + catch (NotFoundException e) { + log.warn("Unable to delete file generated by previous scheduled execution. Continuing scheduled job.", e); + } + } + + File original = printReport(printParameters, report); + File scheduledFile = new File(SCHEDULING_LOCATION_OUTPUT + fileNameShort); + try { + Files.move(original, scheduledFile); // This RENAMES the file + log.debug("Renamed scheduling file [{}] to [{}]", original.getAbsoluteFile(), scheduledFile.getAbsolutePath()); + } + catch (IOException e) { + File originalFileName = original.getAbsoluteFile(); + String destinationFileName = scheduledFile.getAbsolutePath(); + throw new KurtException("Unable to rename file " + originalFileName + " to " + destinationFileName, e); + } + + // Add the scheduled report in the historic folder + String reportFileNameHistory = getReportFileName(report) + printParameters.getOuputFileExtension(); + try { + ReportFolderOutputHelper.copyToHistoryFolder(scheduledFile, reportFileNameHistory); + log.debug("Saved scheduling file [{}] to history [{}]", scheduledFile.getAbsoluteFile(), reportFileNameHistory); + } + catch (IOException e) { + File originalFileName = scheduledFile.getAbsoluteFile(); + throw new KurtException("Unable to copy file " + originalFileName + " to " + reportFileNameHistory, e); + } + + // Now update DB + MngReport mng = new MngReport(); + mng.updateFileName(report.getReportTechnicalUid(), reportFileNameHistory); + log.debug("Registering report {} file name {} to DB ", report.getReportTechnicalUid(), reportFileNameHistory); + return scheduledFile; + } + + @Override + public String getReportFileName(final AbstractExecutionReport report) { + // Give the name : reportcode+"-"+schedulingname+"-"+postingDate + Timestamp date; + SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); + Session session = sessionFactory.openSession(); + try { + MngReport mngReport = new MngReport(); + DbReport dbReport = mngReport.searchByUid(report.getReportTechnicalUid(), session); + List owners = new MngReportOwner().searchReportOwners(session, dbReport.getId()); + if (owners.isEmpty()) { + date = DateHelper.getCurrentSqlTimestamp(); + log.error("No owners of scheduled report, using default scheduling name for file name"); + } + else { + date = owners.get(0).getRequestDate(); + } + } + catch (NotFoundException e) { + date = DateHelper.getCurrentSqlTimestamp(); + log.error("Report not found in DB, using default scheduling name for file name", e); + } + finally { + session.close(); + } + String dateStr = new SimpleDateFormat("yyyyMMdd_HHmmss").format(date); + String fileNameShort = fileNameShort(report); + return fileNameShort + "-" + dateStr; + } + + private String fileNameShort(final AbstractExecutionReport report) { + String reportCode = report.getReportIdentifier().getReportCode(); + String schedulingName = report.getSchedulingName(); + return reportCode + "-" + schedulingName; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/logging/EventsLogger.java b/kurt-utility/src/main/java/com/capgemini/reports/logging/EventsLogger.java new file mode 100644 index 0000000..46efccb --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/logging/EventsLogger.java @@ -0,0 +1,31 @@ +package com.capgemini.reports.logging; + +import lombok.extern.slf4j.Slf4j; + +/** This class merely re-directs logs into this package to have all main events gathered in a single log file. */ +@Slf4j +public final class EventsLogger { + + private EventsLogger() { + // Nothing to do... + } + + /** + * Logs a message. + * + * @param msg a message + */ + public static void log(final String msg) { + log.info(msg); + } + + /** + * Logs an error message, as well as the {@link Throwable} event that caused the error. + * + * @param msg a message. + * @param error an error + */ + public static void log(final String msg, final Throwable error) { + log.error(msg, error); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/logging/ReportLoggerHelper.java b/kurt-utility/src/main/java/com/capgemini/reports/logging/ReportLoggerHelper.java new file mode 100644 index 0000000..8e68740 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/logging/ReportLoggerHelper.java @@ -0,0 +1,181 @@ +package com.capgemini.reports.logging; + +import com.capgemini.framework.common.StringHelper; +import com.capgemini.framework.common.TeamcenterDateFormatter; +import com.capgemini.reports.database.HibernateUtil; +import com.capgemini.reports.database.javabean.DbReport; +import com.capgemini.reports.database.javabean.DbSchedulingReport; +import com.capgemini.reports.database.javabean.DbUser; +import com.capgemini.reports.database.manager.MngCriteriaVal; +import com.capgemini.reports.database.manager.MngReport; +import com.capgemini.reports.database.manager.MngSchedulingCriteriaVal; +import com.capgemini.reports.exceptions.NotFoundException; +import com.capgemini.reports.execution.AbstractExecutionReport; +import com.google.common.base.Joiner; +import lombok.extern.slf4j.Slf4j; +import org.hibernate.Session; +import org.hibernate.SessionFactory; + +import java.text.SimpleDateFormat; + +/** + * This class will provide all methods which will allow to log every step of the report's execution. + */ +@Slf4j +public final class ReportLoggerHelper { + private static final String TITLE_REPORT = "Rapport "; + + private static final String ENTRY_ERROR_MESSAGE = " - Message d'erreur: "; + private static final String ENTRY_WITH_CRITERIA = " - Avec les critères suivants:"; + private static final String ENTRY_BY_USER = " - par l'utilisateur '"; + private static final String ENTRY_UID = " - UID="; + private static final String ENTRY_FINISHED = " - terminé le "; + private static final String ENTRY_STARTED = " - Démarré le "; + private static final String ENTRY_DASH = " - "; + private static final String ENTRY_STATUS = " - TcReleaseStatus="; + + private static final String STATUS_AUTOMATIC = " par workflow"; + private static final String STATUS_DELAYED = " en différé"; + private static final String STATUS_SCHEDULING_LAUNCHED = " programmé par planification et actuellement lancé "; + private static final String STATUS_SCHEDULED = " planifié"; + private static final String MSG_NO_REPORT_FOUND_WITH_THIS_ID = " (No report found with this ID)"; + + private ReportLoggerHelper() { + + } + + /** + * To log the beginning of the report's execution. + * + * @param aTheExecutingReport will provide the informations of the report on the database + * @param aAbstractExecutionReport will provide the informations of the report's execution + */ + public static void logStart(final DbReport aTheExecutingReport, final AbstractExecutionReport aAbstractExecutionReport) { + StringBuilder logMsg = new StringBuilder("Début de l'exécution du rapport ") + .append(aAbstractExecutionReport.getReportIdentifier().buildCompleteReportName()); + logMsg.append(ENTRY_UID).append(getSafeUID(aTheExecutingReport)); + logMsg.append(ENTRY_STARTED).append(aAbstractExecutionReport.getStartTime()); + EventsLogger.log(logMsg.toString()); + + } + + private static String getSafeUID(final DbReport aTheExecutingReport) { + if (aTheExecutingReport == null || aTheExecutingReport.getReportUid() == null) { + return MSG_NO_REPORT_FOUND_WITH_THIS_ID; + } + else { + return aTheExecutingReport.getReportUid(); + } + } + + /** + * Logs the fact that a report's exectution reached completion, in a specific file (the file is specified by the log appender in the logging properties of JBoss). + * + * @param theExecutingReport the report being executed, as written in the database. + * @param fileNameWithExtension the file location of the generated report. + * @param aAbstractExecutionReport will provide the informations of the report + */ + public static void logCompletion(final DbReport theExecutingReport, final String fileNameWithExtension, + final AbstractExecutionReport aAbstractExecutionReport) { + StringBuilder logMsg = new StringBuilder(TITLE_REPORT).append(aAbstractExecutionReport.getReportIdentifier().buildCompleteReportName()) + .append(" terminé avec succès"); + logMsg.append(ENTRY_UID).append(getSafeUID(theExecutingReport)); + logMsg.append(ENTRY_STARTED).append(aAbstractExecutionReport.getStartTime()); + logMsg.append(ENTRY_FINISHED).append(aAbstractExecutionReport.getEndTime()); + logMsg.append(ENTRY_STATUS).append(theExecutingReport == null ? MSG_NO_REPORT_FOUND_WITH_THIS_ID : theExecutingReport.getState()); + logMsg.append(" - Fichier généré : ").append(fileNameWithExtension); + EventsLogger.log(logMsg.toString()); + } + + /** + * Log the provided error and message in a specific file (the file is specified by the log appender in the logginig properties of JBoss). + * + * @param msg An error Message + * @param error the actual error that caused this log + * @param aAbstractExecutionReport will provide the informations of the report + */ + public static void logError(final String msg, final Throwable error, final AbstractExecutionReport aAbstractExecutionReport) { + DbReport theExecutingReport = null; + SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); + Session session = sessionFactory.openSession(); + try { + theExecutingReport = new MngReport().searchByUid(aAbstractExecutionReport.getReportTechnicalUid(), session); + } + catch (NotFoundException e) { + log.error("Unable to find a report in DB, can't log", e); + } + finally { + session.close(); + } + String status; + if (theExecutingReport != null) { + status = theExecutingReport.getState(); + } + else { + status = MSG_NO_REPORT_FOUND_WITH_THIS_ID; + } + + StringBuilder logMsg = + new StringBuilder(TITLE_REPORT).append(aAbstractExecutionReport.getReportIdentifier().buildCompleteReportName()).append(" en échec"); + logMsg.append(ENTRY_UID).append(aAbstractExecutionReport.getReportTechnicalUid()); + logMsg.append(ENTRY_STARTED).append(aAbstractExecutionReport.getStartTime()); + logMsg.append(ENTRY_FINISHED).append(aAbstractExecutionReport.getFailureTime()); + logMsg.append(ENTRY_STATUS).append(status); + logMsg.append(ENTRY_ERROR_MESSAGE).append(msg); + EventsLogger.log(logMsg.toString(), error); + } + + /** + * Logs the fact that a report was requested by a user, in a specific file (the file is specified by the log appender in the logginig properties of JBoss). + */ + public static void logRequest(final DbUser requestingUser, final DbReport theExecutingReport, final AbstractExecutionReport aAbstractExecutionReport) { + StringBuilder logMsg = + new StringBuilder(TITLE_REPORT).append(aAbstractExecutionReport.getReportIdentifier().buildCompleteReportName()).append(" lancé"); + + // Specially for delayed reports + switch (aAbstractExecutionReport.getLaunchType()) { + case AUTOMATIC: + logMsg.append(STATUS_AUTOMATIC); + break; + case DELAYED: + logMsg.append(STATUS_DELAYED); + break; + default: + break; + } + + logMsg.append(ENTRY_UID).append(getSafeUID(theExecutingReport)); + logMsg.append(ENTRY_BY_USER).append(requestingUser.getLogin()).append('\''); + logMsg.append(ENTRY_WITH_CRITERIA); + logMsg.append(StringHelper.implodeList(ENTRY_DASH, new MngCriteriaVal().searchCriteriasByReportUID(theExecutingReport.getReportUid()))); + logMsg.append(ENTRY_STARTED).append(aAbstractExecutionReport.getPostingTime()); + EventsLogger.log(logMsg.toString()); + } + + /** + * Logs the fact that a scheduling was requested by a user, in a specific file (the file is specified by the log appender in the logginig properties of JBoss).
    + */ + public static void logSchedulingRequestWaiting(Session session, final DbUser requestingUser, final DbSchedulingReport theExecutingReport, + final AbstractExecutionReport aAbstractExecutionReport) { + StringBuilder logMsg = new StringBuilder(TITLE_REPORT).append(aAbstractExecutionReport.getReportIdentifier().buildCompleteReportName()) + .append(STATUS_SCHEDULED); + logMsg.append(ENTRY_BY_USER).append(requestingUser.getLogin()).append('\''); + logMsg.append(ENTRY_WITH_CRITERIA); + logMsg.append(Joiner.on(ENTRY_DASH).join(new MngSchedulingCriteriaVal().searchCriteria(session, theExecutingReport.getId()))); + logMsg.append(" - Planifié le ").append(new SimpleDateFormat(TeamcenterDateFormatter.DD_MM_YYYY).format(theExecutingReport.getLastUpdate())); + EventsLogger.log(logMsg.toString()); + } + + + /** + * Logs the fact that a scheduled report was posted, in a specific file (the file is specified by the log appender in the logginig properties of JBoss). + */ + public static void logSchedulingRequest(final DbReport theExecutingReport, final AbstractExecutionReport aAbstractExecutionReport) { + StringBuilder logMsg = new StringBuilder(TITLE_REPORT).append(aAbstractExecutionReport.getReportIdentifier().buildCompleteReportName()) + .append(STATUS_SCHEDULING_LAUNCHED); + logMsg.append(ENTRY_WITH_CRITERIA); + logMsg.append(StringHelper.implodeList(ENTRY_DASH, new MngCriteriaVal().searchCriteriasByReportUID(theExecutingReport.getReportUid()))); + logMsg.append(ENTRY_STARTED).append(aAbstractExecutionReport.getPostingTime()); + EventsLogger.log(logMsg.toString()); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/optimized/Folder.java b/kurt-utility/src/main/java/com/capgemini/reports/optimized/Folder.java new file mode 100644 index 0000000..fa231b7 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/optimized/Folder.java @@ -0,0 +1,53 @@ +package com.capgemini.reports.optimized; + +import java.io.IOException; +import java.nio.file.DirectoryStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +public class Folder { + private final Path path; + + public Folder(Path path) { + this.path = path; + } + + public Path mostRecentFile() throws IOException { + List files = new ArrayList<>(); + try (DirectoryStream directoryStream = Files.newDirectoryStream(path)) { + for (Path file : directoryStream) { + if (!file.toFile().isDirectory()) { + files.add(file); + } + } + } + + // Sort newest file is first element + Collections.sort(files, new Comparator() { + public int compare(Path o1, Path o2) { + try { + return Files.getLastModifiedTime(o2).compareTo(Files.getLastModifiedTime(o1)); + } + catch (IOException e) { + return 0; + } + } + }); + + return files.get(0); + } + + public boolean exist() { + return path.toFile().exists(); + } + + public boolean isEmpty() throws IOException { + try (DirectoryStream directoryStream = Files.newDirectoryStream(path)) { + return !directoryStream.iterator().hasNext(); + } + } +} \ No newline at end of file diff --git a/kurt-utility/src/main/java/com/capgemini/reports/optimized/OptimizedFile.java b/kurt-utility/src/main/java/com/capgemini/reports/optimized/OptimizedFile.java new file mode 100644 index 0000000..7e6376f --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/optimized/OptimizedFile.java @@ -0,0 +1,11 @@ +package com.capgemini.reports.optimized; + +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.reports.reports.parameters.ProductUnit; + +import java.io.IOException; + +public interface OptimizedFile { + + boolean contains(final ProductUnit productUnit) throws KurtException, IOException; +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/optimized/OptimizedFolder.java b/kurt-utility/src/main/java/com/capgemini/reports/optimized/OptimizedFolder.java new file mode 100644 index 0000000..2f75342 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/optimized/OptimizedFolder.java @@ -0,0 +1,10 @@ +package com.capgemini.reports.optimized; + +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.reports.reports.parameters.ProductUnit; + +public interface OptimizedFolder { + + boolean configurationHasNotChanged(ProductUnit productUnit) throws KurtException; + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/optimized/r23report/OptimizedR23File.java b/kurt-utility/src/main/java/com/capgemini/reports/optimized/r23report/OptimizedR23File.java new file mode 100644 index 0000000..92d4ac3 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/optimized/r23report/OptimizedR23File.java @@ -0,0 +1,37 @@ +package com.capgemini.reports.optimized.r23report; + +import com.capgemini.reports.exceptions.InvalidUserInputException; +import com.capgemini.reports.exceptions.UserInputErrorEnum; +import com.capgemini.reports.optimized.OptimizedFile; +import com.capgemini.reports.reports.parameters.ProductUnit; +import com.opencsv.CSVReader; + +import java.io.FileReader; +import java.io.IOException; +import java.nio.file.Path; +import java.util.List; + +public class OptimizedR23File implements OptimizedFile { + + private final Path path; + + public OptimizedR23File(final Path path) { + this.path = path; + } + + @Override + public boolean contains(ProductUnit productUnit) throws IOException, InvalidUserInputException { + try (CSVReader reader = new CSVReader(new FileReader(path.toFile()), ';', '"', 0)) { + List records = reader.readAll(); + for (String[] record : records) { + if (record.length < 1) { + throw new InvalidUserInputException(UserInputErrorEnum.INVALID_FILE); + } + if (record[0].equals(productUnit.getProductID())) { + return true; + } + } + } + return false; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/optimized/r23report/OptimizedR23Folder.java b/kurt-utility/src/main/java/com/capgemini/reports/optimized/r23report/OptimizedR23Folder.java new file mode 100644 index 0000000..16d5f49 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/optimized/r23report/OptimizedR23Folder.java @@ -0,0 +1,26 @@ +package com.capgemini.reports.optimized.r23report; + +import com.capgemini.framework.common.SettingsHelper; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.reports.optimized.Folder; +import com.capgemini.reports.optimized.OptimizedFolder; +import com.capgemini.reports.reports.parameters.ProductUnit; + +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; + +public class OptimizedR23Folder implements OptimizedFolder { + private static final Path PATH = Paths.get(SettingsHelper.getOptimizedFolderR23()); + + @Override + public boolean configurationHasNotChanged(final ProductUnit productUnit) throws KurtException { + Folder folder = new Folder(PATH); + try { + return folder.exist() && !folder.isEmpty() && !new OptimizedR23File(folder.mostRecentFile()).contains(productUnit); + } + catch (IOException e) { + throw new KurtException(e.getMessage(), e); + } + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/optimized/r24report/OptimizedR24File.java b/kurt-utility/src/main/java/com/capgemini/reports/optimized/r24report/OptimizedR24File.java new file mode 100644 index 0000000..a01d3d4 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/optimized/r24report/OptimizedR24File.java @@ -0,0 +1,38 @@ +package com.capgemini.reports.optimized.r24report; + +import com.capgemini.reports.exceptions.InvalidUserInputException; +import com.capgemini.reports.exceptions.UserInputErrorEnum; +import com.capgemini.reports.optimized.OptimizedFile; +import com.capgemini.reports.reports.parameters.ProductUnit; +import com.opencsv.CSVReader; + +import java.io.FileReader; +import java.io.IOException; +import java.nio.file.Path; +import java.util.List; + +public class OptimizedR24File implements OptimizedFile { + + private final Path path; + + public OptimizedR24File(final Path path) { + this.path = path; + } + + @Override + public boolean contains(ProductUnit productUnit) throws IOException, InvalidUserInputException { + try (CSVReader reader = new CSVReader(new FileReader(path.toFile()), ';', '"', 0)) { + List records = reader.readAll(); + for (String[] record : records) { + if (record.length < 2) { + throw new InvalidUserInputException(UserInputErrorEnum.INVALID_FILE); + } + if (record[0].equals(productUnit.getProductID()) && record[1].equals(productUnit.getUnitStr())) { + return true; + } + } + } + + return false; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/optimized/r24report/OptimizedR24Folder.java b/kurt-utility/src/main/java/com/capgemini/reports/optimized/r24report/OptimizedR24Folder.java new file mode 100644 index 0000000..1cb3cff --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/optimized/r24report/OptimizedR24Folder.java @@ -0,0 +1,26 @@ +package com.capgemini.reports.optimized.r24report; + +import com.capgemini.framework.common.SettingsHelper; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.reports.optimized.Folder; +import com.capgemini.reports.optimized.OptimizedFolder; +import com.capgemini.reports.reports.parameters.ProductUnit; + +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; + +public class OptimizedR24Folder implements OptimizedFolder { + private static final Path PATH = Paths.get(SettingsHelper.getOptimizedFolderR24()); + + @Override + public boolean configurationHasNotChanged(final ProductUnit productUnit) throws KurtException { + Folder folder = new Folder(PATH); + try { + return folder.exist() && !folder.isEmpty() && !new OptimizedR24File(folder.mostRecentFile()).contains(productUnit); + } + catch (IOException e) { + throw new KurtException(e.getMessage(), e); + } + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/periodicity/DailyPeriod.java b/kurt-utility/src/main/java/com/capgemini/reports/periodicity/DailyPeriod.java new file mode 100644 index 0000000..de38bf4 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/periodicity/DailyPeriod.java @@ -0,0 +1,44 @@ +package com.capgemini.reports.periodicity; + +import com.capgemini.reports.database.javabean.enumeration.SchedulingEnum; +import com.capgemini.reports.database.manager.MngSchedulingCriteriaVal.SchedulingCriteriaValue; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +import java.util.ArrayList; +import java.util.List; + +/** + * Represents a daily execution. + */ +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class DailyPeriod implements SchedulingPeriod { + + private static final DailyPeriod instance = new DailyPeriod(); + + /** + * Get an instance. All instances are the same as this one (singleton). + * + * @return an instance + */ + public static DailyPeriod getInstance() { + return instance; + } + + @Override + public SchedulingEnum getPeriodicity() { + return SchedulingEnum.DAILY; + } + + @Override + public T accept(final PeriodVisitor visitor) { + return visitor.visit(this); + } + + @Override + public List asCriteriaValues() { + List list = new ArrayList<>(1); + list.add(new SchedulingCriteriaValue(SchedulingEnum.PERIOD, SchedulingEnum.DAILY.getCriteriaName())); + return list; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/periodicity/DayInMonth.java b/kurt-utility/src/main/java/com/capgemini/reports/periodicity/DayInMonth.java new file mode 100644 index 0000000..9d79089 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/periodicity/DayInMonth.java @@ -0,0 +1,45 @@ +package com.capgemini.reports.periodicity; + +import com.capgemini.reports.database.javabean.enumeration.SchedulingEnum; +import com.capgemini.reports.database.manager.MngSchedulingCriteriaVal.SchedulingCriteriaValue; +import lombok.Getter; + +import java.util.ArrayList; +import java.util.List; + +/** + * Represents an periodicity that occurs on a specific day, each month. + */ +@Getter +public class DayInMonth implements SchedulingPeriod { + + private final Integer dayInMonth; + + /** + * Builds a instance. + * + * @param dayInMonth the day in the month. [1-31] + */ + public DayInMonth(final int dayInMonth) { + this.dayInMonth = dayInMonth; + } + + @Override + public SchedulingEnum getPeriodicity() { + return SchedulingEnum.DAY_IN_MONTH_VALUE; + } + + @Override + public T accept(final PeriodVisitor visitor) { + return visitor.visit(this); + } + + @Override + public List asCriteriaValues() { + List list = new ArrayList<>(2); + list.add(new SchedulingCriteriaValue(SchedulingEnum.PERIOD, SchedulingEnum.DAY_IN_MONTH_VALUE.getCriteriaName())); + list.add(new SchedulingCriteriaValue(SchedulingEnum.DAY_IN_MONTH_VALUE, String.valueOf(dayInMonth))); + return list; + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/periodicity/PeriodFactory.java b/kurt-utility/src/main/java/com/capgemini/reports/periodicity/PeriodFactory.java new file mode 100644 index 0000000..b9ed3aa --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/periodicity/PeriodFactory.java @@ -0,0 +1,176 @@ +package com.capgemini.reports.periodicity; + +import com.capgemini.reports.database.javabean.DbSchedulingCriteriaVal; +import com.capgemini.reports.database.javabean.enumeration.SchedulingEnum; +import com.capgemini.reports.exceptions.InvalidInputException; +import com.capgemini.reports.exceptions.InvalidUserInputException; + +import java.text.ParseException; +import java.util.Calendar; +import java.util.List; + +/** Factory class to easily build the various types of scheduling. */ +public final class PeriodFactory { + + private PeriodFactory() { + // Nothing to do + } + + /** + * Builds a {@link SchedulingPeriod} that occurs once every week. + * + * @param dayInWeek the day of the week. + * @return a {@link SchedulingPeriod} + */ + public static WeeklyPeriod weekly(final int dayInWeek) { + return new WeeklyPeriod(dayInWeek); + } + + /** + * Builds a {@link SchedulingPeriod} that occurs every day. + * + * @return a {@link SchedulingPeriod} + */ + public static DailyPeriod daily() { + return DailyPeriod.getInstance(); + } + + /** + * Builds a {@link SchedulingPeriod} that occurs once, on a specific day. + * + * @param day the day of the execution. + * @return a {@link SchedulingPeriod} + * @throws ParseException if unable to parse the String date + */ + public static SpecificDay day(final String day) throws ParseException { + return new SpecificDay(day); + } + + /** + * Builds a {@link SchedulingPeriod} that occurs once every month. + * + * @param dayInMonth the day of the month. + * @return a {@link SchedulingPeriod} + */ + public static DayInMonth dayInMonth(final int dayInMonth) { + return new DayInMonth(dayInMonth); + } + + /** + * Builds a {@link SchedulingPeriod} that occurs once every month, on a weekend. + * + * @param weekend the weekend. + * @return a {@link SchedulingPeriod} + */ + public static WeekendPeriod weekend(final String weekend) { + return WeekendPeriod.getEnum(weekend); + } + + /** + * Builds a {@link SchedulingPeriod} out of a series of Db entries (@link SchedulingPeriod}s). + * + * @param criteria a {@link List} of {@link DbSchedulingCriteriaVal} obtained from the DB + * @return the {@link SchedulingEnum} + * @throws InvalidInputException if unable to construct the period. + */ + public static SchedulingPeriod fromDbSchedulingCriteria(final List criteria) throws InvalidInputException { + // First find periodicity type (date / daily / weekly / monthly / weekend / day_in_month) + SchedulingEnum periodicity = getPeriodicity(criteria); + // Now findAll the value defining the periodicity + String value = getPeriodicityValue(criteria, periodicity); + return fromPeriodicityArguments(periodicity, value); + } + + private static String getPeriodicityValue(final List criteria, final SchedulingEnum periodicity) + throws InvalidInputException { + if (periodicity == SchedulingEnum.DAILY) { + return ""; // No value for daily periodicity + } + for (DbSchedulingCriteriaVal criterion : criteria) { + final String criteriaName = criterion.getDbCriteria().getCriteriaName(); + if (periodicity.getCriteriaName().equals(criteriaName)) { + return criterion.getCriteriaValue(); + } + } + throw new InvalidInputException("Unable to parse criteria for periodicity value : " + criteria.toString()); + } + + private static SchedulingEnum getBasicPeriodicity(final List criteria) throws InvalidInputException { + for (DbSchedulingCriteriaVal criterion : criteria) { + final String criteriaName = criterion.getDbCriteria().getCriteriaName(); + if (SchedulingEnum.PERIOD.toString().equals(criteriaName)) { + final String periodValue = criterion.getCriteriaValue().toLowerCase(); + return SchedulingEnum.getEnum(periodValue); + } + } + throw new InvalidInputException("Unable to parse criteria for periodicity type : " + criteria.toString()); + } + + private static SchedulingEnum getPeriodicity(final List criteria) throws InvalidInputException { + SchedulingEnum periodicity = getBasicPeriodicity(criteria); + if (periodicity == SchedulingEnum.WEEKEND) { + // Special periodicity type, might be constructed in three tiers: + // - period = weekend + // - weekend = day_in_month + // - day_in_month_value = [1..31] + // Instead of usual two-tiers: + // - period = weekend + // - weekend = first_we + String value = getPeriodicityValue(criteria, SchedulingEnum.WEEKEND); + if ("day_in_month_value".equals(value)) { + return SchedulingEnum.DAY_IN_MONTH_VALUE; + } + } + // Normal mode, periodicity was correctly found in 1st iteration + return periodicity; + } + + private static SchedulingPeriod fromPeriodicityArguments(final SchedulingEnum periodicityEnum, final String periodValue) + throws InvalidInputException { + SchedulingPeriod thePeriod; + switch (periodicityEnum) { + case DAILY: + thePeriod = PeriodFactory.daily(); + break; + case DATE: + try { + thePeriod = PeriodFactory.day(periodValue); + } catch (ParseException e) { + throw new InvalidUserInputException("Unable to parse date: " + periodValue, e); + } + break; + case DAY_IN_MONTH_VALUE: + try { + final int dayInMonth = Integer.parseInt(periodValue); + thePeriod = PeriodFactory.dayInMonth(dayInMonth); + } catch (NumberFormatException e) { + throw new InvalidUserInputException("Unable to parse day of month number (int): " + periodValue, e); + } + break; + case WEEKEND: + thePeriod = PeriodFactory.weekend(periodValue); + break; + case WEEKLY: + try { + final int dayInWeek = Integer.parseInt(periodValue); + thePeriod = PeriodFactory.weekly(dayInWeek); + } catch (NumberFormatException e) { + throw new InvalidUserInputException("Unable to parse day of week number (int): " + periodValue, e); + } + break; + default: + final String periodicityStr = periodicityEnum.toString(); + throw new InvalidUserInputException("Unable to understand periodicity value:" + periodicityStr); + } + return thePeriod; + } + + /** + * Returns a {@link SchedulingPeriod} (actually a {@link SpecificDay}) representing today. + * + * @return The schedulingPeriod. + */ + public static SpecificDay today() { + return new SpecificDay(Calendar.getInstance().getTime()); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/periodicity/SchedulingPeriod.java b/kurt-utility/src/main/java/com/capgemini/reports/periodicity/SchedulingPeriod.java new file mode 100644 index 0000000..596ad1c --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/periodicity/SchedulingPeriod.java @@ -0,0 +1,90 @@ +package com.capgemini.reports.periodicity; + +import com.capgemini.reports.database.javabean.enumeration.SchedulingEnum; +import com.capgemini.reports.database.manager.MngSchedulingCriteriaVal.SchedulingCriteriaValue; + +import java.util.List; + +/** + * Object representing various scheduling periodicities and their parameters.
    + * These periodicities are also ablo to presnt themselves as a {@link List} of database entries ({@link SchedulingCriteriaValue}s) using {@link SchedulingPeriod#asCriteriaValues()}. + */ +public interface SchedulingPeriod { + + /** + * Returns the instance of {@link SchedulingEnum} that represents the overall periodicity of this SchedulingPeriod. + * + * @return the instance of {@link SchedulingEnum} + */ + SchedulingEnum getPeriodicity(); + + /** + * Returns a {@link List} of database entries ({@link SchedulingCriteriaValue}s) that represent this period object.
    + * Example: period=weekly, weekly=3 + * + * @return a List of two SchedulingCriteriaValue + */ + List asCriteriaValues(); + + /** + * This object accepts a {@link PeriodVisitor}.
    + * It will invoke one of its visit method and pass itself as a parameter.
    + * This way, the visitor knows exactly which sub-class of {@link SchedulingPeriod} is used. + * + * @param any desired return type + * @param visitor the visitor + * @return any kind of interesting output + */ + T accept(final PeriodVisitor visitor); + + /** + * Visitor of {@link SchedulingPeriod}.
    + * By implementing this interface, you will be able to invoke {@link SchedulingPeriod#accept(PeriodVisitor)} on any SchedulingPeriod instance
    + * The SchedulingPeriod will in turn invoke the visitor's visit methods with itself as a strongly-typed argument. + * + * @param any kind of desired output + */ + interface PeriodVisitor { + + /** + * Behaviour to be had when visiting a {@link DayInMonth}. + * + * @param dayInMonth the day of the month + * @return any kind of desired output + */ + T visit(final DayInMonth dayInMonth); + + /** + * Behaviour to be had when visiting a {@link SpecificDay}. + * + * @param specificDay the day + * @return any kind of desired output + */ + T visit(final SpecificDay specificDay); + + /** + * Behaviour to be had when visiting a {@link WeekendPeriod}. + * + * @param weekend the weekend + * @return any kind of desired output + */ + T visit(final WeekendPeriod weekend); + + /** + * Behaviour to be had when visiting a {@link WeeklyPeriod}. + * + * @param dayInWeek the day of the week + * @return any kind of desired output + */ + T visit(final WeeklyPeriod dayInWeek); + + /** + * Behaviour to be had when visiting a {@link DailyPeriod}. + * + * @param uselessParam this parameter is useless, because a DailPeriod happens every day, by definition. + * @return any kind of desired output + */ + T visit(final DailyPeriod uselessParam); + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/periodicity/SpecificDay.java b/kurt-utility/src/main/java/com/capgemini/reports/periodicity/SpecificDay.java new file mode 100644 index 0000000..4417f56 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/periodicity/SpecificDay.java @@ -0,0 +1,82 @@ +package com.capgemini.reports.periodicity; + +import com.capgemini.framework.common.SettingsHelper; +import com.capgemini.framework.common.TeamcenterDateFormatter; +import com.capgemini.reports.database.javabean.enumeration.SchedulingEnum; +import com.capgemini.reports.database.manager.MngSchedulingCriteriaVal.SchedulingCriteriaValue; +import lombok.Getter; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +/** + * Represents a specific day for execution. Occurs only once. + */ +@Getter +public class SpecificDay implements SchedulingPeriod { + + private static final String LAUNCH_HOUR_STR = SettingsHelper.getDelayedLaunchHour(); + + private final Date day; + + /** + * Build a specific day. + * + * @param day the day using format: "dd-MM-yyyy" + * @throws ParseException if unable to parse the input date. + */ + public SpecificDay(final String day) throws ParseException { + this.day = getScheduledDate(day); + } + + /** + * Build a specific day. + * + * @param day the {@link Date} + * @throws ParseException + */ + protected SpecificDay(final Date day) { + this.day = day; + } + + @Override + public SchedulingEnum getPeriodicity() { + return SchedulingEnum.DATE; + } + + @Override + public T accept(final PeriodVisitor visitor) { + return visitor.visit(this); + } + + @Override + public List asCriteriaValues() { + List list = new ArrayList<>(2); + list.add(new SchedulingCriteriaValue(SchedulingEnum.PERIOD, SchedulingEnum.DATE.getCriteriaName())); + list.add(new SchedulingCriteriaValue(SchedulingEnum.DATE, String.valueOf(dateToString()))); + return list; + } + + /** + * Get the scheduled date. + * + * @param stringValue String - the date value to the TC format dd-MM-yyyy + * + * @throws ParseException if the parse of the {@link SimpleDateFormat} doesn't work. + * + * @return a {@link Date} pointing to the provided day, at the default hour & minute + */ + private Date getScheduledDate(final String stringValue) throws ParseException { + // Create a date with the appropriate value + SimpleDateFormat curFormater = new SimpleDateFormat(TeamcenterDateFormatter.DD_MM_YYYY_HH_MM); + return curFormater.parse(stringValue + " " + LAUNCH_HOUR_STR); + } + + private String dateToString() { + return new SimpleDateFormat(TeamcenterDateFormatter.DD_MM_YYYY).format(day); + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/periodicity/WeekendPeriod.java b/kurt-utility/src/main/java/com/capgemini/reports/periodicity/WeekendPeriod.java new file mode 100644 index 0000000..283308b --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/periodicity/WeekendPeriod.java @@ -0,0 +1,99 @@ +package com.capgemini.reports.periodicity; + +import com.capgemini.reports.database.javabean.enumeration.SchedulingEnum; +import com.capgemini.reports.database.manager.MngSchedulingCriteriaVal.SchedulingCriteriaValue; +import lombok.Getter; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Specific behaviors for the ALL_MONTH period. + */ +public enum WeekendPeriod implements SchedulingPeriod { + + /** + * The report will be executed the first Sunday of the month. + */ + FIRST_WEEK_END("first_we"), + /** + * The report will be executed the second Sunday of the month. + */ + SECOND_WEEK_END("second_we"), + /** + * The report will be executed the third Sunday of the month. + */ + THIRD_WEEK_END("third_we"), + /** + * The report will be executed the fourth Sunday of the month. + */ + FOURTH_WEEK_END("fourth_we"), + /** + * The report will be executed the fifth Sunday of the month. + */ + FIFTH_WEEK_END("fifth_we"), + /** + * The report will be executed the last day of the month. + */ + END_MONTH("end_of_month"); + + /** + * Enumeration cache for conversions. + **/ + private static final Map enumMap; + + static { + enumMap = new HashMap<>(WeekendPeriod.values().length); + for (WeekendPeriod currentEnum : WeekendPeriod.values()) { + enumMap.put(currentEnum.toString(), currentEnum); + } + } + + @Getter + private final String strMonthType; + + WeekendPeriod(final String strMonthType) { + this.strMonthType = strMonthType; + } + + /** + * Give the appropriate {@link WeekendPeriod} associate to the string value.
    + * Else return null. + * + * @param value String - the string value + * @return the appropriate {@link WeekendPeriod}. Return null if the string value doesn't exist. + */ + public static WeekendPeriod getEnum(final String value) { + return enumMap.get(value); + } + + @Override + public SchedulingEnum getPeriodicity() { + return SchedulingEnum.WEEKEND; + } + + @Override + public List asCriteriaValues() { + List list = new ArrayList<>(2); + list.add(new SchedulingCriteriaValue(SchedulingEnum.PERIOD, SchedulingEnum.WEEKEND.getCriteriaName())); + list.add(new SchedulingCriteriaValue(SchedulingEnum.WEEKEND, String.valueOf(this.getStrMonthType()))); + return list; + } + + /** + * Getter for object string value. + * + * @return String value with readable format + **/ + @Override + public String toString() { + return strMonthType; + } + + @Override + public T accept(final PeriodVisitor visitor) { + return visitor.visit(this); + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/periodicity/WeeklyPeriod.java b/kurt-utility/src/main/java/com/capgemini/reports/periodicity/WeeklyPeriod.java new file mode 100644 index 0000000..2ca9f4d --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/periodicity/WeeklyPeriod.java @@ -0,0 +1,35 @@ +package com.capgemini.reports.periodicity; + +import com.capgemini.reports.database.javabean.enumeration.SchedulingEnum; +import com.capgemini.reports.database.manager.MngSchedulingCriteriaVal.SchedulingCriteriaValue; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.ArrayList; +import java.util.List; + +/** Represents an event that occurs every week, on a specific week day. */ +@AllArgsConstructor +@Getter +public class WeeklyPeriod implements SchedulingPeriod { + + private final int dayInWeek; + + @Override + public SchedulingEnum getPeriodicity() { + return SchedulingEnum.WEEKLY; + } + + @Override + public T accept(final PeriodVisitor visitor) { + return visitor.visit(this); + } + + @Override + public List asCriteriaValues() { + List list = new ArrayList<>(2); + list.add(new SchedulingCriteriaValue(SchedulingEnum.PERIOD, SchedulingEnum.WEEKLY.getCriteriaName())); + list.add(new SchedulingCriteriaValue(SchedulingEnum.WEEKLY, String.valueOf(dayInWeek))); + return list; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/printing/PrintParameters.java b/kurt-utility/src/main/java/com/capgemini/reports/printing/PrintParameters.java new file mode 100644 index 0000000..0e5fd4b --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/printing/PrintParameters.java @@ -0,0 +1,444 @@ +package com.capgemini.reports.printing; + +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.reports.exceptions.ReportPrintException; +import com.capgemini.reports.jasper.compilers.JasperCompiler; +import com.capgemini.reports.jasper.fillers.JasperFiller; +import com.capgemini.reports.jasper.fillers.MonoFiller; +import com.capgemini.reports.jasper.fillers.MultiFiller; +import com.capgemini.reports.jasper.printers.JasperCSVPrinter; +import com.capgemini.reports.jasper.printers.JasperPDFPrinter; +import com.capgemini.reports.jasper.printers.JasperPrinter; +import com.capgemini.reports.jasper.printers.JasperXLSXPrinter; +import com.capgemini.reports.printing.Printer.PrintFormat; +import com.capgemini.reports.reports.output.ZipReport; +import net.sf.jasperreports.engine.JRException; +import net.sf.jasperreports.engine.JasperPrint; +import net.sf.jasperreports.engine.JasperReport; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.InputStream; +import java.util.*; +import java.util.Map.Entry; + +/** + * Constructs a report printing parameters. Use the static factory methods to obtain an instance. + */ +public class PrintParameters { + private static final Logger LOGGER = LoggerFactory.getLogger(PrintParameters.class); + private static final String REPORT_TITLE_MARKER = "report_title"; + private static final String ERROR_MESSAGE = "Could not prepare sub-report template from InputStream"; + // Main report content + private final JasperReport template; + private final Map parameters = new HashMap<>(); + private final List> reportData = new ArrayList<>(); + + // Sub reports content + private final Map subReports = new HashMap<>(); + + // Printing data + private final PrintFormat printTypes; + private final String outputFolder; + private final String outputFileName; + + /** + * Creates some {@link PrintParameters} to print the MAIN Report template.
    + * Specifies the file type (.xlsx, .pdf, ...), the file name, the Folder, and the template. + * + * @param printTypes the file type + * @param fileName the file name + * @param folder the Folder + * @param template the template (an {@link InputStream} to the .jrxml file) + * @throws JRException if the compilation goes wrong + */ + protected PrintParameters(final PrintFormat printTypes, final String fileName, final String folder, final InputStream template) + throws JRException { + this.printTypes = printTypes; + this.outputFileName = fileName; + this.outputFolder = folder; + this.template = JasperCompiler.compile(template); + } + + /** + * Creates some {@link PrintParameters} to print the MAIN Report template.
    + * Specifies the file type (.xlsx, .pdf, ...), the file name, the Folder, and the template. + * + * @param printTypes the file type + * @param fileName the file name + * @param folder the Folder + * @param template the template (a {@link String} whith the whole content) + * @throws JRException if the compilation goes wrong + */ + protected PrintParameters(final PrintFormat printTypes, final String fileName, final String folder, final String template) throws JRException { + this.printTypes = printTypes; + this.outputFileName = fileName; + this.outputFolder = folder; + this.template = JasperCompiler.compile(template); + } + + /** + * Creates some {@link PrintParameters} for a subReport, using its template's {@link InputStream}. + * + * @param template the template + * @throws JRException if the compilation goes wrong + */ + protected PrintParameters(final InputStream template) throws JRException { + this.printTypes = null; + this.outputFileName = ""; + this.outputFolder = ""; + this.template = JasperCompiler.compile(template); + } + + + /** + * Creates some {@link PrintParameters} for a subReport, using its template's full content (as a {@link String}). + * + * @param template the template + * @throws JRException if the compilation goes wrong + */ + protected PrintParameters(final String template) throws JRException { + this.printTypes = null; + this.outputFileName = ""; + this.outputFolder = ""; + this.template = JasperCompiler.compile(template); + } + + public PrintParameters(PrintFormat printFormat, String fileName, String folder) { + this.printTypes = printFormat; + this.outputFileName = fileName; + this.outputFolder = folder; + this.template = null; + } + + /** + * Creates some {@link PrintParameters} to be used as a sub-report. + * + * @param template the template (an {@link InputStream} to the .jrxml file) + * @return the {@link PrintParameters} for the sub-report + * @throws ReportPrintException if a Jasper exception was thrown + */ + public static PrintParameters createSubReport(final InputStream template) throws ReportPrintException { + try { + return new PrintParameters(template); + } catch (JRException e) { + throw new ReportPrintException(ERROR_MESSAGE, e); + } + } + + /** + * Creates some {@link PrintParameters} for the main report.
    + * Specifies the file type (.xlsx, .pdf, ...), the file name, the Folder, and the template. + * + * @param printTypes the file type + * @param fileName the file name + * @param folder the Folder + * @param template the template (an {@link InputStream} to the .jrxml file) + * @return the {@link PrintParameters} for the main report + * @throws ReportPrintException if the template could not be understood by the printer. + */ + public static PrintParameters createMainReport(final PrintFormat printTypes, final String fileName, final String folder, + final InputStream template) throws ReportPrintException { + try { + return new PrintParameters(printTypes, fileName, folder, template); + } catch (JRException e) { + throw new ReportPrintException(ERROR_MESSAGE, e); + } + } + + /** + * Creates some {@link PrintParameters} for the main report.
    + * Specifies the file type (.xlsx, .pdf, ...), the file name, the Folder, and the template. + * + * @param printTypes the file type + * @param fileName the file name + * @param folder the Folder + * @param template the template (a {@link String} containing the actual jrxml content) + * @return the {@link PrintParameters} for the main report + * @throws ReportPrintException if a Jasper exception was thrown + */ + public static PrintParameters createMainReport(final PrintFormat printTypes, final String fileName, final String folder, final String template) + throws ReportPrintException { + try { + return new PrintParameters(printTypes, fileName, folder, template); + } catch (JRException e) { + throw new ReportPrintException(ERROR_MESSAGE, e); + } + } + + /** + * Creates some {@link PrintParameters} to be used as a sub-report.
    + * + * @param template the template (a {@link String} containing the actual jrxml content) + * @return the {@link PrintParameters} for the main report + * @throws ReportPrintException if a Jasper exception was thrown + */ + public static PrintParameters createSubReport(final String template) throws ReportPrintException { + try { + return new PrintParameters(template); + } catch (JRException e) { + throw new ReportPrintException("Could not prepare sub-report template from String", e); + } + } + + /** + * Returns true if the report has sub reports, false otherwise. + * + * @return a boolean + */ + boolean hasSubReports() { + return !subReports.isEmpty(); + } + + /** + * Adds some parameters to this report. + * + * @param key the String key + * @param additionalParameter the parameter content + */ + public void addReportParameter(final String key, final Object additionalParameter) { + parameters.put(key, additionalParameter); + } + + /** + * Adds some parameters to this report. + * + * @param key the enum key + * @param additionalParameter the parameter content + * @param generic object + */ + public > void addReportParameter(final K key, final Object additionalParameter) { + parameters.put(key.toString(), additionalParameter); + } + + /** + * Adds some parameters to this report. + * + * @param Generic object + * @param additionalParameters the parameters, as a {@link Map} whose keys are {@link Enum}s + */ + public > void addReportParameters(final Map additionalParameters) { + for (Entry entry : additionalParameters.entrySet()) { + parameters.put(entry.getKey().toString(), entry.getValue()); + } + } + + /** + * Sets the title of the report. + * + * @param title the title of this report + */ + public void setReportTitle(final String title) { + parameters.put(REPORT_TITLE_MARKER, title); + } + + /** + * Adds data to this report. + * + * @param data a {@link Collection} of several {@link Map}s of data. The Maps use {@link String}s as keys. + */ + public void addReportData(final Collection> data) { + reportData.addAll(data); + } + + /** + * Adds data to this report. + * + * @param Generic object + * @param data a {@link Collection} of several {@link EnumMap}s of data. The Maps use {@link Enum}s as keys + */ + public > void addReportDataFromEnum(final Collection> data) { + for (Map map : data) { + Map newMap = new HashMap<>(); + for (Entry entry : map.entrySet()) { + newMap.put(entry.getKey().toString(), entry.getValue()); + } + reportData.add(newMap); + } + } + + /** + * Adds a simple sub-report to this report. + * + * @param key a {@link String} key identifying the name of this sub-report + * @param aTemplate the sub-report's template, as an {@link InputStream} + * @param data the data forming this sub-report + * @param someParams some parameters for this sub-report + * @param An enum whose values will be used as keys to link to the report data, one map of those keys for each line of the report. + * @param An enum whose values will be used as keys to link to report parameters. Parameters are the same throughout the report. + * @throws ReportPrintException if a Jasper exception was thrown + */ + public , V extends Enum> void addSubReport(final String key, final InputStream aTemplate, + final Collection> data, final Map someParams) throws ReportPrintException { + try { + PrintParameters subReport = new PrintParameters(aTemplate); + subReport.addReportDataFromEnum(data); + subReport.addReportParameters(someParams); + subReports.put(key, subReport); + } catch (JRException e) { + throw new ReportPrintException(ERROR_MESSAGE, e); + } + } + + /** + * Adds a potentially more complex sub-report to this report.
    + * The sub-report may itself have some sub-reports + * + * @param key a {@link String} key identifying the name of this sub-report + * @param subReport a {@link PrintParameters} whith all the sub-report data configured + */ + public void addSubReport(final String key, final PrintParameters subReport) { + subReports.put(key, subReport); + } + + /** + * Returns the expected extension of the printed file: ".xlsx", ".csv" etc. + * + * @return the extension (including the dot) + */ + public String getOuputFileExtension() { + String extension; + switch (this.printTypes) { + case CSV: + extension = ".csv"; + break; + case PDF: + extension = ".pdf"; + break; + case XLSX: + extension = ".xlsx"; + break; + case ZIP: + extension = ".zip"; + break; + default: + extension = ".txt"; + break; + } + return extension; + } + + /** + * Creates a {@link JasperFiller} from this report, configured with the template, the data, and the parameters. + * + * @return the {@link JasperFiller} + * @throws JRException if report creation failed + */ + public JasperFiller createReportFiller() throws JRException { + if (this.hasSubReports()) { + return createReportMultiFiller(); + } else { + return createReportMonoFiller(); + } + } + + /** + * Creates a simple mono-report. Must be called only if this report does not have sub-reports. + * + * @return a {@link MultiFiller} set up + */ + private MonoFiller createReportMonoFiller() { + return new MonoFiller(template, reportData, parameters); + } + + /** + * Recursive for sub-(sub)-reports. + * + * @return a {@link MultiFiller} set up + */ + private MultiFiller createReportMultiFiller() { + MultiFiller mainFiller = new MultiFiller(template, reportData, parameters); + for (Entry entry : subReports.entrySet()) { + PrintParameters subReport = entry.getValue(); + JasperReport compiledTemplate = subReport.getTemplate(); + if (subReport.hasSubReports()) { + MultiFiller subReportFiller = subReport.createReportMultiFiller(); + mainFiller.addSubReport(entry.getKey(), subReportFiller); + } else { + mainFiller.addSubReport(entry.getKey(), compiledTemplate, subReport.getReportData(), subReport.getParameters()); + } + } + return mainFiller; + } + + /** + * Effectue l'impression proprement dite ave le plugin JASPER. + */ + File jasperPrint() throws ReportPrintException { + // Fill in the data + JasperPrint print; + try { + print = createReportFiller().generate(); + } catch (JRException e) { + throw new ReportPrintException("An exception occurred while filling the reports", e); + } + + // Print + try { + return jasperPrinter().print(print); + } catch (JRException e) { + throw new ReportPrintException("An exception occurred while printing the reports", e); + + } + } + + private JasperPrinter jasperPrinter() { + // Create the printer + switch (printTypes) { + case PDF: + return new JasperPDFPrinter(outputFolder, outputFileName); + case XLSX: + return new JasperXLSXPrinter(outputFolder, outputFileName); + case CSV: + default: + return new JasperCSVPrinter(outputFolder, outputFileName); + } + } + + File createZip() throws KurtException { + List filesToZip = new ArrayList<>(); + for (Entry entry : subReports.entrySet()) { + PrintParameters printParameters = entry.getValue(); + if (printParameters.printTypes == PrintFormat.ZIP) { + filesToZip.add(printParameters.createZip()); + } + else { + filesToZip.add(printParameters.jasperPrint()); + } + } + return new ZipReport(outputFolder + outputFileName + ".zip", filesToZip).print().getFile(); + } + + /** + * Prints to console. + */ + File consolePrint() { + // Print + LOGGER.info("Printing to console"); + LOGGER.info("outputFolder ={}", outputFolder); + LOGGER.info("outputFileName ={}", outputFileName); + LOGGER.info("Parameters ={}", parameters); + LOGGER.info("dataMaps size ={}", reportData.size()); + for (Map line : reportData) { + LOGGER.info(" + {}", line.toString()); + } + return null; // No file to be had! this is console + } + + public JasperReport getTemplate() { + return template; + } + + public List> getReportData() { + return reportData; + } + + public Map getParameters() { + return parameters; + } + + public Map getSubReports() { + return subReports; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/printing/PrintReportHelper.java b/kurt-utility/src/main/java/com/capgemini/reports/printing/PrintReportHelper.java new file mode 100644 index 0000000..c139065 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/printing/PrintReportHelper.java @@ -0,0 +1,65 @@ +package com.capgemini.reports.printing; + +import com.capgemini.reports.exceptions.ReportPrintException; +import com.capgemini.reports.execution.AbstractExecutionReport; + +import java.io.InputStream; + +/** + * This class helper will allow to use the method which will set up the parameters for the printing. + * + */ +public final class PrintReportHelper { + + private PrintReportHelper() { + + } + + /** + * Sets up basic printing parameters. + *
      + *
    • Main report Template
    • + *
    • Output folder
    • + *
    • File name
    • + *
    • Report title
    • + *
    + * + * @param template the report template. NOTE: the {@link InputStream} is consumed in this method, but it is the resposibility of the caller to perform the {@link InputStream#close() close()} operation. + * @param outputFolder folder where the file will be saved + * @param outputFileName name of the file as it will be saved on disc + * @param aAbstractExecutionReport will provide all informations for the report which is executing + * @return the PrintParameters configured + * @throws ReportPrintException if the template could not be understood by the printer. + */ + public static PrintParameters setupPrintParameters(final InputStream template, final String outputFolder, final String outputFileName, + final AbstractExecutionReport aAbstractExecutionReport) throws ReportPrintException { + PrintParameters printParameters = + PrintParameters.createMainReport(aAbstractExecutionReport.getPrintingFormat(), outputFileName, outputFolder, template); + printParameters.setReportTitle(aAbstractExecutionReport.getReportIdentifier().getReportTitle()); + return printParameters; + } + + /** + * Sets up basic printing parameters. + *
      + *
    • Main report Template
    • + *
    • Output folder
    • + *
    • File name
    • + *
    • Report title
    • + *
    + * + * @param template the template (a {@link String} containing the actual .jrxml content) + * @param outputFolder the folder where the file will be saved + * @param outputFileName the file name + * @param aAbstractExecutionReport will provide all informations for the report which is executing + * @return the PrintParameters configured + * @throws ReportPrintException if unable to create the report template + */ + public static PrintParameters setupPrintParameters(final String template, final String outputFolder, final String outputFileName, + final AbstractExecutionReport aAbstractExecutionReport) throws ReportPrintException { + PrintParameters printParameters = + PrintParameters.createMainReport(aAbstractExecutionReport.getPrintingFormat(), outputFileName, outputFolder, template); + printParameters.setReportTitle(aAbstractExecutionReport.getReportIdentifier().getReportTitle()); + return printParameters; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/printing/Printer.java b/kurt-utility/src/main/java/com/capgemini/reports/printing/Printer.java new file mode 100644 index 0000000..681560d --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/printing/Printer.java @@ -0,0 +1,60 @@ +package com.capgemini.reports.printing; + +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.reports.exceptions.ReportPrintException; + +import java.io.File; + +/** + * This class can print a report using a certain API (JASPER, BURT...) on a {@link PrintParameters}. + */ +public class Printer { + + private final AvailablePrinter availablePrinter; + + /** + * Construit un Printer en specifiant le plugin a utiliser (JASPER, BURT...). + * + * @param printer le plugin a utiliser pour imprimer + */ + public Printer(final AvailablePrinter printer) { + this.availablePrinter = printer; + } + + /** + * Effectue l'impression proprement dite. + * + * @param params les parametres d'impression + * @return a {@link File} referencing the produced document + * @throws ReportPrintException if a Jasper exception was thrown + */ + public File print(final PrintParameters params) throws KurtException { + switch (availablePrinter) { + case JASPER: + return params.jasperPrint(); + case ZIP: + return params.createZip(); + default: + return params.consolePrint(); + } + } + + /** + * All sorts of available output formats. + */ + public enum PrintFormat { + PDF, + XLSX, + CSV, + ZIP + } + + /** + * All sorts of available output formats. + */ + public enum AvailablePrinter { + JASPER, + ZIP, + TEST + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/queuing/ReportPriority.java b/kurt-utility/src/main/java/com/capgemini/reports/queuing/ReportPriority.java new file mode 100644 index 0000000..52d4fd5 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/queuing/ReportPriority.java @@ -0,0 +1,76 @@ +package com.capgemini.reports.queuing; + +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; + +/** Reflects the priority level of each report. */ +@Getter +@Slf4j +public enum ReportPriority { + HIGH_PRIORITY(1), + MED_PRIORITY(2), + LOW_PRIORITY(3); + + private static final int HIGH_PRIORITY_VALUE = 1; + private static final int MED_PRIORITY_VALUE = 2; + private static final int LOW_PRIORITY_VALUE = 3; + + private final int priorityValue; + + ReportPriority(final int priorityValue) { + this.priorityValue = priorityValue; + } + + @Override + public String toString() { + String val; + switch (this) { + case HIGH_PRIORITY: + val = "High Priority Queue"; + break; + case MED_PRIORITY: + val = "Medium Priority Queue"; + break; + case LOW_PRIORITY: + val = "Low Priority Queue"; + break; + default: + val = "No Queue"; + break; + } + return val; + } + + /** + * Give the appropriate {@link ReportPriority} associate to a code:
    + *
      + *
    • Code 1 : HIGH_PRIORITY
    • + *
    • Code 2 : MED_PRIORITY
    • + *
    • Code 3 : LOW_PRIORITY
    • + *
    + * Else return null. + * + * @param value int - the code value + * @return the appropriate {@link ReportPriority} + */ + public static ReportPriority getReportPriority(final int value) { + ReportPriority priority; + switch (value) { + case HIGH_PRIORITY_VALUE: + priority = ReportPriority.HIGH_PRIORITY; + break; + case MED_PRIORITY_VALUE: + priority = ReportPriority.MED_PRIORITY; + break; + case LOW_PRIORITY_VALUE: + priority = ReportPriority.LOW_PRIORITY; + break; + default: + log.error("No priority found for reports. The int {} is not valid (only 1, 2, 3 allowed). Defaulting to LOW priority", + String.valueOf(value)); + priority = ReportPriority.LOW_PRIORITY; + break; + } + return priority; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/reports/IReportVisitor.java b/kurt-utility/src/main/java/com/capgemini/reports/reports/IReportVisitor.java new file mode 100644 index 0000000..6b8c500 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/reports/IReportVisitor.java @@ -0,0 +1,24 @@ +package com.capgemini.reports.reports; + +import java.util.List; +import java.util.Map; + +import com.capgemini.reports.bomlineholder.BOMLineHolder; + +/** + * Interface Generic Report Generator using the Visitor pattern. + * + * @param key + * @param value + */ +public interface IReportVisitor { + + /** + * visits a report and presents a result that the printer can understand. + * + * @param holder the top {@link BOMLineHolder} + * @return the report contents + */ + List> visitReport(final BOMLineHolder holder); + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/reports/output/ReportOutput.java b/kurt-utility/src/main/java/com/capgemini/reports/reports/output/ReportOutput.java new file mode 100644 index 0000000..31fadb1 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/reports/output/ReportOutput.java @@ -0,0 +1,8 @@ +package com.capgemini.reports.reports.output; + +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import net.lingala.zip4j.core.ZipFile; + +public interface ReportOutput { + ZipFile print() throws KurtException; +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/reports/output/ZipReport.java b/kurt-utility/src/main/java/com/capgemini/reports/reports/output/ZipReport.java new file mode 100644 index 0000000..705a009 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/reports/output/ZipReport.java @@ -0,0 +1,53 @@ +package com.capgemini.reports.reports.output; + + +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import net.lingala.zip4j.core.ZipFile; +import net.lingala.zip4j.exception.ZipException; +import net.lingala.zip4j.model.ZipParameters; +import net.lingala.zip4j.util.Zip4jConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.util.List; + +public class ZipReport implements ReportOutput { + private static final Logger LOGGER = LoggerFactory.getLogger(ZipReport.class); + + private final String zipFilePath; + private final List filesToCompress; + + public ZipReport(final String zipFilePath, final List filesToCompress) { + this.zipFilePath = zipFilePath; + this.filesToCompress = filesToCompress; + } + + @Override + public ZipFile print() throws KurtException { + try { + ZipFile zipFile = new ZipFile(zipFilePath); + ZipParameters parameters = zipParameters(); + addFilesToZip(zipFile, parameters); + return zipFile; + } catch (ZipException e) { + throw new KurtException(e.getMessage(), e); + } + } + + private ZipParameters zipParameters() { + ZipParameters parameters = new ZipParameters(); + parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE); + parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL); + return parameters; + } + + private void addFilesToZip(ZipFile zipFile, ZipParameters parameters) throws ZipException { + for (File file : filesToCompress) { + zipFile.addFile(file, parameters); + if (file.delete()) { + LOGGER.debug("Archive file {} deleted.", file.getName()); + } + } + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/templates/Alignment.java b/kurt-utility/src/main/java/com/capgemini/reports/templates/Alignment.java new file mode 100644 index 0000000..79859b6 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/templates/Alignment.java @@ -0,0 +1,22 @@ +package com.capgemini.reports.templates; + +/** + * Horizontal Text alignment for jrxml template. + */ +public enum Alignment { + LEFT("Left"), + CENTER("Center"), + RIGHT("Right"), + JUSTIFIED("Justified"); + + private final String value; + + Alignment(final String str) { + value = str; + } + + @Override + public String toString() { + return value; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/templates/Cell.java b/kurt-utility/src/main/java/com/capgemini/reports/templates/Cell.java new file mode 100644 index 0000000..eeefefe --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/templates/Cell.java @@ -0,0 +1,237 @@ +package com.capgemini.reports.templates; + +import com.capgemini.framework.common.StringHelper; +import lombok.Getter; + +import java.util.Map; + +/** + * Represents a Cell in a jrxml Grid Template.
    + * A Cell may be a static textfield, a dynamic Parameter textfield, or a dynamic Field textfield. + */ +@Getter +public final class Cell { + // Parameters and field declarations + private static final String REPORT_FIELD_BEGIN = "\n "; + + // Text elements to create a Cell + private static final String BEGIN_TEXTFIELD = "\n "; + private static final String BEGIN_TEXTFIELD_STRETCH_WITH_OVERFLOW = "\n "; + private static final String BEGIN_STATICTEXT = "\n "; + private static final String BEGIN_STATICTEXT_STRETCH_WITH_OVERFLOW = "\n "; + private static final String BEGIN_ELEMENT = "\n "; + private static final String HTML_MARKUP_BEGIN = "\n \n"; + private static final String END_TEXTELEMENT = "\n "; + private static final String BEGIN_FIELD = "\n "; + private static final String BEGIN_TEXT = "\n "; + private static final String END_TEXTFIELD = "\n "; + private static final String END_STATICTEXT = "\n "; + + // Make a nice box af any textField + private static final String BOX_L1 = "\n "; + private static final String BOX_L2 = "\n "; + private static final String BOX_L3 = "\n "; + private static final String BOX_L4 = "\n "; + private static final String BOX_L5 = "\n "; + private static final String BOX_L6 = "\n "; + + + // Final Cell properties + private final boolean dynamic; + private final boolean isHeader; + private final boolean isStretchWithOverflow; + private final String content; + private final String xPosition; + private final String yPosition; + private final String width; + + private final CellFormat format; + private String nameStyle; + + // The Cell height may vary, do not make this final + private int height; + + private static final String END_STYLE = "\""; + + /** + * Creates a static textfield, with fixed text content (Cannot stretch with overflow). + * + *
    +     * < textField>}
    +     *     < reportElement x="0" y="0" width="100" height="20"/>
    +     *     < textFieldExpression>< ![CDATA[Some text content]]>< /textFieldExpression>}
    +     * < /textField>
    +     * 
    + * + * @param content the text content as a {@link String} + * @param height the Cell height + * @param width the Cell width + * @param xPosition the Cell horizontal position + * @param yPosition the Cell vertical position + * @param format this cell's format + * @return a properly built {@link Cell} + */ + public static Cell makeStaticCell(final String content, final int height, final int width, final int xPosition, final int yPosition, + final CellFormat format) { + return new Cell(content, false, true, false, height, width, xPosition, yPosition, format); + } + + /** + * Creates a dynamic Field textfield, whose content will be replaced using the value with a matching key in the field {@link Map}.
    + * Exemple: + * + *
    +     * < textField>
    +     *     < reportElement x="0" y="0" width="100" height="20"/>
    +     *     < textFieldExpression>< ![CDATA[$F{FIELD_KEY_HERE}]]>< /textFieldExpression>
    +     * < /textField>
    +     * 
    + * + * @param fieldKey the field key as a {@link String} + * @param height the Cell height + * @param width the Cell width + * @param stretchWithOverflow if true, the cell will expand downwards to shall all the text inside it + * @param xPosition the Cell horizontal position + * @param yPosition the Cell vertical position + * @param format this cell's format + * @return a properly built {@link Cell} + */ + public static Cell makeFieldCell(final String fieldKey, final int height, final int width, final boolean stretchWithOverflow, + final int xPosition, final int yPosition, final CellFormat format) { + return new Cell(fieldKey, true, false, stretchWithOverflow, height, width, xPosition, yPosition, format); + } + + + /** + * Creates a dynamic Parameter textfield, whose content will be replaced using the value with a matching key in the parameters {@link Map}.
    + * Exemple: + * + *
    +     * < textField>
    +     *     < reportElement x="0" y="0" width="100" height="20"/>
    +     *     < textFieldExpression>< ![CDATA[$P{PARAMETER_KEY_HERE}]]>< /textFieldExpression>
    +     * < /textField>
    +     * 
    + * + * @param parameterKey the parameter key as a {@link String} + * @param height the Cell height + * @param width the Cell width + * @param stretchWithOverflow if true, the cell will expand downwards to shall all the text inside it + * @param xPosition the Cell horizontal position + * @param yPosition the Cell vertical position + * @param format this cell's format + * @return a properly built {@link Cell} + */ + public static Cell makeParameterCell(final String parameterKey, final int height, final int width, final boolean stretchWithOverflow, + final int xPosition, final int yPosition, final CellFormat format) { + return new Cell(parameterKey, true, true, stretchWithOverflow, height, width, xPosition, yPosition, format); + } + + private Cell(final String content, final boolean dynamic, final boolean isHeader, final boolean stretchWithOverflow, final int height, + final int width, final int xPosition, final int yPosition, final CellFormat format) { + this.content = content; + this.dynamic = dynamic; + this.isHeader = isHeader; + this.isStretchWithOverflow = dynamic && stretchWithOverflow; // can only use stretch With Overflow in dynamic cell + this.height = height; + this.width = String.valueOf(width); + this.xPosition = String.valueOf(xPosition); + this.yPosition = String.valueOf(yPosition); + this.format = format == null ? new CellFormat() : format; + } + + /** + * Adds some extra height to this Cell, increasing its height towards the bottom. + * + * @param extraHeight the extra height, in pixels + */ + public void addHeight(final int extraHeight) { + this.height += extraHeight; + } + + /** + * Generates a cell declaration for a jrxml template. + * + * @return a String containing the full cell template + */ + public String makeCell() { + String heightStr = String.valueOf(height); + String alignmentStr = format.getAlignment(); + String color = format.getColor(); + String bold = format.getIsBold(); + String aLignementVertical = format.getVerticalAligement(); + if (dynamic) { + if (nameStyle != null) { + return StringHelper.concatToString(isStretchWithOverflow ? BEGIN_TEXTFIELD_STRETCH_WITH_OVERFLOW : BEGIN_TEXTFIELD, BEGIN_ELEMENT, + isStretchWithOverflow ? STRETCH_TYPE : "", BEGIN_STYLE, nameStyle, END_STYLE, BEGIN_XPOS, xPosition, X_TO_Y, yPosition, + Y_TO_WIDTH, width, HEIGHT, heightStr, END_ELEMENT, BOX_L1, BOX_L2, BOX_L3, BOX_L4, BOX_L5, BOX_L6, HTML_MARKUP_BEGIN, + alignmentStr, HTML_MARKUP_END, END_TEXTELEMENT, BEGIN_FIELD, content, END_EXPRESSION, END_TEXTFIELD); + + } + else { + return StringHelper.concatToString(isStretchWithOverflow ? BEGIN_TEXTFIELD_STRETCH_WITH_OVERFLOW : BEGIN_TEXTFIELD, BEGIN_ELEMENT, + isStretchWithOverflow ? STRETCH_TYPE : "", BEGIN_XPOS, xPosition, X_TO_Y, yPosition, Y_TO_WIDTH, width, HEIGHT, heightStr, + END_ELEMENT, BOX_L1, BOX_L2, BOX_L3, BOX_L4, BOX_L5, BOX_L6, HTML_MARKUP_BEGIN, alignmentStr, HTML_MARKUP_END, + END_TEXTELEMENT, isHeader ? BEGIN_PARAMETER : BEGIN_FIELD, content, END_EXPRESSION, END_TEXTFIELD); + } + } + else { + return StringHelper.concatToString(isStretchWithOverflow ? BEGIN_STATICTEXT_STRETCH_WITH_OVERFLOW : BEGIN_STATICTEXT, BEGIN_ELEMENT, + isStretchWithOverflow ? STRETCH_TYPE : "", BEGIN_XPOS, xPosition, X_TO_Y, yPosition, Y_TO_WIDTH, width, HEIGHT, heightStr, color, + END_ELEMENT, BOX_L1, BOX_L2, BOX_L3, BOX_L4, BOX_L5, BOX_L6, HTML_MARKUP_BEGIN, alignmentStr, aLignementVertical, + HTML_MARKUP_END, bold, END_TEXTELEMENT, BEGIN_TEXT, content, END_TEXT, END_STATICTEXT); + } + + } + + /** + * Returns a declaration of this cell's Field key, if it is a dynamic field. + * + * @return the {@link String} key + */ + public String getFieldsDeclaration() { + if (!this.isDynamic() || this.isHeader) { + return ""; + } + else { + return REPORT_FIELD_BEGIN + content + REPORT_FIELD_OR_PARAM_END; + } + } + + /** + * Returns a declaration of this cell's Parameter key, if it is a dynamic parameter. + * + * @return the {@link String} key + */ + public String getParametersDeclaration() { + if (!this.isDynamic() || !this.isHeader) { + return ""; + } + else { + return REPORT_PARAMETER_BEGIN + content + REPORT_FIELD_OR_PARAM_END; + } + } + + /** + * Gives the Cell a style by the provided name. + * + * @param aNameStyle the name of the style. Use null to remove style. + */ + public void setNameStyle(final String aNameStyle) { + nameStyle = aNameStyle; + } +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/templates/CellFormat.java b/kurt-utility/src/main/java/com/capgemini/reports/templates/CellFormat.java new file mode 100644 index 0000000..e455577 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/templates/CellFormat.java @@ -0,0 +1,93 @@ +package com.capgemini.reports.templates; + +import lombok.Getter; + +/** Represents a Cell's format: stretch with overflow, color, alignment. */ +@Getter +public class CellFormat { + + private static final String EMPTY_STRING = ""; + private static final String BEGIN_COLOR = "\" mode=\"Opaque\" backcolor=\""; + private static final String FORECOLOR = " forecolor =\""; + private static final String END_COLOR = ""; + private static final String ALIGNMENT_BEGIN = " textAlignment=\""; + private static final String ALIGNMENT_END = "\""; + private static final String BEGIN_BOLD = "\n "; + private static final String VERTICAL_ALIGNEMENT = " verticalAlignment=\""; + private static final String END_ALIGNEMENT = ">"; + + protected String alignment; + protected String color; + protected String verticalAligement; + + private String isBold; + protected String colorForecolor; + + /** Basic constructor. Color is black, Alignment is default (left). */ + public CellFormat() { + this.alignment = EMPTY_STRING; + this.color = EMPTY_STRING; + this.isBold = EMPTY_STRING; + this.verticalAligement = EMPTY_STRING; + } + + /** + * Specify an {@link Alignment}. + * + * @param anAlignment + * @return same object, for chaining + */ + public CellFormat setAlignment(final Alignment anAlignment) { + this.alignment = makeAlignmentDeclaration(anAlignment); + return this; + } + + /** + * If null, the cell is transparent. Otherwise, this is a color code like '#E3E3E3' -> grey. + * + * @param colorID + * @return this same object, for chaining + */ + public CellFormat setColor(final String colorID) { + this.color = makeColorDeclaration(colorID); + return this; + } + + /** + * Method which allow to put the value of a cell in bold. + * + * @param isBold + * @return the object CellFormat + */ + public CellFormat setBold(final boolean isBold) { + this.isBold = makeBoldDeclaration(isBold); + return this; + } + + /** + * Make an alignment for the cell's value. + * + * @param nameVerticalAlignement + */ + public void setAlignment(final String nameVerticalAlignement) { + this.verticalAligement = makeVerticalAlignmentDeclaration(nameVerticalAlignement); + } + + private String makeBoldDeclaration(boolean isBold2) { + return isBold == null ? EMPTY_STRING : BEGIN_BOLD + isBold2 + END; + } + + private String makeColorDeclaration(final String aColor) { + return aColor == null ? EMPTY_STRING : BEGIN_COLOR + aColor + END_COLOR; + } + + private String makeAlignmentDeclaration(final Alignment anAlignment) { + return anAlignment == null ? EMPTY_STRING : ALIGNMENT_BEGIN + anAlignment.toString() + ALIGNMENT_END; + } + + private String makeVerticalAlignmentDeclaration(final String anAlignment) { + return anAlignment == null ? EMPTY_STRING : VERTICAL_ALIGNEMENT + anAlignment; + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/templates/Column.java b/kurt-utility/src/main/java/com/capgemini/reports/templates/Column.java new file mode 100644 index 0000000..847f102 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/templates/Column.java @@ -0,0 +1,122 @@ +package com.capgemini.reports.templates; + +import lombok.Getter; + +import java.util.ArrayList; +import java.util.List; + +/** + * Represents a column for a .jrxml dynamic table template.
    + * A {@link Column} specifies a series of content Dynamic field {@link Cell Cells}, and may (optionally) specify some Header {@link Cell Cells}. These header cells may contain static text, or a reference to a report parameter key. + */ +@Getter +public class Column { + + private final List headers; + private final Cell field; + private final int width; + private final int xPosition; + /** The total height of all the headers. grows whenever a new header {@link Cell} is added. */ + private int totalHeaderHeight; + + + + /** + * Creates a {@link Column} object. Field cells are always transparent. + * + * @param fieldKey The field key to put into the table body + * @param width The Column width, in pixels. All {@link Cell Cells} inside this column will have the same width + * @param stretchWithOverflow if true, the cell will expand downwards to shall all the text inside it + * @param xPosition the Column's horizontal position, in pixels + * @param contentHeight the height of any field cell in the table's body + * @param fieldFormat the format of this field + */ + public Column(final String fieldKey, final int width, final int xPosition, final boolean stretchWithOverflow, final int contentHeight, + final CellFormat fieldFormat) { + this.headers = new ArrayList<>(); + this.field = Cell.makeFieldCell(fieldKey, contentHeight, width, stretchWithOverflow, xPosition, 0, fieldFormat); + this.width = width; + this.xPosition = xPosition; + this.totalHeaderHeight = 0; + } + + /** + * Adds a Header {@link Cell} to this column. This Cell is added as the last header cell, right before the table body. + * + * @param dynamic if true, then this header clel will contain a reference to a report parameter using the content argument as a key + * @param content the Header content. If this header is dynamic, it is the name of the paremeter key. If it is not dynamic, this content will be the raw static text to display in the cell. + * @param height this header cell's height + * @param stretchWithOverflow if true, the cell will expand downwards to shall all the text inside it. Ignored if the cell is Static + * @param format This header line's format + */ + public void addHeader(final String content, final boolean dynamic, final int height, final boolean stretchWithOverflow, final CellFormat format) { + if (dynamic) { + headers.add(Cell.makeParameterCell(content, height, width, stretchWithOverflow, xPosition, totalHeaderHeight, format)); + } + else { + headers.add(Cell.makeStaticCell(content, height, width, xPosition, totalHeaderHeight, format)); + } + totalHeaderHeight += height; + } + + /** + * Lengthens the previous header Cell (if any). To be used to fuse cells istead of creating a new one. + * + * @param heightPx the height to add to the previous header cell, in pixels + */ + public void addToPreviousHeaderCellHeight(final int heightPx) { + if (!headers.isEmpty()) { + headers.get(headers.size() - 1).addHeight(heightPx); + totalHeaderHeight += heightPx; + } + } + + /** + * Generates the .jrxml code for this column's headers. + * + * @return a String containing the text to put in the template + */ + public String makeHeaders() { + StringBuilder output = new StringBuilder(); + for (Cell header : headers) { + output.append(header.makeCell()); + } + return output.toString(); + } + + /** + * Generates the .jrxml code for this column's body field. + * + * @return a String containing the text to put in the template + */ + public String makeContent() { + return field.makeCell(); + } + + /** + * Returns a declaration of this Column's Field key, if it is a dynamic field. + * + * @return the {@link String} key + */ + public String getFieldsDeclaration() { + return field.getFieldsDeclaration(); + } + + /** + * Returns all the declarations of this Column's Parameter keys, if any. + * + * @return the {@link String} declarations, or an empty string if none are required + */ + public String getParametersDeclaration() { + StringBuilder stringBuilder = new StringBuilder(); + for (Cell header : headers) { + if (header.isDynamic()) { + stringBuilder.append(header.getParametersDeclaration()); + } + } + return stringBuilder.toString(); + } + + + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/templates/DynamicGridTemplateBuilder.java b/kurt-utility/src/main/java/com/capgemini/reports/templates/DynamicGridTemplateBuilder.java new file mode 100644 index 0000000..44834ed --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/templates/DynamicGridTemplateBuilder.java @@ -0,0 +1,220 @@ +package com.capgemini.reports.templates; + +import com.capgemini.framework.common.FileTemplate; +import com.capgemini.framework.common.ResourceHelper; +import com.capgemini.reports.exceptions.FileLoadingException; +import com.capgemini.reports.exceptions.InvalidInputException; + +import java.util.ArrayList; +import java.util.List; + +/** + * Dynamically creates a jrxml template for a table with an arbitrary number of columns. + */ +public class DynamicGridTemplateBuilder extends FileTemplate { + + // Keys to replace in the template.jrxml + private static final String HEADER_HEIGHT = "HEADER_HEIGHT"; + private static final String CONTENT_HEIGHT = "CONTENT_HEIGHT"; + protected static final String TITLE_HEIGHT = "TITLE_HEIGHT"; + private static final String TOTAL_HEIGHT = "TOTAL_HEIGHT"; + private static final String TOTAL_WIDTH = "TOTAL_WIDTH"; + private static final String PARAMETERS = "PARAMETERS"; + private static final String FIELDS = "FIELDS"; + private static final String HEADERS = "HEADERS"; + private static final String CONTENT = "CONTENT"; + protected static final String PROPERTY = "PROPERTY"; + private static final String IS_IGNORE_PAGINATION = "IS_IGNORE_PAGINATION"; + protected static final String STYLE = "STYLE"; + protected static final String TITLE = "TITLE"; + protected static final String NAME_SHEET = "NAME_SHEET"; + protected StringBuilder parametersDeclaration = new StringBuilder(); + protected StringBuilder fieldsDeclaration = new StringBuilder(); + protected StringBuilder contentStyle = new StringBuilder(); + private final StringBuilder headersDeclaration = new StringBuilder(); + private final StringBuilder contentFields = new StringBuilder(); + protected StringBuilder titleDeclaration = new StringBuilder(); + protected StringBuilder propertyDeclaration = new StringBuilder(); + protected String nameSheetDeclaration = ""; + protected final List columns; + private final int contentLineHeight; + private final int numberOfColumns; + private final int totalGridWidth; + protected int heigthTitle; + private int totalHeaderHeight; + protected static final String BEGIN_STYLE = "\n "; + protected static final String END_STYLE_FIRST = "\n "; + protected static final String MULTIPLE_CONDITIONAL_INCLUSIF = " && "; + protected static final String MULTIPLE_CONDITIONAL_EXCLUSIF = " || "; + protected static final String BEGIN_VARIABLE_DATA = ""; + protected static final String TOP_PEN = " listElementTitle = new ArrayList<>(); + + /** + * Builds a table template. + * + * @param widths The widths of every columns in this table + * @param contentKeys the String keys of each column's content fields + * @param contentLineHeight The height of each content rows, in pixels + * @param formats (optional) a List of field {@link CellFormat}. If the list is null or empty, no format is specified + * @param stretchWithOverFlow (optional) a List of field alignments. If the list is null or empty, no stretch will be performed + * @throws FileLoadingException if the template could not be loaded + * @throws InvalidInputException if input list length do not match + */ + public DynamicGridTemplateBuilder(final List widths, final List contentKeys, final List formats, + final List stretchWithOverFlow, final int contentLineHeight) throws FileLoadingException, InvalidInputException { + super(); + heigthTitle = 0; + if (widths == null || contentKeys == null || widths.size() != contentKeys.size()) { + throw new InvalidInputException("Column size mismatch: widths List must be the same length as contentKeys list"); + } + if (formats != null && !formats.isEmpty() && formats.size() != widths.size()) { + throw new InvalidInputException("Alignments specified but do not match the table size"); + } + this.numberOfColumns = widths.size(); + // Setup each column + int incrementalWidth = 0; + this.columns = new ArrayList<>(numberOfColumns); + this.contentLineHeight = contentLineHeight; + for (int numCol = 0; numCol < numberOfColumns; numCol++) { + Integer width = widths.get(numCol); + CellFormat fieldFormat = (formats == null || formats.isEmpty()) ? null : formats.get(numCol); + boolean isStretch = (stretchWithOverFlow == null || stretchWithOverFlow.isEmpty()) ? false : stretchWithOverFlow.get(numCol); + columns.add(new Column(contentKeys.get(numCol), width, incrementalWidth, isStretch, contentLineHeight, fieldFormat)); + incrementalWidth += width; + } + totalGridWidth = incrementalWidth; + this.setTemplateContent(ResourceHelper.getResourceContent("/Jasper/template/dynamic_table/template.jrxml")); + this.setTagValue(IS_IGNORE_PAGINATION, "false"); + + } + + /** + * Makes this template nover change page (use this to have a single long excel sheet). + */ + public void ignorePagination() { + this.setTagValue(IS_IGNORE_PAGINATION, "true"); + } + + /** + * Adds a header line to this table. The line is added as the last of the header lines, just before the main body. + * + * @param heightPx th eline's height, in pixels + * @param lineContent the line's content: Either the static text, the dynamic parameter key, or null if the cell above should be fused with this one + * @param dynamic a list of booleans, telling this line if each of the columns above are dynamic (tru) or static (false) or null if the cell above should be fused with this one + * @param formats a List of field Formats. + * @param stretchWithOverFlow (optional) a List of field alignments. If the list is null or empty, no stretch will be performed + * @throws InvalidInputException when the line's 'content' or 'dynamic' params are not of the same legntth as the number of columns in the report + */ + public void addHeaderLine(final int heightPx, final List lineContent, final List dynamic, final List formats, + final List stretchWithOverFlow) throws InvalidInputException { + if (lineContent.size() != numberOfColumns || dynamic.size() != numberOfColumns) { + throw new InvalidInputException("Line content length does not match the number of columns (" + numberOfColumns + ")"); + } + CellFormat defaultFormatWithOnlyColor = new CellFormat(); + boolean defaultFormat = formats == null || formats.isEmpty() || formats.size() != numberOfColumns; + for (int numCol = 0; numCol < numberOfColumns; numCol++) { + String cellContent = lineContent.get(numCol); + Column column = columns.get(numCol); + Boolean isDynamic = dynamic.get(numCol); + if (cellContent == null || isDynamic == null) { + column.addToPreviousHeaderCellHeight(heightPx); + } + else { + CellFormat format; + if (defaultFormat) { + format = defaultFormatWithOnlyColor; + } + else { + format = formats.get(numCol); + } + boolean isStretch = (stretchWithOverFlow == null || stretchWithOverFlow.isEmpty()) ? false : stretchWithOverFlow.get(numCol); + column.addHeader(cellContent, isDynamic, heightPx, isStretch, format); + } + } + totalHeaderHeight += heightPx; + } + + /** + * Adds a header line to this table. The line is added as the last of the header lines, just before the main body. + * + * @param heightPx th eline's height, in pixels + * @param lineContent the line's content: Either the static text, the dynamic parameter key, or null if the cell above should be fused with this one + * @param dynamic a list of booleans, telling this line if each of the columns above are dynamic (tru) or static (false) or null if the cell above should be fused with this one + * @param theFormat the Format for all fields. If null, no format is specified. + * @param stretchWithOverFlow (optional) a List of field alignments. If the list is null or empty, no stretch will be performed + * @throws InvalidInputException when the line's 'content' or 'dynamic' params are not of the same legntth as the number of columns in the report + */ + public void addHeaderLine(final int heightPx, final List lineContent, final List dynamic, final CellFormat theFormat, + final List stretchWithOverFlow) throws InvalidInputException { + if (lineContent.size() != numberOfColumns || dynamic.size() != numberOfColumns) { + throw new InvalidInputException("Line content length does not match the number of columns (" + numberOfColumns + ")"); + } + for (int numCol = 0; numCol < numberOfColumns; numCol++) { + String cellContent = lineContent.get(numCol); + Column column = columns.get(numCol); + Boolean isDynamic = dynamic.get(numCol); + if (cellContent == null || isDynamic == null) { + column.addToPreviousHeaderCellHeight(heightPx); + } + else { + boolean isStretch = (stretchWithOverFlow == null || stretchWithOverFlow.isEmpty()) ? false : stretchWithOverFlow.get(numCol); + column.addHeader(cellContent, isDynamic, heightPx, isStretch, theFormat); + } + } + totalHeaderHeight += heightPx; + } + + @Override + public String generateCode() { + + for (Column col : columns) { + parametersDeclaration.append(col.getParametersDeclaration()); + fieldsDeclaration.append(col.getFieldsDeclaration()); + headersDeclaration.append(col.makeHeaders()); + contentFields.append(col.makeContent()); + } + // Setup the proper tags + + super.setTagValue(PARAMETERS, parametersDeclaration.toString()); + super.setTagValue(FIELDS, fieldsDeclaration.toString()); + super.setTagValue(HEADERS, headersDeclaration.toString()); + super.setTagValue(CONTENT, contentFields.toString()); + super.setTagValue(HEADER_HEIGHT, String.valueOf(totalHeaderHeight)); + super.setTagValue(CONTENT_HEIGHT, String.valueOf(contentLineHeight)); + super.setTagValue(TOTAL_HEIGHT, String.valueOf(totalHeaderHeight + contentLineHeight + heigthTitle)); + super.setTagValue(TOTAL_WIDTH, String.valueOf(totalGridWidth)); + // Generate the content + return super.generateCode(); + } + +} diff --git a/kurt-utility/src/main/resources/Jasper/images/Snecma_logo.png b/kurt-utility/src/main/resources/Jasper/images/Snecma_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..e40717b639e8a24db9990e597b390c0d07d49b4d GIT binary patch literal 3973 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 E7agyn3jhEB literal 0 HcmV?d00001 diff --git a/kurt-utility/src/main/resources/Jasper/images/confidentiel_industrie.jpg b/kurt-utility/src/main/resources/Jasper/images/confidentiel_industrie.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3008bffedfa4f4c12577b88d522293572ad7df29 GIT binary patch literal 33675 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 literal 0 HcmV?d00001 diff --git a/kurt-utility/src/main/resources/Jasper/template/dynamic_table/template.jrxml b/kurt-utility/src/main/resources/Jasper/template/dynamic_table/template.jrxml new file mode 100644 index 0000000..86687d3 --- /dev/null +++ b/kurt-utility/src/main/resources/Jasper/template/dynamic_table/template.jrxml @@ -0,0 +1,17 @@ + +[[PARAMETERS]] + + + [[FIELDS]] + + + + + [[HEADERS]] + + + + [[CONTENT]] + + + \ No newline at end of file diff --git a/kurt-utility/src/main/resources/Jasper/template/report_r01.jrxml b/kurt-utility/src/main/resources/Jasper/template/report_r01.jrxml new file mode 100644 index 0000000..f96b030 --- /dev/null +++ b/kurt-utility/src/main/resources/Jasper/template/report_r01.jrxml @@ -0,0 +1,1076 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/Jasper/template/report_r03.jrxml b/kurt-utility/src/main/resources/Jasper/template/report_r03.jrxml new file mode 100644 index 0000000..39b0ecc --- /dev/null +++ b/kurt-utility/src/main/resources/Jasper/template/report_r03.jrxml @@ -0,0 +1,726 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/Jasper/template/report_r10.jrxml b/kurt-utility/src/main/resources/Jasper/template/report_r10.jrxml new file mode 100644 index 0000000..efa9bad --- /dev/null +++ b/kurt-utility/src/main/resources/Jasper/template/report_r10.jrxml @@ -0,0 +1,918 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/Jasper/template/report_r11.jrxml b/kurt-utility/src/main/resources/Jasper/template/report_r11.jrxml new file mode 100644 index 0000000..c7f76ab --- /dev/null +++ b/kurt-utility/src/main/resources/Jasper/template/report_r11.jrxml @@ -0,0 +1,638 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <band height="160" splitType="Stretch"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + <staticText> + <reportElement x="-20" y="100" width="320" height="20" uuid="33d7e186-0b67-416e-8a86-26655b01cf0c"/> + <textElement> + <font size="8"/> + </textElement> + <text><![CDATA[Nombre de repères fonctionnels avec mise en maquette cohérente]]></text> + </staticText> + <staticText> + <reportElement x="-20" y="20" width="320" height="20" uuid="b554ec37-e2af-4344-a385-263bd5dffdab"/> + <textElement> + <font size="8"/> + </textElement> + <text><![CDATA[Nombre de repères fonctionnels mis en maquette :]]></text> + </staticText> + <staticText> + <reportElement x="-20" y="40" width="320" height="20" uuid="4628b4ee-acce-490a-a3cc-5ff1289d5db0"/> + <textElement> + <font size="8"/> + </textElement> + <text><![CDATA[Pourcentage de mise en maquette :]]></text> + </staticText> + <staticText> + <reportElement x="-20" y="60" width="320" height="20" uuid="d2763629-2316-46e2-8d08-bc2f012aa4be"/> + <textElement> + <font size="8"/> + </textElement> + <text><![CDATA[Nombre de repères fonctionnels avec une incohérence de mise en maquette :]]></text> + </staticText> + <staticText> + <reportElement x="-20" y="80" width="320" height="20" uuid="594ca80b-2686-45e1-a831-1d32b7d0e891"/> + <textElement> + <font size="8"/> + </textElement> + <text><![CDATA[Pourcentage de repères fonctionnels mis en maquette incohérente]]></text> + </staticText> + <textField> + <reportElement x="300" y="0" width="80" height="20" uuid="1ad40902-0de9-428b-aa8a-7a6f21d3c998"/> + <textFieldExpression><![CDATA[$P{NOMBRE_REPERE_FONCTIONNEL_METTRE_EN_MAQUETTE}]]></textFieldExpression> + </textField> + <textField> + <reportElement x="300" y="20" width="80" height="20" uuid="dd6c4654-9f34-4bdd-84df-55ef28c91c67"/> + <textFieldExpression><![CDATA[$P{NOMBRE_REPERE_FONCTIONNEL_MAQUETTE}]]></textFieldExpression> + </textField> + <textField> + <reportElement x="300" y="40" width="80" height="20" uuid="6fb1523c-9e69-45aa-b61d-5a8ae9b6ef19"/> + <textFieldExpression><![CDATA[$P{MISE_EN_MAQUETTE_POURCENTAGE}]]></textFieldExpression> + </textField> + <textField> + <reportElement x="300" y="60" width="80" height="20" uuid="a90d110c-893d-4f00-83d6-0ad6a7454926"/> + <textFieldExpression><![CDATA[$P{NOMBRE_REPERE_FONCTIONNEL_INCOHERENT}]]></textFieldExpression> + </textField> + <textField> + <reportElement x="300" y="80" width="80" height="20" uuid="f8c79aed-4af3-44d3-bc43-a4ac7fb08f4d"/> + <textFieldExpression><![CDATA[$P{REPERE_FONCTIONNEL_MAQUETTE_INCOHERENTE_POURCENTAGE}]]></textFieldExpression> + </textField> + <staticText> + <reportElement x="-20" y="0" width="320" height="20" uuid="686e3570-9ad2-4202-8d37-a7e6f8cdb515"/> + <textElement> + <font size="8"/> + </textElement> + <text><![CDATA[Nombre de repères fonctionnels à mettre en maquette]]></text> + </staticText> + <staticText> + <reportElement x="-20" y="120" width="320" height="20" uuid="87021f19-7594-4bdd-a6ff-8ea485226e51"/> + <textElement> + <font size="8"/> + </textElement> + <text><![CDATA[Pourcentage de repères fonctionnels mis en maquette cohérente]]></text> + </staticText> + <textField> + <reportElement x="300" y="120" width="80" height="20" uuid="08415e62-0b9f-439f-af0f-0ab21019984b"/> + <textFieldExpression><![CDATA[$P{POURCENTAGE_MAQUETTE_COHERENTE}]]></textFieldExpression> + </textField> + <textField> + <reportElement x="300" y="100" width="80" height="20" uuid="7a9d71de-3528-41f3-a26d-481290de89c6"/> + <textFieldExpression><![CDATA[$P{NOMBRE_REPERE_FONCTIONNEL_MISE_EN_MAQUETTE_COHERENTE}]]></textFieldExpression> + </textField> + </band> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/Jasper/template/report_r13/report_r13_cr.jrxml b/kurt-utility/src/main/resources/Jasper/template/report_r13/report_r13_cr.jrxml new file mode 100644 index 0000000..0ced7e3 --- /dev/null +++ b/kurt-utility/src/main/resources/Jasper/template/report_r13/report_r13_cr.jrxml @@ -0,0 +1,975 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/Jasper/template/report_r13/report_r13_fpp.jrxml b/kurt-utility/src/main/resources/Jasper/template/report_r13/report_r13_fpp.jrxml new file mode 100644 index 0000000..0543af8 --- /dev/null +++ b/kurt-utility/src/main/resources/Jasper/template/report_r13/report_r13_fpp.jrxml @@ -0,0 +1,579 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/Jasper/template/report_r15r16.jrxml b/kurt-utility/src/main/resources/Jasper/template/report_r15r16.jrxml new file mode 100644 index 0000000..732d64b --- /dev/null +++ b/kurt-utility/src/main/resources/Jasper/template/report_r15r16.jrxml @@ -0,0 +1,695 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1]]> + + + + + + + + + + + + + <band height="761"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + <image> + <reportElement x="0" y="0" width="180" height="40" uuid="bd1c5457-daa9-4754-9f61-54f1400686ee"> + <property name="local_mesure_unitwidth" value="pixel"/> + <property name="com.jaspersoft.studio.unit.width" value="px"/> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <imageExpression><![CDATA[$P{SNECMA_LOGO}]]></imageExpression> + </image> + <staticText> + <reportElement positionType="Float" x="0" y="521" width="150" height="30" uuid="c8e9f5f7-1896-4aaf-b18a-0c09312016cd"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + <printWhenExpression><![CDATA[$P{IS_PREVIOUS_DEF}]]></printWhenExpression> + </reportElement> + <textElement verticalAlignment="Middle"> + <font size="8" isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[MT +MT Number]]></text> + </staticText> + <staticText> + <reportElement positionType="Float" x="0" y="551" width="150" height="30" uuid="62981c54-a5b2-48bf-9840-cc4e60859226"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + <printWhenExpression><![CDATA[$P{IS_PREVIOUS_DEF}]]></printWhenExpression> + </reportElement> + <textElement verticalAlignment="Middle"> + <font size="8" isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Date de lancement +Release date]]></text> + </staticText> + <textField> + <reportElement positionType="Float" x="150" y="551" width="405" height="30" uuid="2c240f3e-0a02-4bcd-a98c-8c894e9e1d19"> + <printWhenExpression><![CDATA[$P{IS_PREVIOUS_DEF}]]></printWhenExpression> + </reportElement> + <textElement verticalAlignment="Middle"> + <font size="8" pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{PREVIOUS_RELEASE_DATE}]]></textFieldExpression> + </textField> + <textField> + <reportElement positionType="Float" stretchType="RelativeToTallestObject" x="150" y="521" width="405" height="30" uuid="2830e066-9f5f-4682-bc32-64bc41b898fa"> + <printWhenExpression><![CDATA[$P{IS_PREVIOUS_DEF}]]></printWhenExpression> + </reportElement> + <textElement verticalAlignment="Middle"> + <font size="8" pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{MT_NUMBER}]]></textFieldExpression> + </textField> + <staticText> + <reportElement x="0" y="280" width="150" height="30" uuid="d58f0c3a-9c3f-42a0-9a74-c4b13a4bfc9e"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font size="8" isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Dénomination Française +French Designation]]></text> + </staticText> + <textField> + <reportElement x="150" y="280" width="405" height="30" uuid="e5081414-e2bf-40bd-bccc-567131df6a5e"/> + <textElement verticalAlignment="Middle"> + <font size="8" pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{FRENCH_DESIGNATION}]]></textFieldExpression> + </textField> + <staticText> + <reportElement x="0" y="490" width="150" height="30" uuid="c71a994c-a413-4f90-a94a-fcadd4a82a17"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font size="8" isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Obturation +Obturation]]></text> + </staticText> + <textField> + <reportElement x="150" y="400" width="405" height="30" uuid="48b02918-dd5b-45ea-bce6-6423778e1596"/> + <textElement verticalAlignment="Middle"> + <font size="8" pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{LOG_DOCUMENT}]]></textFieldExpression> + </textField> + <textField> + <reportElement x="150" y="160" width="405" height="30" uuid="b8f4eb10-ca2d-498c-94ce-7589f0d24c80"/> + <textElement verticalAlignment="Middle"> + <font size="8" pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{PRODUCT_TYPE}]]></textFieldExpression> + </textField> + <textField> + <reportElement x="150" y="190" width="405" height="30" uuid="06a0f02d-35ff-49f5-a0da-43fd541563bb"/> + <textElement verticalAlignment="Middle"> + <font size="8" pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{PART_NUMBER}]]></textFieldExpression> + </textField> + <staticText> + <reportElement x="0" y="400" width="150" height="30" uuid="a329c593-2261-491c-8216-3449466dd821"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font size="8" isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Document de contrôle +Log Document]]></text> + </staticText> + <staticText> + <reportElement x="0" y="250" width="150" height="30" uuid="c887a61f-5bdf-4759-b01f-ca535f263f7c"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font size="8" isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Version de l’article +Part version]]></text> + </staticText> + <staticText> + <reportElement x="0" y="160" width="150" height="30" uuid="0b2fbdcf-2b30-4936-b89a-b237bc00858a"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font size="8" isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Type produit +Product Type]]></text> + </staticText> + <textField> + <reportElement x="150" y="490" width="405" height="30" uuid="f9019024-1120-45c1-a3fa-a4f6b6c00eab"/> + <textElement verticalAlignment="Middle"> + <font size="8" pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{OBTURATION}]]></textFieldExpression> + </textField> + <textField> + <reportElement x="150" y="220" width="405" height="30" uuid="04f2420a-7fd1-42b0-8da2-422f0b2a99c5"/> + <textElement verticalAlignment="Middle"> + <font size="8" pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{MANUFACTURER_CODE}]]></textFieldExpression> + </textField> + <staticText> + <reportElement x="0" y="370" width="150" height="30" uuid="a3f18762-a923-47c2-9dab-0bb02dea7ec5"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font size="8" isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Suivi Utilisation +Field OPN serialisation]]></text> + </staticText> + <textField> + <reportElement x="150" y="370" width="405" height="30" uuid="0f42ed3c-21a3-48ab-bab2-7e61699bdc78"/> + <textElement verticalAlignment="Middle"> + <font size="8" pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{FIELD_OPN_SERIALISATION}]]></textFieldExpression> + </textField> + <staticText> + <reportElement x="0" y="340" width="150" height="30" uuid="e74a400e-5b28-4206-9538-0e5322e395be"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font size="8" isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Classement +Classification]]></text> + </staticText> + <textField> + <reportElement x="150" y="340" width="405" height="30" uuid="5531e836-80a9-4bb9-8216-98637993b852"/> + <textElement verticalAlignment="Middle"> + <font size="8" pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{CLASSIFICATION}]]></textFieldExpression> + </textField> + <staticText> + <reportElement x="0" y="190" width="150" height="30" uuid="a760d63d-8652-4c30-a0fc-80032474925f"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font size="8" isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Référence de l’article +Part Number]]></text> + </staticText> + <textField> + <reportElement x="150" y="250" width="405" height="30" uuid="7acd17db-c975-482b-b33a-5a50cd7e495e"/> + <textElement verticalAlignment="Middle"> + <font size="8" pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{PART_VERSION}]]></textFieldExpression> + </textField> + <staticText> + <reportElement x="0" y="220" width="150" height="30" uuid="56254219-d62f-4d1f-b7e2-e7ba6b55db05"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font size="8" isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Code Fabricant +Manufacturer code]]></text> + </staticText> + <textField> + <reportElement x="60" y="80" width="120" height="20" uuid="16a34db8-b544-4ed7-aa30-723bbd0f2c97"> + <property name="local_mesure_unity" value="pixel"/> + <property name="com.jaspersoft.studio.unit.y" value="px"/> + </reportElement> + <box leftPadding="5"> + <topPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <leftPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <bottomPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <rightPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + </box> + <textElement verticalAlignment="Middle"> + <font pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{ITEM_ID}]]></textFieldExpression> + </textField> + <textField> + <reportElement x="200" y="120" width="290" height="20" uuid="5cd5ea2e-370d-4843-86ec-284dd5cc4669"/> + <box leftPadding="5"> + <topPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <leftPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <bottomPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <rightPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + </box> + <textElement verticalAlignment="Middle"> + <font pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{RELEASE_DATE}]]></textFieldExpression> + </textField> + <textField isStretchWithOverflow="true"> + <reportElement x="200" y="80" width="290" height="20" uuid="90631035-798d-4f4d-800a-1ae0da7199ce"/> + <box leftPadding="5"> + <topPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <leftPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <bottomPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <rightPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + </box> + <textElement verticalAlignment="Middle"> + <font pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{ITEM_REVISION_ID}]]></textFieldExpression> + </textField> + <textField> + <reportElement x="60" y="120" width="120" height="20" uuid="ae3b956d-b485-4801-81d9-dc75765b5f27"/> + <box leftPadding="5"> + <topPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <leftPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <bottomPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <rightPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + </box> + <textElement verticalAlignment="Middle"> + <font pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{PRODUCT_UNIT}]]></textFieldExpression> + </textField> + <textField isStretchWithOverflow="true"> + <reportElement stretchType="RelativeToTallestObject" x="20" y="681" width="510" height="80" uuid="0953ec0c-dd4c-4d2b-bfdf-bc17f90863e7"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Center" markup="styled"> + <font size="7" isBold="false" pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{CLAUSE_PROPRIETE}]]></textFieldExpression> + </textField> + <line> + <reportElement x="0" y="680" width="555" height="1" uuid="c8a04261-d21b-476f-a9c8-3513667543fe"> + <property name="local_mesure_unity" value="pixel"/> + <property name="com.jaspersoft.studio.unit.y" value="px"/> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + </line> + <textField> + <reportElement x="520" y="741" width="34" height="20" uuid="f3f0d26b-5d68-4356-88f2-fc0b8d32b880"/> + <textElement textAlignment="Right"> + <font isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <textFieldExpression><![CDATA[$V{PAGE_NUMBER}]]></textFieldExpression> + </textField> + <textField> + <reportElement x="150" y="310" width="405" height="30" uuid="1e3b2e3b-8658-4332-8baa-1492978ab190"/> + <textElement verticalAlignment="Middle"> + <font size="8" pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{ENGLISH_DESIGNATION}]]></textFieldExpression> + </textField> + <staticText> + <reportElement x="0" y="310" width="150" height="30" uuid="1026facf-47bb-4163-939d-a87d49e93d9e"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font size="8" isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Dénomination Anglaise +English designation]]></text> + </staticText> + <staticText> + <reportElement x="0" y="430" width="150" height="30" uuid="58157510-6554-420b-b0eb-97ade29844ae"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font size="8" isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Frontière Avion +Installation Interface]]></text> + </staticText> + <textField> + <reportElement x="150" y="460" width="405" height="30" uuid="a12899e5-d6f2-42f0-9de5-5acdc64ed2a2"/> + <textElement verticalAlignment="Middle"> + <font size="8" pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{PARTNER_INTERFACE}]]></textFieldExpression> + </textField> + <staticText> + <reportElement x="0" y="460" width="150" height="30" uuid="5a2f3dcd-1fbd-4e8f-b46f-577c64544d37"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font size="8" isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Frontière Coopérant +Partner Interface]]></text> + </staticText> + <textField> + <reportElement x="150" y="430" width="405" height="30" uuid="ab848d3a-8005-4763-8583-384bb8c70cfc"/> + <textElement verticalAlignment="Middle"> + <font size="8" pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{INSTALLATION_INTERFACE}]]></textFieldExpression> + </textField> + <textField> + <reportElement x="80" y="40" width="380" height="30" uuid="3f7c9d3f-0877-4237-a0c2-5b2c3e0e561c"/> + <textElement textAlignment="Center" verticalAlignment="Middle" markup="styled"> + <font isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <textFieldExpression><![CDATA[$P{REPORT_TITLE}]]></textFieldExpression> + </textField> + <textField isStretchWithOverflow="true"> + <reportElement x="0" y="520" width="554" height="1" uuid="0ce0810e-0f14-4a0c-a06f-7f6665643d74"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + <printWhenExpression><![CDATA[$P{IS_PREVIOUS_DEF}]]></printWhenExpression> + </reportElement> + <textElement textAlignment="Center" verticalAlignment="Middle"> + <font isBold="true"/> + </textElement> + <textFieldExpression><![CDATA["\nDéfinition précédente / Previous Definition\n"]]></textFieldExpression> + </textField> + </band> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/Jasper/template/report_r17.jrxml b/kurt-utility/src/main/resources/Jasper/template/report_r17.jrxml new file mode 100644 index 0000000..996a677 --- /dev/null +++ b/kurt-utility/src/main/resources/Jasper/template/report_r17.jrxml @@ -0,0 +1,620 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1]]> + + + + + + + + + + + + + <band height="760"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + <image> + <reportElement x="0" y="0" width="180" height="40" uuid="bd1c5457-daa9-4754-9f61-54f1400686ee"> + <property name="local_mesure_unitwidth" value="pixel"/> + <property name="com.jaspersoft.studio.unit.width" value="px"/> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <imageExpression><![CDATA[$P{SNECMA_LOGO}]]></imageExpression> + </image> + <staticText> + <reportElement x="0" y="560" width="150" height="30" uuid="c8e9f5f7-1896-4aaf-b18a-0c09312016cd"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement verticalAlignment="Middle"> + <font size="8" isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[MT +MT Number]]></text> + </staticText> + <staticText> + <reportElement x="0" y="590" width="150" height="30" uuid="62981c54-a5b2-48bf-9840-cc4e60859226"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement verticalAlignment="Middle"> + <font size="8" isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Date de lancement +Release date]]></text> + </staticText> + <staticText> + <reportElement x="180" y="530" width="300" height="20" uuid="7cd156c7-8245-4fad-bac6-3244c82501c8"/> + <textElement> + <font isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Définition précédente / Previous Definition]]></text> + </staticText> + <textField> + <reportElement x="150" y="590" width="405" height="30" uuid="2c240f3e-0a02-4bcd-a98c-8c894e9e1d19"/> + <textElement verticalAlignment="Middle"> + <font size="8" pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{PREVIOUS_RELEASE_DATE}]]></textFieldExpression> + </textField> + <textField> + <reportElement x="150" y="560" width="405" height="30" uuid="2830e066-9f5f-4682-bc32-64bc41b898fa"/> + <textElement verticalAlignment="Middle"> + <font size="8" pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{MT_NUMBER}]]></textFieldExpression> + </textField> + <staticText> + <reportElement x="0" y="280" width="150" height="30" uuid="d58f0c3a-9c3f-42a0-9a74-c4b13a4bfc9e"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font size="8" isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Dénomination Française +French Designation]]></text> + </staticText> + <textField> + <reportElement x="150" y="280" width="405" height="30" uuid="e5081414-e2bf-40bd-bccc-567131df6a5e"/> + <textElement verticalAlignment="Middle"> + <font size="8" pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{FRENCH_DESIGNATION}]]></textFieldExpression> + </textField> + <staticText> + <reportElement x="0" y="430" width="150" height="30" uuid="c71a994c-a413-4f90-a94a-fcadd4a82a17"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font size="8" isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Obturation +Obturation]]></text> + </staticText> + <textField> + <reportElement x="150" y="400" width="405" height="30" uuid="48b02918-dd5b-45ea-bce6-6423778e1596"/> + <textElement verticalAlignment="Middle"> + <font size="8" pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{LOG_DOCUMENT}]]></textFieldExpression> + </textField> + <textField> + <reportElement x="150" y="160" width="405" height="30" uuid="b8f4eb10-ca2d-498c-94ce-7589f0d24c80"/> + <textElement verticalAlignment="Middle"> + <font size="8" pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{PRODUCT_TYPE}]]></textFieldExpression> + </textField> + <textField> + <reportElement x="150" y="190" width="405" height="30" uuid="06a0f02d-35ff-49f5-a0da-43fd541563bb"/> + <textElement verticalAlignment="Middle"> + <font size="8" pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{PART_NUMBER}]]></textFieldExpression> + </textField> + <staticText> + <reportElement x="0" y="400" width="150" height="30" uuid="a329c593-2261-491c-8216-3449466dd821"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font size="8" isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Document de contrôle +Log Document]]></text> + </staticText> + <staticText> + <reportElement x="0" y="250" width="150" height="30" uuid="c887a61f-5bdf-4759-b01f-ca535f263f7c"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font size="8" isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Version de l’article +Part version]]></text> + </staticText> + <staticText> + <reportElement x="0" y="160" width="150" height="30" uuid="0b2fbdcf-2b30-4936-b89a-b237bc00858a"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font size="8" isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Type produit +Product Type]]></text> + </staticText> + <textField> + <reportElement x="150" y="430" width="405" height="30" uuid="f9019024-1120-45c1-a3fa-a4f6b6c00eab"/> + <textElement verticalAlignment="Middle"> + <font size="8" pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{OBTURATION}]]></textFieldExpression> + </textField> + <textField> + <reportElement x="150" y="220" width="405" height="30" uuid="04f2420a-7fd1-42b0-8da2-422f0b2a99c5"/> + <textElement verticalAlignment="Middle"> + <font size="8" pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{MANUFACTURER_CODE}]]></textFieldExpression> + </textField> + <staticText> + <reportElement x="0" y="370" width="150" height="30" uuid="a3f18762-a923-47c2-9dab-0bb02dea7ec5"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font size="8" isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Suivi Utilisation +Field OPN serialisation]]></text> + </staticText> + <textField> + <reportElement x="150" y="370" width="405" height="30" uuid="0f42ed3c-21a3-48ab-bab2-7e61699bdc78"/> + <textElement verticalAlignment="Middle"> + <font size="8" pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{FIELD_OPN_SERIALISATION}]]></textFieldExpression> + </textField> + <staticText> + <reportElement x="0" y="340" width="150" height="30" uuid="e74a400e-5b28-4206-9538-0e5322e395be"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font size="8" isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Classement +Classification]]></text> + </staticText> + <textField> + <reportElement x="150" y="340" width="405" height="30" uuid="5531e836-80a9-4bb9-8216-98637993b852"/> + <textElement verticalAlignment="Middle"> + <font size="8" pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{CLASSIFICATION}]]></textFieldExpression> + </textField> + <staticText> + <reportElement x="0" y="190" width="150" height="30" uuid="a760d63d-8652-4c30-a0fc-80032474925f"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font size="8" isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Référence de l’article +Part Number]]></text> + </staticText> + <textField> + <reportElement x="150" y="250" width="405" height="30" uuid="7acd17db-c975-482b-b33a-5a50cd7e495e"/> + <textElement verticalAlignment="Middle"> + <font size="8" pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{PART_VERSION}]]></textFieldExpression> + </textField> + <staticText> + <reportElement x="0" y="220" width="150" height="30" uuid="56254219-d62f-4d1f-b7e2-e7ba6b55db05"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font size="8" isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Code Fabricant +Manufacturer code]]></text> + </staticText> + <textField> + <reportElement x="60" y="80" width="120" height="20" uuid="16a34db8-b544-4ed7-aa30-723bbd0f2c97"> + <property name="local_mesure_unity" value="pixel"/> + <property name="com.jaspersoft.studio.unit.y" value="px"/> + </reportElement> + <box leftPadding="5"> + <topPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <leftPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <bottomPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <rightPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + </box> + <textElement verticalAlignment="Middle"> + <font pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{ITEM_ID}]]></textFieldExpression> + </textField> + <textField> + <reportElement x="200" y="120" width="290" height="20" uuid="5cd5ea2e-370d-4843-86ec-284dd5cc4669"/> + <box leftPadding="5"> + <topPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <leftPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <bottomPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <rightPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + </box> + <textElement verticalAlignment="Middle"> + <font pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{RELEASE_DATE}]]></textFieldExpression> + </textField> + <textField isStretchWithOverflow="true"> + <reportElement x="200" y="80" width="290" height="20" uuid="90631035-798d-4f4d-800a-1ae0da7199ce"/> + <box leftPadding="5"> + <topPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <leftPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <bottomPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <rightPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + </box> + <textElement verticalAlignment="Middle"> + <font pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{ITEM_REVISION_ID}]]></textFieldExpression> + </textField> + <textField isStretchWithOverflow="true"> + <reportElement stretchType="RelativeToTallestObject" x="20" y="680" width="520" height="80" uuid="0953ec0c-dd4c-4d2b-bfdf-bc17f90863e7"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Center" markup="styled"> + <font size="7" isBold="false" pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{CLAUSE_PROPRIETE}]]></textFieldExpression> + </textField> + <line> + <reportElement x="0" y="680" width="555" height="1" uuid="c8a04261-d21b-476f-a9c8-3513667543fe"> + <property name="local_mesure_unity" value="pixel"/> + <property name="com.jaspersoft.studio.unit.y" value="px"/> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + </line> + <textField> + <reportElement x="530" y="740" width="24" height="20" uuid="f3f0d26b-5d68-4356-88f2-fc0b8d32b880"/> + <textElement textAlignment="Right"> + <font isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <textFieldExpression><![CDATA[$V{PAGE_NUMBER}]]></textFieldExpression> + </textField> + <staticText> + <reportElement x="0" y="310" width="150" height="30" uuid="7807ccdf-9479-42d0-8a5c-a41805923c37"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font size="8" isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Dénomination Anglaise +English designation]]></text> + </staticText> + <textField> + <reportElement x="150" y="310" width="405" height="30" uuid="fdd0ad29-2a8c-4c0a-88f8-da8648ca3f5d"/> + <textElement verticalAlignment="Middle"> + <font size="8" pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{ENGLISH_DESIGNATION}]]></textFieldExpression> + </textField> + <rectangle> + <reportElement x="60" y="120" width="120" height="20" uuid="fe8029bb-5c43-450a-bb89-70908609e531"/> + </rectangle> + <textField> + <reportElement x="80" y="40" width="380" height="30" uuid="13308d92-200e-48eb-8dcf-77e6f9f271b9"/> + <textElement textAlignment="Center" verticalAlignment="Middle" markup="styled"> + <font isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <textFieldExpression><![CDATA[$P{REPORT_TITLE}]]></textFieldExpression> + </textField> + </band> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/Jasper/template/report_r19.jrxml b/kurt-utility/src/main/resources/Jasper/template/report_r19.jrxml new file mode 100644 index 0000000..37c5dea --- /dev/null +++ b/kurt-utility/src/main/resources/Jasper/template/report_r19.jrxml @@ -0,0 +1,649 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/Jasper/template/report_r20/Snecma_logo.png b/kurt-utility/src/main/resources/Jasper/template/report_r20/Snecma_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..e40717b639e8a24db9990e597b390c0d07d49b4d GIT binary patch literal 3973 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 E7agyn3jhEB literal 0 HcmV?d00001 diff --git a/kurt-utility/src/main/resources/Jasper/template/report_r20/page2/r20_p2_generics.jrxml b/kurt-utility/src/main/resources/Jasper/template/report_r20/page2/r20_p2_generics.jrxml new file mode 100644 index 0000000..e060ed0 --- /dev/null +++ b/kurt-utility/src/main/resources/Jasper/template/report_r20/page2/r20_p2_generics.jrxml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/Jasper/template/report_r20/page2/r20_p2_impacts.jrxml b/kurt-utility/src/main/resources/Jasper/template/report_r20/page2/r20_p2_impacts.jrxml new file mode 100644 index 0000000..a21b676 --- /dev/null +++ b/kurt-utility/src/main/resources/Jasper/template/report_r20/page2/r20_p2_impacts.jrxml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/Jasper/template/report_r20/page2/r20_p2_noimpacts.jrxml b/kurt-utility/src/main/resources/Jasper/template/report_r20/page2/r20_p2_noimpacts.jrxml new file mode 100644 index 0000000..962ba07 --- /dev/null +++ b/kurt-utility/src/main/resources/Jasper/template/report_r20/page2/r20_p2_noimpacts.jrxml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/Jasper/template/report_r20/page3/report_r20_p3.jrxml b/kurt-utility/src/main/resources/Jasper/template/report_r20/page3/report_r20_p3.jrxml new file mode 100644 index 0000000..6ba0f72 --- /dev/null +++ b/kurt-utility/src/main/resources/Jasper/template/report_r20/page3/report_r20_p3.jrxml @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + [[SUBTABLES]] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/Jasper/template/report_r20/report_r20_master.jrxml b/kurt-utility/src/main/resources/Jasper/template/report_r20/report_r20_master.jrxml new file mode 100644 index 0000000..9bb472e --- /dev/null +++ b/kurt-utility/src/main/resources/Jasper/template/report_r20/report_r20_master.jrxml @@ -0,0 +1,286 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + >)$P{SUBREPORT_P2}.get("DATA"))]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + >)$P{SUBREPORT_P1}.get("DATA"))]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + >)$P{SUBREPORT_P3}.get("DATA"))]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + >)$P{SUBREPORT_P4}.get("DATA"))]]> + + + + + + + + + + + + Ce document est la propriété de Safran Aircraft Engines. Il ne peut être utilisé, reproduit ou communiqué sans son autorisation.
    F0301"]]>
    +
    +
    +
    + + + + + + + + + + + +
    diff --git a/kurt-utility/src/main/resources/Jasper/template/report_r20/report_r20_p1.jrxml b/kurt-utility/src/main/resources/Jasper/template/report_r20/report_r20_p1.jrxml new file mode 100644 index 0000000..a9d34e5 --- /dev/null +++ b/kurt-utility/src/main/resources/Jasper/template/report_r20/report_r20_p1.jrxml @@ -0,0 +1,255 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/Jasper/template/report_r20/report_r20_p2.jrxml b/kurt-utility/src/main/resources/Jasper/template/report_r20/report_r20_p2.jrxml new file mode 100644 index 0000000..d6cd26b --- /dev/null +++ b/kurt-utility/src/main/resources/Jasper/template/report_r20/report_r20_p2.jrxml @@ -0,0 +1,106 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + >)$P{SUBREPORT_GENERIC}.get("DATA"))]]> + + + + + + + + + + + + + + + + + + + + >)$P{SUBREPORT_IMPACTS}.get("DATA"))]]> + + + + + + + + + + + + + >)$P{SUBREPORT_NOIMPACTS}.get("DATA"))]]> + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/Jasper/template/report_r20/report_r20_p4.jrxml b/kurt-utility/src/main/resources/Jasper/template/report_r20/report_r20_p4.jrxml new file mode 100644 index 0000000..46b2b08 --- /dev/null +++ b/kurt-utility/src/main/resources/Jasper/template/report_r20/report_r20_p4.jrxml @@ -0,0 +1,265 @@ + + + + + + + + + + + + + + + + + + + + + + + + + <band height="103" splitType="Stretch"> + <staticText> + <reportElement x="0" y="0" width="800" height="30" uuid="92028f51-246a-47f2-8c73-95be69612b49"/> + <textElement textAlignment="Center"> + <font isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[DOCUMENT DE GEL DE UNIT FINAL (ANNEXE) +CALCUL DES REFERENCES TECHNIQUES]]></text> + </staticText> + <staticText> + <reportElement x="0" y="30" width="800" height="20" uuid="75b69c65-ad19-482b-905e-786a7605cd9a"/> + <text><![CDATA[L'impact de chaque modification sur les références des assemblages est décrit dans le tableau suivant : ]]></text> + </staticText> + <textField> + <reportElement x="0" y="50" width="800" height="20" uuid="510054a1-5695-4b3c-954e-fc5b312835aa"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textFieldExpression><![CDATA["Avant : UNIT " + $P{UNIT_AVANT} + " " + $P{EXCEPTIONNEL_AVANT} + " du produit " + $P{DOMAINE_PRODUIT_AVANT} + " " + $P{LIGNE_PRODUIT_AVANT}]]></textFieldExpression> + </textField> + <textField> + <reportElement x="0" y="70" width="800" height="20" uuid="b9a32778-73b0-4b97-9616-c06f6f4f2c92"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textFieldExpression><![CDATA["Après : UNIT " + $P{UNIT_APRES} + " " + $P{EXCEPTIONNEL_APRES} + " du produit " + $P{DOMAINE_PRODUIT_APRES} + " " + $P{LIGNE_PRODUIT_APRES}]]></textFieldExpression> + </textField> + <textField> + <reportElement mode="Opaque" x="0" y="90" width="290" height="13" backcolor="#E3E3E3" uuid="c4e431d0-0c8a-4266-9c73-97958c24f127"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <box leftPadding="5"> + <topPen lineWidth="0.5"/> + <leftPen lineWidth="0.5"/> + <bottomPen lineWidth="0.5"/> + <rightPen lineWidth="0.5"/> + </box> + <textFieldExpression><![CDATA[$P{LIGNE_PRODUIT_APRES}]]></textFieldExpression> + </textField> + <rectangle> + <reportElement x="290" y="90" width="130" height="13" backcolor="#E3E3E3" uuid="c0013ff2-080b-4606-869c-e4105272fdbc"/> + <graphicElement> + <pen lineWidth="0.5"/> + </graphicElement> + </rectangle> + <staticText> + <reportElement mode="Opaque" x="420" y="90" width="190" height="13" backcolor="#E3E3E3" uuid="e43f8acf-e867-4e00-8108-c15fd3ebc4d2"/> + <box> + <topPen lineWidth="0.5"/> + <leftPen lineWidth="0.5"/> + <bottomPen lineWidth="0.5"/> + <rightPen lineWidth="0.5"/> + </box> + <textElement textAlignment="Center"/> + <text><![CDATA[Ancienne référence]]></text> + </staticText> + <staticText> + <reportElement mode="Opaque" x="610" y="90" width="190" height="13" backcolor="#E3E3E3" uuid="dcdf2e41-3751-4d1c-9950-7bb9b71f7042"/> + <box> + <topPen lineWidth="0.5"/> + <leftPen lineWidth="0.5"/> + <bottomPen lineWidth="0.5"/> + <rightPen lineWidth="0.5"/> + </box> + <textElement textAlignment="Center"/> + <text><![CDATA[Nouvelle référence]]></text> + </staticText> + </band> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/Jasper/template/report_r21.jrxml b/kurt-utility/src/main/resources/Jasper/template/report_r21.jrxml new file mode 100644 index 0000000..cb34e75 --- /dev/null +++ b/kurt-utility/src/main/resources/Jasper/template/report_r21.jrxml @@ -0,0 +1,1027 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/Jasper/template/report_r22.jrxml b/kurt-utility/src/main/resources/Jasper/template/report_r22.jrxml new file mode 100644 index 0000000..3ae0027 --- /dev/null +++ b/kurt-utility/src/main/resources/Jasper/template/report_r22.jrxml @@ -0,0 +1,912 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <band height="181"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + <image> + <reportElement x="0" y="0" width="802" height="30" uuid="02f283fc-725c-4091-a6df-64b3fe139563"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <imageExpression><![CDATA[$P{LOGO_SNECMA}]]></imageExpression> + </image> + <staticText> + <reportElement stretchType="RelativeToTallestObject" x="0" y="20" width="802" height="40" uuid="6f86d0ba-b648-4c52-b7dd-f6882be41c2e"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Center"> + <font fontName="SansSerif" size="24" isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Extraction de nomenclatures sur effectivité par DATE]]></text> + </staticText> + <staticText> + <reportElement x="0" y="60" width="802" height="20" uuid="3ee15cb1-b6f7-4e0a-8ce4-55531cc1cd0c"/> + <textElement textAlignment="Center"> + <font fontName="SansSerif" size="14" isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Bills of material using date effectivity]]></text> + </staticText> + <staticText> + <reportElement x="0" y="80" width="30" height="20" uuid="8213394e-7143-4f85-8259-f11a9e9f6da1"/> + <textElement verticalAlignment="Bottom"> + <font fontName="SansSerif" isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Date :]]></text> + </staticText> + <staticText> + <reportElement x="0" y="100" width="90" height="20" uuid="16268bcd-1f46-436a-8985-139d61ae36ca"/> + <textElement verticalAlignment="Bottom"> + <font fontName="SansSerif" isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Date d'effectivité :]]></text> + </staticText> + <staticText> + <reportElement x="0" y="120" width="90" height="20" uuid="ed387d70-8182-4a54-ad00-903b07d1cf5e"/> + <textElement verticalAlignment="Bottom"> + <font fontName="SansSerif" isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Référence article :]]></text> + </staticText> + <staticText> + <reportElement x="0" y="140" width="40" height="20" uuid="adc6bff6-2abe-41b5-8ed9-296c4ec7649b"/> + <textElement verticalAlignment="Bottom"> + <font fontName="SansSerif" isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Niveau :]]></text> + </staticText> + <staticText> + <reportElement x="0" y="160" width="50" height="20" uuid="223b27bf-23e1-4c1d-bf84-b487debd8fb2"/> + <textElement verticalAlignment="Bottom"> + <font fontName="SansSerif" isBold="true" pdfFontName="Helvetica-Bold"/> + </textElement> + <text><![CDATA[Résultat :]]></text> + </staticText> + <textField evaluationTime="Report"> + <reportElement x="30" y="80" width="772" height="20" uuid="2b6b80bd-3694-4680-9b89-8d80a4369f7c"/> + <textElement verticalAlignment="Bottom"> + <font fontName="SansSerif" pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{DATE_TRAITEMENT}]]></textFieldExpression> + </textField> + <textField evaluationTime="Report"> + <reportElement x="90" y="100" width="712" height="20" uuid="d5cc6967-759a-4822-908b-a0dee6741a2c"/> + <textElement verticalAlignment="Bottom"> + <font fontName="SansSerif" pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{DATE_EFFECTIVITE}]]></textFieldExpression> + </textField> + <textField evaluationTime="Report"> + <reportElement x="90" y="120" width="712" height="20" uuid="d2f8d509-7634-472c-a313-aecb48ed601a"/> + <textElement verticalAlignment="Bottom"> + <font fontName="SansSerif" pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[$P{REFERENCE_ARTICLE}]]></textFieldExpression> + </textField> + <textField evaluationTime="Report"> + <reportElement x="40" y="140" width="762" height="20" uuid="2f49bcdb-558b-45f0-810c-8f20fd157827"/> + <textElement verticalAlignment="Bottom"> + <font fontName="SansSerif" pdfFontName="Helvetica"/> + </textElement> + <textFieldExpression><![CDATA[" " + $P{NIVEAU}]]></textFieldExpression> + </textField> + <staticText> + <reportElement x="50" y="160" width="752" height="20" uuid="abcf5995-dfdf-44f2-820a-ecc79f1bf320"/> + <textElement verticalAlignment="Bottom"> + <font fontName="SansSerif" pdfFontName="Helvetica"/> + </textElement> + <text><![CDATA[pdf]]></text> + </staticText> + <break> + <reportElement x="0" y="180" width="96" height="1" uuid="76003345-b03a-4011-b34c-9c3d6a49d511"/> + </break> + </band> + + + + + + 1]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/Jasper/template/report_r23.jrxml b/kurt-utility/src/main/resources/Jasper/template/report_r23.jrxml new file mode 100644 index 0000000..eade002 --- /dev/null +++ b/kurt-utility/src/main/resources/Jasper/template/report_r23.jrxml @@ -0,0 +1,1404 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/Jasper/template/report_r24.jrxml b/kurt-utility/src/main/resources/Jasper/template/report_r24.jrxml new file mode 100644 index 0000000..a83b0ad --- /dev/null +++ b/kurt-utility/src/main/resources/Jasper/template/report_r24.jrxml @@ -0,0 +1,499 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <band height="510"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + <staticText> + <reportElement positionType="Float" x="0" y="441" width="150" height="30" uuid="c8e9f5f7-1896-4aaf-b18a-0c09312016cd"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + <printWhenExpression><![CDATA[$P{IS_PREVIOUS_DEF}]]></printWhenExpression> + </reportElement> + <textElement verticalAlignment="Middle"> + <font size="8" isBold="true"/> + </textElement> + <text><![CDATA[MT +MT Number]]></text> + </staticText> + <staticText> + <reportElement positionType="Float" x="0" y="471" width="150" height="30" uuid="62981c54-a5b2-48bf-9840-cc4e60859226"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + <printWhenExpression><![CDATA[$P{IS_PREVIOUS_DEF}]]></printWhenExpression> + </reportElement> + <textElement verticalAlignment="Middle"> + <font size="8" isBold="true"/> + </textElement> + <text><![CDATA[Date de lancement +Release date]]></text> + </staticText> + <textField> + <reportElement positionType="Float" x="150" y="471" width="405" height="30" uuid="2c240f3e-0a02-4bcd-a98c-8c894e9e1d19"> + <printWhenExpression><![CDATA[$P{IS_PREVIOUS_DEF}]]></printWhenExpression> + </reportElement> + <textElement verticalAlignment="Middle"> + <font size="8"/> + </textElement> + <textFieldExpression><![CDATA[$P{PREVIOUS_RELEASE_DATE}]]></textFieldExpression> + </textField> + <textField> + <reportElement positionType="Float" stretchType="RelativeToTallestObject" x="150" y="441" width="405" height="30" uuid="2830e066-9f5f-4682-bc32-64bc41b898fa"> + <printWhenExpression><![CDATA[$P{IS_PREVIOUS_DEF}]]></printWhenExpression> + </reportElement> + <textElement verticalAlignment="Middle"> + <font size="8"/> + </textElement> + <textFieldExpression><![CDATA[$P{MT_NUMBER}]]></textFieldExpression> + </textField> + <staticText> + <reportElement x="0" y="200" width="150" height="30" uuid="d58f0c3a-9c3f-42a0-9a74-c4b13a4bfc9e"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font size="8" isBold="true"/> + </textElement> + <text><![CDATA[Dénomination Française +French Designation]]></text> + </staticText> + <textField> + <reportElement x="150" y="200" width="405" height="30" uuid="e5081414-e2bf-40bd-bccc-567131df6a5e"/> + <textElement verticalAlignment="Middle"> + <font size="8"/> + </textElement> + <textFieldExpression><![CDATA[$P{FRENCH_DESIGNATION}]]></textFieldExpression> + </textField> + <staticText> + <reportElement x="0" y="410" width="150" height="30" uuid="c71a994c-a413-4f90-a94a-fcadd4a82a17"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font size="8" isBold="true"/> + </textElement> + <text><![CDATA[Obturation +Obturation]]></text> + </staticText> + <textField> + <reportElement x="150" y="320" width="405" height="30" uuid="48b02918-dd5b-45ea-bce6-6423778e1596"/> + <textElement verticalAlignment="Middle"> + <font size="8"/> + </textElement> + <textFieldExpression><![CDATA[$P{LOG_DOCUMENT}]]></textFieldExpression> + </textField> + <textField> + <reportElement x="150" y="80" width="405" height="30" uuid="b8f4eb10-ca2d-498c-94ce-7589f0d24c80"/> + <textElement verticalAlignment="Middle"> + <font size="8"/> + </textElement> + <textFieldExpression><![CDATA[$P{PRODUCT_TYPE}]]></textFieldExpression> + </textField> + <textField> + <reportElement x="150" y="110" width="405" height="30" uuid="06a0f02d-35ff-49f5-a0da-43fd541563bb"/> + <textElement verticalAlignment="Middle"> + <font size="8"/> + </textElement> + <textFieldExpression><![CDATA[$P{PART_NUMBER}]]></textFieldExpression> + </textField> + <staticText> + <reportElement x="0" y="320" width="150" height="30" uuid="a329c593-2261-491c-8216-3449466dd821"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font size="8" isBold="true"/> + </textElement> + <text><![CDATA[Document de contrôle +Log Document]]></text> + </staticText> + <staticText> + <reportElement x="0" y="170" width="150" height="30" uuid="c887a61f-5bdf-4759-b01f-ca535f263f7c"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font size="8" isBold="true"/> + </textElement> + <text><![CDATA[Version de l’article +Part version]]></text> + </staticText> + <staticText> + <reportElement x="0" y="80" width="150" height="30" uuid="0b2fbdcf-2b30-4936-b89a-b237bc00858a"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font size="8" isBold="true"/> + </textElement> + <text><![CDATA[Type produit +Product Type]]></text> + </staticText> + <textField> + <reportElement x="150" y="410" width="405" height="30" uuid="f9019024-1120-45c1-a3fa-a4f6b6c00eab"/> + <textElement verticalAlignment="Middle"> + <font size="8"/> + </textElement> + <textFieldExpression><![CDATA[$P{OBTURATION}]]></textFieldExpression> + </textField> + <textField> + <reportElement x="150" y="140" width="405" height="30" uuid="04f2420a-7fd1-42b0-8da2-422f0b2a99c5"/> + <textElement verticalAlignment="Middle"> + <font size="8"/> + </textElement> + <textFieldExpression><![CDATA[$P{MANUFACTURER_CODE}]]></textFieldExpression> + </textField> + <staticText> + <reportElement x="0" y="290" width="150" height="30" uuid="a3f18762-a923-47c2-9dab-0bb02dea7ec5"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font size="8" isBold="true"/> + </textElement> + <text><![CDATA[Suivi Utilisation +Field OPN serialisation]]></text> + </staticText> + <textField> + <reportElement x="150" y="290" width="405" height="30" uuid="0f42ed3c-21a3-48ab-bab2-7e61699bdc78"/> + <textElement verticalAlignment="Middle"> + <font size="8"/> + </textElement> + <textFieldExpression><![CDATA[$P{FIELD_OPN_SERIALISATION}]]></textFieldExpression> + </textField> + <staticText> + <reportElement x="0" y="260" width="150" height="30" uuid="e74a400e-5b28-4206-9538-0e5322e395be"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font size="8" isBold="true"/> + </textElement> + <text><![CDATA[Classement +Classification]]></text> + </staticText> + <textField> + <reportElement x="150" y="260" width="405" height="30" uuid="5531e836-80a9-4bb9-8216-98637993b852"/> + <textElement verticalAlignment="Middle"> + <font size="8"/> + </textElement> + <textFieldExpression><![CDATA[$P{CLASSIFICATION}]]></textFieldExpression> + </textField> + <staticText> + <reportElement x="0" y="110" width="150" height="30" uuid="a760d63d-8652-4c30-a0fc-80032474925f"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font size="8" isBold="true"/> + </textElement> + <text><![CDATA[Référence de l’article +Part Number]]></text> + </staticText> + <textField> + <reportElement x="150" y="170" width="405" height="30" uuid="7acd17db-c975-482b-b33a-5a50cd7e495e"/> + <textElement verticalAlignment="Middle"> + <font size="8"/> + </textElement> + <textFieldExpression><![CDATA[$P{PART_VERSION}]]></textFieldExpression> + </textField> + <staticText> + <reportElement x="0" y="140" width="150" height="30" uuid="56254219-d62f-4d1f-b7e2-e7ba6b55db05"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font size="8" isBold="true"/> + </textElement> + <text><![CDATA[Code Fabricant +Manufacturer code]]></text> + </staticText> + <textField> + <reportElement x="60" y="0" width="120" height="20" uuid="16a34db8-b544-4ed7-aa30-723bbd0f2c97"> + <property name="local_mesure_unity" value="pixel"/> + <property name="com.jaspersoft.studio.unit.y" value="px"/> + <propertyExpression name="net.sf.jasperreports.export.xls.sheet.name"><![CDATA[$P{ITEM_ID}+ "_" + $V{PAGE_NUMBER}]]></propertyExpression> + </reportElement> + <box leftPadding="5"> + <topPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <leftPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <bottomPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <rightPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + </box> + <textElement verticalAlignment="Middle"/> + <textFieldExpression><![CDATA[$P{ITEM_ID}]]></textFieldExpression> + </textField> + <textField> + <reportElement x="200" y="40" width="290" height="20" uuid="5cd5ea2e-370d-4843-86ec-284dd5cc4669"/> + <box leftPadding="5"> + <topPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <leftPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <bottomPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <rightPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + </box> + <textElement verticalAlignment="Middle"/> + <textFieldExpression><![CDATA[$P{RELEASE_DATE}]]></textFieldExpression> + </textField> + <textField isStretchWithOverflow="true"> + <reportElement x="200" y="0" width="290" height="20" uuid="90631035-798d-4f4d-800a-1ae0da7199ce"/> + <box leftPadding="5"> + <topPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <leftPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <bottomPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <rightPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + </box> + <textElement verticalAlignment="Middle"/> + <textFieldExpression><![CDATA[$P{ITEM_REVISION_ID}]]></textFieldExpression> + </textField> + <textField> + <reportElement x="60" y="40" width="120" height="20" uuid="ae3b956d-b485-4801-81d9-dc75765b5f27"/> + <box leftPadding="5"> + <topPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <leftPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <bottomPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <rightPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + </box> + <textElement verticalAlignment="Middle"/> + <textFieldExpression><![CDATA[$P{PRODUCT_UNIT}]]></textFieldExpression> + </textField> + <textField> + <reportElement x="150" y="230" width="405" height="30" uuid="1e3b2e3b-8658-4332-8baa-1492978ab190"/> + <textElement verticalAlignment="Middle"> + <font size="8"/> + </textElement> + <textFieldExpression><![CDATA[$P{ENGLISH_DESIGNATION}]]></textFieldExpression> + </textField> + <staticText> + <reportElement x="0" y="230" width="150" height="30" uuid="1026facf-47bb-4163-939d-a87d49e93d9e"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font size="8" isBold="true"/> + </textElement> + <text><![CDATA[Dénomination Anglaise +English designation]]></text> + </staticText> + <staticText> + <reportElement x="0" y="350" width="150" height="30" uuid="58157510-6554-420b-b0eb-97ade29844ae"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font size="8" isBold="true"/> + </textElement> + <text><![CDATA[Frontière Avion +Installation Interface]]></text> + </staticText> + <textField> + <reportElement x="150" y="380" width="405" height="30" uuid="a12899e5-d6f2-42f0-9de5-5acdc64ed2a2"/> + <textElement verticalAlignment="Middle"> + <font size="8"/> + </textElement> + <textFieldExpression><![CDATA[$P{PARTNER_INTERFACE}]]></textFieldExpression> + </textField> + <staticText> + <reportElement x="0" y="380" width="150" height="30" uuid="5a2f3dcd-1fbd-4e8f-b46f-577c64544d37"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font size="8" isBold="true"/> + </textElement> + <text><![CDATA[Frontière Coopérant +Partner Interface]]></text> + </staticText> + <textField> + <reportElement x="150" y="350" width="405" height="30" uuid="ab848d3a-8005-4763-8583-384bb8c70cfc"/> + <textElement verticalAlignment="Middle"> + <font size="8"/> + </textElement> + <textFieldExpression><![CDATA[$P{INSTALLATION_INTERFACE}]]></textFieldExpression> + </textField> + <textField isStretchWithOverflow="true"> + <reportElement x="0" y="440" width="554" height="1" uuid="0ce0810e-0f14-4a0c-a06f-7f6665643d74"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + <printWhenExpression><![CDATA[$P{IS_PREVIOUS_DEF}]]></printWhenExpression> + </reportElement> + <textElement textAlignment="Center" verticalAlignment="Middle"> + <font isBold="true"/> + </textElement> + <textFieldExpression><![CDATA["\nDéfinition précédente / Previous Definition\n"]]></textFieldExpression> + </textField> + </band> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/Jasper/template/report_r25.jrxml b/kurt-utility/src/main/resources/Jasper/template/report_r25.jrxml new file mode 100644 index 0000000..ea1af4f --- /dev/null +++ b/kurt-utility/src/main/resources/Jasper/template/report_r25.jrxml @@ -0,0 +1,790 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <band height="510"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + <staticText> + <reportElement positionType="Float" x="0" y="441" width="150" height="30" + uuid="c8e9f5f7-1896-4aaf-b18a-0c09312016cd"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + <printWhenExpression><![CDATA[$P{IS_PREVIOUS_DEF}]]></printWhenExpression> + </reportElement> + <textElement verticalAlignment="Middle"> + <font size="8" isBold="true"/> + </textElement> + <text><![CDATA[MT +MT Number]]></text> + </staticText> + <staticText> + <reportElement positionType="Float" x="0" y="471" width="150" height="30" + uuid="62981c54-a5b2-48bf-9840-cc4e60859226"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + <printWhenExpression><![CDATA[$P{IS_PREVIOUS_DEF}]]></printWhenExpression> + </reportElement> + <textElement verticalAlignment="Middle"> + <font size="8" isBold="true"/> + </textElement> + <text><![CDATA[Date de lancement +Release date]]></text> + </staticText> + <textField> + <reportElement positionType="Float" x="150" y="471" width="405" height="30" + uuid="2c240f3e-0a02-4bcd-a98c-8c894e9e1d19"> + <printWhenExpression><![CDATA[$P{IS_PREVIOUS_DEF}]]></printWhenExpression> + </reportElement> + <textElement verticalAlignment="Middle"> + <font size="8"/> + </textElement> + <textFieldExpression><![CDATA[$P{PREVIOUS_RELEASE_DATE}]]></textFieldExpression> + </textField> + <textField> + <reportElement positionType="Float" stretchType="RelativeToTallestObject" x="150" y="441" width="405" + height="30" uuid="2830e066-9f5f-4682-bc32-64bc41b898fa"> + <printWhenExpression><![CDATA[$P{IS_PREVIOUS_DEF}]]></printWhenExpression> + </reportElement> + <textElement verticalAlignment="Middle"> + <font size="8"/> + </textElement> + <textFieldExpression><![CDATA[$P{MT_NUMBER}]]></textFieldExpression> + </textField> + <staticText> + <reportElement x="0" y="200" width="150" height="30" uuid="d58f0c3a-9c3f-42a0-9a74-c4b13a4bfc9e"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font size="8" isBold="true"/> + </textElement> + <text><![CDATA[Dénomination Française +French Designation]]></text> + </staticText> + <textField> + <reportElement x="150" y="200" width="405" height="30" uuid="e5081414-e2bf-40bd-bccc-567131df6a5e"/> + <textElement verticalAlignment="Middle"> + <font size="8"/> + </textElement> + <textFieldExpression><![CDATA[$P{FRENCH_DESIGNATION}]]></textFieldExpression> + </textField> + <staticText> + <reportElement x="0" y="410" width="150" height="30" uuid="c71a994c-a413-4f90-a94a-fcadd4a82a17"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font size="8" isBold="true"/> + </textElement> + <text><![CDATA[Obturation +Obturation]]></text> + </staticText> + <textField> + <reportElement x="150" y="320" width="405" height="30" uuid="48b02918-dd5b-45ea-bce6-6423778e1596"/> + <textElement verticalAlignment="Middle"> + <font size="8"/> + </textElement> + <textFieldExpression><![CDATA[$P{LOG_DOCUMENT}]]></textFieldExpression> + </textField> + <textField> + <reportElement x="150" y="80" width="405" height="30" uuid="b8f4eb10-ca2d-498c-94ce-7589f0d24c80"/> + <textElement verticalAlignment="Middle"> + <font size="8"/> + </textElement> + <textFieldExpression><![CDATA[$P{PRODUCT_TYPE}]]></textFieldExpression> + </textField> + <textField> + <reportElement x="150" y="110" width="405" height="30" uuid="06a0f02d-35ff-49f5-a0da-43fd541563bb"/> + <textElement verticalAlignment="Middle"> + <font size="8"/> + </textElement> + <textFieldExpression><![CDATA[$P{PART_NUMBER}]]></textFieldExpression> + </textField> + <staticText> + <reportElement x="0" y="320" width="150" height="30" uuid="a329c593-2261-491c-8216-3449466dd821"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font size="8" isBold="true"/> + </textElement> + <text><![CDATA[Document de contrôle +Log Document]]></text> + </staticText> + <staticText> + <reportElement x="0" y="170" width="150" height="30" uuid="c887a61f-5bdf-4759-b01f-ca535f263f7c"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font size="8" isBold="true"/> + </textElement> + <text><![CDATA[Version de l’article +Part version]]></text> + </staticText> + <staticText> + <reportElement x="0" y="80" width="150" height="30" uuid="0b2fbdcf-2b30-4936-b89a-b237bc00858a"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font size="8" isBold="true"/> + </textElement> + <text><![CDATA[Type produit +Product Type]]></text> + </staticText> + <textField> + <reportElement x="150" y="410" width="405" height="30" uuid="f9019024-1120-45c1-a3fa-a4f6b6c00eab"/> + <textElement verticalAlignment="Middle"> + <font size="8"/> + </textElement> + <textFieldExpression><![CDATA[$P{OBTURATION}]]></textFieldExpression> + </textField> + <textField> + <reportElement x="150" y="140" width="405" height="30" uuid="04f2420a-7fd1-42b0-8da2-422f0b2a99c5"/> + <textElement verticalAlignment="Middle"> + <font size="8"/> + </textElement> + <textFieldExpression><![CDATA[$P{MANUFACTURER_CODE}]]></textFieldExpression> + </textField> + <staticText> + <reportElement x="0" y="290" width="150" height="30" uuid="a3f18762-a923-47c2-9dab-0bb02dea7ec5"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font size="8" isBold="true"/> + </textElement> + <text><![CDATA[Suivi Utilisation +Field OPN serialisation]]></text> + </staticText> + <textField> + <reportElement x="150" y="290" width="405" height="30" uuid="0f42ed3c-21a3-48ab-bab2-7e61699bdc78"/> + <textElement verticalAlignment="Middle"> + <font size="8"/> + </textElement> + <textFieldExpression><![CDATA[$P{FIELD_OPN_SERIALISATION}]]></textFieldExpression> + </textField> + <staticText> + <reportElement x="0" y="260" width="150" height="30" uuid="e74a400e-5b28-4206-9538-0e5322e395be"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font size="8" isBold="true"/> + </textElement> + <text><![CDATA[Classement +Classification]]></text> + </staticText> + <textField> + <reportElement x="150" y="260" width="405" height="30" uuid="5531e836-80a9-4bb9-8216-98637993b852"/> + <textElement verticalAlignment="Middle"> + <font size="8"/> + </textElement> + <textFieldExpression><![CDATA[$P{CLASSIFICATION}]]></textFieldExpression> + </textField> + <staticText> + <reportElement x="0" y="110" width="150" height="30" uuid="a760d63d-8652-4c30-a0fc-80032474925f"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font size="8" isBold="true"/> + </textElement> + <text><![CDATA[Référence de l’article +Part Number]]></text> + </staticText> + <textField> + <reportElement x="150" y="170" width="405" height="30" uuid="7acd17db-c975-482b-b33a-5a50cd7e495e"/> + <textElement verticalAlignment="Middle"> + <font size="8"/> + </textElement> + <textFieldExpression><![CDATA[$P{PART_VERSION}]]></textFieldExpression> + </textField> + <staticText> + <reportElement x="0" y="140" width="150" height="30" uuid="56254219-d62f-4d1f-b7e2-e7ba6b55db05"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font size="8" isBold="true"/> + </textElement> + <text><![CDATA[Code Fabricant +Manufacturer code]]></text> + </staticText> + <textField> + <reportElement x="60" y="0" width="120" height="20" uuid="16a34db8-b544-4ed7-aa30-723bbd0f2c97"> + <property name="local_mesure_unity" value="pixel"/> + <property name="com.jaspersoft.studio.unit.y" value="px"/> + <propertyExpression name="net.sf.jasperreports.export.xls.sheet.name"> + <![CDATA[$P{ITEM_ID}+ "_" + $V{PAGE_NUMBER}]]></propertyExpression> + </reportElement> + <box leftPadding="5"> + <topPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <leftPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <bottomPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <rightPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + </box> + <textElement verticalAlignment="Middle"/> + <textFieldExpression><![CDATA[$P{ITEM_ID}]]></textFieldExpression> + </textField> + <textField> + <reportElement x="200" y="40" width="290" height="20" uuid="5cd5ea2e-370d-4843-86ec-284dd5cc4669"/> + <box leftPadding="5"> + <topPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <leftPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <bottomPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <rightPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + </box> + <textElement verticalAlignment="Middle"/> + <textFieldExpression><![CDATA[$P{RELEASE_DATE}]]></textFieldExpression> + </textField> + <textField isStretchWithOverflow="true"> + <reportElement x="200" y="0" width="290" height="20" uuid="90631035-798d-4f4d-800a-1ae0da7199ce"/> + <box leftPadding="5"> + <topPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <leftPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <bottomPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <rightPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + </box> + <textElement verticalAlignment="Middle"/> + <textFieldExpression><![CDATA[$P{ITEM_REVISION_ID}]]></textFieldExpression> + </textField> + <textField> + <reportElement x="60" y="40" width="120" height="20" uuid="ae3b956d-b485-4801-81d9-dc75765b5f27"/> + <box leftPadding="5"> + <topPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <leftPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <bottomPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + <rightPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/> + </box> + <textElement verticalAlignment="Middle"/> + <textFieldExpression><![CDATA[$P{PRODUCT_UNIT}]]></textFieldExpression> + </textField> + <textField> + <reportElement x="150" y="230" width="405" height="30" uuid="1e3b2e3b-8658-4332-8baa-1492978ab190"/> + <textElement verticalAlignment="Middle"> + <font size="8"/> + </textElement> + <textFieldExpression><![CDATA[$P{ENGLISH_DESIGNATION}]]></textFieldExpression> + </textField> + <staticText> + <reportElement x="0" y="230" width="150" height="30" uuid="1026facf-47bb-4163-939d-a87d49e93d9e"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font size="8" isBold="true"/> + </textElement> + <text><![CDATA[Dénomination Anglaise +English designation]]></text> + </staticText> + <staticText> + <reportElement x="0" y="350" width="150" height="30" uuid="58157510-6554-420b-b0eb-97ade29844ae"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font size="8" isBold="true"/> + </textElement> + <text><![CDATA[Frontière Avion +Installation Interface]]></text> + </staticText> + <textField> + <reportElement x="150" y="380" width="405" height="30" uuid="a12899e5-d6f2-42f0-9de5-5acdc64ed2a2"/> + <textElement verticalAlignment="Middle"> + <font size="8"/> + </textElement> + <textFieldExpression><![CDATA[$P{PARTNER_INTERFACE}]]></textFieldExpression> + </textField> + <staticText> + <reportElement x="0" y="380" width="150" height="30" uuid="5a2f3dcd-1fbd-4e8f-b46f-577c64544d37"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + </reportElement> + <textElement textAlignment="Left" verticalAlignment="Middle"> + <font size="8" isBold="true"/> + </textElement> + <text><![CDATA[Frontière Coopérant +Partner Interface]]></text> + </staticText> + <textField> + <reportElement x="150" y="350" width="405" height="30" uuid="ab848d3a-8005-4763-8583-384bb8c70cfc"/> + <textElement verticalAlignment="Middle"> + <font size="8"/> + </textElement> + <textFieldExpression><![CDATA[$P{INSTALLATION_INTERFACE}]]></textFieldExpression> + </textField> + <textField isStretchWithOverflow="true"> + <reportElement x="0" y="440" width="554" height="1" uuid="0ce0810e-0f14-4a0c-a06f-7f6665643d74"> + <property name="local_mesure_unitheight" value="pixel"/> + <property name="com.jaspersoft.studio.unit.height" value="px"/> + <printWhenExpression><![CDATA[$P{IS_PREVIOUS_DEF}]]></printWhenExpression> + </reportElement> + <textElement textAlignment="Center" verticalAlignment="Middle"> + <font isBold="true"/> + </textElement> + <textFieldExpression><![CDATA["\nDéfinition précédente / Previous Definition\n"]]></textFieldExpression> + </textField> + </band> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/Jasper/template/report_r26/report_r26_master.jrxml b/kurt-utility/src/main/resources/Jasper/template/report_r26/report_r26_master.jrxml new file mode 100644 index 0000000..4740970 --- /dev/null +++ b/kurt-utility/src/main/resources/Jasper/template/report_r26/report_r26_master.jrxml @@ -0,0 +1,142 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + >)$P{SUBREPORT_P1}.get("DATA"))]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + >)$P{SUBREPORT_P2}.get("DATA"))]]> + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/Jasper/template/report_r26/report_r26_subreport.jrxml b/kurt-utility/src/main/resources/Jasper/template/report_r26/report_r26_subreport.jrxml new file mode 100644 index 0000000..73ea70d --- /dev/null +++ b/kurt-utility/src/main/resources/Jasper/template/report_r26/report_r26_subreport.jrxml @@ -0,0 +1,536 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/Jasper/template/report_r27.jrxml b/kurt-utility/src/main/resources/Jasper/template/report_r27.jrxml new file mode 100644 index 0000000..8be1c10 --- /dev/null +++ b/kurt-utility/src/main/resources/Jasper/template/report_r27.jrxml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/Jasper/template/report_r28.jrxml b/kurt-utility/src/main/resources/Jasper/template/report_r28.jrxml new file mode 100644 index 0000000..6d9fc05 --- /dev/null +++ b/kurt-utility/src/main/resources/Jasper/template/report_r28.jrxml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/Jasper/template/template_R07.jrxml b/kurt-utility/src/main/resources/Jasper/template/template_R07.jrxml new file mode 100644 index 0000000..5ed3b37 --- /dev/null +++ b/kurt-utility/src/main/resources/Jasper/template/template_R07.jrxml @@ -0,0 +1,18 @@ + +[[PROPERTY]][[STYLE]][[PARAMETERS]][[FIELDS]] + + + + + <band height = "[[TITLE_HEIGHT]]" splitType="Stretch">[[TITLE]] + </band> + + + [[HEADERS]] + + + + [[CONTENT]] + + + \ No newline at end of file diff --git a/kurt-utility/src/main/resources/hibernate.cfg.xml b/kurt-utility/src/main/resources/hibernate.cfg.xml new file mode 100644 index 0000000..77d9a61 --- /dev/null +++ b/kurt-utility/src/main/resources/hibernate.cfg.xml @@ -0,0 +1,42 @@ + + + + + + + + + org.hibernate.dialect.Oracle10gDialect + java:jboss/datasources/ReportDS + + + org.hibernate.cache.NoCacheProvider + + org.hibernate.transaction.JDBCTransactionFactory + + + thread + + + false + + + update + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/hibernate/DbCriteriaVal_mapping.xml b/kurt-utility/src/main/resources/hibernate/DbCriteriaVal_mapping.xml new file mode 100644 index 0000000..9f49460 --- /dev/null +++ b/kurt-utility/src/main/resources/hibernate/DbCriteriaVal_mapping.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/hibernate/DbCriteria_mapping.xml b/kurt-utility/src/main/resources/hibernate/DbCriteria_mapping.xml new file mode 100644 index 0000000..98c9485 --- /dev/null +++ b/kurt-utility/src/main/resources/hibernate/DbCriteria_mapping.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/hibernate/DbMemMonitor_mapping.xml b/kurt-utility/src/main/resources/hibernate/DbMemMonitor_mapping.xml new file mode 100644 index 0000000..2f64619 --- /dev/null +++ b/kurt-utility/src/main/resources/hibernate/DbMemMonitor_mapping.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/hibernate/DbReportOwner_mapping.xml b/kurt-utility/src/main/resources/hibernate/DbReportOwner_mapping.xml new file mode 100644 index 0000000..05173ae --- /dev/null +++ b/kurt-utility/src/main/resources/hibernate/DbReportOwner_mapping.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/hibernate/DbReportType_mapping.xml b/kurt-utility/src/main/resources/hibernate/DbReportType_mapping.xml new file mode 100644 index 0000000..d2b8cd9 --- /dev/null +++ b/kurt-utility/src/main/resources/hibernate/DbReportType_mapping.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/hibernate/DbReport_mapping.xml b/kurt-utility/src/main/resources/hibernate/DbReport_mapping.xml new file mode 100644 index 0000000..40c01a5 --- /dev/null +++ b/kurt-utility/src/main/resources/hibernate/DbReport_mapping.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/hibernate/DbSchedulingCriteriaVal_mapping.xml b/kurt-utility/src/main/resources/hibernate/DbSchedulingCriteriaVal_mapping.xml new file mode 100644 index 0000000..55c4236 --- /dev/null +++ b/kurt-utility/src/main/resources/hibernate/DbSchedulingCriteriaVal_mapping.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/hibernate/DbSchedulingReport_mapping.xml b/kurt-utility/src/main/resources/hibernate/DbSchedulingReport_mapping.xml new file mode 100644 index 0000000..b524945 --- /dev/null +++ b/kurt-utility/src/main/resources/hibernate/DbSchedulingReport_mapping.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/hibernate/DbUser_mapping.xml b/kurt-utility/src/main/resources/hibernate/DbUser_mapping.xml new file mode 100644 index 0000000..527feff --- /dev/null +++ b/kurt-utility/src/main/resources/hibernate/DbUser_mapping.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/html/email/template_email_bad_parameters.html b/kurt-utility/src/main/resources/html/email/template_email_bad_parameters.html new file mode 100644 index 0000000..37762dc --- /dev/null +++ b/kurt-utility/src/main/resources/html/email/template_email_bad_parameters.html @@ -0,0 +1,7 @@ +

    Notification de fin d'exécution du rapport

    +
    +Date/heure de lancement: [[POSTING_TIME]]
    +Nom du rapport: [[REPORT_NAME]]

    +Date/heure de début de génération: [[START_TIME]]

    +Date/heure de fin de génération: [[END_TIME]]
    +[[ERROR_MESSAGE]]
    \ No newline at end of file diff --git a/kurt-utility/src/main/resources/html/email/template_email_failed.html b/kurt-utility/src/main/resources/html/email/template_email_failed.html new file mode 100644 index 0000000..347e21f --- /dev/null +++ b/kurt-utility/src/main/resources/html/email/template_email_failed.html @@ -0,0 +1,7 @@ +

    Notification de fin d'exécution du rapport

    +
    +Date/heure de lancement: [[POSTING_TIME]]
    +Nom du rapport: [[REPORT_NAME]]

    +Date/heure de début de génération: [[START_TIME]]

    +Date/heure de fin de génération: [[END_TIME]]

    +[[ERROR_MESSAGE]]
    \ No newline at end of file diff --git a/kurt-utility/src/main/resources/html/email/template_email_failed_admin.html b/kurt-utility/src/main/resources/html/email/template_email_failed_admin.html new file mode 100644 index 0000000..347e21f --- /dev/null +++ b/kurt-utility/src/main/resources/html/email/template_email_failed_admin.html @@ -0,0 +1,7 @@ +

    Notification de fin d'exécution du rapport

    +
    +Date/heure de lancement: [[POSTING_TIME]]
    +Nom du rapport: [[REPORT_NAME]]

    +Date/heure de début de génération: [[START_TIME]]

    +Date/heure de fin de génération: [[END_TIME]]

    +[[ERROR_MESSAGE]]
    \ No newline at end of file diff --git a/kurt-utility/src/main/resources/html/email/template_email_finished.html b/kurt-utility/src/main/resources/html/email/template_email_finished.html new file mode 100644 index 0000000..2f037bf --- /dev/null +++ b/kurt-utility/src/main/resources/html/email/template_email_finished.html @@ -0,0 +1,7 @@ +

    Notification de fin d'exécution du rapport

    +
    +Date/heure de lancement: [[POSTING_TIME]]
    +Nom du rapport: [[REPORT_NAME]]

    +Date/heure de début de génération: [[START_TIME]]

    +Date/heure de fin de génération: [[END_TIME]]
    +Lien de récupération du rapport: [[REPORT_LOCATION]]
    diff --git a/kurt-utility/src/main/resources/html/email/template_email_posted.html b/kurt-utility/src/main/resources/html/email/template_email_posted.html new file mode 100644 index 0000000..2f3173a --- /dev/null +++ b/kurt-utility/src/main/resources/html/email/template_email_posted.html @@ -0,0 +1,4 @@ +

    Détails du lancement effectué

    +
    +Nom du rapport: [[REPORT_NAME]]
    +Nom de la file d'attente: [[QUEUE_NAME]]
    \ No newline at end of file diff --git a/kurt-utility/src/main/resources/html/email/template_email_started.html b/kurt-utility/src/main/resources/html/email/template_email_started.html new file mode 100644 index 0000000..f3ac27d --- /dev/null +++ b/kurt-utility/src/main/resources/html/email/template_email_started.html @@ -0,0 +1,5 @@ +

    Notification de début d'exécution du rapport

    +
    +Date/heure de lancement: [[POSTING_TIME]]
    +Nom du rapport: [[REPORT_NAME]]
    +Date/heure de début de génération: [[START_TIME]]

    diff --git a/kurt-utility/src/main/resources/html/error_jsp_page.html b/kurt-utility/src/main/resources/html/error_jsp_page.html new file mode 100644 index 0000000..5fadccb --- /dev/null +++ b/kurt-utility/src/main/resources/html/error_jsp_page.html @@ -0,0 +1,30 @@ + + + [[ERROR_TITLE]] + + + +

    + + The following error occurred on the server side: + +

    + + + + + +
    ![[ERROR_MESSAGE]]
    + +
    + +
  • Go back to the previous page + +
  • + + \ No newline at end of file diff --git a/kurt-utility/src/main/resources/log4j.properties b/kurt-utility/src/main/resources/log4j.properties new file mode 100644 index 0000000..ed54611 --- /dev/null +++ b/kurt-utility/src/main/resources/log4j.properties @@ -0,0 +1,16 @@ +log4j.logger.com.teamcenter.soa=WARN, stdout +log4j.additivity.com.teamcenter.soa=false +log4j.logger.com.teamcenter.soa.client.Connection=INFO, stdout +log4j.additivity.com.teamcenter.soa.client.Connection=false +log4j.logger.org.apache=WARN, stdout +log4j.logger.httpclient=WARN, stdout + +# Direct log messages to stdout +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.Target=System.out +log4j.appender.stdout.threshold=DEBUG +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %c{1}:%L - %m%n + +# Root logger option +log4j.rootLogger=DEBUG, stdout diff --git a/kurt-utility/src/main/resources/quartz.properties b/kurt-utility/src/main/resources/quartz.properties new file mode 100644 index 0000000..6a3eb28 --- /dev/null +++ b/kurt-utility/src/main/resources/quartz.properties @@ -0,0 +1,56 @@ +#========================================================================== +# Configure Main Scheduler Properties +#========================================================================== +org.quartz.scheduler.instanceName: DefaultQuartzScheduler +org.quartz.scheduler.rmi.export: false +org.quartz.scheduler.rmi.proxy: false +org.quartz.scheduler.wrapJobExecutionInUserTransaction: false +org.quartz.scheduler.batchTriggerAcquisitionMaxCount = 100 +org.quartz.scheduler.batchTriggerAcquisitionFireAheadTimeWindow =1 + +# Amount of time in milliseconds that the scheduler will wait before re-queries for available triggers when the scheduler is otherwise idle +org.quartz.scheduler.idleWaitTime: 1000 + +# Amount of time in milliseconds that the scheduler will wait between re-tries when it has detected a loss of connectivity to the database (obviously not meaningful with RamJobStore) +org.quartz.scheduler.dbFailureRetryInterval: 3600 + +#========================================================================== +# Configure ThreadPool +#========================================================================== +org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool + +# Number of threads that are available for concurrent execution of jobs +org.quartz.threadPool.threadCount: 100 + +# Thread priority (Can be any int between Thread.MIN_PRIORITY (which is 1) and Thread.MAX_PRIORITY (which is 10). The default is Thread.NORM_PRIORITY (5)) +org.quartz.threadPool.threadPriority: 5 + +org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread: true + +#========================================================================== +# Configure JobStore +#========================================================================== +org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX +org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate +org.quartz.jobStore.dataSource=quartzDS +org.quartz.jobStore.tablePrefix=QRTZ_ +org.quartz.jobStore.useProperties = false +org.quartz.jobStore.misfireThreshold = 60000 +org.quartz.jobStore.isClustered = false +org.quartz.jobStore.maxMisfiresToHandleAtATime = 20 +org.quartz.jobStore.dontSetAutoCommitFalse = false + +# "{0}" is replaced during run-time with the TABLE_PREFIX that you configured above and "{1}" with the scheduler's name +org.quartz.jobStore.selectWithLockSQL = "SELECT * FROM {0}LOCKS WHERE SCHED_NAME = {1} AND LOCK_NAME = ? FOR UPDATE" + +org.quartz.jobStore.txIsolationLevelSerializable = false +org.quartz.jobStore.acquireTriggersWithinLock = true + +#========================================================================== +# Configure Datasources +#========================================================================== +org.quartz.dataSource.quartzDS.jndiURL=java:jboss/datasources/QuartzDS +org.quartz.dataSource.quartzDSNoTx.jndiURL=java:jboss/datasources/QuartzDS + +# Be configured to be at least the number of worker threads in the thread pool plus three +org.quartz.dataSource.quartzDS.maxConnections=103 diff --git a/kurt-utility/src/main/resources/reporting.properties b/kurt-utility/src/main/resources/reporting.properties new file mode 100644 index 0000000..ad7243c --- /dev/null +++ b/kurt-utility/src/main/resources/reporting.properties @@ -0,0 +1,99 @@ +# Configuration resolution parameters +com.capgemini.report.common.bom.revisionRule.default=\ DMA Configuration Interface +com.capgemini.report.common.bom.revisionRule.REPORT_R01=\ DMA Configuration Interface R01 +com.capgemini.report.common.bom.revisionRule.REPORT_R03=\ DMA Configuration Interface +com.capgemini.report.common.bom.revisionRule.REPORT_R05=\ DMA Configuration Interface +com.capgemini.report.common.bom.revisionRule.REPORT_R06=\ DMA Configuration Interface +com.capgemini.report.common.bom.revisionRule.REPORT_R07=\ DMA Configuration Rapport PU +com.capgemini.report.common.bom.revisionRule.REPORT_R10=\ DMA Configuration Validated +com.capgemini.report.common.bom.revisionRule.REPORT_R11=\ DMA Configuration Mockup Best So Far +com.capgemini.report.common.bom.revisionRule.REPORT_R13=\ DMA Configuration Interface +com.capgemini.report.common.bom.revisionRule.REPORT_R15=\ DMA Configuration Interface +com.capgemini.report.common.bom.revisionRule.REPORT_W15=\ DMA Configuration Interface +com.capgemini.report.common.bom.revisionRule.REPORT_R16=\ DMA Configuration Validated +com.capgemini.report.common.bom.revisionRule.REPORT_R17=\ DMA Configuration Interface +com.capgemini.report.common.bom.revisionRule.REPORT_R19=\ Generic / Generic Assemb R19 +com.capgemini.report.common.bom.revisionRule.REPORT_R20=\ DMA Configuration Interface +com.capgemini.report.common.bom.revisionRule.REPORT_R21=\ DMA Configuration Interface +com.capgemini.report.common.bom.revisionRule.REPORT_R22=\ DMA Configuration Interface +com.capgemini.report.common.bom.revisionRule.REPORT_W22=\ DMA Configuration Interface +com.capgemini.report.common.bom.revisionRule.REPORT_R23=\ DMA Configuration Interface PU R23 +com.capgemini.report.common.bom.revisionRule.REPORT_R24=\ DMA Configuration Validated +com.capgemini.report.common.bom.revisionRule.REPORT_R25=\ DMA Configuration Descriptif R25 +com.capgemini.report.common.bom.revisionRule.REPORT_R26=\ DMA Configuration Interface + +# Report titles +com.capgemini.report.title.REPORT_R01=BOM assemblage PU +com.capgemini.report.title.REPORT_R03=BOM fabrication date +com.capgemini.report.title.REPORT_R05=BOM Multi récepteursPU +com.capgemini.report.title.REPORT_R06=Statut Def et Indus PU +com.capgemini.report.title.REPORT_R07=Comparaison BOM PU +com.capgemini.report.title.REPORT_R10=Documents associés générique +com.capgemini.report.title.REPORT_R11=Mise en maquette et cohérence +com.capgemini.report.title.REPORT_R13=Etat avancement processus +com.capgemini.report.title.REPORT_R15=Fiche article +com.capgemini.report.title.REPORT_W15=Fiche article +com.capgemini.report.title.REPORT_R16=Fiche générique +com.capgemini.report.title.REPORT_R17=Liste documents associés article +com.capgemini.report.title.REPORT_R19=Cas utilisation document +com.capgemini.report.title.REPORT_R20=Gel de UNIT +com.capgemini.report.title.REPORT_R21=Compare Net +com.capgemini.report.title.REPORT_R22=BOM fabrication date PDF eDOC +com.capgemini.report.title.REPORT_W22=BOM fabrication date PDF eDOC +com.capgemini.report.title.REPORT_R23=Bom assemblage PU(s) +com.capgemini.report.title.REPORT_R24=Fiche(s) générique(s) +com.capgemini.report.title.REPORT_R25=Liste des documents des génériques +com.capgemini.report.title.REPORT_R26=Cas d'emploi d'un article +com.capgemini.report.title.REPORT_R27=Extraction des articles de type pièces +com.capgemini.report.title.REPORT_R28=Extraction des repères fonctionnels + +# Report priorities (1=High, 2=Medium, 3=Low) +com.capgemini.report.priority.REPORT_R01=2 +com.capgemini.report.priority.REPORT_R03=1 +com.capgemini.report.priority.REPORT_R05=3 +com.capgemini.report.priority.REPORT_R06=3 +com.capgemini.report.priority.REPORT_R07=3 +com.capgemini.report.priority.REPORT_R10=3 +com.capgemini.report.priority.REPORT_R11=2 +com.capgemini.report.priority.REPORT_R13=2 +com.capgemini.report.priority.REPORT_R15=1 +com.capgemini.report.priority.REPORT_W15=1 +com.capgemini.report.priority.REPORT_R16=1 +com.capgemini.report.priority.REPORT_R17=1 +com.capgemini.report.priority.REPORT_R19=1 +com.capgemini.report.priority.REPORT_R20=2 +com.capgemini.report.priority.REPORT_R21=3 +com.capgemini.report.priority.REPORT_R22=1 +com.capgemini.report.priority.REPORT_W22=1 +com.capgemini.report.priority.REPORT_R23=2 +com.capgemini.report.priority.REPORT_R24=1 +com.capgemini.report.priority.REPORT_R25=1 +com.capgemini.report.priority.REPORT_R26=1 +com.capgemini.report.priority.REPORT_R27=1 +com.capgemini.report.priority.REPORT_R28=1 + +# Report launch type parameters (immediate or delayed) +com.capgemini.report.common.launch.launchType.default=immediate +com.capgemini.report.common.launch.launchType.REPORT_R01=immediate +com.capgemini.report.common.launch.launchType.REPORT_R03=immediate +com.capgemini.report.common.launch.launchType.REPORT_R05=immediate +com.capgemini.report.common.launch.launchType.REPORT_R06=immediate +com.capgemini.report.common.launch.launchType.REPORT_R07=immediate +com.capgemini.report.common.launch.launchType.REPORT_R10=immediate +com.capgemini.report.common.launch.launchType.REPORT_R11=immediate +com.capgemini.report.common.launch.launchType.REPORT_R13=immediate +com.capgemini.report.common.launch.launchType.REPORT_R15=immediate +com.capgemini.report.common.launch.launchType.REPORT_W15=immediate +com.capgemini.report.common.launch.launchType.REPORT_R16=immediate +com.capgemini.report.common.launch.launchType.REPORT_R17=immediate +com.capgemini.report.common.launch.launchType.REPORT_R19=immediate +com.capgemini.report.common.launch.launchType.REPORT_R20=immediate +com.capgemini.report.common.launch.launchType.REPORT_R21=immediate +com.capgemini.report.common.launch.launchType.REPORT_R22=immediate +com.capgemini.report.common.launch.launchType.REPORT_W22=immediate +com.capgemini.report.common.launch.launchType.REPORT_R23=immediate +com.capgemini.report.common.launch.launchType.REPORT_R24=immediate +com.capgemini.report.common.launch.launchType.REPORT_R25=immediate +com.capgemini.report.common.launch.launchType.REPORT_R26=immediate +com.capgemini.report.common.launch.launchType.REPORT_R27=immediate +com.capgemini.report.common.launch.launchType.REPORT_R28=immediate diff --git a/kurt-utility/src/main/resources/xml/policies/r01report/R01_policy_full.xml b/kurt-utility/src/main/resources/xml/policies/r01report/R01_policy_full.xml new file mode 100644 index 0000000..b1ca931 --- /dev/null +++ b/kurt-utility/src/main/resources/xml/policies/r01report/R01_policy_full.xml @@ -0,0 +1,128 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/xml/policies/r01report/R01_policy_light.xml b/kurt-utility/src/main/resources/xml/policies/r01report/R01_policy_light.xml new file mode 100644 index 0000000..1354d8a --- /dev/null +++ b/kurt-utility/src/main/resources/xml/policies/r01report/R01_policy_light.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/xml/policies/r03report/R03_policy_full.xml b/kurt-utility/src/main/resources/xml/policies/r03report/R03_policy_full.xml new file mode 100644 index 0000000..f125d80 --- /dev/null +++ b/kurt-utility/src/main/resources/xml/policies/r03report/R03_policy_full.xml @@ -0,0 +1,127 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/xml/policies/r03report/R03_policy_light.xml b/kurt-utility/src/main/resources/xml/policies/r03report/R03_policy_light.xml new file mode 100644 index 0000000..d46c6f7 --- /dev/null +++ b/kurt-utility/src/main/resources/xml/policies/r03report/R03_policy_light.xml @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/xml/policies/r07report/R07_policy_full.xml b/kurt-utility/src/main/resources/xml/policies/r07report/R07_policy_full.xml new file mode 100644 index 0000000..8a22480 --- /dev/null +++ b/kurt-utility/src/main/resources/xml/policies/r07report/R07_policy_full.xml @@ -0,0 +1,145 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/xml/policies/r07report/R07_policy_light.xml b/kurt-utility/src/main/resources/xml/policies/r07report/R07_policy_light.xml new file mode 100644 index 0000000..1354d8a --- /dev/null +++ b/kurt-utility/src/main/resources/xml/policies/r07report/R07_policy_light.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/xml/policies/r10report/R10_policy_full.xml b/kurt-utility/src/main/resources/xml/policies/r10report/R10_policy_full.xml new file mode 100644 index 0000000..f5c3508 --- /dev/null +++ b/kurt-utility/src/main/resources/xml/policies/r10report/R10_policy_full.xml @@ -0,0 +1,167 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/kurt-utility/src/main/resources/xml/policies/r10report/R10_policy_light.xml b/kurt-utility/src/main/resources/xml/policies/r10report/R10_policy_light.xml new file mode 100644 index 0000000..1354d8a --- /dev/null +++ b/kurt-utility/src/main/resources/xml/policies/r10report/R10_policy_light.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/xml/policies/r11report/R11_policy_full.xml b/kurt-utility/src/main/resources/xml/policies/r11report/R11_policy_full.xml new file mode 100644 index 0000000..e0d4588 --- /dev/null +++ b/kurt-utility/src/main/resources/xml/policies/r11report/R11_policy_full.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/xml/policies/r11report/R11_policy_light.xml b/kurt-utility/src/main/resources/xml/policies/r11report/R11_policy_light.xml new file mode 100644 index 0000000..1354d8a --- /dev/null +++ b/kurt-utility/src/main/resources/xml/policies/r11report/R11_policy_light.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/xml/policies/r13report/R13_policy_full.xml b/kurt-utility/src/main/resources/xml/policies/r13report/R13_policy_full.xml new file mode 100644 index 0000000..b226910 --- /dev/null +++ b/kurt-utility/src/main/resources/xml/policies/r13report/R13_policy_full.xml @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/xml/policies/r13report/R13_policy_light.xml b/kurt-utility/src/main/resources/xml/policies/r13report/R13_policy_light.xml new file mode 100644 index 0000000..c8bcf6e --- /dev/null +++ b/kurt-utility/src/main/resources/xml/policies/r13report/R13_policy_light.xml @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/kurt-utility/src/main/resources/xml/policies/r15report/R15_policy_full.xml b/kurt-utility/src/main/resources/xml/policies/r15report/R15_policy_full.xml new file mode 100644 index 0000000..123cdad --- /dev/null +++ b/kurt-utility/src/main/resources/xml/policies/r15report/R15_policy_full.xml @@ -0,0 +1,115 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/xml/policies/r15report/R15_policy_light.xml b/kurt-utility/src/main/resources/xml/policies/r15report/R15_policy_light.xml new file mode 100644 index 0000000..0b516e6 --- /dev/null +++ b/kurt-utility/src/main/resources/xml/policies/r15report/R15_policy_light.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/xml/policies/r15report/R15_policy_wkf.xml b/kurt-utility/src/main/resources/xml/policies/r15report/R15_policy_wkf.xml new file mode 100644 index 0000000..887ddcb --- /dev/null +++ b/kurt-utility/src/main/resources/xml/policies/r15report/R15_policy_wkf.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/xml/policies/r16report/R16_policy_full.xml b/kurt-utility/src/main/resources/xml/policies/r16report/R16_policy_full.xml new file mode 100644 index 0000000..05d7552 --- /dev/null +++ b/kurt-utility/src/main/resources/xml/policies/r16report/R16_policy_full.xml @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/xml/policies/r16report/R16_policy_light.xml b/kurt-utility/src/main/resources/xml/policies/r16report/R16_policy_light.xml new file mode 100644 index 0000000..da9a0b7 --- /dev/null +++ b/kurt-utility/src/main/resources/xml/policies/r16report/R16_policy_light.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/xml/policies/r17report/R17_policy_full.xml b/kurt-utility/src/main/resources/xml/policies/r17report/R17_policy_full.xml new file mode 100644 index 0000000..3e4e8af --- /dev/null +++ b/kurt-utility/src/main/resources/xml/policies/r17report/R17_policy_full.xml @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/xml/policies/r17report/R17_policy_light.xml b/kurt-utility/src/main/resources/xml/policies/r17report/R17_policy_light.xml new file mode 100644 index 0000000..68358af --- /dev/null +++ b/kurt-utility/src/main/resources/xml/policies/r17report/R17_policy_light.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/xml/policies/r19report/R19_policy_full.xml b/kurt-utility/src/main/resources/xml/policies/r19report/R19_policy_full.xml new file mode 100644 index 0000000..93d848c --- /dev/null +++ b/kurt-utility/src/main/resources/xml/policies/r19report/R19_policy_full.xml @@ -0,0 +1,144 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/xml/policies/r19report/R19_policy_light.xml b/kurt-utility/src/main/resources/xml/policies/r19report/R19_policy_light.xml new file mode 100644 index 0000000..784a89f --- /dev/null +++ b/kurt-utility/src/main/resources/xml/policies/r19report/R19_policy_light.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/xml/policies/r20report/R20_policy_full.xml b/kurt-utility/src/main/resources/xml/policies/r20report/R20_policy_full.xml new file mode 100644 index 0000000..f60f99c --- /dev/null +++ b/kurt-utility/src/main/resources/xml/policies/r20report/R20_policy_full.xml @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/xml/policies/r20report/R20_policy_light.xml b/kurt-utility/src/main/resources/xml/policies/r20report/R20_policy_light.xml new file mode 100644 index 0000000..9bad06b --- /dev/null +++ b/kurt-utility/src/main/resources/xml/policies/r20report/R20_policy_light.xml @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/kurt-utility/src/main/resources/xml/policies/r21report/R21_policy_full.xml b/kurt-utility/src/main/resources/xml/policies/r21report/R21_policy_full.xml new file mode 100644 index 0000000..4d2a202 --- /dev/null +++ b/kurt-utility/src/main/resources/xml/policies/r21report/R21_policy_full.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/xml/policies/r21report/R21_policy_light.xml b/kurt-utility/src/main/resources/xml/policies/r21report/R21_policy_light.xml new file mode 100644 index 0000000..df6f145 --- /dev/null +++ b/kurt-utility/src/main/resources/xml/policies/r21report/R21_policy_light.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/xml/policies/r22report/R22_policy_full.xml b/kurt-utility/src/main/resources/xml/policies/r22report/R22_policy_full.xml new file mode 100644 index 0000000..d3d09b1 --- /dev/null +++ b/kurt-utility/src/main/resources/xml/policies/r22report/R22_policy_full.xml @@ -0,0 +1,119 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/xml/policies/r22report/R22_policy_light.xml b/kurt-utility/src/main/resources/xml/policies/r22report/R22_policy_light.xml new file mode 100644 index 0000000..68358af --- /dev/null +++ b/kurt-utility/src/main/resources/xml/policies/r22report/R22_policy_light.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/xml/policies/r22report/R22_policy_wkf.xml b/kurt-utility/src/main/resources/xml/policies/r22report/R22_policy_wkf.xml new file mode 100644 index 0000000..79531e1 --- /dev/null +++ b/kurt-utility/src/main/resources/xml/policies/r22report/R22_policy_wkf.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/xml/policies/r23report/R23_policy_full.xml b/kurt-utility/src/main/resources/xml/policies/r23report/R23_policy_full.xml new file mode 100644 index 0000000..f8338bb --- /dev/null +++ b/kurt-utility/src/main/resources/xml/policies/r23report/R23_policy_full.xml @@ -0,0 +1,152 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/xml/policies/r23report/R23_policy_light.xml b/kurt-utility/src/main/resources/xml/policies/r23report/R23_policy_light.xml new file mode 100644 index 0000000..1354d8a --- /dev/null +++ b/kurt-utility/src/main/resources/xml/policies/r23report/R23_policy_light.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/xml/policies/r24report/R24_policy_full.xml b/kurt-utility/src/main/resources/xml/policies/r24report/R24_policy_full.xml new file mode 100644 index 0000000..3336432 --- /dev/null +++ b/kurt-utility/src/main/resources/xml/policies/r24report/R24_policy_full.xml @@ -0,0 +1,100 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/xml/policies/r24report/R24_policy_light.xml b/kurt-utility/src/main/resources/xml/policies/r24report/R24_policy_light.xml new file mode 100644 index 0000000..da9a0b7 --- /dev/null +++ b/kurt-utility/src/main/resources/xml/policies/r24report/R24_policy_light.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/xml/policies/r25report/R25_policy_full.xml b/kurt-utility/src/main/resources/xml/policies/r25report/R25_policy_full.xml new file mode 100644 index 0000000..3336432 --- /dev/null +++ b/kurt-utility/src/main/resources/xml/policies/r25report/R25_policy_full.xml @@ -0,0 +1,100 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/xml/policies/r25report/R25_policy_light.xml b/kurt-utility/src/main/resources/xml/policies/r25report/R25_policy_light.xml new file mode 100644 index 0000000..da9a0b7 --- /dev/null +++ b/kurt-utility/src/main/resources/xml/policies/r25report/R25_policy_light.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/xml/policies/r26report/R26_policy_full.xml b/kurt-utility/src/main/resources/xml/policies/r26report/R26_policy_full.xml new file mode 100644 index 0000000..8d58050 --- /dev/null +++ b/kurt-utility/src/main/resources/xml/policies/r26report/R26_policy_full.xml @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/kurt-utility/src/main/resources/xml/policies/r26report/R26_policy_light.xml b/kurt-utility/src/main/resources/xml/policies/r26report/R26_policy_light.xml new file mode 100644 index 0000000..1354d8a --- /dev/null +++ b/kurt-utility/src/main/resources/xml/policies/r26report/R26_policy_light.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/xml/policies/r27report/R27_policy_full.xml b/kurt-utility/src/main/resources/xml/policies/r27report/R27_policy_full.xml new file mode 100644 index 0000000..5065e17 --- /dev/null +++ b/kurt-utility/src/main/resources/xml/policies/r27report/R27_policy_full.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/xml/policies/r27report/R27_policy_light.xml b/kurt-utility/src/main/resources/xml/policies/r27report/R27_policy_light.xml new file mode 100644 index 0000000..5065e17 --- /dev/null +++ b/kurt-utility/src/main/resources/xml/policies/r27report/R27_policy_light.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/xml/policies/r28report/R28_policy_full.xml b/kurt-utility/src/main/resources/xml/policies/r28report/R28_policy_full.xml new file mode 100644 index 0000000..1bc28bc --- /dev/null +++ b/kurt-utility/src/main/resources/xml/policies/r28report/R28_policy_full.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/xml/policies/r28report/R28_policy_light.xml b/kurt-utility/src/main/resources/xml/policies/r28report/R28_policy_light.xml new file mode 100644 index 0000000..1bc28bc --- /dev/null +++ b/kurt-utility/src/main/resources/xml/policies/r28report/R28_policy_light.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/main/resources/xsd/policies.xsd b/kurt-utility/src/main/resources/xsd/policies.xsd new file mode 100644 index 0000000..ab69397 --- /dev/null +++ b/kurt-utility/src/main/resources/xsd/policies.xsd @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/kurt-utility/src/main/sh/JenkinsDeploy.bat b/kurt-utility/src/main/sh/JenkinsDeploy.bat new file mode 100644 index 0000000..3b783aa --- /dev/null +++ b/kurt-utility/src/main/sh/JenkinsDeploy.bat @@ -0,0 +1,41 @@ +@echo off +rem The NOPAUSE env variable should be set to avoid prompt confirmations + +rem Define environment variables +set LOG_FILE=%TEMP%/JenkinsDeploy.log +set DEPLOYMENT_DIR=C:\JBoss-7.1\standalone\packages\deploy +set TOKEN_FILE=%DEPLOYMENT_DIR%\deploy.token +cd %DEPLOYMENT_DIR% + +rem Check if an EAR file should be deployed +if exist "%TOKEN_FILE%" ( + del "%TOKEN_FILE%" +) else ( + echo No token detected at %TOKEN_FILE% + pause + exit +) + +rem Reset log file +date /t > %LOG_FILE% + +echo ========================= +echo Jenkins deployment in VAL +echo ========================= + +echo - Undeploy previous EAR +call C:\JBoss-7.1\bin\jboss-cli.bat --connect --command="undeploy snecma-reports.ear" + +echo - Deploy new EAR +call C:\JBoss-7.1\bin\jboss-cli.bat --connect --command="deploy snecma-reports.ear" + +echo - Restart FSC +net stop "Teamcenter FSC Service FSC_pvtc10_tcadmin" >> %LOG_FILE% +net start "Teamcenter FSC Service FSC_pvtc10_tcadmin" >> %LOG_FILE% + +echo - Restart Teamcenter +net stop "TeamcenterServerManager_TC10" >> %LOG_FILE% +net start "TeamcenterServerManager_TC10" >> %LOG_FILE% + +del "%DEPLOYMENT_DIR%\snecma-reports.ear" + diff --git a/kurt-utility/src/main/sh/JenkinsDeploy.bat:Zone.Identifier b/kurt-utility/src/main/sh/JenkinsDeploy.bat:Zone.Identifier new file mode 100644 index 0000000..a45e1ac --- /dev/null +++ b/kurt-utility/src/main/sh/JenkinsDeploy.bat:Zone.Identifier @@ -0,0 +1,2 @@ +[ZoneTransfer] +ZoneId=3 diff --git a/kurt-utility/src/main/sh/JenkinsDeploy.vbs b/kurt-utility/src/main/sh/JenkinsDeploy.vbs new file mode 100644 index 0000000..312dac7 --- /dev/null +++ b/kurt-utility/src/main/sh/JenkinsDeploy.vbs @@ -0,0 +1,8 @@ +' *** Script start *** +Set oShell = CreateObject("WScript.Shell") + +' Lance le script batch en arrière plan pour les tâches planifiées +oShell.Run "C:\JBoss-7.1\standalone\packages\JenkinsDeploy.bat", 0, False + +' Quitte avec le code retour 0 +WScript.Quit 0 diff --git a/kurt-utility/src/main/sh/JenkinsDeploy.vbs:Zone.Identifier b/kurt-utility/src/main/sh/JenkinsDeploy.vbs:Zone.Identifier new file mode 100644 index 0000000..a45e1ac --- /dev/null +++ b/kurt-utility/src/main/sh/JenkinsDeploy.vbs:Zone.Identifier @@ -0,0 +1,2 @@ +[ZoneTransfer] +ZoneId=3 diff --git a/kurt-utility/src/main/sh/jenkins_packaging.sh b/kurt-utility/src/main/sh/jenkins_packaging.sh new file mode 100644 index 0000000..fad1e1f --- /dev/null +++ b/kurt-utility/src/main/sh/jenkins_packaging.sh @@ -0,0 +1,165 @@ +# Reset Kurt packaging temporary folders +# ====================================================== +export TMP_KURT=/tmp/kurt +rm -rf $TMP_KURT + + +export TMP_PACKAGING_KURT=$TMP_KURT/package +export TMP_SOURCE_KURT=$TMP_KURT/source +export TMP_UPLOAD_KURT=$TMP_KURT/upload +export TMP_DEPLOY_KURT=$TMP_KURT/deploy + +mkdir -p $TMP_PACKAGING_KURT +mkdir -p $TMP_SOURCE_KURT +mkdir -p $TMP_UPLOAD_KURT +mkdir -p $TMP_DEPLOY_KURT + +export HOST="10.24.192.36" + +export BUILD_FILENAME="build_infos.txt" +export BUILD_FILE="${TMP_PACKAGING_KURT}/${BUILD_FILENAME}" + +cd /tmp +echo "Build information:" > ${BUILD_FILE} +echo " - Job name: ${JOB_NAME}" >> ${BUILD_FILE} +echo " - Reference: ${BUILD_ID}" >> ${BUILD_FILE} +echo " - Number: ${BUILD_NUMBER}" >> ${BUILD_FILE} +echo " - SVN revision: ${SVN_REVISION}" >> ${BUILD_FILE} +echo " - Jenkins URL: ${BUILD_URL}" >> ${BUILD_FILE} +echo " - Workspace: ${WORKSPACE}" >> ${BUILD_FILE} + +# Group sources +# ====================================================== +cp ${WORKSPACE}/kurt-ejb/target/kurt-ejb-*-sources.jar $TMP_SOURCE_KURT +cp ${WORKSPACE}/jasper/target/jasper-*-sources.jar $TMP_SOURCE_KURT +cp ${WORKSPACE}/kurt-utility/target/kurt-utility-*-sources.jar $TMP_SOURCE_KURT +cp ${WORKSPACE}/kurt-web/target/kurt-web-*-sources.jar $TMP_SOURCE_KURT +cp ${WORKSPACE}/teamcenter/target/teamcenter-*-sources.jar $TMP_SOURCE_KURT + +# Create source package for report WebApp +cd $TMP_SOURCE_KURT +zip -r ${TMP_PACKAGING_KURT}/snecma-reports-${TAG_VERSION}-sources.zip . + +# Deploy policies on Teamcenter +# ====================================================== +cd ${WORKSPACE}/policies +ftp -n ${HOST} < ${TMP_DEPLOY_KURT}/deploy.token +date >> ${TMP_DEPLOY_KURT}/deploy.token +cd $TMP_DEPLOY_KURT +ftp -n ${HOST} < + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/kurt-utility/src/test/java/com/capgemini/framework/common/DateHelperTest.java b/kurt-utility/src/test/java/com/capgemini/framework/common/DateHelperTest.java new file mode 100644 index 0000000..6e1cc77 --- /dev/null +++ b/kurt-utility/src/test/java/com/capgemini/framework/common/DateHelperTest.java @@ -0,0 +1,43 @@ +package com.capgemini.framework.common; + +import org.testng.annotations.Test; + +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Locale; + +import static org.assertj.core.api.Assertions.assertThat; + +public class DateHelperTest { + private static final String PATTERN_YEAR_DASH_MONTH = "^[\\d]{4}-[\\d]{2}$"; // 4 digits, followed by a dash ('-'), followed by two difits, end of String. + private static final String DATE_USER_INPUT = "08-12-2014"; + private static final String EXPECTED_DATE_OUTPUT_US = "08-Dec-2014"; + private static final String DATE_USER_INPUT_EMPTY = ""; + private static final String EXPECTED_DATE_TODAY = "[\\d]{2}-[\\d]{2}-[\\d]{4}"; //25-01-2016 + + @Test + public void testMakeTeamcenterCalendar() { + assertThat(TeamcenterDateFormatter.makeTeamcenterCalendar(DATE_USER_INPUT)).isNotNull(); + assertThat(TeamcenterDateFormatter.makeTeamcenterCalendar(DATE_USER_INPUT_EMPTY)).isNotNull(); + } + + @Test + public void testMakeDateFormatForRequest() { + assertThat(TeamcenterDateFormatter.translateDateFormatForRequest(DATE_USER_INPUT)).isEqualTo(EXPECTED_DATE_OUTPUT_US); + assertThat(TeamcenterDateFormatter.translateDateFormatForRequest(DATE_USER_INPUT_EMPTY)).isEqualTo(getCurrentDate()); + } + + @Test + public void testGetMonthPeriod() { + assertThat(DateHelper.getMonthPeriod()).matches(PATTERN_YEAR_DASH_MONTH); + } + + @Test + public void testGetDate() { + assertThat(DateHelper.getDate()).matches(EXPECTED_DATE_TODAY); + } + + private String getCurrentDate() { + return new SimpleDateFormat("dd-MMM-yyyy", Locale.US).format(Calendar.getInstance().getTime()); + } +} diff --git a/kurt-utility/src/test/java/com/capgemini/framework/common/DoubleFormatterTest.java b/kurt-utility/src/test/java/com/capgemini/framework/common/DoubleFormatterTest.java new file mode 100644 index 0000000..c44a21d --- /dev/null +++ b/kurt-utility/src/test/java/com/capgemini/framework/common/DoubleFormatterTest.java @@ -0,0 +1,52 @@ +package com.capgemini.framework.common; + +import org.testng.annotations.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class DoubleFormatterTest { + + @Test + public void toSignificantDigitsTest() { + // Some Integers + tryToFormat(0, 1, "0"); // Simple integer + tryToFormat(20001054, 9, "20001054"); // Simple integer + tryToFormat(20001054, 8, "20001054"); // Simple integer, exact size + tryToFormat(20001054, 3, "20000000"); // Integer, with truncation of non-significant digits + tryToFormat(20001054, 6, "20001100"); // Integer, with rounding of non-significant digits + tryToFormat(-20001054, 9, "-20001054"); // [Negative] Simple integer + tryToFormat(-20001054, 8, "-20001054"); // [Negative] Simple integer, exact size + tryToFormat(-20001054, 3, "-20000000"); // [Negative] Integer, with truncation of non-significant digits + tryToFormat(-20001054, 6, "-20001100"); // [Negative] Integer, with rounding of non-significant digits + + // Some positive powers + tryToFormat(200010.54, 9, "200010.54"); // Simple real number + tryToFormat(200010.54, 8, "200010.54"); // Simple real number, exact size + tryToFormat(200010.54, 3, "200000"); // Real number, with truncation of non-significant digits before the coma + tryToFormat(200010.54, 7, "200010.5"); // Real number, with truncation of non-significant digits after the coma + tryToFormat(200010.56, 7, "200010.6"); // Real number, with rounding of non-significant digits after the coma + tryToFormat(-200010.54, 9, "-200010.54"); // [Negative] Simple real number + tryToFormat(-200010.54, 8, "-200010.54"); // [Negative] Simple real number, exact size + tryToFormat(-200010.54, 3, "-200000"); // [Negative] Real number, with truncation of non-significant digits before the coma [NOTE the zeroes and the coma must go away] + tryToFormat(-200010.54, 7, "-200010.5"); // [Negative] Real number, with truncation of non-significant digits after the coma + tryToFormat(-200010.56, 7, "-200010.6"); // [Negative] Real number, with rounding of non-significant digits after the coma + + // Very high number of significant digits, must still be correct (16 is the max) + tryToFormat(-100.0002005105412345, 16, "-100.0002005105412"); // [Negative] + + // Extremely high number of significant digits, must fail due to Long being too short :D + tryToFormat(-100.0002005105412345, 25, "-100.0002005105412"); // [Negative] + + // Some negative powers + tryToFormat(0.0002, 15, "0.0002"); // Test simple printing + tryToFormat(0.00020051024, 6, "0.00020051"); // Test truncating [NOTE the zeroes after the last digit must go away] + tryToFormat(0.00020051054, 3, "0.000201"); // Test rounding up the last significant digit + tryToFormat(-0.0002, 6, "-0.0002"); // [Negative] Test simple printing + tryToFormat(-0.00020051024, 6, "-0.00020051"); // [Negative] Test truncating [NOTE the zeroes after the last digit must go away] + tryToFormat(-0.00020051054, 3, "-0.000201"); // [Negative] Test rounding up the last significant digit + } + + private void tryToFormat(final double value, final int significantDigits, final String expectedResult) { + assertThat(DoubleFormatter.toSignificantDigits(value, significantDigits)).isEqualTo(expectedResult); + } +} diff --git a/kurt-utility/src/test/java/com/capgemini/framework/common/DynamicErrorTemplateHelperTest.java b/kurt-utility/src/test/java/com/capgemini/framework/common/DynamicErrorTemplateHelperTest.java new file mode 100644 index 0000000..51237d1 --- /dev/null +++ b/kurt-utility/src/test/java/com/capgemini/framework/common/DynamicErrorTemplateHelperTest.java @@ -0,0 +1,14 @@ +package com.capgemini.framework.common; + + +import org.testng.annotations.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class DynamicErrorTemplateHelperTest { + + @Test + public void testResolve() { + assertThat("ChangeRequest MOD079600 inconnu.").isEqualTo(new DynamicErrorTemplateHelper("ChangeRequest {} inconnu.", "MOD079600").resolve()); + } +} diff --git a/kurt-utility/src/test/java/com/capgemini/reports/definition/r26report/RangesTest.java b/kurt-utility/src/test/java/com/capgemini/reports/definition/r26report/RangesTest.java new file mode 100644 index 0000000..6ce549d --- /dev/null +++ b/kurt-utility/src/test/java/com/capgemini/reports/definition/r26report/RangesTest.java @@ -0,0 +1,306 @@ +package com.capgemini.reports.definition.r26report; + +import org.testng.annotations.Test; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +public class RangesTest { + + + @Test + public void oneRangeShouldReturnTheRange() { + List rangesList = new ArrayList<>(); + rangesList.add(new Range("A", 1, 10)); + Ranges ranges = new Ranges(rangesList); + assertThat(ranges.toString("A")).isEqualTo("1-10"); + } + + @Test + public void oneRangeWithSameBornInfBorneSupShouldReturnTheRange() { + List rangesList = new ArrayList<>(); + rangesList.add(new Range("A", 10, 10)); + Ranges ranges = new Ranges(rangesList); + assertThat(ranges.toString("A")).isEqualTo("10"); + } + + @Test + public void twoExcludedRangeShouldReturnTwoRange() { + List rangesList = new ArrayList<>(); + rangesList.add(new Range("A", 1, 10)); + rangesList.add(new Range("A", 20, 30)); + + Ranges ranges = new Ranges(rangesList); + assertThat(ranges.toString("A")).isEqualTo("1-10;20-30"); + } + + @Test + public void twoExcludedRangeShouldReturnTwoRange2() { + List rangesList = new ArrayList<>(); + rangesList.add(new Range("A", 1, 10)); + rangesList.add(new Range("A", 20, 30)); + rangesList.add(new Range("B", 40, 60)); + + Ranges ranges = new Ranges(rangesList); + assertThat(ranges.toString("A")).isEqualTo("1-10;20-30"); + assertThat(ranges.toString("B")).isEqualTo("40-60"); + } + + @Test + public void twoExcludedRangeShouldReturnTwoRange3() { + List rangesList = new ArrayList<>(); + rangesList.add(new Range("A", 1, 10)); + rangesList.add(new Range("A", 20, 30)); + rangesList.add(new Range("B", 40, 50)); + rangesList.add(new Range("B", 60, 80)); + + Ranges ranges = new Ranges(rangesList); + assertThat(ranges.toString("A")).isEqualTo("1-10;20-30"); + assertThat(ranges.toString("B")).isEqualTo("40-50;60-80"); + } + + @Test + public void twoPartiallyIncludedRangeShouldReturnTwoRange() { + List rangesList = new ArrayList<>(); + rangesList.add(new Range("A", 1, 20)); + rangesList.add(new Range("A", 10, 30)); + + Ranges ranges = new Ranges(rangesList); + assertThat(ranges.toString("A")).isEqualTo("1-30"); + } + + @Test + public void secondeRangeRangeShouldBeFirstRange() { + List rangesList = new ArrayList<>(); + rangesList.add(new Range("A", 1, 100)); + rangesList.add(new Range("A", 200, 400)); + + Ranges ranges = new Ranges(rangesList); + assertThat(ranges.toString("A")).isEqualTo("1-100;200-400"); + } + + @Test + public void twoTotallyIncludedRangeWithSameBorneIfBorneSupShouldReturnThreeRange() { + List rangesList = new ArrayList<>(); + rangesList.add(new Range("A", 1, 20)); + rangesList.add(new Range("B", 10, 10)); + + Ranges ranges = new Ranges(rangesList); + assertThat(ranges.toString("A")).isEqualTo("1-9;11-20"); + assertThat(ranges.toString("B")).isEqualTo("10"); + } + + @Test + public void twoTotallyIncludedRangeShouldReturnThreeRange() { + List rangesList = new ArrayList<>(); + rangesList.add(new Range("A", 1, 20)); + rangesList.add(new Range("B", 10, 15)); + + Ranges ranges = new Ranges(rangesList); + assertThat(ranges.toString("A")).isEqualTo("1-9;16-20"); + assertThat(ranges.toString("B")).isEqualTo("10-15"); + } + + @Test + public void twoTotallyIncludedWithUpRangeShouldReturnTwoRange() { + List rangesList = new ArrayList<>(); + rangesList.add(new Range("A", 1, 2147483646)); + rangesList.add(new Range("B", 10, 2147483646)); + + Ranges ranges = new Ranges(rangesList); + assertThat(ranges.toString("A")).isEqualTo("1-9"); + assertThat(ranges.toString("B")).isEqualTo("10-UP"); + } + + @Test + public void multipleRangeShouldReturnEightRange() { + List rangesList = new ArrayList<>(); + rangesList.add(new Range("A", 1, 2147483646)); // 1-UP + rangesList.add(new Range("B", 1, 2147483646)); // 1-UP + rangesList.add(new Range("C", 100, 150)); // 1-99;100-150;151-UP + rangesList.add(new Range("B", 150, 2147483646)); // 1-149;150-UP + rangesList.add(new Range("C", 250, 250)); // 1-99;100-150;151-249;250;251-299;300-UP + rangesList.add(new Range("C", 300, 2147483646)); // 1-99;100-150;151-299;300-UP + rangesList.add(new Range("D", 500, 500)); // 1-99;100-150;151-249;250;251-299;300-499;500;501-UP + + Ranges ranges = new Ranges(rangesList); + assertThat(ranges.toString("A")).isEmpty(); + assertThat(ranges.toString("B")).isEqualTo("1-99;150-249;251-299"); + assertThat(ranges.toString("C")).isEqualTo("100-149;250;300-499;501-UP"); + assertThat(ranges.toString("D")).isEqualTo("500"); + } + + @Test + public void multipleRangeShouldReturnSevenRange() { + List rangesList = new ArrayList<>(); + rangesList.add(new Range("A", 1, 2147483646)); // 1-UP + rangesList.add(new Range("B", 1, 2147483646)); // 1-UP + rangesList.add(new Range("C", 100, 160)); // 1-99;100-149;150-160;161-UP + rangesList.add(new Range("B", 150, 2147483646)); // 1-149;150-UP + rangesList.add(new Range("C", 150, 2147483646)); // 1-99;100-149;150-UP + rangesList.add(new Range("C", 250, 250)); // 1-99;100-149;150-249;250;251-UP + rangesList.add(new Range("D", 500, 500)); // 1-99;100-149;150-249;250;251-499;500;501-UP + + Ranges ranges = new Ranges(rangesList); + assertThat(ranges.toString("A")).isEmpty(); + assertThat(ranges.toString("B")).isEqualTo("1-99;150"); + assertThat(ranges.toString("C")).isEqualTo("100-149;151-499;501-UP"); + assertThat(ranges.toString("D")).isEqualTo("500"); + } + + @Test + public void twoTotallyIncludedWithUpRangeShouldReturnThreeRange() { + List rangesList = new ArrayList<>(); + rangesList.add(new Range("B", 20, 300)); // 20-49;50-199;301-399;400-UP + rangesList.add(new Range("A", 50, 2147483646)); // 50-UP + rangesList.add(new Range("B", 200, 2147483646)); // 50-199;200-UP + rangesList.add(new Range("B", 400, 2147483646)); // 50-199;200-399;400-UP + + Ranges ranges = new Ranges(rangesList); + assertThat(ranges.toString("A")).isEqualTo("50-199"); + assertThat(ranges.toString("B")).isEqualTo("20-49;200-UP"); + } + + @Test + public void twoTotallyIncludedWithUpRangeShouldReturnThreeRange2() { + List rangesList = new ArrayList<>(); + rangesList.add(new Range("C", 600, 600)); // 600 + rangesList.add(new Range("G", 650, 800)); // 600;650-800 + rangesList.add(new Range("G", 700, 700)); // 600;700 + rangesList.add(new Range("I", 900, 900)); // 600;650-800;900;1000-UP + rangesList.add(new Range("G", 1000, 2147483646)); // 600;650-800;1000-UP + + Ranges ranges = new Ranges(rangesList); + assertThat(ranges.toString("C")).isEqualTo("600"); + assertThat(ranges.toString("G")).isEqualTo("650-800;1000-UP"); + assertThat(ranges.toString("I")).isEqualTo("900"); + } + + @Test + public void twoTotallyIncludedWithUpRangeShouldReturnThreeRange3() { + List rangesList = new ArrayList<>(); + rangesList.add(new Range("C", 600, 600)); // 600 + rangesList.add(new Range("G", 700, 700)); // 600;700 + rangesList.add(new Range("I", 900, 900)); // 600;700;900;1000-UP + rangesList.add(new Range("G", 1000, 2147483646)); // 600;700;1000-UP + + Ranges ranges = new Ranges(rangesList); + assertThat(ranges.toString("C")).isEqualTo("600"); + assertThat(ranges.toString("G")).isEqualTo("700;1000-UP"); + assertThat(ranges.toString("I")).isEqualTo("900"); + } + + @Test + public void twoTotallyIncludedWithUpRangeShouldReturnThreeRange4() { + List rangesList = new ArrayList<>(); + rangesList.add(new Range("C", 600, 600)); // 600 + rangesList.add(new Range("G", 650, 850)); // 600;650-850 + rangesList.add(new Range("G", 700, 700)); // 600;700 + rangesList.add(new Range("G", 800, 800)); // 600;700;800 + rangesList.add(new Range("I", 900, 900)); // 600;650-850;900;1000-UP + rangesList.add(new Range("G", 1000, 2147483646)); // 600;650-850;1000-UP + + Ranges ranges = new Ranges(rangesList); + assertThat(ranges.toString("C")).isEqualTo("600"); + assertThat(ranges.toString("G")).isEqualTo("650-850;1000-UP"); + assertThat(ranges.toString("I")).isEqualTo("900"); + } + + @Test + public void twoTotallyIncludedWithUpRangeShouldReturnThreeRange5() { + List rangesList = new ArrayList<>(); + rangesList.add(new Range("G", 1, 2147483646)); // 1-UP + rangesList.add(new Range("G", 300, 300)); // 300;700 + rangesList.add(new Range("G", 700, 700)); // 700 + + Ranges ranges = new Ranges(rangesList); + assertThat(ranges.toString("G")).isEqualTo("1-UP"); + } + + @Test + public void twoTotallyIncludedWithUpRangeShouldReturnThreeRange6() { + List rangesList = new ArrayList<>(); + rangesList.add(new Range("A", 600, 600)); // 600 + rangesList.add(new Range("B", 700, 700)); // 600;700 + rangesList.add(new Range("E", 800, 2147483646)); // 600;700;800-899;900;901-999;1000-1099;1100;1101-UP + rangesList.add(new Range("C", 900, 900)); // 600;700;900;1000-UP + rangesList.add(new Range("B", 1000, 2147483646)); // 600;700;1000-UP + rangesList.add(new Range("D", 1100, 1100)); // 600;700;900;1000-1099;1100;1101-UP + + Ranges ranges = new Ranges(rangesList); + assertThat(ranges.toString("A")).isEqualTo("600"); + assertThat(ranges.toString("B")).isEqualTo("700;1000-1099;1101-UP"); + assertThat(ranges.toString("C")).isEqualTo("900"); + assertThat(ranges.toString("D")).isEqualTo("1100"); + assertThat(ranges.toString("E")).isEqualTo("800-899;901-999"); + } + + @Test + public void twoTotallyIncludedWithUpRangeShouldReturnThreeRange7() { + List rangesList = new ArrayList<>(); + rangesList.add(new Range("F", 1, 2147483646)); // 600;700;800-UP + rangesList.add(new Range("A", 600, 600)); // 600 + rangesList.add(new Range("G", 600, 600)); // 600;700;800-UP + rangesList.add(new Range("B", 700, 700)); // 600;700 + rangesList.add(new Range("E", 800, 2147483646)); // 600;700;800-UP + rangesList.add(new Range("C", 900, 900)); // 600;700;900;1000-UP + rangesList.add(new Range("B", 1000, 2147483646)); // 600;700;1000-UP + rangesList.add(new Range("D", 1100, 1100)); // 600;700;900;1000-1099;1100;1101-UP + + Ranges ranges = new Ranges(rangesList); + assertThat(ranges.toString("A")).isEmpty(); + assertThat(ranges.toString("B")).isEqualTo("700;1000-1099;1101-UP"); + assertThat(ranges.toString("C")).isEqualTo("900"); + assertThat(ranges.toString("D")).isEqualTo("1100"); + assertThat(ranges.toString("E")).isEqualTo("800-899;901-999"); + assertThat(ranges.toString("F")).isEqualTo("1-599;601-699;701-799"); + assertThat(ranges.toString("G")).isEqualTo("600"); + } + + @Test + public void twoTotallyIncludedWithUpRangeShouldReturnThreeRange8() { + List rangesList = new ArrayList<>(); + rangesList.add(new Range("B", 5, 2147483646)); // 5-9;10-UP + rangesList.add(new Range("A", 10, 2147483646)); // 10-UP + rangesList.add(new Range("C", 20, 2147483646)); // 5-9;10-19;20-UP + rangesList.add(new Range("D", 30, 2147483646)); // 5-9;10-19;20-29;30-UP + + Ranges ranges = new Ranges(rangesList); + assertThat(ranges.toString("A")).isEqualTo("10-19"); + assertThat(ranges.toString("B")).isEqualTo("5-9"); + assertThat(ranges.toString("C")).isEqualTo("20-29"); + assertThat(ranges.toString("D")).isEqualTo("30-UP"); + } + + @Test + public void twoTotallyIncludedWithUpRangeShouldReturnThreeRange9() { + List rangesList = new ArrayList<>(); + rangesList.add(new Range("A", 600, 600)); // 1-599;600;601-UP + rangesList.add(new Range("B", 700, 700)); // 1-599;600;601-699;700;701-UP + rangesList.add(new Range("B", 1000, 2147483646));// 1-599;600;601-699;700;701-799;800-849;850-899;900;901-999;1000-UP + rangesList.add(new Range("C", 900, 900)); // 1-599;600;601-699;700;701-799;800-849;850-899;900;901-UP + rangesList.add(new Range("D", 1100, 1100));// 1-599;600;601-699;700;701-799;800-849;850-899;900;901-999;1000-1099;1100;1101-UP + rangesList.add(new Range("E", 800, 2147483646)); // 1-599;600;601-699;700;701-799;800-UP + rangesList.add(new Range("F", 1, 2147483646)); // 1-UP + rangesList.add(new Range("G", 600, 600)); // 1-599;600;601-UP + rangesList.add(new Range("H", 850, 900)); // 1-599;600;601-699;700;701-799;800-849;850-900;901-UP + Collections.sort(rangesList, new Comparator() { + public int compare(Range r1, Range r2) { + return Integer.compare(r1.borneInf(), r2.borneInf()); + } + }); + Ranges ranges = new Ranges(rangesList); + assertThat(ranges.toString("A")).isEmpty(); + assertThat(ranges.toString("B")).isEqualTo("700;1000-1099;1101-UP"); + assertThat(ranges.toString("C")).isEqualTo("900"); + assertThat(ranges.toString("D")).isEqualTo("1100"); + assertThat(ranges.toString("E")).isEqualTo("800-849;901-999"); + assertThat(ranges.toString("F")).isEqualTo("1-599;601-699;701-799"); + assertThat(ranges.toString("G")).isEqualTo("600"); + assertThat(ranges.toString("H")).isEqualTo("850-899"); + } +} \ No newline at end of file diff --git a/kurt-utility/src/test/java/com/capgemini/reports/printing/PrintParametersTest.java b/kurt-utility/src/test/java/com/capgemini/reports/printing/PrintParametersTest.java new file mode 100644 index 0000000..b7a1256 --- /dev/null +++ b/kurt-utility/src/test/java/com/capgemini/reports/printing/PrintParametersTest.java @@ -0,0 +1,36 @@ +package com.capgemini.reports.printing; + +import com.capgemini.framework.common.ResourceHelper; +import com.capgemini.reports.exceptions.FileLoadingException; +import com.capgemini.reports.printing.Printer.PrintFormat; +import net.sf.jasperreports.engine.JRException; +import org.testng.annotations.Test; + +import java.io.IOException; +import java.io.InputStream; + +import static org.assertj.core.api.Assertions.assertThat; + + +public class PrintParametersTest { + + private static final String PARAM_KEY = "Parameter Key"; + private static final String PARAM_VALUE = "Parameter Value"; + private static final String TEMPLATE = "/Jasper/template/dynamic_table/reference.jrxml"; + private static final String FOLDER = "Folder"; + private static final String FILENAME = "Filename"; + + + @Test + public void printParametersTest() throws FileLoadingException, JRException, IOException { + try (InputStream templateIS = ResourceHelper.getResourceAsStream(TEMPLATE)) { + PrintParameters mainReport = new PrintParameters(PrintFormat.PDF, FILENAME, FOLDER, templateIS); + assertThat(mainReport.getTemplate()).isNotNull(); + assertThat(mainReport.getParameters()).isEmpty(); + assertThat(mainReport.hasSubReports()).isFalse(); + + mainReport.addReportParameter(PARAM_KEY, PARAM_VALUE); + assertThat(mainReport.getParameters().get(PARAM_KEY)).isEqualTo(PARAM_VALUE); + } + } +} diff --git a/kurt-utility/src/test/java/com/capgemini/reports/templates/CellTest.java b/kurt-utility/src/test/java/com/capgemini/reports/templates/CellTest.java new file mode 100644 index 0000000..354a49c --- /dev/null +++ b/kurt-utility/src/test/java/com/capgemini/reports/templates/CellTest.java @@ -0,0 +1,148 @@ +package com.capgemini.reports.templates; + +import lombok.extern.slf4j.Slf4j; +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + + +@Slf4j +public class CellTest { + + private static final int INITIAL_HEIGHT = 20; + private static final int EXTRA_HEIGHT = 8; + private static final String CONTENT = "Some Content"; + + private final String expectedCell = "" + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n\n " + + "\n " + + "\n "; + + private final String expectedStretchCell = "" + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n\n " + + "\n " + + "\n "; + + private final String expectedGreyCell = "" + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n\n " + + "\n " + + "\n "; + + private final String expectedJustifiedCell = "" + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n " + + "\n\n " + + "\n " + + "\n "; + + @Test + public void testMakeStaticCell() { + Cell cell = Cell.makeStaticCell(CONTENT, INITIAL_HEIGHT, 50, 12, 30, null); + assertThat(cell.isDynamic()).isFalse(); + assertThat(CONTENT).isEqualTo(cell.getContent()); + assertThat(INITIAL_HEIGHT).isEqualTo(cell.getHeight()); + assertThat("50").isEqualTo(cell.getWidth()); + assertThat("12").isEqualTo(cell.getXPosition()); + assertThat("30").isEqualTo(cell.getYPosition()); + assertThat(cell.isStretchWithOverflow()).isFalse(); + } + + @Test + public void testMakeParameterCell() { + Cell cell = Cell.makeParameterCell(CONTENT, INITIAL_HEIGHT, 50, false, 12, 30, null); + assertThat(cell.isDynamic()).isTrue(); + assertThat(cell.isHeader()).isTrue(); + assertThat(CONTENT).isEqualTo(cell.getContent()); + assertThat(INITIAL_HEIGHT).isEqualTo(cell.getHeight()); + assertThat("50").isEqualTo(cell.getWidth()); + assertThat("12").isEqualTo(cell.getXPosition()); + assertThat("30").isEqualTo(cell.getYPosition()); + assertThat(cell.isStretchWithOverflow()).isFalse(); + } + + @Test + public void testCellWithOverflow() { + Cell cell = Cell.makeParameterCell(CONTENT, INITIAL_HEIGHT, 50, true, 12, 30, null); + assertThat(cell.isDynamic()).isTrue(); + assertThat(CONTENT).isEqualTo(cell.getContent()); + assertThat(INITIAL_HEIGHT).isEqualTo(cell.getHeight()); + assertThat("50").isEqualTo(cell.getWidth()); + assertThat("12").isEqualTo(cell.getXPosition()); + assertThat("30").isEqualTo(cell.getYPosition()); + assertThat(cell.isStretchWithOverflow()).isTrue(); + } + + @Test + public void testMakeFieldCell() { + Cell cell = Cell.makeFieldCell(CONTENT, INITIAL_HEIGHT, 50, false, 0, 30, null); + assertThat(cell.isDynamic()).isTrue(); + assertThat(cell.isHeader()).isFalse(); + assertThat(CONTENT).isEqualTo(cell.getContent()); + } + + @Test + public void testMakeCell() { + Cell cell = Cell.makeStaticCell(CONTENT, INITIAL_HEIGHT, 50, 0, 30, null); + assertThat(expectedCell).isEqualTo(cell.makeCell()); + } + + @Test + public void testStretchCell() { + Cell cell = Cell.makeParameterCell(CONTENT, INITIAL_HEIGHT, 50, true, 0, 30, null); + assertThat(expectedStretchCell).isEqualTo(cell.makeCell()); + } + + @Test + public void testAddHeight() { + Cell cell = Cell.makeStaticCell(CONTENT, INITIAL_HEIGHT, 50, 0, 30, null); + assertThat(INITIAL_HEIGHT).isEqualTo(cell.getHeight()); + cell.addHeight(EXTRA_HEIGHT); + assertThat(INITIAL_HEIGHT + EXTRA_HEIGHT).isEqualTo(cell.getHeight()); + } + + @Test + public void testGreyCell() { + Cell cell = Cell.makeStaticCell(CONTENT, INITIAL_HEIGHT, 50, 0, 30, new CellFormat().setColor("#E3E3E3")); + assertThat(expectedGreyCell).isEqualTo(cell.makeCell()); + } + + @Test + public void testJustifiedCell() { + Cell cell = Cell.makeStaticCell(CONTENT, INITIAL_HEIGHT, 50, 0, 30, new CellFormat().setAlignment(Alignment.JUSTIFIED)); + assertThat(expectedJustifiedCell).isEqualTo(cell.makeCell()); + } +} diff --git a/kurt-utility/src/test/java/com/capgemini/reports/templates/ColumnTest.java b/kurt-utility/src/test/java/com/capgemini/reports/templates/ColumnTest.java new file mode 100644 index 0000000..e64ecfa --- /dev/null +++ b/kurt-utility/src/test/java/com/capgemini/reports/templates/ColumnTest.java @@ -0,0 +1,125 @@ +package com.capgemini.reports.templates; + + +import org.testng.annotations.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class ColumnTest { + + private static final int CONTENT_HEIGHT = 13; + private static final int HEADER_HEIGHT = 20; + private static final int EXTRA_HEIGHT = 10; + private static final String HEADER_KEY = "HEADER_KEY"; + private static final String CONTENT_KEY = "CONTENT_KEY"; + private static final int WIDTH = 100; + private static final int XPOS = 0; + private static final String COLOR = "#E3E3E3"; + + private static final String EXPECTED_CONTENT = "" /*------------------------------------------------------------------------------------------*/ + + "\n " /*------------------------------------------------------------------------------------------------------*/ + + "\n " /*--------*/ + + "\n "/*---------------------------------------------------------------------------------------*/ + + "\n " /*------------------------------------------------------------------------------*/ + + "\n " /*-----------------------------------------------------------------------------*/ + + "\n "/*----------------------------------------------------------------------------*/ + + "\n " /*----------------------------------------------------------------------------*/ + + "\n " /*-------------------------------------------------------------------------------------------------------*/ + + "\n " /*-------------------------------------------------------------------------------*/ + + "\n\n "/*-------------------------------------------------------------------------------------------------*/ + + "\n "/*--------------------------------*/ + + "\n "; + + private static final String EXPECTED_HEADER = ""/*--------------------------------------------------------------------------------------------*/ + + "\n "/*------------------------------------------------------------------------------------------------------*/ + + "\n " /*---------*/ + + "\n " /*--------------------------------------------------------------------------------------*/ + + "\n "/*-------------------------------------------------------------------------------*/ + + "\n " /*-----------------------------------------------------------------------------*/ + + "\n "/*----------------------------------------------------------------------------*/ + + "\n " /*----------------------------------------------------------------------------*/ + + "\n " /*-------------------------------------------------------------------------------------------------------*/ + + "\n " /*-------------------------------------------------------------------------------*/ + + "\n\n "/*-------------------------------------------------------------------------------------------------*/ + + "\n "/*-------------------------------------------------------------------*/ + + "\n "; + + private static final String EXPECTED_GREY_HEADER = ""/*---------------------------------------------------------------------------------------*/ + + "\n " /*-----------------------------------------------------------------------------------------------------*/ + + "\n "/*-------------------------------------------------------------------------------------------*/ + + "\n "/*---------------------------------------------------------------------------------------*/ + + "\n "/*-------------------------------------------------------------------------------*/ + + "\n " /*-----------------------------------------------------------------------------*/ + + "\n "/*----------------------------------------------------------------------------*/ + + "\n " /*----------------------------------------------------------------------------*/ + + "\n " /*-------------------------------------------------------------------------------------------------------*/ + + "\n " /*-------------------------------------------------------------------------------*/ + + "\n\n "/*-------------------------------------------------------------------------------------------------*/ + + "\n " /*------------------------------------------------------------------*/ + + "\n "; + + private static final String EXPECTED_EXTRA_HIGH_HEADER = "" /*--------------------------------------------------------------------------------*/ + + "\n " /*-----------------------------------------------------------------------------------------------------*/ + + "\n " /*---------------------------------------------------------------------------------------------------------------------------*/ + + "\n " /*--------------------------------------------------------------------------------------*/ + + "\n " /*------------------------------------------------------------------------------*/ + + "\n " /*-----------------------------------------------------------------------------*/ + + "\n " /*---------------------------------------------------------------------------*/ + + "\n "/*-----------------------------------------------------------------------------*/ + + "\n " /*-------------------------------------------------------------------------------------------------------*/ + + "\n " /*-------------------------------------------------------------------------------*/ + + "\n\n "/*-------------------------------------------------------------------------------------------------*/ + + "\n " /*------------------------------------------------------------------*/ + + "\n "; /*---------------------------------------------------------------------------------------------------*/ + + @Test + public void testColumnField() { + Column col = new Column(CONTENT_KEY, WIDTH, XPOS, false, CONTENT_HEIGHT, null); + assertThat(col.makeContent()).isEqualTo(EXPECTED_CONTENT); + assertThat(col.makeHeaders()).isEmpty(); + } + + @Test + public void testAddHeader() { + Column col = new Column(CONTENT_KEY, WIDTH, XPOS, false, HEADER_HEIGHT, null); + String headerStr = col.makeHeaders(); + assertThat(headerStr).isEmpty(); + col.addHeader(HEADER_KEY, false, HEADER_HEIGHT, false, null); + headerStr = col.makeHeaders(); + assertThat(headerStr).isEqualTo(EXPECTED_HEADER); + } + + @Test + public void testGreyHeader() { + Column col = new Column(CONTENT_KEY, WIDTH, XPOS, false, HEADER_HEIGHT, null); + col.addHeader(HEADER_KEY, false, HEADER_HEIGHT, false, new CellFormat().setColor(COLOR)); + String headerStr = col.makeHeaders(); + assertThat(headerStr).isEqualTo(EXPECTED_GREY_HEADER); + } + + @Test + public void testAddToPreviousHeaderCellHeight() { + Column col = new Column(CONTENT_KEY, WIDTH, XPOS, false, HEADER_HEIGHT, null); + col.addHeader(HEADER_KEY, false, HEADER_HEIGHT, false, null); + col.addToPreviousHeaderCellHeight(EXTRA_HEIGHT); + assertThat(col.makeHeaders()).isEqualTo(EXPECTED_EXTRA_HIGH_HEADER); + } + + @Test + public void testGetParametersDeclaration() { + // No parameter yet (No header) + Column col = new Column(CONTENT_KEY, WIDTH, XPOS, false, HEADER_HEIGHT, null); + assertThat(col.getParametersDeclaration()).isEmpty(); + + // Still no parameters (header is static) + col.addHeader(HEADER_KEY, false, HEADER_HEIGHT, false, null); + assertThat(col.getParametersDeclaration()).isEmpty(); + + // Now there is a parameter + col.addHeader(HEADER_KEY, true, HEADER_HEIGHT, false, null); + String parametersDeclaration = col.getParametersDeclaration(); + assertThat(parametersDeclaration).isEqualTo("\n "); + } +} diff --git a/kurt-utility/src/test/java/com/capgemini/reports/templates/DynamicGridTemplateBuilderTest.java b/kurt-utility/src/test/java/com/capgemini/reports/templates/DynamicGridTemplateBuilderTest.java new file mode 100644 index 0000000..afddc98 --- /dev/null +++ b/kurt-utility/src/test/java/com/capgemini/reports/templates/DynamicGridTemplateBuilderTest.java @@ -0,0 +1,69 @@ +package com.capgemini.reports.templates; + +import com.capgemini.framework.common.ResourceHelper; +import com.capgemini.reports.exceptions.FileLoadingException; +import com.capgemini.reports.exceptions.InvalidInputException; +import com.capgemini.reports.jasper.compilers.JasperCompiler; +import net.sf.jasperreports.engine.JRException; +import net.sf.jasperreports.engine.JasperReport; +import org.testng.annotations.Test; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + + +public class DynamicGridTemplateBuilderTest { + + private static final String COLOR = "#E3E3E3"; + + @Test + public void generateCodeTest() throws JRException, FileLoadingException, InvalidInputException { + // iInitialise the data + String refContent = ResourceHelper.getResourceContent("/Jasper/template/dynamic_table/reference.jrxml"); + List header1 = new ArrayList<>(); + List header2 = new ArrayList<>(); + List dynamicHeader = new ArrayList<>(); + List widths = new ArrayList<>(); + List keys = new ArrayList<>(); + + Map aContentLine = new HashMap<>(); + Map parameters = new HashMap<>(); + for (int col = 0; col < 5; col++) { + if (col == 0) { + header1.add("Top Left"); + header2.add("Line Headers"); + dynamicHeader.add(false); + widths.add(200); + String key = "ROW_HEADER" + col; + keys.add(key); + aContentLine.put(key, "Row Number 0"); + } + else { + String headerKey = "COL_HEADER" + col; + header1.add(headerKey); + parameters.put(headerKey, "Column Number " + col); + header2.add(null); // Merge with the above + dynamicHeader.add(true); + widths.add(50); + String contentKey = "COL" + col; + keys.add(contentKey); + aContentLine.put(contentKey, "Value " + col); + } + } + + // Build the template + DynamicGridTemplateBuilder template = new DynamicGridTemplateBuilder(widths, keys, null, null, 13); + template.addHeaderLine(13, header1, dynamicHeader, new CellFormat().setColor(COLOR), null); + template.addHeaderLine(26, header2, dynamicHeader, new CellFormat().setColor(COLOR), null); + String generatedTemplate = template.generateCode(); + assertThat(refContent).isEqualTo(generatedTemplate); + + // Compile + JasperReport compiledTemplate = JasperCompiler.compile(generatedTemplate); + assertThat(compiledTemplate).isNotNull(); + } +} diff --git a/kurt-utility/src/test/resources/Jasper/template/dynamic_table/reference.jrxml b/kurt-utility/src/test/resources/Jasper/template/dynamic_table/reference.jrxml new file mode 100644 index 0000000..c1a4d6a --- /dev/null +++ b/kurt-utility/src/test/resources/Jasper/template/dynamic_table/reference.jrxml @@ -0,0 +1,175 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/test/resources/Jasper/template/dynamic_table/template.jrxml b/kurt-utility/src/test/resources/Jasper/template/dynamic_table/template.jrxml new file mode 100644 index 0000000..509c616 --- /dev/null +++ b/kurt-utility/src/test/resources/Jasper/template/dynamic_table/template.jrxml @@ -0,0 +1,23 @@ + + + [[PARAMETERS]] + + + [[FIELDS]] + + + + + [[HEADERS]] + + + + [[CONTENT]] + + + diff --git a/kurt-utility/src/test/resources/hibernate.cfg.xml b/kurt-utility/src/test/resources/hibernate.cfg.xml new file mode 100644 index 0000000..be6101c --- /dev/null +++ b/kurt-utility/src/test/resources/hibernate.cfg.xml @@ -0,0 +1,49 @@ + + + + + + + + + org.hibernate.dialect.Oracle10gDialect + oracle.jdbc.OracleDriver + jdbc:oracle:thin:@10.24.192.36:1521:TC + PLIC + PLIC + PLIC + + + 1 + + + org.hibernate.cache.NoCacheProvider + + org.hibernate.transaction.JDBCTransactionFactory + + + thread + + + false + + + update + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/test/resources/html/email/template_email_bad_parameters.html b/kurt-utility/src/test/resources/html/email/template_email_bad_parameters.html new file mode 100644 index 0000000..5aa7682 --- /dev/null +++ b/kurt-utility/src/test/resources/html/email/template_email_bad_parameters.html @@ -0,0 +1,8 @@ +

    Notification de fin d'exécution du rapport

    +
    +Date/heure de lancement: [[POSTING_TIME]]
    +Nom du rapport: [[REPORT_NAME]]

    +Date/heure de début de génération: [[START_TIME]]

    +Date/heure de fin de génération: [[END_TIME]]
    +Aucune donnée n'a pu être extraite: Vérifier vos cirtères d'impression.
    +[[ERROR_MESSAGE]]
    \ No newline at end of file diff --git a/kurt-utility/src/test/resources/html/email/template_email_failed.html b/kurt-utility/src/test/resources/html/email/template_email_failed.html new file mode 100644 index 0000000..9fca525 --- /dev/null +++ b/kurt-utility/src/test/resources/html/email/template_email_failed.html @@ -0,0 +1,7 @@ +

    Ce rapport s'est terminé en erreur

    +
    +Date/heure de lancement: [[POSTING_TIME]]
    +Nom du rapport: [[REPORT_NAME]]

    +Date/heure de début de génération: [[START_TIME]]

    +Date/heure de fin de génération: [[END_TIME]]

    +[[ERROR_MESSAGE]]
    \ No newline at end of file diff --git a/kurt-utility/src/test/resources/html/email/template_email_failed_admin.html b/kurt-utility/src/test/resources/html/email/template_email_failed_admin.html new file mode 100644 index 0000000..347e21f --- /dev/null +++ b/kurt-utility/src/test/resources/html/email/template_email_failed_admin.html @@ -0,0 +1,7 @@ +

    Notification de fin d'exécution du rapport

    +
    +Date/heure de lancement: [[POSTING_TIME]]
    +Nom du rapport: [[REPORT_NAME]]

    +Date/heure de début de génération: [[START_TIME]]

    +Date/heure de fin de génération: [[END_TIME]]

    +[[ERROR_MESSAGE]]
    \ No newline at end of file diff --git a/kurt-utility/src/test/resources/html/email/template_email_finished.html b/kurt-utility/src/test/resources/html/email/template_email_finished.html new file mode 100644 index 0000000..2f037bf --- /dev/null +++ b/kurt-utility/src/test/resources/html/email/template_email_finished.html @@ -0,0 +1,7 @@ +

    Notification de fin d'exécution du rapport

    +
    +Date/heure de lancement: [[POSTING_TIME]]
    +Nom du rapport: [[REPORT_NAME]]

    +Date/heure de début de génération: [[START_TIME]]

    +Date/heure de fin de génération: [[END_TIME]]
    +Lien de récupération du rapport: [[REPORT_LOCATION]]
    diff --git a/kurt-utility/src/test/resources/html/email/template_email_posted.html b/kurt-utility/src/test/resources/html/email/template_email_posted.html new file mode 100644 index 0000000..2f3173a --- /dev/null +++ b/kurt-utility/src/test/resources/html/email/template_email_posted.html @@ -0,0 +1,4 @@ +

    Détails du lancement effectué

    +
    +Nom du rapport: [[REPORT_NAME]]
    +Nom de la file d'attente: [[QUEUE_NAME]]
    \ No newline at end of file diff --git a/kurt-utility/src/test/resources/html/email/template_email_started.html b/kurt-utility/src/test/resources/html/email/template_email_started.html new file mode 100644 index 0000000..f3ac27d --- /dev/null +++ b/kurt-utility/src/test/resources/html/email/template_email_started.html @@ -0,0 +1,5 @@ +

    Notification de début d'exécution du rapport

    +
    +Date/heure de lancement: [[POSTING_TIME]]
    +Nom du rapport: [[REPORT_NAME]]
    +Date/heure de début de génération: [[START_TIME]]

    diff --git a/kurt-utility/src/test/resources/log4j.properties b/kurt-utility/src/test/resources/log4j.properties new file mode 100644 index 0000000..8f372cd --- /dev/null +++ b/kurt-utility/src/test/resources/log4j.properties @@ -0,0 +1,13 @@ +log4j.logger.com.teamcenter.soa=WARN +log4j.logger.org.apache=WARN +log4j.logger.httpclient=WARN + +# Direct log messages to stdout +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.Target=System.out +log4j.appender.stdout.threshold=DEBUG +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %c{1}:%L - %m%n + +# Root logger option +log4j.rootLogger=DEBUG, stdout diff --git a/kurt-utility/src/test/resources/xml/policies/PoliciesDomParserTest.xml b/kurt-utility/src/test/resources/xml/policies/PoliciesDomParserTest.xml new file mode 100644 index 0000000..735c1ee --- /dev/null +++ b/kurt-utility/src/test/resources/xml/policies/PoliciesDomParserTest.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/test/resources/xml/policies/bom_policy.xml b/kurt-utility/src/test/resources/xml/policies/bom_policy.xml new file mode 100644 index 0000000..761b32a --- /dev/null +++ b/kurt-utility/src/test/resources/xml/policies/bom_policy.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/kurt-utility/src/test/resources/xml/policies/policy_full.xml b/kurt-utility/src/test/resources/xml/policies/policy_full.xml new file mode 100644 index 0000000..17d09f6 --- /dev/null +++ b/kurt-utility/src/test/resources/xml/policies/policy_full.xml @@ -0,0 +1,171 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/kurt-utility/src/test/resources/xml/policies/policy_light.xml b/kurt-utility/src/test/resources/xml/policies/policy_light.xml new file mode 100644 index 0000000..1354d8a --- /dev/null +++ b/kurt-utility/src/test/resources/xml/policies/policy_light.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/test/resources/xml/policies/test_policy.xml b/kurt-utility/src/test/resources/xml/policies/test_policy.xml new file mode 100644 index 0000000..6c3eadd --- /dev/null +++ b/kurt-utility/src/test/resources/xml/policies/test_policy.xml @@ -0,0 +1,159 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/test/resources/xml/ref/MultiStructureServiceCallerTest_item.xml b/kurt-utility/src/test/resources/xml/ref/MultiStructureServiceCallerTest_item.xml new file mode 100644 index 0000000..aa88d29 --- /dev/null +++ b/kurt-utility/src/test/resources/xml/ref/MultiStructureServiceCallerTest_item.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/kurt-utility/src/test/resources/xml/ref/MultiStructureServiceCallerTest_item_revision.xml b/kurt-utility/src/test/resources/xml/ref/MultiStructureServiceCallerTest_item_revision.xml new file mode 100644 index 0000000..61544df --- /dev/null +++ b/kurt-utility/src/test/resources/xml/ref/MultiStructureServiceCallerTest_item_revision.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/kurt-utility/src/test/resources/xml/ref/StructureServiceCallerTest_mono.xml b/kurt-utility/src/test/resources/xml/ref/StructureServiceCallerTest_mono.xml new file mode 100644 index 0000000..014572c --- /dev/null +++ b/kurt-utility/src/test/resources/xml/ref/StructureServiceCallerTest_mono.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/kurt-utility/src/test/resources/xml/ref/StructureServiceCallerTest_multi.xml b/kurt-utility/src/test/resources/xml/ref/StructureServiceCallerTest_multi.xml new file mode 100644 index 0000000..8658eda --- /dev/null +++ b/kurt-utility/src/test/resources/xml/ref/StructureServiceCallerTest_multi.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/test/resources/xml/ref/TripleStructureServiceCallerTest_item.xml b/kurt-utility/src/test/resources/xml/ref/TripleStructureServiceCallerTest_item.xml new file mode 100644 index 0000000..54187d9 --- /dev/null +++ b/kurt-utility/src/test/resources/xml/ref/TripleStructureServiceCallerTest_item.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/kurt-utility/src/test/resources/xml/ref/TripleStructureServiceCallerTest_item_revision.xml b/kurt-utility/src/test/resources/xml/ref/TripleStructureServiceCallerTest_item_revision.xml new file mode 100644 index 0000000..e69de29 diff --git a/kurt-utility/src/val/java/com/capgemini/reports/definition/r01report/Test_R01.java b/kurt-utility/src/val/java/com/capgemini/reports/definition/r01report/Test_R01.java new file mode 100644 index 0000000..e5ddd74 --- /dev/null +++ b/kurt-utility/src/val/java/com/capgemini/reports/definition/r01report/Test_R01.java @@ -0,0 +1,106 @@ +package com.capgemini.reports.definition.r01report; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.InvalidConfigurationException; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.exceptions.NoTeamcenterConnectionException; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.reports.builder.R01Builder; +import com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum; +import com.capgemini.reports.execution.strategies.ImmediateExecutionStrategy; +import lombok.extern.slf4j.Slf4j; +import org.apache.poi.ss.usermodel.DataFormatter; +import org.apache.poi.xssf.usermodel.XSSFCell; +import org.apache.poi.xssf.usermodel.XSSFRow; +import org.apache.poi.xssf.usermodel.XSSFSheet; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.assertj.core.api.SoftAssertions; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Optional; +import org.testng.annotations.Parameters; +import org.testng.annotations.Test; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + +@Slf4j +public class Test_R01 { + private static final TcSession session = new TcSession(); + private SoftAssertions softAssert = new SoftAssertions(); + // Dossier parent du fichier de référence + private static final String INPUT_FOLDER = "com.capgemini.report.location.default.input"; + // Sous-dossier du fichier de référence + private static final String SPECIFIC_INPUT_FOLDER = "r01"; + // Dossier de stockage temporaire des fichiers générés initialement + private static final String TEMPORARY_OUTPUT_FOLDER = "com.capgemini.report.location.default.output"; + // Type de fichier traités + private static final String SUFFIX = ".xlsx"; + private static final PolicyLocation XML_POLICY = PolicyLocation.make("test_policy", "/xml/policies/r01report/R01_policy_full.xml"); + private Properties localproperties; + + + @BeforeClass + public void login() throws NoTeamcenterConnectionException, InvalidConfigurationException, IOException { + session.login(); + session.setObjectPropPolicy(XML_POLICY); + localproperties = new Properties(); + localproperties.load(getClass().getResourceAsStream("/reporting.properties")); + } + + @AfterClass + public void logout() { + session.close(); + } + + //@BeforeMethod + //TODO : Supprimer xls files dans Generated, checker Tempfile TempDirectory + + + @Parameters({"productID", "unit", "monomulti", "effectivityDate", "genericAssemb", "generic", "refFile"}) + @Test + public void test01(String productID, Integer unit, String monomulti, @Optional String + effectivityDate, @Optional String genericAssemb, @Optional String generic, String refFile) throws + KurtException, IOException { + // Génération du rapport de test + Map data = new HashMap<>(); + data.put(ReportCriteriaEnum.PRODUCT, productID); + data.put(ReportCriteriaEnum.UNIT, unit.toString()); + data.put(ReportCriteriaEnum.MONO_MULTI, monomulti); + data.put(ReportCriteriaEnum.GENERIC, generic); + data.put(ReportCriteriaEnum.GENERIC_ASSEMB, genericAssemb); + data.put(ReportCriteriaEnum.EFFECTIVITY_DATE, effectivityDate); + + ExecutionR01 execution = new R01Builder().build(data); + new DataReportPreparatorR01().print(session, execution, new ImmediateExecutionStrategy()); + + try (FileInputStream fileInput = new FileInputStream(new File((localproperties.getProperty(INPUT_FOLDER)) + SPECIFIC_INPUT_FOLDER + "/" + refFile)); + FileInputStream fileOutput = new FileInputStream(new File(localproperties.getProperty(TEMPORARY_OUTPUT_FOLDER) + execution.getFileNameOnDisc() + SUFFIX))) { + + XSSFWorkbook workbookRef = new XSSFWorkbook(fileInput); + XSSFWorkbook workbookGen = new XSSFWorkbook(fileOutput); + DataFormatter df = new DataFormatter(); + + softAssert.assertThat(workbookRef.getNumberOfSheets()).isEqualTo(workbookGen.getNumberOfSheets()); + for (int h = 0; h < workbookGen.getNumberOfSheets() && h < workbookRef.getNumberOfSheets(); h++) { + // Un fichier excel est composé de plusieurs feuilles, on y accède de la manière suivante + XSSFSheet sheetRef = workbookRef.getSheetAt(h); + XSSFSheet sheetGen = workbookGen.getSheetAt(h); + for (int i = 0; i <= sheetRef.getLastRowNum(); i++) { + XSSFRow rowRef = sheetRef.getRow(i); + XSSFRow rowGen = sheetGen.getRow(i); + for (int j = 0; j <= rowRef.getLastCellNum(); j++) { + XSSFCell cellRef = rowRef.getCell(j); + XSSFCell cellGen = rowGen.getCell(j); + softAssert.assertThat(df.formatCellValue(cellGen)).isEqualTo(df.formatCellValue(cellRef)); + } + } + } + } + softAssert.assertAll(); + } +} diff --git a/kurt-utility/src/val/java/com/capgemini/reports/definition/r03report/Test_R03.java b/kurt-utility/src/val/java/com/capgemini/reports/definition/r03report/Test_R03.java new file mode 100644 index 0000000..405f224 --- /dev/null +++ b/kurt-utility/src/val/java/com/capgemini/reports/definition/r03report/Test_R03.java @@ -0,0 +1,103 @@ +package com.capgemini.reports.definition.r03report; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.InvalidConfigurationException; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.exceptions.NoTeamcenterConnectionException; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.reports.builder.R03Builder; +import com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum; +import com.capgemini.reports.execution.strategies.ImmediateExecutionStrategy; +import lombok.extern.slf4j.Slf4j; +import org.apache.poi.ss.usermodel.DataFormatter; +import org.apache.poi.xssf.usermodel.XSSFCell; +import org.apache.poi.xssf.usermodel.XSSFRow; +import org.apache.poi.xssf.usermodel.XSSFSheet; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.assertj.core.api.SoftAssertions; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Parameters; +import org.testng.annotations.Test; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + + +@Slf4j +public class Test_R03 { + private static final TcSession session = new TcSession(); + private SoftAssertions softAssert = new SoftAssertions(); + // Dossier parent du fichier de référence + private static final String INPUT_FOLDER = "com.capgemini.report.location.default.input"; + // Sous-dossier du fichier de référence + private static final String SPECIFIC_INPUT_FOLDER = "r03"; + // Dossier de stockage temporaire des fichiers générés initialement + private static final String TEMPORARY_OUTPUT_FOLDER = "com.capgemini.report.location.default.output"; + // Type de fichier traités + private static final String SUFFIX = ".xlsx"; + private static final PolicyLocation XML_POLICY = PolicyLocation.make("test_policy", "/xml/policies/r03report/R03_policy_full.xml"); + private Properties localproperties; + + + @BeforeClass + public void login() throws NoTeamcenterConnectionException, InvalidConfigurationException, IOException { + session.login(); + session.setObjectPropPolicy(XML_POLICY); + localproperties = new Properties(); + localproperties.load(getClass().getResourceAsStream("/reporting.properties")); + } + + @AfterClass + public void logout() { + session.close(); + } + + //@BeforeMethod + //TODO : Supprimer xls files dans Generated, checker Tempfile TempDirectory + + + @Parameters({"partId", "partRev", "refFile"}) + @Test + + + public void test03(String partId, String partRev, String refFile) throws KurtException, IOException { + + // Génération du rapport de test + Map data = new HashMap<>(); + data.put(ReportCriteriaEnum.PART_ID, partId); + data.put(ReportCriteriaEnum.PART_REVISION, partRev); + + ExecutionR03 execution = new R03Builder().build(data); + new DataReportPreparatorR03().print(session, execution, new ImmediateExecutionStrategy()); + + try (FileInputStream fileInput = new FileInputStream(new File((localproperties.getProperty(INPUT_FOLDER)) + SPECIFIC_INPUT_FOLDER + "/" + refFile)); + FileInputStream fileOutput = new FileInputStream(new File(localproperties.getProperty(TEMPORARY_OUTPUT_FOLDER) + execution.getFileNameOnDisc() + SUFFIX))) { + + XSSFWorkbook workbookRef = new XSSFWorkbook(fileInput); + XSSFWorkbook workbookGen = new XSSFWorkbook(fileOutput); + DataFormatter df = new DataFormatter(); + + softAssert.assertThat(workbookRef.getNumberOfSheets()).isEqualTo(workbookGen.getNumberOfSheets()); + for (int h = 0; h < workbookGen.getNumberOfSheets() && h < workbookRef.getNumberOfSheets(); h++) { + // Un fichier excel est composé de plusieurs feuilles, on y accède de la manière suivante + XSSFSheet sheetRef = workbookRef.getSheetAt(h); + XSSFSheet sheetGen = workbookGen.getSheetAt(h); + for (int i = 0; i <= sheetRef.getLastRowNum(); i++) { + XSSFRow rowRef = sheetRef.getRow(i); + XSSFRow rowGen = sheetGen.getRow(i); + for (int j = 0; j <= rowRef.getLastCellNum(); j++) { + XSSFCell cellRef = rowRef.getCell(j); + XSSFCell cellGen = rowGen.getCell(j); + softAssert.assertThat(df.formatCellValue(cellGen)).isEqualTo(df.formatCellValue(cellRef)); + } + } + } + } + softAssert.assertAll(); + } +} \ No newline at end of file diff --git a/kurt-utility/src/val/java/com/capgemini/reports/definition/r07report/Test_R07.java b/kurt-utility/src/val/java/com/capgemini/reports/definition/r07report/Test_R07.java new file mode 100644 index 0000000..3bd3327 --- /dev/null +++ b/kurt-utility/src/val/java/com/capgemini/reports/definition/r07report/Test_R07.java @@ -0,0 +1,108 @@ +package com.capgemini.reports.definition.r07report; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.InvalidConfigurationException; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.exceptions.NoTeamcenterConnectionException; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.reports.builder.R07Builder; +import com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum; +import com.capgemini.reports.definition.r07report.data.DataReportPreparatorR07; +import com.capgemini.reports.execution.strategies.ImmediateExecutionStrategy; +import lombok.extern.slf4j.Slf4j; +import org.apache.poi.ss.usermodel.DataFormatter; +import org.apache.poi.xssf.usermodel.XSSFCell; +import org.apache.poi.xssf.usermodel.XSSFRow; +import org.apache.poi.xssf.usermodel.XSSFSheet; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.assertj.core.api.SoftAssertions; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Optional; +import org.testng.annotations.Parameters; +import org.testng.annotations.Test; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + + +@Slf4j +public class Test_R07 { + private static final TcSession session = new TcSession(); + private SoftAssertions softAssert = new SoftAssertions(); + // Dossier parent du fichier de référence + private static final String INPUT_FOLDER = "com.capgemini.report.location.default.input"; + // Sous-dossier du fichier de référence + private static final String SPECIFIC_INPUT_FOLDER = "r07"; + // Dossier de stockage temporaire des fichiers générés initialement + private static final String TEMPORARY_OUTPUT_FOLDER = "com.capgemini.report.location.default.output"; + // Type de fichier traités + private static final String SUFFIX = ".xlsx"; + private static final PolicyLocation XML_POLICY = PolicyLocation.make("test_policy", "/xml/policies/r07report/R07_policy_full.xml"); + private Properties localproperties; + + + @BeforeClass + public void login() throws NoTeamcenterConnectionException, InvalidConfigurationException, IOException { + session.login(); + session.setObjectPropPolicy(XML_POLICY); + localproperties = new Properties(); + localproperties.load(getClass().getResourceAsStream("/reporting.properties")); + } + + @AfterClass + public void logout() { + session.close(); + } + + //@BeforeMethod + //TODO : Supprimer xls files dans Generated, checker Tempfile TempDirectory + + + @Parameters({"productID", "unit1", "unit2", "generic", "genericAssemb", "refFile"}) + @Test + public void test07(String productID, String unit1, String unit2, + @Optional String generic, @Optional String genericAssemb, + String refFile) throws KurtException, IOException { + + // Génération du rapport de test + Map data = new HashMap<>(); + data.put(ReportCriteriaEnum.PRODUCT, productID); + data.put(ReportCriteriaEnum.UNIT_CONFIGURATION_1, unit1); + data.put(ReportCriteriaEnum.UNIT_CONFIGURATION_2, unit2); + data.put(ReportCriteriaEnum.GENERIC, generic); + data.put(ReportCriteriaEnum.GENERIC_ASSEMB, genericAssemb); + + ExecutionR07 execution = new R07Builder().build(data); + new DataReportPreparatorR07().print(session, execution, new ImmediateExecutionStrategy()); + + try (FileInputStream fileInput = new FileInputStream(new File((localproperties.getProperty(INPUT_FOLDER)) + SPECIFIC_INPUT_FOLDER + "/" + refFile)); + FileInputStream fileOutput = new FileInputStream(new File(localproperties.getProperty(TEMPORARY_OUTPUT_FOLDER) + execution.getFileNameOnDisc() + SUFFIX))) { + + XSSFWorkbook workbookRef = new XSSFWorkbook(fileInput); + XSSFWorkbook workbookGen = new XSSFWorkbook(fileOutput); + DataFormatter df = new DataFormatter(); + + softAssert.assertThat(workbookRef.getNumberOfSheets()).isEqualTo(workbookGen.getNumberOfSheets()); + for (int h = 0; h < workbookGen.getNumberOfSheets() && h < workbookRef.getNumberOfSheets(); h++) { + // Un fichier excel est composé de plusieurs feuilles, on y accède de la manière suivante + XSSFSheet sheetRef = workbookRef.getSheetAt(h); + XSSFSheet sheetGen = workbookGen.getSheetAt(h); + for (int i = 2; i <= sheetRef.getLastRowNum(); i++) { + XSSFRow rowRef = sheetRef.getRow(i); + XSSFRow rowGen = sheetGen.getRow(i); + for (int j = 1; j <= rowRef.getLastCellNum(); j++) { + XSSFCell cellRef = rowRef.getCell(j); + XSSFCell cellGen = rowGen.getCell(j); + softAssert.assertThat(df.formatCellValue(cellGen)).isEqualTo(df.formatCellValue(cellRef)); + } + } + } + } + softAssert.assertAll(); + } +} diff --git a/kurt-utility/src/val/java/com/capgemini/reports/definition/r10report/Test_R10.java b/kurt-utility/src/val/java/com/capgemini/reports/definition/r10report/Test_R10.java new file mode 100644 index 0000000..9857a60 --- /dev/null +++ b/kurt-utility/src/val/java/com/capgemini/reports/definition/r10report/Test_R10.java @@ -0,0 +1,115 @@ +package com.capgemini.reports.definition.r10report; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.InvalidConfigurationException; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.exceptions.NoTeamcenterConnectionException; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.reports.builder.R10Builder; +import com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum; +import com.capgemini.reports.execution.strategies.ImmediateExecutionStrategy; +import lombok.extern.slf4j.Slf4j; +import org.apache.poi.ss.usermodel.DataFormatter; +import org.apache.poi.xssf.usermodel.XSSFCell; +import org.apache.poi.xssf.usermodel.XSSFRow; +import org.apache.poi.xssf.usermodel.XSSFSheet; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.assertj.core.api.SoftAssertions; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Optional; +import org.testng.annotations.Parameters; +import org.testng.annotations.Test; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + + +@Slf4j +public class Test_R10 { + private static final TcSession session = new TcSession(); + private SoftAssertions softAssert = new SoftAssertions(); + // Dossier parent du fichier de référence + private static final String INPUT_FOLDER = "com.capgemini.report.location.default.input"; + // Sous-dossier du fichier de référence + private static final String SPECIFIC_INPUT_FOLDER = "r10"; + // Dossier de stockage temporaire des fichiers générés initialement + private static final String TEMPORARY_OUTPUT_FOLDER = "com.capgemini.report.location.default.output"; + // Dossier de stockage final des fichiers + private static final String RECORDS_FOLDER = "com.capgemini.report.location.default.records"; + // Type de fichier traités + private static final String SUFFIX = ".xlsx"; + private static final PolicyLocation XML_POLICY = PolicyLocation.make("test_policy", "/xml/policies/r10report/R10_policy_full.xml"); + private Properties localproperties; + + + @BeforeClass + public void login() throws NoTeamcenterConnectionException, InvalidConfigurationException, IOException { + session.login(); + session.setObjectPropPolicy(XML_POLICY); + localproperties = new Properties(); + localproperties.load(getClass().getResourceAsStream("/reporting.properties")); + } + + @AfterClass + public void logout() { + session.close(); + } + + //@BeforeMethod + //TODO : Supprimer xls files dans Generated, checker Tempfile TempDirectory + + + @Parameters({"productID", "unit", "monomulti", "generic", "genericAssemb", "effectivity", "refFile"}) + @Test + + public void test10(String productID, String unit, String monomulti, + @Optional String generic, @Optional String genericAssemb, @Optional String effectivity, String refFile) + throws KurtException, IOException { + + // Génération du rapport de test + Map data = new HashMap(); + data.put(ReportCriteriaEnum.PRODUCT, productID); + data.put(ReportCriteriaEnum.UNIT, unit); + data.put(ReportCriteriaEnum.MONO_MULTI, monomulti); + data.put(ReportCriteriaEnum.GENERIC, generic); + data.put(ReportCriteriaEnum.GENERIC_ASSEMB, genericAssemb); + data.put(ReportCriteriaEnum.EFFECTIVITY_DATE, effectivity); + + + ExecutionR10 execution = new R10Builder().build(data); + String print = new DataReportPreparatorR10().print(session, execution, new ImmediateExecutionStrategy()); + + try (FileInputStream fileInput = new FileInputStream(new File((localproperties.getProperty(INPUT_FOLDER)) + SPECIFIC_INPUT_FOLDER + "/" + refFile)); + FileInputStream fileOutput = new FileInputStream(new File(localproperties.getProperty(TEMPORARY_OUTPUT_FOLDER) + execution.getFileNameOnDisc() + SUFFIX))) { + + + XSSFWorkbook workbookRef = new XSSFWorkbook(fileInput); + XSSFWorkbook workbookGen = new XSSFWorkbook(fileOutput); + DataFormatter df = new DataFormatter(); + + softAssert.assertThat(workbookRef.getNumberOfSheets()).isEqualTo(workbookGen.getNumberOfSheets()); + for (int h = 0; h < workbookGen.getNumberOfSheets() && h < workbookRef.getNumberOfSheets(); h++) { + // Un fichier excel est composé de plusieurs feuilles, on y accède de la manière suivante + XSSFSheet sheetRef = workbookRef.getSheetAt(h); + XSSFSheet sheetGen = workbookGen.getSheetAt(h); + for (int i = 0; i <= sheetRef.getLastRowNum(); i++) { + XSSFRow rowRef = sheetRef.getRow(i); + XSSFRow rowGen = sheetGen.getRow(i); + for (int j = 0; j <= rowRef.getLastCellNum(); j++) { + XSSFCell cellRef = rowRef.getCell(j); + XSSFCell cellGen = rowGen.getCell(j); + softAssert.assertThat(df.formatCellValue(cellGen)).isEqualTo(df.formatCellValue(cellRef)); + } + } + } + } + softAssert.assertAll(); + } +} + + diff --git a/kurt-utility/src/val/java/com/capgemini/reports/definition/r11report/Test_R11.java b/kurt-utility/src/val/java/com/capgemini/reports/definition/r11report/Test_R11.java new file mode 100644 index 0000000..79de46f --- /dev/null +++ b/kurt-utility/src/val/java/com/capgemini/reports/definition/r11report/Test_R11.java @@ -0,0 +1,110 @@ +package com.capgemini.reports.definition.r11report; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.InvalidConfigurationException; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.exceptions.NoTeamcenterConnectionException; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.reports.builder.R11Builder; +import com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum; +import com.capgemini.reports.execution.strategies.ImmediateExecutionStrategy; +import lombok.extern.slf4j.Slf4j; +import org.apache.poi.ss.usermodel.DataFormatter; +import org.apache.poi.xssf.usermodel.XSSFCell; +import org.apache.poi.xssf.usermodel.XSSFRow; +import org.apache.poi.xssf.usermodel.XSSFSheet; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.assertj.core.api.SoftAssertions; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Optional; +import org.testng.annotations.Parameters; +import org.testng.annotations.Test; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + + +@Slf4j +public class Test_R11 { + private static final TcSession session = new TcSession(); + private SoftAssertions softAssert = new SoftAssertions(); + // Dossier parent du fichier de référence + private static final String INPUT_FOLDER = "com.capgemini.report.location.default.input"; + // Sous-dossier du fichier de référence + private static final String SPECIFIC_INPUT_FOLDER = "r11"; + // Dossier de stockage temporaire des fichiers générés initialement + private static final String TEMPORARY_OUTPUT_FOLDER = "com.capgemini.report.location.default.output"; + // Type de fichier traités + private static final String SUFFIX = ".xlsx"; + private static final PolicyLocation XML_POLICY = PolicyLocation.make("test_policy", "/xml/policies/r11report/R11_policy_full.xml"); + private Properties localproperties; + + + @BeforeClass + public void login() throws NoTeamcenterConnectionException, InvalidConfigurationException, IOException { + session.login(); + session.setObjectPropPolicy(XML_POLICY); + localproperties = new Properties(); + localproperties.load(getClass().getResourceAsStream("/reporting.properties")); + } + + @AfterClass + public void logout() { + session.close(); + } + + //@BeforeMethod + //TODO : Supprimer xls files dans Generated, checker Tempfile TempDirectory + + + @Parameters({"productID", "unit", "monomulti", "generic", "effectivity", "refFile"}) + @Test + + + public void test11 + (String productID, String unit, String monomulti, + @Optional String generic, String effectivity, String refFile) throws KurtException, IOException { + + // Génération du rapport de test + Map data = new HashMap<>(); + data.put(ReportCriteriaEnum.PRODUCT, productID); + data.put(ReportCriteriaEnum.UNIT, unit); + data.put(ReportCriteriaEnum.MONO_MULTI, monomulti); + data.put(ReportCriteriaEnum.GENERIC, generic); + data.put(ReportCriteriaEnum.EFFECTIVITY_DATE, effectivity); + + + ExecutionR11 execution = new R11Builder().build(data); + new DataReportPreparatorR11().print(session, execution, new ImmediateExecutionStrategy()); + + try (FileInputStream fileInput = new FileInputStream(new File((localproperties.getProperty(INPUT_FOLDER)) + SPECIFIC_INPUT_FOLDER + "/" + refFile)); + FileInputStream fileOutput = new FileInputStream(new File(localproperties.getProperty(TEMPORARY_OUTPUT_FOLDER) + execution.getFileNameOnDisc() + SUFFIX))) { + + XSSFWorkbook workbookRef = new XSSFWorkbook(fileInput); + XSSFWorkbook workbookGen = new XSSFWorkbook(fileOutput); + DataFormatter df = new DataFormatter(); + + softAssert.assertThat(workbookRef.getNumberOfSheets()).isEqualTo(workbookGen.getNumberOfSheets()); + for (int h = 0; h < workbookGen.getNumberOfSheets() && h < workbookRef.getNumberOfSheets(); h++) { + // Un fichier excel est composé de plusieurs feuilles, on y accède de la manière suivante + XSSFSheet sheetRef = workbookRef.getSheetAt(h); + XSSFSheet sheetGen = workbookGen.getSheetAt(h); + for (int i = 0; i <= sheetRef.getLastRowNum(); i++) { + XSSFRow rowRef = sheetRef.getRow(i); + XSSFRow rowGen = sheetGen.getRow(i); + for (int j = 0; j <= rowRef.getLastCellNum(); j++) { + XSSFCell cellRef = rowRef.getCell(j); + XSSFCell cellGen = rowGen.getCell(j); + softAssert.assertThat(df.formatCellValue(cellGen)).isEqualTo(df.formatCellValue(cellRef)); + } + } + } + } + softAssert.assertAll(); + } +} \ No newline at end of file diff --git a/kurt-utility/src/val/java/com/capgemini/reports/definition/r13report/Test_CrR13.java b/kurt-utility/src/val/java/com/capgemini/reports/definition/r13report/Test_CrR13.java new file mode 100644 index 0000000..3597cf0 --- /dev/null +++ b/kurt-utility/src/val/java/com/capgemini/reports/definition/r13report/Test_CrR13.java @@ -0,0 +1,105 @@ +package com.capgemini.reports.definition.r13report; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.InvalidConfigurationException; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.exceptions.NoTeamcenterConnectionException; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.reports.builder.R13CrBuilder; +import com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum; +import com.capgemini.reports.definition.r13report.datapreparator.DataReportPreparatorR13CR; +import com.capgemini.reports.definition.r13report.execution.ExecutionR13CR; +import com.capgemini.reports.execution.strategies.ImmediateExecutionStrategy; +import lombok.extern.slf4j.Slf4j; +import org.apache.poi.ss.usermodel.DataFormatter; +import org.apache.poi.xssf.usermodel.XSSFCell; +import org.apache.poi.xssf.usermodel.XSSFRow; +import org.apache.poi.xssf.usermodel.XSSFSheet; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.assertj.core.api.SoftAssertions; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Parameters; +import org.testng.annotations.Test; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + + +@Slf4j +public class Test_CrR13 { + private static final TcSession session = new TcSession(); + private SoftAssertions softAssert = new SoftAssertions(); + // Dossier parent du fichier de référence + private static final String INPUT_FOLDER = "com.capgemini.report.location.default.input"; + // Sous-dossier du fichier de référence + private static final String SPECIFIC_INPUT_FOLDER = "r13"; + // Dossier de stockage temporaire des fichiers générés initialement + private static final String TEMPORARY_OUTPUT_FOLDER = "com.capgemini.report.location.default.output"; + // Type de fichier traités + private static final String SUFFIX = ".xlsx"; + private static final PolicyLocation XML_POLICY = PolicyLocation.make("test_policy", "/xml/policies/r13report/R13_policy_full.xml"); + private Properties localproperties; + + + @BeforeClass + public void login() throws NoTeamcenterConnectionException, InvalidConfigurationException, IOException { + session.login(); + session.setObjectPropPolicy(XML_POLICY); + localproperties = new Properties(); + localproperties.load(getClass().getResourceAsStream("/reporting.properties")); + } + + @AfterClass + public void logout() { + session.close(); + } + + //@BeforeMethod + //TODO : Supprimer xls files dans Generated, checker Tempfile TempDirectory + + + @Parameters({"objectType", "beginDate", "endDate", "refFile"}) + @Test + public void test13_cr(String objectType, String beginDate, String endDate, String refFile) throws KurtException, IOException { + + // Génération du rapport de test + Map data = new HashMap<>(); + data.put(ReportCriteriaEnum.TYPE_OBJET, objectType); + data.put(ReportCriteriaEnum.DATE_DEBUT, beginDate); + data.put(ReportCriteriaEnum.DATE_FIN, endDate); + + ExecutionR13CR execution = new R13CrBuilder().build(data); + new DataReportPreparatorR13CR().print(session, execution, new ImmediateExecutionStrategy()); + + try (FileInputStream fileInput = new FileInputStream(new File((localproperties.getProperty(INPUT_FOLDER)) + SPECIFIC_INPUT_FOLDER + "/" + refFile)); + FileInputStream fileOutput = new FileInputStream(new File(localproperties.getProperty(TEMPORARY_OUTPUT_FOLDER) + execution.getFileNameOnDisc() + SUFFIX))) { + + + XSSFWorkbook workbookRef = new XSSFWorkbook(fileInput); + XSSFWorkbook workbookGen = new XSSFWorkbook(fileOutput); + DataFormatter df = new DataFormatter(); + + softAssert.assertThat(workbookRef.getNumberOfSheets()).isEqualTo(workbookGen.getNumberOfSheets()); + for (int h = 0; h < workbookGen.getNumberOfSheets() && h < workbookRef.getNumberOfSheets(); h++) { + // Un fichier excel est composé de plusieurs feuilles, on y accède de la manière suivante + XSSFSheet sheetRef = workbookRef.getSheetAt(h); + XSSFSheet sheetGen = workbookGen.getSheetAt(h); + for (int i = 0; i <= sheetRef.getLastRowNum(); i++) { + XSSFRow rowRef = sheetRef.getRow(i); + XSSFRow rowGen = sheetGen.getRow(i); + for (int j = 0; j <= 34; j++) { + XSSFCell cellRef = rowRef.getCell(j); + XSSFCell cellGen = rowGen.getCell(j); + softAssert.assertThat(df.formatCellValue(cellGen)).isEqualTo(df.formatCellValue(cellRef)); + } + } + } + } + softAssert.assertAll(); + } +} diff --git a/kurt-utility/src/val/java/com/capgemini/reports/definition/r13report/Test_FppR13.java b/kurt-utility/src/val/java/com/capgemini/reports/definition/r13report/Test_FppR13.java new file mode 100644 index 0000000..dfc8738 --- /dev/null +++ b/kurt-utility/src/val/java/com/capgemini/reports/definition/r13report/Test_FppR13.java @@ -0,0 +1,106 @@ +package com.capgemini.reports.definition.r13report; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.InvalidConfigurationException; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.exceptions.NoTeamcenterConnectionException; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.reports.builder.R13FppBuilder; +import com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum; +import com.capgemini.reports.definition.r13report.datapreparator.DataReportPreparatorR13FPP; +import com.capgemini.reports.definition.r13report.execution.ExecutionR13FPP; +import com.capgemini.reports.execution.strategies.ImmediateExecutionStrategy; +import lombok.extern.slf4j.Slf4j; +import org.apache.poi.ss.usermodel.DataFormatter; +import org.apache.poi.xssf.usermodel.XSSFCell; +import org.apache.poi.xssf.usermodel.XSSFRow; +import org.apache.poi.xssf.usermodel.XSSFSheet; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.assertj.core.api.SoftAssertions; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Parameters; +import org.testng.annotations.Test; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + + +@Slf4j +public class Test_FppR13 { + private static final TcSession session = new TcSession(); + private SoftAssertions softAssert = new SoftAssertions(); + // Dossier parent du fichier de référence + private static final String INPUT_FOLDER = "com.capgemini.report.location.default.input"; + // Sous-dossier du fichier de référence + private static final String SPECIFIC_INPUT_FOLDER = "r13"; + // Dossier de stockage temporaire des fichiers générés initialement + private static final String TEMPORARY_OUTPUT_FOLDER = "com.capgemini.report.location.default.output"; + // Type de fichier traités + private static final String SUFFIX = ".xlsx"; + private static final PolicyLocation XML_POLICY = PolicyLocation.make("test_policy", "/xml/policies/r13report/R13_policy_full.xml"); + private Properties localproperties; + + + @BeforeClass + public void login() throws NoTeamcenterConnectionException, InvalidConfigurationException, IOException { + session.login(); + session.setObjectPropPolicy(XML_POLICY); + localproperties = new Properties(); + localproperties.load(getClass().getResourceAsStream("/reporting.properties")); + } + + @AfterClass + public void logout() { + session.close(); + } + + //@BeforeMethod + //TODO : Supprimer xls files dans Generated, checker Tempfile TempDirectory + + + @Parameters({"objectType", "beginDate", "endDate", "refFile"}) + @Test + public void test13_fpp(String objectType, String beginDate, String endDate, String refFile) throws KurtException, IOException { + + // Génération du rapport de test + Map data = new HashMap(); + data.put(ReportCriteriaEnum.TYPE_OBJET, objectType); + data.put(ReportCriteriaEnum.DATE_DEBUT, beginDate); + data.put(ReportCriteriaEnum.DATE_FIN, endDate); + + ExecutionR13FPP execution = new R13FppBuilder().build(data); + new DataReportPreparatorR13FPP().print(session, execution, new ImmediateExecutionStrategy()); + + try (FileInputStream fileInput = new FileInputStream(new File((localproperties.getProperty(INPUT_FOLDER)) + SPECIFIC_INPUT_FOLDER + "/" + refFile)); + FileInputStream fileOutput = new FileInputStream(new File(localproperties.getProperty(TEMPORARY_OUTPUT_FOLDER) + execution.getFileNameOnDisc() + SUFFIX))) { + + + XSSFWorkbook workbookRef = new XSSFWorkbook(fileInput); + XSSFWorkbook workbookGen = new XSSFWorkbook(fileOutput); + DataFormatter df = new DataFormatter(); + + softAssert.assertThat(workbookRef.getNumberOfSheets()).isEqualTo(workbookGen.getNumberOfSheets()); + for (int h = 0; h < workbookGen.getNumberOfSheets() && h < workbookRef.getNumberOfSheets(); h++) { + // Un fichier excel est composé de plusieurs feuilles, on y accède de la manière suivante + XSSFSheet sheetRef = workbookRef.getSheetAt(h); + XSSFSheet sheetGen = workbookGen.getSheetAt(h); + for (int i = 0; i <= sheetRef.getLastRowNum(); i++) { + XSSFRow rowRef = sheetRef.getRow(i); + XSSFRow rowGen = sheetGen.getRow(i); + for (int j = 0; j <= 19; j++) { + XSSFCell cellRef = rowRef.getCell(j); + XSSFCell cellGen = rowGen.getCell(j); + softAssert.assertThat(df.formatCellValue(cellGen)).isEqualTo(df.formatCellValue(cellRef)); + } + } + } + } + softAssert.assertAll(); + } +} + diff --git a/kurt-utility/src/val/java/com/capgemini/reports/definition/r15report/Test_R15.java b/kurt-utility/src/val/java/com/capgemini/reports/definition/r15report/Test_R15.java new file mode 100644 index 0000000..585d916 --- /dev/null +++ b/kurt-utility/src/val/java/com/capgemini/reports/definition/r15report/Test_R15.java @@ -0,0 +1,94 @@ +package com.capgemini.reports.definition.r15report; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.InvalidConfigurationException; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.exceptions.NoTeamcenterConnectionException; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.reports.builder.R15Builder; +import com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum; +import com.capgemini.reports.definition.r15r16r17reports.r15r17reports.r15report.DataReportPreparatorR15; +import com.capgemini.reports.definition.r15r16r17reports.r15r17reports.r15report.ExecutionR15; +import com.capgemini.reports.execution.strategies.ImmediateExecutionStrategy; +import com.lowagie.text.pdf.PdfReader; +import com.lowagie.text.pdf.parser.PdfTextExtractor; +import lombok.extern.slf4j.Slf4j; +import org.assertj.core.api.SoftAssertions; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Parameters; +import org.testng.annotations.Test; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + + +@Slf4j +public class Test_R15 { + private static final TcSession session = new TcSession(); + private SoftAssertions softAssert = new SoftAssertions(); + // Dossier parent du fichier de référence + private static final String INPUT_FOLDER = "com.capgemini.report.location.default.input"; + // Sous-dossier du fichier de référence + private static final String SPECIFIC_INPUT_FOLDER = "r15"; + public static final String PRINTINGFOLDER = "com.capgemini.report.location.default.output"; + // Dossier de stockage temporaire des fichiers générés initialement + private static final String TEMPORARY_OUTPUT_FOLDER = "com.capgemini.report.location.default.output"; + // Dossier de stockage final des fichiers + private static final String RECORDS_FOLDER = "com.capgemini.report.location.default.records"; + private static final PolicyLocation XML_POLICY = PolicyLocation.make("test_policy", "/xml/policies/r15report/R15_policy_full.xml"); + public static final String SUFFIX = ".pdf"; + public Properties localproperties; + + + @BeforeClass + public void login() throws NoTeamcenterConnectionException, InvalidConfigurationException, IOException { + session.login(); + session.setObjectPropPolicy(XML_POLICY); + localproperties = new Properties(); + localproperties.load(getClass().getResourceAsStream("/reporting.properties")); + } + + @AfterClass + public void logout() { + session.close(); + } + + @BeforeMethod + //TODO : Supprimer pdf files dans Generated, checker Tempfile TempDirectory + + + @Parameters({"language", "partId", "partRevision", "refFile"}) + @Test + public void test15(String language, String partId, String partRevision, String refFile) throws KurtException, IOException { + + // Génération du rapport de test + Map data = new HashMap(); + data.put(ReportCriteriaEnum.PART_ID, partId); + data.put(ReportCriteriaEnum.PART_REVISION, partRevision); + data.put((ReportCriteriaEnum.LANGUAGE), language); + ExecutionR15 execution = new R15Builder().build(data); + new DataReportPreparatorR15().print(session, execution, new ImmediateExecutionStrategy()); + + + PdfReader readerRef = new PdfReader(localproperties.getProperty(INPUT_FOLDER) + SPECIFIC_INPUT_FOLDER + "/" + refFile); + PdfReader readerGen = new PdfReader(localproperties.getProperty((TEMPORARY_OUTPUT_FOLDER)) + execution.getFileNameOnDisc() + SUFFIX); + + try { + softAssert.assertThat(readerRef.getNumberOfPages()).isEqualTo(readerGen.getNumberOfPages()); + for (int i = 1; i < readerRef.getNumberOfPages(); i++) { + String textFromPageRef = new PdfTextExtractor(readerRef).getTextFromPage(i); + String textFromPageGen = new PdfTextExtractor(readerGen).getTextFromPage(i); + softAssert.assertThat(textFromPageRef).isEqualTo(textFromPageGen); + } + } + finally { + readerGen.close(); + readerRef.close(); + } + softAssert.assertAll(); + } +} diff --git a/kurt-utility/src/val/java/com/capgemini/reports/definition/r16report/Test_R16.java b/kurt-utility/src/val/java/com/capgemini/reports/definition/r16report/Test_R16.java new file mode 100644 index 0000000..0bcb5dc --- /dev/null +++ b/kurt-utility/src/val/java/com/capgemini/reports/definition/r16report/Test_R16.java @@ -0,0 +1,96 @@ +package com.capgemini.reports.definition.r16report; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.InvalidConfigurationException; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.exceptions.NoTeamcenterConnectionException; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.reports.builder.R16Builder; +import com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum; +import com.capgemini.reports.definition.r15r16r17reports.r16report.DataReportPreparatorR16; +import com.capgemini.reports.definition.r15r16r17reports.r16report.ExecutionR16; +import com.capgemini.reports.execution.strategies.ImmediateExecutionStrategy; +import com.lowagie.text.pdf.PdfReader; +import com.lowagie.text.pdf.parser.PdfTextExtractor; +import lombok.extern.slf4j.Slf4j; +import org.assertj.core.api.SoftAssertions; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Parameters; +import org.testng.annotations.Test; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + + +@Slf4j +public class Test_R16 { + private static final TcSession session = new TcSession(); + private SoftAssertions softAssert = new SoftAssertions(); + // Dossier parent du fichier de référence + private static final String INPUT_FOLDER = "com.capgemini.report.location.default.input"; + // Sous-dossier du fichier de référence + private static final String SPECIFIC_INPUT_FOLDER = "r16"; + public static final String PRINTINGFOLDER = "com.capgemini.report.location.default.output"; + // Dossier de stockage temporaire des fichiers générés initialement + private static final String TEMPORARY_OUTPUT_FOLDER = "com.capgemini.report.location.default.output"; + private static final PolicyLocation XML_POLICY = PolicyLocation.make("test_policy", "/xml/policies/r16report/R16_policy_full.xml"); + public static final String SUFFIX = ".pdf"; + public Properties localproperties; + + + @BeforeClass + public void login() throws NoTeamcenterConnectionException, InvalidConfigurationException, IOException { + session.login(); + session.setObjectPropPolicy(XML_POLICY); + localproperties = new Properties(); + localproperties.load(getClass().getResourceAsStream("/reporting.properties")); + } + + @AfterClass + public void logout() { + session.close(); + } + + @BeforeMethod + //TODO : Supprimer pdf files dans Generated, checker Tempfile TempDirectory + + + @Parameters({"product", "unitStr", "idTopGeneric", "typeImpression", "language", "refFile"}) + @Test + public void test16(String product, String unitStr, String idTopGeneric, + String typeImpression, String language, String refFile) throws KurtException, IOException { + + // Génération du rapport de test + Map data = new HashMap<>(); + data.put(ReportCriteriaEnum.PRODUCT, product); + data.put(ReportCriteriaEnum.PART_ID, idTopGeneric); + data.put(ReportCriteriaEnum.UNIT, unitStr); + data.put(ReportCriteriaEnum.TYPE_IMPRESSION, typeImpression); + data.put(ReportCriteriaEnum.LANGUAGE, language); + + ExecutionR16 execution = new R16Builder().build(data); + new DataReportPreparatorR16().print(session, execution, new ImmediateExecutionStrategy()); + + + PdfReader readerRef = new PdfReader(localproperties.getProperty(INPUT_FOLDER) + SPECIFIC_INPUT_FOLDER + "/" + refFile); + PdfReader readerGen = new PdfReader(localproperties.getProperty((TEMPORARY_OUTPUT_FOLDER)) + execution.getFileNameOnDisc() + SUFFIX); + + try { + softAssert.assertThat(readerRef.getNumberOfPages()).isEqualTo(readerGen.getNumberOfPages()); + for (int i = 1; i < readerRef.getNumberOfPages(); i++) { + String textFromPageRef = new PdfTextExtractor(readerRef).getTextFromPage(i); + String textFromPageGen = new PdfTextExtractor(readerGen).getTextFromPage(i); + softAssert.assertThat(textFromPageRef).isEqualTo(textFromPageGen); + } + } + finally { + readerGen.close(); + readerRef.close(); + } + softAssert.assertAll(); + } +} \ No newline at end of file diff --git a/kurt-utility/src/val/java/com/capgemini/reports/definition/r17report/Test_R17.java b/kurt-utility/src/val/java/com/capgemini/reports/definition/r17report/Test_R17.java new file mode 100644 index 0000000..6957b43 --- /dev/null +++ b/kurt-utility/src/val/java/com/capgemini/reports/definition/r17report/Test_R17.java @@ -0,0 +1,91 @@ +package com.capgemini.reports.definition.r17report; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.InvalidConfigurationException; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.exceptions.NoTeamcenterConnectionException; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.reports.builder.R17Builder; +import com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum; +import com.capgemini.reports.definition.r15r16r17reports.r15r17reports.r17report.DataReportPreparatorR17; +import com.capgemini.reports.definition.r15r16r17reports.r15r17reports.r17report.ExecutionR17; +import com.capgemini.reports.execution.strategies.ImmediateExecutionStrategy; +import com.lowagie.text.pdf.PdfReader; +import com.lowagie.text.pdf.parser.PdfTextExtractor; +import lombok.extern.slf4j.Slf4j; +import org.assertj.core.api.SoftAssertions; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Parameters; +import org.testng.annotations.Test; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + + +@Slf4j +public class Test_R17 { + private static final TcSession session = new TcSession(); + private SoftAssertions softAssert = new SoftAssertions(); + // Dossier parent du fichier de référence + private static final String INPUT_FOLDER = "com.capgemini.report.location.default.input"; + // Sous-dossier du fichier de référence + private static final String SPECIFIC_INPUT_FOLDER = "r17"; + // Dossier de stockage temporaire des fichiers générés initialement + private static final String TEMPORARY_OUTPUT_FOLDER = "com.capgemini.report.location.default.output"; + private static final PolicyLocation XML_POLICY = PolicyLocation.make("test_policy", "/xml/policies/r17report/R17_policy_full.xml"); + public static final String SUFFIX = ".pdf"; + public Properties localproperties; + + + @BeforeClass + public void login() throws NoTeamcenterConnectionException, InvalidConfigurationException, IOException { + session.login(); + session.setObjectPropPolicy(XML_POLICY); + localproperties = new Properties(); + localproperties.load(getClass().getResourceAsStream("/reporting.properties")); + } + + @AfterClass + public void logout() { + session.close(); + } + + @BeforeMethod + //TODO : Supprimer pdf files dans Generated, checker Tempfile TempDirectory + + + @Parameters({"language", "partId", "partRevision", "refFile"}) + @Test + public void test17(String language, String partId, String partRevision, String refFile) throws KurtException, IOException { + + // Génération du rapport de test + Map data = new HashMap<>(); + data.put(ReportCriteriaEnum.PART_ID, partId); + data.put(ReportCriteriaEnum.PART_REVISION, partRevision); + data.put((ReportCriteriaEnum.LANGUAGE), language); + ExecutionR17 execution = new R17Builder().build(data); + new DataReportPreparatorR17().print(session, execution, new ImmediateExecutionStrategy()); + + + PdfReader readerRef = new PdfReader(localproperties.getProperty(INPUT_FOLDER) + SPECIFIC_INPUT_FOLDER + "/" + refFile); + PdfReader readerGen = new PdfReader(localproperties.getProperty((TEMPORARY_OUTPUT_FOLDER)) + execution.getFileNameOnDisc() + SUFFIX); + + try { + softAssert.assertThat(readerRef.getNumberOfPages()).isEqualTo(readerGen.getNumberOfPages()); + for (int i = 1; i < readerRef.getNumberOfPages(); i++) { + String textFromPageRef = new PdfTextExtractor(readerRef).getTextFromPage(i); + String textFromPageGen = new PdfTextExtractor(readerGen).getTextFromPage(i); + softAssert.assertThat(textFromPageRef).isEqualTo(textFromPageGen); + } + } + finally { + readerGen.close(); + readerRef.close(); + } + softAssert.assertAll(); + } +} \ No newline at end of file diff --git a/kurt-utility/src/val/java/com/capgemini/reports/definition/r19report/Test_R19.java b/kurt-utility/src/val/java/com/capgemini/reports/definition/r19report/Test_R19.java new file mode 100644 index 0000000..3d39731 --- /dev/null +++ b/kurt-utility/src/val/java/com/capgemini/reports/definition/r19report/Test_R19.java @@ -0,0 +1,107 @@ +package com.capgemini.reports.definition.r19report; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.InvalidConfigurationException; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.exceptions.NoTeamcenterConnectionException; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.reports.builder.R19Builder; +import com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum; +import com.capgemini.reports.execution.strategies.ImmediateExecutionStrategy; +import lombok.extern.slf4j.Slf4j; +import org.apache.poi.ss.usermodel.DataFormatter; +import org.apache.poi.xssf.usermodel.XSSFCell; +import org.apache.poi.xssf.usermodel.XSSFRow; +import org.apache.poi.xssf.usermodel.XSSFSheet; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.assertj.core.api.SoftAssertions; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Parameters; +import org.testng.annotations.Test; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + + +@Slf4j +public class Test_R19 { + private static final TcSession session = new TcSession(); + private SoftAssertions softAssert = new SoftAssertions(); + // Dossier parent du fichier de référence + private static final String INPUT_FOLDER = "com.capgemini.report.location.default.input"; + // Sous-dossier du fichier de référence + private static final String SPECIFIC_INPUT_FOLDER = "r19"; + // Dossier de stockage temporaire des fichiers générés initialement + private static final String TEMPORARY_OUTPUT_FOLDER = "com.capgemini.report.location.default.output"; + // Type de fichier traités + private static final String SUFFIX = ".xlsx"; + private static final PolicyLocation XML_POLICY = PolicyLocation.make("test_policy", "/xml/policies/r19report/R19_policy_full.xml"); + private Properties localproperties; + + + @BeforeClass + public void login() throws NoTeamcenterConnectionException, InvalidConfigurationException, IOException { + session.login(); + session.setObjectPropPolicy(XML_POLICY); + localproperties = new Properties(); + localproperties.load(getClass().getResourceAsStream("/reporting.properties")); + } + + @AfterClass + public void logout() { + session.close(); + } + + //@BeforeMethod + //TODO : Supprimer xls files dans Generated, checker Tempfile TempDirectory + + + @Parameters({"docId", "revision", "typeObject", "refFile"}) + @Test + + public void test19(String docId, String revision, String typeObject, String refFile) + throws KurtException, IOException { + + // Génération du rapport de test + Map data = new HashMap<>(); + data.put(ReportCriteriaEnum.DOCUMENT_ID, docId); + data.put(ReportCriteriaEnum.DOCUMENT_REVISION, revision); + data.put(ReportCriteriaEnum.TYPE_OBJET, typeObject); + + + ExecutionR19 execution = new R19Builder().build(data); + new DataReportPreparatorR19().print(session, execution, new ImmediateExecutionStrategy()); + + try (FileInputStream fileInput = new FileInputStream(new File((localproperties.getProperty(INPUT_FOLDER)) + SPECIFIC_INPUT_FOLDER + "/" + refFile)); + FileInputStream fileOutput = new FileInputStream(new File(localproperties.getProperty(TEMPORARY_OUTPUT_FOLDER) + execution.getFileNameOnDisc() + SUFFIX))) { + + XSSFWorkbook workbookRef = new XSSFWorkbook(fileInput); + XSSFWorkbook workbookGen = new XSSFWorkbook(fileOutput); + DataFormatter df = new DataFormatter(); + + softAssert.assertThat(workbookRef.getNumberOfSheets()).isEqualTo(workbookGen.getNumberOfSheets()); + for (int h = 0; h < workbookGen.getNumberOfSheets() && h < workbookRef.getNumberOfSheets(); h++) { + // Un fichier excel est composé de plusieurs feuilles, on y accède de la manière suivante + XSSFSheet sheetRef = workbookRef.getSheetAt(h); + XSSFSheet sheetGen = workbookGen.getSheetAt(h); + for (int i = 0; i <= sheetRef.getLastRowNum(); i++) { + XSSFRow rowRef = sheetRef.getRow(i); + XSSFRow rowGen = sheetGen.getRow(i); + for (int j = 0; j <= rowRef.getLastCellNum(); j++) { + XSSFCell cellRef = rowRef.getCell(j); + XSSFCell cellGen = rowGen.getCell(j); + softAssert.assertThat(df.formatCellValue(cellGen)).isEqualTo(df.formatCellValue(cellRef)); + } + } + } + } + softAssert.assertAll(); + } +} + + diff --git a/kurt-utility/src/val/java/com/capgemini/reports/definition/r20report/Test_R20.java b/kurt-utility/src/val/java/com/capgemini/reports/definition/r20report/Test_R20.java new file mode 100644 index 0000000..d52faa9 --- /dev/null +++ b/kurt-utility/src/val/java/com/capgemini/reports/definition/r20report/Test_R20.java @@ -0,0 +1,96 @@ +package com.capgemini.reports.definition.r20report; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.InvalidConfigurationException; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.exceptions.NoTeamcenterConnectionException; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.reports.builder.R20Builder; +import com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum; +import com.capgemini.reports.execution.strategies.ImmediateExecutionStrategy; +import com.lowagie.text.pdf.PdfReader; +import com.lowagie.text.pdf.parser.PdfTextExtractor; +import lombok.extern.slf4j.Slf4j; +import org.assertj.core.api.SoftAssertions; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Optional; +import org.testng.annotations.Parameters; +import org.testng.annotations.Test; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + + +@Slf4j +public class Test_R20 { + private static final TcSession session = new TcSession(); + private SoftAssertions softAssert = new SoftAssertions(); + // Dossier parent du fichier de référence + private static final String INPUT_FOLDER = "com.capgemini.report.location.default.input"; + // Sous-dossier du fichier de référence + private static final String SPECIFIC_INPUT_FOLDER = "r20"; + // Dossier de stockage temporaire des fichiers générés initialement + private static final String TEMPORARY_OUTPUT_FOLDER = "com.capgemini.report.location.default.output"; + private static final PolicyLocation XML_POLICY = PolicyLocation.make("test_policy", "/xml/policies/r20report/R20_policy_full.xml"); + public static final String SUFFIX = ".pdf"; + public Properties localproperties; + + + @BeforeClass + public void login() throws NoTeamcenterConnectionException, InvalidConfigurationException, IOException { + session.login(); + session.setObjectPropPolicy(XML_POLICY); + localproperties = new Properties(); + localproperties.load(getClass().getResourceAsStream("/reporting.properties")); + } + + @AfterClass + public void logout() { + session.close(); + } + + + @Test + @Parameters({"prodIDBefore", "prodIDAfter", "unitBefore", "unitAfter", "matricule", "listModif", "classe", "majMin", "conjoint", "refFile"}) + public void test20(String prodIDBefore, String prodIDAfter, String unitBefore, String unitAfter, + String matricule, @Optional String listModif, String classe, String majMin, String conjoint, + String refFile) throws KurtException, IOException { + + // Génération du rapport de test + Map data = new HashMap<>(); + data.put(ReportCriteriaEnum.PRODUCT_BEFORE, prodIDBefore); + data.put(ReportCriteriaEnum.PRODUCT_AFTER, prodIDAfter); + data.put(ReportCriteriaEnum.UNIT_BEFORE, unitBefore); + data.put(ReportCriteriaEnum.UNIT_AFTER, unitAfter); + data.put(ReportCriteriaEnum.MATRICULE, matricule); + data.put(ReportCriteriaEnum.LMR, listModif); + data.put(ReportCriteriaEnum.CLASSE, classe); + data.put(ReportCriteriaEnum.MAJOR_MINOR, majMin); + data.put(ReportCriteriaEnum.CONJOINT_UNIQUE, conjoint); + + + ExecutionR20 execution = new R20Builder().build(data); + new DataReportPreparatorR20().print(session, execution, new ImmediateExecutionStrategy()); + + + PdfReader readerRef = new PdfReader(localproperties.getProperty(INPUT_FOLDER) + SPECIFIC_INPUT_FOLDER + "/" + refFile); + PdfReader readerGen = new PdfReader(localproperties.getProperty((TEMPORARY_OUTPUT_FOLDER)) + execution.getFileNameOnDisc() + SUFFIX); + + try { + softAssert.assertThat(readerRef.getNumberOfPages()).isEqualTo(readerGen.getNumberOfPages()); + for (int i = 1; i < readerRef.getNumberOfPages(); i++) { + String textFromPageRef = new PdfTextExtractor(readerRef).getTextFromPage(i); + String textFromPageGen = new PdfTextExtractor(readerGen).getTextFromPage(i); + softAssert.assertThat(textFromPageRef).isEqualTo(textFromPageGen); + } + } + finally { + readerGen.close(); + readerRef.close(); + } + softAssert.assertAll(); + } +} diff --git a/kurt-utility/src/val/java/com/capgemini/reports/definition/r21report/Test_R21.java b/kurt-utility/src/val/java/com/capgemini/reports/definition/r21report/Test_R21.java new file mode 100644 index 0000000..5858e9e --- /dev/null +++ b/kurt-utility/src/val/java/com/capgemini/reports/definition/r21report/Test_R21.java @@ -0,0 +1,109 @@ +package com.capgemini.reports.definition.r21report; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.InvalidConfigurationException; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.exceptions.NoTeamcenterConnectionException; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.reports.builder.R21Builder; +import com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum; +import com.capgemini.reports.execution.strategies.ImmediateExecutionStrategy; +import lombok.extern.slf4j.Slf4j; +import org.apache.poi.ss.usermodel.DataFormatter; +import org.apache.poi.xssf.usermodel.XSSFCell; +import org.apache.poi.xssf.usermodel.XSSFRow; +import org.apache.poi.xssf.usermodel.XSSFSheet; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.assertj.core.api.SoftAssertions; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Optional; +import org.testng.annotations.Parameters; +import org.testng.annotations.Test; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + + +@Slf4j +public class Test_R21 { + private static final TcSession session = new TcSession(); + private SoftAssertions softAssert = new SoftAssertions(); + // Dossier parent du fichier de référence + private static final String INPUT_FOLDER = "com.capgemini.report.location.default.input"; + // Sous-dossier du fichier de référence + private static final String SPECIFIC_INPUT_FOLDER = "r21"; + // Dossier de stockage temporaire des fichiers générés initialement + private static final String TEMPORARY_OUTPUT_FOLDER = "com.capgemini.report.location.default.output"; + // Type de fichier traités + private static final String SUFFIX = ".xlsx"; + private static final PolicyLocation XML_POLICY = PolicyLocation.make("test_policy", "/xml/policies/r21report/R21_policy_full.xml"); + private Properties localproperties; + + + @BeforeClass + public void login() throws NoTeamcenterConnectionException, InvalidConfigurationException, IOException { + session.login(); + session.setObjectPropPolicy(XML_POLICY); + localproperties = new Properties(); + localproperties.load(getClass().getResourceAsStream("/reporting.properties")); + } + + @AfterClass + public void logout() { + session.close(); + } + + //@BeforeMethod + //TODO : Supprimer xls files dans Generated, checker Tempfile TempDirectory + + + @Parameters({"productID", "unit", "generic", "genericAssemb", "effectivity", "refFile"}) + @Test + + public void test21(String productID, String unit, String generic, String genericAssemb, @Optional String effectivity, String refFile) + throws KurtException, IOException { + + // Génération du rapport de test + Map data = new HashMap(); + data.put(ReportCriteriaEnum.PRODUCT, productID); + data.put(ReportCriteriaEnum.UNIT, unit); + data.put(ReportCriteriaEnum.GENERIC, generic); + data.put(ReportCriteriaEnum.GENERIC_ASSEMB, genericAssemb); + data.put(ReportCriteriaEnum.EFFECTIVITY_DATE, effectivity); + + + ExecutionR21 execution = new R21Builder().build(data); + new DataReportPreparatorR21().print(session, execution, new ImmediateExecutionStrategy()); + + try (FileInputStream fileInput = new FileInputStream(new File((localproperties.getProperty(INPUT_FOLDER)) + SPECIFIC_INPUT_FOLDER + "/" + refFile)); + FileInputStream fileOutput = new FileInputStream(new File(localproperties.getProperty(TEMPORARY_OUTPUT_FOLDER) + execution.getFileNameOnDisc() + SUFFIX))) { + + XSSFWorkbook workbookRef = new XSSFWorkbook(fileInput); + XSSFWorkbook workbookGen = new XSSFWorkbook(fileOutput); + DataFormatter df = new DataFormatter(); + + + softAssert.assertThat(workbookRef.getNumberOfSheets()).isEqualTo(workbookGen.getNumberOfSheets()); + for (int h = 0; h < workbookGen.getNumberOfSheets() && h < workbookRef.getNumberOfSheets(); h++) { + // Un fichier excel est composé de plusieurs feuilles, on y accède de la manière suivante + XSSFSheet sheetRef = workbookRef.getSheetAt(h); + XSSFSheet sheetGen = workbookGen.getSheetAt(h); + for (int i = 0; i <= sheetRef.getLastRowNum(); i++) { + XSSFRow rowRef = sheetRef.getRow(i); + XSSFRow rowGen = sheetGen.getRow(i); + for (int j = 0; j <= rowRef.getLastCellNum(); j++) { + XSSFCell cellRef = rowRef.getCell(j); + XSSFCell cellGen = rowGen.getCell(j); + softAssert.assertThat(df.formatCellValue(cellGen)).isEqualTo(df.formatCellValue(cellRef)); + } + } + } + } + softAssert.assertAll(); + } +} diff --git a/kurt-utility/src/val/java/com/capgemini/reports/definition/r22report/Test_R22.java b/kurt-utility/src/val/java/com/capgemini/reports/definition/r22report/Test_R22.java new file mode 100644 index 0000000..76ee2e8 --- /dev/null +++ b/kurt-utility/src/val/java/com/capgemini/reports/definition/r22report/Test_R22.java @@ -0,0 +1,98 @@ +package com.capgemini.reports.definition.r22report; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.InvalidConfigurationException; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.exceptions.NoTeamcenterConnectionException; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.reports.builder.R22Builder; +import com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum; +import com.capgemini.reports.execution.strategies.ImmediateExecutionStrategy; +import com.lowagie.text.pdf.PdfReader; +import com.lowagie.text.pdf.parser.PdfTextExtractor; +import lombok.extern.slf4j.Slf4j; +import org.assertj.core.api.SoftAssertions; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Parameters; +import org.testng.annotations.Test; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + + +@Slf4j +public class Test_R22 { + private static final TcSession session = new TcSession(); + private SoftAssertions softAssert = new SoftAssertions(); + // Dossier parent du fichier de référence + private static final String INPUT_FOLDER = "com.capgemini.report.location.default.input"; + // Sous-dossier du fichier de référence + private static final String SPECIFIC_INPUT_FOLDER = "r22"; + // Dossier de stockage temporaire des fichiers générés initialement + private static final String TEMPORARY_OUTPUT_FOLDER = "com.capgemini.report.location.default.output"; + private static final PolicyLocation XML_POLICY = PolicyLocation.make("test_policy", "/xml/policies/r22report/R22_policy_full.xml"); + public static final String SUFFIX = ".pdf"; + public Properties localproperties; + + + @BeforeClass + public void login() throws NoTeamcenterConnectionException, InvalidConfigurationException, IOException { + session.login(); + session.setObjectPropPolicy(XML_POLICY); + localproperties = new Properties(); + localproperties.load(getClass().getResourceAsStream("/reporting.properties")); + } + + @AfterClass + public void logout() { + session.close(); + } + + @BeforeMethod + //TODO : Supprimer pdf files dans Generated, checker Tempfile TempDirectory + + + @Parameters({"partID", "partRevisionID", "refFile"}) + @Test + public void test22(String partID, String partRevisionID, String refFile) throws KurtException, IOException { + + // Génération du rapport de test + Map data = new HashMap<>(); + data.put(ReportCriteriaEnum.PART_ID, partID); + data.put(ReportCriteriaEnum.PART_REVISION, partRevisionID); + ExecutionR22 execution = new R22Builder().build(data); + new DataReportPreparatorR22().print(session, execution, new ImmediateExecutionStrategy()); + + + PdfReader readerRef = new PdfReader(localproperties.getProperty(INPUT_FOLDER) + SPECIFIC_INPUT_FOLDER + "/" + refFile); + PdfReader readerGen = new PdfReader(localproperties.getProperty((TEMPORARY_OUTPUT_FOLDER)) + execution.getFileNameOnDisc() + SUFFIX); + + String stringUncheckable = ".*[0-9]{1,2}\\s[a-z]{3,9}\\s[0-9]{4}.*"; + + try { + softAssert.assertThat(readerRef.getNumberOfPages()).isEqualTo(readerGen.getNumberOfPages()); + for (int i = 1; i < readerRef.getNumberOfPages(); i++) { + String textFromPageRef = new PdfTextExtractor(readerRef).getTextFromPage(i); + String textFromPageGen = new PdfTextExtractor(readerGen).getTextFromPage(i); + String[] tableauTextGen = textFromPageGen.split("\n"); + String[] tableauTextRef = textFromPageRef.split("\n"); + for (int j = 0; j < tableauTextGen.length; j++) { + if (tableauTextGen[j].matches(stringUncheckable) && tableauTextRef[j].matches(stringUncheckable)) { + // Dates of R22 reports are not compared + continue; + } + softAssert.assertThat(tableauTextGen[j]).isEqualTo(tableauTextRef[j]); + } + } + } + finally { + readerGen.close(); + readerRef.close(); + } + softAssert.assertAll(); + } +} diff --git a/kurt-utility/src/val/java/com/capgemini/reports/definition/r23report/Test_R23.java b/kurt-utility/src/val/java/com/capgemini/reports/definition/r23report/Test_R23.java new file mode 100644 index 0000000..0fcbc2c --- /dev/null +++ b/kurt-utility/src/val/java/com/capgemini/reports/definition/r23report/Test_R23.java @@ -0,0 +1,130 @@ +package com.capgemini.reports.definition.r23report; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.InvalidConfigurationException; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.exceptions.NoTeamcenterConnectionException; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.reports.builder.R23Builder; +import com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum; +import com.capgemini.reports.execution.strategies.ImmediateExecutionStrategy; +import lombok.extern.slf4j.Slf4j; +import net.lingala.zip4j.core.ZipFile; +import net.lingala.zip4j.exception.ZipException; +import org.apache.poi.ss.usermodel.DataFormatter; +import org.apache.poi.xssf.usermodel.XSSFCell; +import org.apache.poi.xssf.usermodel.XSSFRow; +import org.apache.poi.xssf.usermodel.XSSFSheet; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.assertj.core.api.SoftAssertions; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Optional; +import org.testng.annotations.Parameters; +import org.testng.annotations.Test; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; + + +@Slf4j +public class Test_R23 { + private static final TcSession session = new TcSession(); + private SoftAssertions softAssert = new SoftAssertions(); + private static final String INPUT_FOLDER = "com.capgemini.report.location.default.input"; + private static final String SPECIFIC_INPUT_FOLDER = "r23"; + private static final String TEMPORARY_OUTPUT_FOLDER = "com.capgemini.report.location.default.output"; + private static final String SUFFIX = ".zip"; + private static final PolicyLocation XML_POLICY = PolicyLocation.make("test_policy", "/xml/policies/r23report/R23_policy_full.xml"); + private Properties localproperties; + + + @BeforeClass + public void login() throws NoTeamcenterConnectionException, InvalidConfigurationException, IOException { + session.login(); + session.setObjectPropPolicy(XML_POLICY); + localproperties = new Properties(); + localproperties.load(getClass().getResourceAsStream("/reporting.properties")); + } + + @AfterClass + public void logout() { + session.close(); + } + + //@BeforeMethod + //TODO : Supprimer xls files dans Generated, checker Tempfile TempDirectory + + + @Parameters({"productID", "monomulti", "effectivityDate", "genericAssemb", "generic", "refFile"}) + @Test + public void test23(String productID, String monomulti, @Optional String + effectivityDate, @Optional String genericAssemb, @Optional String generic, String refFile) throws + KurtException, IOException, ZipException { + // Génération du rapport de test + Map data = new HashMap<>(); + data.put(ReportCriteriaEnum.PRODUCT, productID); + data.put(ReportCriteriaEnum.MONO_MULTI, monomulti); + data.put(ReportCriteriaEnum.GENERIC, generic); + data.put(ReportCriteriaEnum.GENERIC_ASSEMB, genericAssemb); + data.put(ReportCriteriaEnum.EFFECTIVITY_DATE, effectivityDate); + + ExecutionR23 execution = new R23Builder().build(data); + new DataReportPreparatorR23().print(session, execution, new ImmediateExecutionStrategy()); + + List excelListRef = new ArrayList<>(); + List excelListGen = new ArrayList<>(); + + Path tempDirGenerated = Files.createTempDirectory("tempfilesGenerated"); + Path tempDirReferenced = Files.createTempDirectory("tempfilesReferenced"); + + + ZipFile sourceGen = new ZipFile(localproperties.getProperty(TEMPORARY_OUTPUT_FOLDER) + execution.getFileNameOnDisc() + SUFFIX); + sourceGen.extractAll(tempDirGenerated.toString()); + + ZipFile sourceRef = new ZipFile(localproperties.getProperty(INPUT_FOLDER) + SPECIFIC_INPUT_FOLDER + "/" + refFile); + sourceRef.extractAll(tempDirReferenced.toString()); + + + for (File fileInList : tempDirReferenced.toFile().listFiles()) { + try (FileInputStream fileInput = new FileInputStream(fileInList)) { + excelListRef.add(new XSSFWorkbook(fileInput)); + } + } + + for (File fileOutList : tempDirGenerated.toFile().listFiles()) { + try (FileInputStream fileOutput = new FileInputStream(fileOutList)) { + excelListGen.add(new XSSFWorkbook(fileOutput)); + } + } + + softAssert.assertThat(excelListGen.size()).isEqualTo(excelListRef.size()); + for (int a = 0; a < excelListGen.size() && a < excelListRef.size(); a++) { + if (excelListGen.get(a).getNumberOfSheets() == excelListRef.get(a).getNumberOfSheets()) { + for (int b = 0; b < excelListGen.get(a).getNumberOfSheets(); b++) { + XSSFSheet sheetRef = excelListRef.get(a).getSheetAt(b); + XSSFSheet sheetGen = excelListGen.get(a).getSheetAt(b); + DataFormatter df = new DataFormatter(); + for (int i = 1; i < sheetRef.getLastRowNum(); i++) { + XSSFRow rowRef = sheetRef.getRow(i); + XSSFRow rowGen = sheetGen.getRow(i); + for (int j = 0; j < rowRef.getLastCellNum(); j++) { + XSSFCell cellRef = rowRef.getCell(j); + XSSFCell cellGen = rowGen.getCell(j); + softAssert.assertThat(df.formatCellValue(cellGen)).isEqualTo(df.formatCellValue(cellRef)); + } + } + } + } + } + softAssert.assertAll(); + } +} diff --git a/kurt-utility/src/val/java/com/capgemini/reports/definition/r24report/Test_R24.java b/kurt-utility/src/val/java/com/capgemini/reports/definition/r24report/Test_R24.java new file mode 100644 index 0000000..f542d29 --- /dev/null +++ b/kurt-utility/src/val/java/com/capgemini/reports/definition/r24report/Test_R24.java @@ -0,0 +1,138 @@ +package com.capgemini.reports.definition.r24report; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.InvalidConfigurationException; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.exceptions.NoTeamcenterConnectionException; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.reports.builder.R24Builder; +import com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum; +import com.capgemini.reports.execution.strategies.ImmediateExecutionStrategy; +import lombok.extern.slf4j.Slf4j; +import net.lingala.zip4j.core.ZipFile; +import net.lingala.zip4j.exception.ZipException; +import org.apache.poi.ss.usermodel.DataFormatter; +import org.apache.poi.xssf.usermodel.XSSFCell; +import org.apache.poi.xssf.usermodel.XSSFRow; +import org.apache.poi.xssf.usermodel.XSSFSheet; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.assertj.core.api.SoftAssertions; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Parameters; +import org.testng.annotations.Test; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; + + +@Slf4j +public class Test_R24 { + private static final TcSession session = new TcSession(); + private SoftAssertions softAssert = new SoftAssertions(); + private static final String INPUT_FOLDER = "com.capgemini.report.location.default.input"; + private static final String SPECIFIC_INPUT_FOLDER = "r24"; + private static final String TEMPORARY_OUTPUT_FOLDER = "com.capgemini.report.location.default.output"; + private static final String SUFFIX = ".zip"; + private static final PolicyLocation XML_POLICY = PolicyLocation.make("test_policy", "/xml/policies/r24report/R24_policy_full.xml"); + private Properties localproperties; + + + @BeforeClass + public void login() throws NoTeamcenterConnectionException, InvalidConfigurationException, IOException { + session.login(); + session.setObjectPropPolicy(XML_POLICY); + localproperties = new Properties(); + localproperties.load(getClass().getResourceAsStream("/reporting.properties")); + } + + @AfterClass + public void logout() { + session.close(); + } + + //@BeforeMethod + //TODO : Supprimer xls files dans Generated, checker Tempfile TempDirectory + + + @Parameters({"productID", "unit", "typeImpr", "language", "refFile"}) + @Test + public void test24(String productID, String unit, String typeImpr, String language, String refFile) throws + KurtException, IOException, ZipException { + // Génération du rapport de test + Map data = new HashMap<>(); + data.put(ReportCriteriaEnum.PRODUCT, productID); + data.put(ReportCriteriaEnum.UNIT, unit); + data.put(ReportCriteriaEnum.TYPE_IMPRESSION, typeImpr); + data.put(ReportCriteriaEnum.LANGUAGE, language); + + ExecutionR24 execution = (ExecutionR24) new R24Builder().build(data); + new DataReportPreparatorR24().print(session, execution, new ImmediateExecutionStrategy()); + + List excelListRef = new ArrayList<>(); + List excelListGen = new ArrayList<>(); + + Path tempDirGenerated = Files.createTempDirectory("tempfilesGenerated"); + Path tempDirReferenced = Files.createTempDirectory("tempfilesReferenced"); + + + ZipFile sourceGen = new ZipFile(localproperties.getProperty(TEMPORARY_OUTPUT_FOLDER) + execution.getFileNameOnDisc() + SUFFIX); + sourceGen.extractAll(tempDirGenerated.toString()); + + ZipFile sourceRef = new ZipFile(localproperties.getProperty(INPUT_FOLDER) + SPECIFIC_INPUT_FOLDER + "/" + refFile); + sourceRef.extractAll(tempDirReferenced.toString()); + + + for (File fileInList : tempDirReferenced.toFile().listFiles()) { + try (FileInputStream fileInput = new FileInputStream(fileInList)) { + excelListRef.add(new XSSFWorkbook(fileInput)); + } + } + + for (File fileOutList : tempDirGenerated.toFile().listFiles()) { + try (FileInputStream fileOutput = new FileInputStream(fileOutList)) { + excelListGen.add(new XSSFWorkbook(fileOutput)); + } + } + + softAssert.assertThat(excelListGen.size()).isEqualTo(excelListRef.size()); + for (int a = 0; a < excelListGen.size() && a < excelListRef.size(); a++) { + if (excelListGen.get(a).getNumberOfSheets() == excelListRef.get(a).getNumberOfSheets()) { + for (int b = 0; b < excelListGen.get(a).getNumberOfSheets(); b++) { + XSSFSheet sheetRef = excelListRef.get(a).getSheetAt(b); + XSSFSheet sheetGen = excelListGen.get(a).getSheetAt(b); + DataFormatter df = new DataFormatter(); + for (int i = 1; i < sheetRef.getLastRowNum(); i++) { + XSSFRow rowRef = sheetRef.getRow(i); + XSSFRow rowGen = sheetGen.getRow(i); + for (int j = 0; j < rowRef.getLastCellNum(); j++) { + XSSFCell cellRef = rowRef.getCell(j); + XSSFCell cellGen = rowGen.getCell(j); + softAssert.assertThat(df.formatCellValue(cellGen)).isEqualTo(df.formatCellValue(cellRef)); + } + } + } + } + } + softAssert.assertAll(); + } +} + + + + + + + + + + + diff --git a/kurt-utility/src/val/java/com/capgemini/reports/definition/r25report/Test_R25.java b/kurt-utility/src/val/java/com/capgemini/reports/definition/r25report/Test_R25.java new file mode 100644 index 0000000..2bab021 --- /dev/null +++ b/kurt-utility/src/val/java/com/capgemini/reports/definition/r25report/Test_R25.java @@ -0,0 +1,161 @@ +package com.capgemini.reports.definition.r25report; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.InvalidConfigurationException; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.exceptions.NoTeamcenterConnectionException; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.reports.builder.R25Builder; +import com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum; +import com.capgemini.reports.execution.strategies.ImmediateExecutionStrategy; +import lombok.extern.slf4j.Slf4j; +import net.lingala.zip4j.core.ZipFile; +import net.lingala.zip4j.exception.ZipException; +import org.apache.poi.ss.usermodel.DataFormatter; +import org.apache.poi.xssf.usermodel.XSSFCell; +import org.apache.poi.xssf.usermodel.XSSFRow; +import org.apache.poi.xssf.usermodel.XSSFSheet; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.assertj.core.api.SoftAssertions; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Optional; +import org.testng.annotations.Parameters; +import org.testng.annotations.Test; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + + +@Slf4j +public class Test_R25 { + private static final TcSession session = new TcSession(); + private SoftAssertions softAssert = new SoftAssertions(); + private static final String ZIP_INPUT_FOLDER = "com.capgemini.report.location.default.input"; + private static final String TEMPORARY_OUTPUT_FOLDER = "com.capgemini.report.location.default.output"; + private static final String SUFFIX = ".zip"; + private static final PolicyLocation XML_POLICY = PolicyLocation.make("test_policy", "/xml/policies/r25report/R25_policy_full.xml"); + private Properties localproperties; + + + @BeforeClass + public void login() throws NoTeamcenterConnectionException, InvalidConfigurationException, IOException { + session.login(); + session.setObjectPropPolicy(XML_POLICY); + localproperties = new Properties(); + localproperties.load(getClass().getResourceAsStream("/reporting.properties")); + } + + @AfterClass + public void logout() { + session.close(); + } + + + @Parameters({"productID", "unit", "typeImpression", "language", "refFile"}) + @Test + public void test25(String productID, @Optional String unit, String typeImpression, String language, String refFile) throws + KurtException, IOException, ZipException { + // Génération du rapport de test + Map data = new HashMap<>(); + data.put(ReportCriteriaEnum.PRODUCT, productID); + data.put(ReportCriteriaEnum.UNIT, unit); + data.put(ReportCriteriaEnum.TYPE_IMPRESSION, typeImpression); + data.put(ReportCriteriaEnum.LANGUAGE, language); + + ExecutionR25 execution = (ExecutionR25) new R25Builder().build(data); + new DataReportPreparatorR25().print(session, execution, new ImmediateExecutionStrategy()); + + + ArrayList excelListRef = new ArrayList<>(); + ArrayList excelListGen = new ArrayList<>(); + Path tempDirZipGenerated = Files.createTempDirectory("tempfilesZipGenerated"); + Path tempDirExcelGenerated = Files.createTempDirectory("tempfilesExcelGenerated"); + Path tempDirExcelReferenced = Files.createTempDirectory("tempfilesExcelReferenced"); + Path tempDirZipReferenced = Files.createTempDirectory("tempfilesZipReferenced"); + + DataFormatter df = new DataFormatter(); + + // Extraction du Zip parent Fichier Generated + ZipFile sourceGen2 = new ZipFile(localproperties.getProperty(TEMPORARY_OUTPUT_FOLDER) + execution.getFileNameOnDisc() + SUFFIX); + sourceGen2.extractAll(tempDirZipGenerated.toString()); + + // Extraction des Zips enfants Fichier Generated + + for (File aFileGen : tempDirZipGenerated.toFile().listFiles()) { + ZipFile sourceGen = new ZipFile(String.valueOf(aFileGen)); + sourceGen.extractAll(tempDirExcelGenerated.toString()); + } + + + System.out.println("<------------- FICHIERS GENERES ------------------>"); + + + // Extraction des données Excel du Fichier Generated + for (File fileListExcelGen : tempDirExcelGenerated.toFile().listFiles()) { + if (fileListExcelGen.getAbsolutePath().endsWith(".xlsx")) { + System.out.println("NOM DU FICHIER GENERE: " + fileListExcelGen); + FileInputStream fileInput = new FileInputStream( + new File(String.valueOf(fileListExcelGen))); + XSSFWorkbook workbookGen = new XSSFWorkbook(fileInput); + excelListGen.add(workbookGen); + } + } + + // Extraction du Zip parent Fichier Referenced + ZipFile sourceRef2 = new ZipFile(localproperties.getProperty(ZIP_INPUT_FOLDER) + "/r25/" + refFile); + sourceRef2.extractAll(tempDirZipReferenced.toString()); + + // Extraction des Zips enfants Fichier Referenced + for (File aFileRef : tempDirZipReferenced.toFile().listFiles()) { + ZipFile sourceRef = new ZipFile(String.valueOf(aFileRef)); + sourceRef.extractAll(tempDirExcelReferenced.toString()); + } + + System.out.println("<------------- FICHIERS DE REFERENCE ------------------>"); + + // Extraction des données Excel du Fichier Referenced + for (File fileListExcelRef : tempDirExcelReferenced.toFile().listFiles()) { + if (fileListExcelRef.getAbsolutePath().endsWith(".xlsx")) { + System.out.println("NOM DU FICHIER DE REFERENCE: " + fileListExcelRef); + FileInputStream fileInput = new FileInputStream( + new File(String.valueOf(fileListExcelRef))); + XSSFWorkbook workbookRef = new XSSFWorkbook(fileInput); + excelListRef.add(workbookRef); + } + } + + softAssert.assertThat(excelListGen.size()).isEqualTo(excelListRef.size()); + for (int a = 0; a < excelListGen.size() && a < excelListRef.size(); a++) { + if (excelListGen.get(a).getNumberOfSheets() == excelListRef.get(a).getNumberOfSheets()) { + for (int b = 0; b < excelListGen.get(a).getNumberOfSheets(); b++) { + System.out.println(excelListRef.get(a)); + System.out.println(excelListGen.get(a)); + System.out.println("WORKBOOKREF = " + excelListRef.get(a).getCTWorkbook()); + System.out.println("WORKBOOKGEN = " + excelListGen.get(a).getCTWorkbook()); + XSSFSheet sheetRef = excelListRef.get(a).getSheetAt(b); + XSSFSheet sheetGen = excelListGen.get(a).getSheetAt(b); + for (int i = 2; i < sheetRef.getLastRowNum(); i++) { + XSSFRow rowRef = sheetRef.getRow(i); + XSSFRow rowGen = sheetGen.getRow(i); + for (int j = 0; j < rowRef.getLastCellNum(); j++) { + XSSFCell cellRef = rowRef.getCell(j); + XSSFCell cellGen = rowGen.getCell(j); + System.out.println(cellRef.getReference()); + System.out.println(cellGen.getReference()); + softAssert.assertThat(df.formatCellValue(cellGen)).isEqualTo(df.formatCellValue(cellRef)); + } + } + } + } + } + softAssert.assertAll(); + } +} \ No newline at end of file diff --git a/kurt-utility/src/val/java/compare/Comparer_XML.java b/kurt-utility/src/val/java/compare/Comparer_XML.java new file mode 100644 index 0000000..4454aa7 --- /dev/null +++ b/kurt-utility/src/val/java/compare/Comparer_XML.java @@ -0,0 +1,112 @@ +package compare; + +import javax.xml.parsers.DocumentBuilderFactory; + +import com.capgemini.framework.teamcenter.authent.AuthentPropLoader; +import lombok.val; +import org.w3c.dom.*; +import org.xml.sax.SAXException; +import javax.xml.parsers.*; +import javax.xml.transform.*; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; +import java.io.File; +import java.io.IOException; + + + +public class Comparer_XML { + + private static String URLXmlComp = AuthentPropLoader.getString("com.capgemini.report.location.default.outputXml");; + + + public static void writerFile(String entry, CriteresComparaison criteresComparaison){ + + String filePath = entry; + File xmlFile = new File(filePath); + DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder dBuilder; + try { + dBuilder = dbFactory.newDocumentBuilder(); + Document doc = dBuilder.parse(xmlFile); + doc.getDocumentElement().normalize(); + NodeList node = doc.getElementsByTagName("TestUnitaire"); + Element rap = null; + Element plateforme; + Element report; + Element typeFile; + Element UseCase; + Element nameFileWithDate; + Element locationFileReference; + Element nameSheetFileReference; + + for (int i = 0; i < node.getLength(); i++) { + rap = (Element) node.item(i); + plateforme = doc.createElement("plateforme"); + plateforme.setAttribute("name",criteresComparaison.getPlateforme()); + report = doc.createElement("report"); + report.setAttribute("id",criteresComparaison.getReport()); + typeFile = doc.createElement("typeFile"); + typeFile.setAttribute("name",criteresComparaison.getTypeFile()); + UseCase = doc.createElement("UseCase"); + UseCase.setAttribute("id",criteresComparaison.getUseCase()); + nameFileWithDate = doc.createElement("nameFileWithDate"); + nameFileWithDate.appendChild(doc.createTextNode(criteresComparaison.getNameFileWithDate())); + locationFileReference = doc.createElement("locationFileGenerated"); + locationFileReference.appendChild(doc.createTextNode(criteresComparaison.getLocationFileReference())); + nameSheetFileReference = doc.createElement("nameSheetFileGenerated"); + nameSheetFileReference.appendChild(doc.createTextNode(criteresComparaison.getNameSheetFileReference())); + UseCase.appendChild(nameFileWithDate); + UseCase.appendChild(locationFileReference); + UseCase.appendChild(nameSheetFileReference); + typeFile.appendChild(UseCase); + report.appendChild(typeFile); + plateforme.appendChild(report); + rap.appendChild(plateforme); + + } + + doc.getDocumentElement().normalize(); + TransformerFactory transformerFactory = TransformerFactory.newInstance(); + Transformer transformer = transformerFactory.newTransformer(); + DOMSource source = new DOMSource(doc); + StreamResult result = new StreamResult(new File(URLXmlComp)); + transformer.setOutputProperty(OutputKeys.INDENT, "yes"); + transformer.transform(source, result); + + + } catch (ParserConfigurationException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } catch (SAXException e) { + e.printStackTrace(); + } catch (TransformerConfigurationException e) { + e.printStackTrace(); + } catch (TransformerException e) { + e.printStackTrace(); + } + } + + + public static void creerEntry(String nomEntre) { + + try { + DocumentBuilderFactory XML_Comparaison = DocumentBuilderFactory.newInstance(); + DocumentBuilder XML_Comp = XML_Comparaison.newDocumentBuilder(); + Document XML_Document = XML_Comp.newDocument(); + Element TestUnitaire = XML_Document.createElement("TestUnitaire"); + XML_Document.appendChild(TestUnitaire); + TransformerFactory XMLTransformeur = TransformerFactory.newInstance(); + Transformer XML_Transformeur = XMLTransformeur.newTransformer(); + DOMSource source = new DOMSource(XML_Document); + StreamResult resultat = new StreamResult(new File(nomEntre)); + XML_Transformeur.transform(source, resultat); + } catch (ParserConfigurationException pce) { + pce.printStackTrace(); + } catch (TransformerException tfe) { + tfe.printStackTrace(); + } + } + +} diff --git a/kurt-utility/src/val/java/compare/CriteresComparaison.java b/kurt-utility/src/val/java/compare/CriteresComparaison.java new file mode 100644 index 0000000..123262a --- /dev/null +++ b/kurt-utility/src/val/java/compare/CriteresComparaison.java @@ -0,0 +1,54 @@ +package compare; + +/** + * Created by mfarouj on 21/06/2017. + */ +public class CriteresComparaison { + + String plateforme; + String report; + String typeFile; + String UseCase; + String nameFileWithDate; + String locationFileReference; + String nameSheetFileReference; + + public CriteresComparaison(String plateforme, String report, String typeFile, String useCase, + String nameFileWithDate, String locationFileReference, String nameSheetFileReference) { + this.plateforme = plateforme; + this.report = report; + this.typeFile = typeFile; + UseCase = useCase; + this.nameFileWithDate = nameFileWithDate; + this.locationFileReference = locationFileReference; + this.nameSheetFileReference = nameSheetFileReference; + } + + public String getPlateforme() { + return plateforme; + } + + public String getReport() { + return report; + } + + public String getTypeFile() { + return typeFile; + } + + public String getUseCase() { + return UseCase; + } + + public String getNameFileWithDate() { + return nameFileWithDate; + } + + public String getLocationFileReference() { + return locationFileReference; + } + + public String getNameSheetFileReference() { + return nameSheetFileReference; + } +} diff --git a/kurt-utility/src/val/java/compare/ExcelTest.java b/kurt-utility/src/val/java/compare/ExcelTest.java new file mode 100644 index 0000000..6cf8d63 --- /dev/null +++ b/kurt-utility/src/val/java/compare/ExcelTest.java @@ -0,0 +1,152 @@ +/* +package compare; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.InvalidConfigurationException; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.exceptions.NoTeamcenterConnectionException; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.reports.builder.R01Builder; +import com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum; +import com.capgemini.reports.execution.strategies.ImmediateExecutionStrategy; +import lombok.extern.slf4j.Slf4j; +import org.apache.poi.ss.usermodel.DataFormatter; +import org.apache.poi.xssf.usermodel.XSSFCell; +import org.apache.poi.xssf.usermodel.XSSFRow; +import org.apache.poi.xssf.usermodel.XSSFSheet; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.testng.annotations.*; +import org.testng.annotations.Optional; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.*; + +import static org.assertj.core.api.Assertions.assertThat; + + +@Slf4j +public abstract class ExcelTest { + private static final TcSession session = new TcSession(); + // Dossier parent du fichier de référence + private static final String INPUT_FOLDER = "com.capgemini.report.location.default.input"; + // Sous-dossier du fichier de référence + private static final String SPECIFIC_INPUT_FOLDER = ""; + // Dossier de stockage temporaire des fichiers générés initialement + private static final String TEMPORARY_OUTPUT_FOLDER = "com.capgemini.report.location.default.output"; + // Dossier de stockage final des fichiers + private static final String RECORDS_FOLDER = "com.capgemini.report.location.default.records"; + // Type de fichier traités + private static final String SUFFIX = ""; + private static final PolicyLocation XML_POLICY = + PolicyLocation.make("test_policy", "/test_policy.xml"); + private Properties localproperties; + + + @BeforeClass + public void login() throws NoTeamcenterConnectionException, InvalidConfigurationException, IOException { + session.login(); + session.setObjectPropPolicy(XML_POLICY); + localproperties = new Properties(); + localproperties.load(getClass().getResourceAsStream("/reporting.properties")); + } + + @AfterClass + public void logout() { + session.close(); + } + + //@BeforeMethod + //TODO : Supprimer xls files dans Generated, checker Tempfile TempDirectory + + + @Parameters({"productID", "unit", "monomulti", "effectivityDate", "genericAssemb", "generic", "refFile"}) + @Test + public void test01 (String productID, Integer unit, String monomulti, @Optional String + effectivityDate, @Optional String genericAssemb, @Optional String generic, String refFile) throws + KurtException, IOException { + // Génération du rapport de test + Map data = new HashMap<>(); + data.put(ReportCriteriaEnum.PRODUCT, productID); + data.put(ReportCriteriaEnum.UNIT, unit.toString()); + data.put(ReportCriteriaEnum.MONO_MULTI, monomulti); + data.put(ReportCriteriaEnum.GENERIC, generic); + data.put(ReportCriteriaEnum.GENERIC_ASSEMB, genericAssemb); + data.put(ReportCriteriaEnum.EFFECTIVITY_DATE, effectivityDate); + + ExecutionR01 execution = new R01Builder().build(data); + String print = new DataReportPreparatorR01().print(session, execution, new ImmediateExecutionStrategy()); + + FileInputStream fileInput = new FileInputStream( + new File(localproperties.getProperty(INPUT_FOLDER) + "/" + SPECIFIC_INPUT_FOLDER + "/" + refFile)); + XSSFWorkbook workbookRef = new XSSFWorkbook(fileInput); + + File generatedFile = new File(localproperties.getProperty(TEMPORARY_OUTPUT_FOLDER) + execution.getFileNameOnDisc() + SUFFIX); + FileInputStream fileOutput = new FileInputStream(generatedFile); + XSSFWorkbook workbookGen = new XSSFWorkbook(fileOutput); + + if (workbookRef.getNumberOfSheets() == workbookGen.getNumberOfSheets()) { + for (int h = 0; h < workbookGen.getNumberOfSheets() && h < workbookRef.getNumberOfSheets(); h++) { + // Un fichier excel est composé de plusieurs feuilles, on y accède de la manière suivante + XSSFSheet sheetRef = workbookRef.getSheetAt(h); + XSSFSheet sheetGen = workbookRef.getSheetAt(h); + DataFormatter df = new DataFormatter(); + for (int i = 2; i < sheetRef.getLastRowNum(); i++) { + XSSFRow rowRef = sheetRef.getRow(i); + XSSFRow rowGen = sheetGen.getRow(i); + for (int j = 0; j < rowRef.getLastCellNum(); j++) { + XSSFCell cellRef = rowRef.getCell(j); + XSSFCell cellGen = rowGen.getCell(j); + assertThat(df.formatCellValue(cellGen)).isEqualTo(df.formatCellValue(cellRef)); + } + } + } + } + move(generatedFile); + } + + private void move (File file) { + file.renameTo(new File (localproperties.getProperty(RECORDS_FOLDER) + SPECIFIC_INPUT_FOLDER + "/" + file.getName())); + System.out.println("File is moved successfully!"); + } +} + + + + +*/ +/* for (int i = 2; i < sheetRef.getLastRowNum() + 1; i++) { + Cell cell = sheetRef.getRow(i).getCell(i); + if (df.formatCellValue(cell).equals(df.formatCellValue(sheetGen.getRow(i).getCell(0)))) + { //If cell is the same value as the one in the row below it + System.out.println("Test réussi"); + } else + {//If cell has a different value as the one in the row below it + System.out.println("Test échec"); + } + }*//* + + + +*/ +/* for (int i = 0; i < sheetRef.getPhysicalNumberOfRows(); i++) { + assertThat(sheetRef.getRow(i).equals(sheetGen.getRow(i))).isTrue(); + }*//* + + +*/ +/* + List sheetNamesRef = new ArrayList(); + List sheetNamesGen = new ArrayList(); + for (int i=0; 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 U0l>pYKtO{3*x=2t4(Mq0A1p}pssI20 literal 0 HcmV?d00001 diff --git a/kurt-utility/src/val/resources/FolderFilesReferenced/r01/r01.xlsx:Zone.Identifier b/kurt-utility/src/val/resources/FolderFilesReferenced/r01/r01.xlsx:Zone.Identifier new file mode 100644 index 0000000..a45e1ac --- /dev/null +++ b/kurt-utility/src/val/resources/FolderFilesReferenced/r01/r01.xlsx:Zone.Identifier @@ -0,0 +1,2 @@ +[ZoneTransfer] +ZoneId=3 diff --git a/kurt-utility/src/val/resources/FolderFilesReferenced/r03/r03.xlsx b/kurt-utility/src/val/resources/FolderFilesReferenced/r03/r03.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..a6584877bfd94ea9addff805a489966e3a5dd313 GIT binary patch literal 15745 zcma)j1z1$;_P(MB(kdlw&;lymEdr9t08)DB9AfBFDFFd#9dZCc89Id_q&r4(7`kKV z27&(`Jok6bJ(qi*|Mv00Ei-$4Yke!;cYS-QD_^-vehD8R{}R6Uqi2`?c98=AcC+De z1v^^*0R~%hyV=@=MJQW0JS6j9Kc&dVpY3n8gOMAHev;^uwR+|$kX;%spM%HAZ+qq) zD|9*fxt(aIPjNA7OPkmPZ!rTYtU~#SIaTjo#`x^c_RQf?GIuE3@uTl2kIiT!3-S$A zJ=bm9KUsUKk8*v$rBCcmotAhy`q2EwcYEeSXwSG@Y4}osb&lhH5}nwq0LK<|?FOl7og~CwUanQ>W*5b5$^0PAPDVJGU6`7) zPys*lG12#%_qtWRSW=^D8bv0}x2O+6f?9`L{V^*+L;ID%3I3GZZApg%If=}-6Fwea zF|WYvsNXobqOOdG&+b0IehL^S_41`l>i^Yr#J^4F1aY@9b;25M0Hh2?KP0Nz*T%2R zS9+W}d=1@1$<*-1maUg)QLE5G?<+&#eRDlspd z596%0rVr6bE}78+K&2j#;<>np3@phbI7F{?Z^&hUhqPY5HP5MwU zOdv`m9~w72e#uloNKu-y7)22o!-;A5CY_g29PR&eDG*?sC2NTAC4?83xjfz zUiv@@D8O4vk3;OFqJ^TAa)fEY-Tll$EP?H$0gJt;fv@LHEd#iBJB9t;Nk@il)pxBNHm<)?9wT)yYrO z_r2tvaI@BluSp%=_j*@TBpjvu!jH^V<)cei-&7h4Qrm?*df_Vus*&o=v&V=Fj=efp z|4=cLHl4noJFFAA=lzlPAzY}k$oWgeNqw8y>hsRePx@EH7CtXbe_HtU!|8P24TLLx zUs{rQb*R8;MouYL9E``rDUB1+P}%=$t0F4_BL76-`8`f~3x1((KDn4kU1l4)@9FJfxO z+2iZZ4do+YUmy4qSBuvwxjLNQ`^xQe8S9iyc#yo8IF~Lx!T(=QN%Pw&jT}vFoc=AU zxv~F~`?1Xm2yLnLQ-VkPIxeIz@{St+clo*!Qmr$%dW6uny?u@Amb4bIpyWW*xLBqY zx62LI4}9)fshxymiyzim1lfcz6WaN`{ko-1@=i1`2ZH-Q!|&nVb8?H0>UJY1R)^%jYL@r;Y~?n5!eyB_JG!JM$ulb2~g)B$fC9Xqo&! zgYy>f2|Zb`9mLcQV)Vk@-qgte8=|?<9d`8($>sLF0_M2x26AU-E4@Ot6s^AVd9yNl zpWCNxsOq$)>@7$}QTIoC@IvzE;Cu0*Ng$Ie3}5&uk|>@l{lM2#?gQ;O9g4W8h8}*^ zU!!LVF22S&5-`bdTNe3tUPlLyg(GYi8g#I%H~(E{lX7?r;?d*JfBD%b|5@pUdou0j z76&hJw~9jB?^MPTGphw5V?Y|;qUA@-WqZs0%HrGWndYBK#_r+4m=aC{b*UT0*u)yX zJ1G$`q;(5qN{Iew+uR6wI)59J(cnNwO`od&O^B3rkser>Tq4kY!N z>PIifGAkTczp~GaR3%BvT;Jqb{Ng8oA3AJplh_6+^+p9Ch-jg;JOrM=y^$nUDz zrFn0HvMK!7^-7KU;2w?_I{rsxR)eoSO`zgbWPev`n53N-bJTZ$H-xN-xwd>@53uod^(-(3l<2$rQ$Z{b_(>&N#1T;n{BWN^MAMS zqm>P=(5L*pB&&--=e-4=>flHJ0Gt=5E@FNDkH-98L*6nsUcD~+VU0;n{Yn@0cV`pL zpSqI9&(hZeWSyIm8wGk?>wRg}&1}9DJyG5W%k#dRV?cK@gU+L+7yyl#J>G1gg^5dO zR>-BTvnx&hsy_C|ReSLM#q%7GI20k)4r&{tCgp&Z5C5kfsQ<$be_5b93GIk}8dti0 z%uZHwbcX-@+7BlMEtNNS-}AD)^H=FfYR@$IFjyyz%=^p={kE_XO8it&Yap|fcj#Ri zyx}$C#9>aAO_1{DRVv@3h_lKX#~K?KS2Q{y#mLQkjnLd_du{JzZ+@nSXL%rp*JG2h z_Sa0-1laYg^4PW*b=F{MXz#SY9Xhdhtaj$LySz3APFU$c6r%60ciUaZ>fkFKt6iaZ!M!~6OA z7#OYQ$^%^vH`d4a94_r`pIUhqR}2fgrsU`IxSoll^v6z5w+Z)~;6^?kyR3UY==bzy z7>od;kIxOaAYX~om6g@`eMIdEO8D8YAvD^T{xquUOz?~6-s>Gy;k?=8egbKHO8(x! z>iVYH@n*TVllpO&_336G0u4tTPb99aPU+Oz=kc7a92_HhT#wN!g6RF@iE!VulPNX7 z;=0Y+mZ6E-USBs@L`}i*Mm_gY{dfbR=OW=TDGw%{hfb`@{!NYj!AAX^qk3cmp~50z z3n>p>I?v8%3&mtT&xzCK4|t2Gz63*+PgM)z74%oj!0gOInxxv34XZ6i?P$_`mNN(b!~cF$Z{^rC zIs-Qp|I~?$%8WnmnD0TLCz8e{Z06PUJf`S;Xg|>6IVYx!)2B9HPeRN{@}Ct|3%e~j z)_QJssG*z5UBiY?C&$jJjv7e`|Gq$<37WNh5j?58894jCwAS?n_m5+0T@s;$g3&qgq7R_SD|| z*p$e;nbYnL)9Yi|03yMALGb7;OXPcUgSd_?dE=wS32&=BdLG~E5itg67M|j8yCk^Q zCTRtoa5ASLEx|nJ=e1j6(L5;Ta5@27lf9)T;98DOI6K>65*BWqcDh$P=6jMZOl#m< zb95AB4ss8tL=MhMd#mzGgdrQ_<%SNeeszQ(Apo-TM;1 ztTpa^O_{oSu#pb-kx+}+hSHfI?M5J0TM}kKW7j(tmu`#~WYxh>%v`A_L+w8eW*i(2 z%#DrB+Ye1yu9oLwrnY@NOREtv5vRUoG}9*wW?goP`?L!kAfYFhJ*Twk!Xt~T-6s-D zW*KFF7;X;;Dj+N}?Y*fn5dV2_dF`1qY(>%mhPJUgb%CughHlpCb+!#~;H2E!Ab%@+ zHTjOc|BpvFtoVs{?E`-Z<51!2-`&uE7eKjK*$^(e>>N0z(L#}j`}B|_QFvi{ORS14 zkAo`1jp>s(yZa5wt~q4W-pZK(2<0|whY{oJJ%|SziNGtN_rE+u3bx7(naF?PIpFywd{#w4 z7ti&gXj2M8C#|)(FU7|qy`7GfLx5ODw8WECp1Mzca8gy$%zFEcZ#cN(-UiXzdsoA6 z2uV+pzvaE!edD{-WR$_A`P!!B6wBpr7|)s^qa;^v*ZcZ-Oiub@zVTWa8B2yOQT@45 zLoj>O;=87J-sLkMC*h(P#jHYTOiD#E>+P!UIyb+ZBz|34)U5|e1LT58nzYL+zIIL? zWIjcgt-a13AA9t)4|!JBsJ1KDs46+ua1*;sui%TxPU62czN$(lBtJ>?*6AuY+4uYL zq2_zL0=a#(&PO$i%v7xpsCp*MDcId3J8Q~~!KV}O)%Y3uc2YF$(zUrLIw2Ak#bi8< zMX{2j2^xd%ccn<2RN~A=enc0!7aQlFjv_=`PO4t*w>}#(QA`^vhNg{KzrU8l6(Z`U z*;l`O3<6DPiyHwpYFk!RTzmE~_KE1G$3+_*wbE3-qG(z^q0bSfdkW0)Sf-N+tAbgD+bJddX$l5Ks8Duil`FWryScQJf-=9tx3 znd=5qlo}FsL~we@gk&bE-`={adP7KdlI|_xRqnQc=>)E%7cMPb0UHPQ#vN4P#(Twp ziv($9+}~cL6Mez(VA;NuAjxv^0c{H5-L~e)D=(v&Kiee6#O}?smJH4wq`3k+;ELUW zp5Sp6tCw#3t?dYf>@3)Ib{=;@_TbXv7c_H?l{ef1f84-n!B1qe5BYH$X8~WI$-XTQ zvtZD+#Z>AFCZ?ZI^%eO~|^X_N+_v zmX8GIEdHR01`C|Ulo|dcv(&67Dt3oYl%2z~G|+It*_7E=KC_giCH^Fq zJoZFOmX9oKwcp5g5&Ua6zxNUH73rsW+V-3plfoR9UvWi3y}=zaJ49*s-iO~2dAmrS z#{0hePUV}$C<8vqb?)My5!&C9SAxMjvbPM_Ao@*KWnMv_>0LDQ>wB+TA7b8Xfn&qT3!4f z`$BLY8u4$65`^3&u2%c_;(m+xX~yqWnM48>iPD_jb2C+%#D|BCMgQE7@0^*BuUm@@ z<|aSN`-2}nA}(yh@NC>A9I??7>e03fICwGhZG)8l*u9C~&Osa8B4lw|5z_kWwUT@7 zPt-z2sH?%|J2lHomi5b_Pt>gLCP`A@375M1Crd-FA|J`Ik|oJNt|5ixsK^Y82s04;6fKhyAN52%0pmU8M6K@xNmhoc^7|}7-+LUF=)t8=b-8nD z*gL-rz}(qCOB5vz+T1Q$0#>jDte{FXBokP{ry2vzgq9}*!_XQT5G_3Tvjq9iYe?Sr z;Y=cdi&xX0zwc%e30lNSQ+BBv#w?-b=t-(ndp52=vPdHgu!HM#m3bafs;tpL^((2R zNUXX*e~h*lTe`jeC`#pC5H+or%ASYPH1X8FZu4A&*o~2V)qp3ztC-Mcd!$kIvzpp1 zkWq=Nz+~&_;d71S{sGtrfeQpD>4@RCC`BOBYb5F1ytTbGNm@uWI&HfsksH zXv=_6KF}?+s;s*u*+sid^`Xn9QUx>lW8KY8dt6l(Wl1mwDumjW_i;f-zb6IW?HgA5 zp!#fi#5N0dz*k1@E}DBYH8YK7LxRmNYxi-#7=nyHU!EbR>3o0pRIOeDAH?vzzi4+? z8pT%x&f4-+mC$xsFlzn)2Dpw&!YUs-F*pnMov(}|Jvh2@+Jz=W(U|k0O_o;F&lfMQ zpyq0fI|L5OeXObM=L_3-$^ez#^Pa18-Tc3+BrlUH=qM_F_$`a@U)#86Bvv2(%jMLC z`|x3mYcu8Ro!0@4ycTBGWjOAnxi>wqTFtYr!FC;c#1NCb5uHheVyr4U-bf%*Rt#mO zVZMdRTAGv5OGAi|*X6RvlB6LdNL;yi%uR=$(YjY`2%#iT0T<7Pw-Yw0O{=`*UYWgy z6mZL8Z@Xx3fvO&p+hTIX__S3N5Hf2(Ra?%C6lq?)VhZZA9*)Zv9NBMe>?a&d?p^_0 zM|%5ZMyjqiMDNbEumKavO5!<~^o2=6#5gpJkG68p{$BRV-t7Jtm_1)W4c24Vm7^O} zvtL>Mk{PEs&k^aI(Ul!qTKOcdS0@H>`1NQ!6V@o{ z=tYwG_59nAx(1dh#9cOBASN1NE)JTC5UU@0$tJToUz=7PCb;doz&Fax9Ap4-Y0=S8 z$9y$;)N{h1KL(gY-Yrt6-FmNjN5pTDE{*U#H;Q>WncnVo2c@dgL`$6DSu{98c3YpV zM7zoA$dK<=xX^ntTbjx<30FDyuzNpyIM7< zJgkaK6hiX_|SU>|q^(H%hC1k#2G7;}EKHDDfjCeJ^4qE_NuZNWRi zJ<5Poqh@3) ztZmqzw6HoiaY>MuH-nfE2&GXd;AO|Di)$VZ)-?vB(4Hrns1bzBC=I*~B^pzEVe0oN zOxX?FQ(efXPyXmsjnwgxA!#>yZc!OBP~t9=r*b+nbIWn9fweV&@h5>u2)|w&vWo&| zIQ4TbihxM1_1o2gZ(pw!t$Vk84Zb8W!TkpCYbI0YXoEX%fB*&;$!geKn5yE#7hYlt zQ9@apsk~br^b<}^4+JbS2?Lse7+zm5Y*0g>dyE8*Pv*N(m?Tm(=R%*>%#dK3UNo~m z)j*XGeI5wLj-eCjRdS&et=mQm!PC5Mm|enO?Ot*kQiCx`px*Xl-8;mq8)maPKo1FDc&))-4R@rb3YuC0yk z6GH7)D?hU`GtP&Y60M>UY?j8<%yi3v62S2T^PJ|Tg-2;Sa#EvfTGHjpV%iidi=?L+4lt&d9J-t1H?g@T_`yR?Y8+Y^R_v^;x<)~=p)|? zOObNcgdjo^z6uZ?Ngj_p&c;vrQrK)_&}7987Ff^Y!BsF1h+tUDsc%NY-GyVE|p#5MwORIRUokQ*xQnJaT(@#n%U;a?hB$9 z$>!G!vGnX&RziE8mo3z!R?!q-{gLaYeysAgMC0YWZbrK$e84vQvGUuB_;7@zj0ns0 zTwwoz>Ey#FqO4!ICRBswE7UED07rKdO^OW!?!*7+iZg|PHMJpN6Kr)nT!jGeVuB|7 zEyii$ks0kTy_Ql!Z$P!Yq7h9_|C&N5CXPnwt>5AWDW!UptE}Hva}sJjlx(R?{N)Gx z4q)T5G0o!J5!-V`mM(3PFpOXsN%}obliJ@I``9uTBM6wWOxj&CH~wU>w8Lkmtj&jZ zSEOO>sf%j>Mi8`J*O%q%>g?1A7aI9iA&UfGP?g&YD~!fD zS0y@rDjX($lvDi+x{aN?my~=jz|d3?UGh>1hBP}Oc|-9$ zIH@~=0o~X|P+jgB*oaz}y<=}9|71cN|Lu7+ecV6dxMRvr*^Y@XU<^D0^W$aS(1|A2Y1oEffEgettLvn1ZG|yqy-d*P zjBG54&Q)^&-twm9l{@1Bn}`@WQ47cv;-*r?quI9x<0(Ph0l%WHj(Fr8b654izM|Dg^oBzt|18wp6tv3beJkNcA-$_^r&47QHe*#-4+p3?_e-%f z*j-(utcFCs2TAeS%ixX&2^0m*mD+QTofXC^D1{nQ)F9L=S1w#BQ!FelbPgaF1@#RM z!umxnP8>~l8It29G6wl;EA5P)<@&KysxKCY40tv7i&XlH>GVgyoIBjb`Ne!mn+6Ky zZyOli$@?wR#XYu41e+aXQFDqK#U1;Y>17WaqKL5ytNLYS?jEZ@0I(G#?BIEk+@Br4 zI#=C`(8WJz)(X(HBx3oTJ_YnxjxdJh2!5+MJDVQfnBDLc>-D29@Y?4M&?14zdw#vx zwkBPJwkFu;+$G+ug9;arR+$6EfRsShbHB3s+EPQr*YAc2Uxh-|YJi-*8wDL@ooGa= z(o-viT;R^y;Z3$XpfJ7-Q3IpSyVY+1-7OG+?neSg1A85SqtUiNSd)@fbOWWmt9tX| zsa{t+oBv|ct8PQ57lTYy9Q(siFss;idujwJ9wvl7y|!X*RnaNM~`xVx?h1BNr`P z`+Z(Izcf7P@ybPkrO31WHee`v#IGSpcFZS>$2V*km#;5Cra>zwb5nU-XKGuva;K?E z!s}rvbg275Nm{PZ52Bj?H z&|7^=78D(URAEzqJKAhzY(NZI-MPhwN$5+Uxebd;n717b8_vVR`BBq%6P370n0pH6TEP|Y z`#spOA8X^zix(RzR!&|i4e2hjcL50EVv2Z2_uwuac}xKvcz*{J$!yH?|$wO(t6G?SQiBENk8kkqfzZmJWEc4T`Q z&Luk@2bb%>u3)<@FfaZAu!6XiQl*BXhmZghU}^LP-*%zB4IX!`jnYzgCdNqk5R7dn7>RE>xUng! zo~MEN=ZhIT_rGTMerAz&n1>j!+HcJ|JL7wC(@(J92M49i3~zlH&m*J9!}76L2SSxf zE{P#lOrjI6IV0E32K`pI#yxVk#vh33+*uDByedxJ?tNiRN0``%eTpgDeZ{t?axS>p zPtkJR5B5s1Oe`Ib^D5#uuNBi_Mghh1W74`PgN>i>Or1A^uT0{zyYWh0PR(px3Cn!l z^g~t#q6<4QZF~%)f^H8vZI|kL#i$5Y0pdl;(5ckNKt$gKzI9MX*liO z_bOj-mM0CI9wr~j{e#~YQ1Z0HFNwD$zDOO`pk2I6trFi)p+Xg+ZOr-otG|1-sTOf2 zJUagxeSwrqUe>dra$bYlfTfovu%e^1r6{OAWi|j$_U~Ru-G!6EKG|?BR{r?>E80HU zgwQ1!*g8-%9RHSb6uU2$f7r!LQZmY!v|-mnv?dYf5c)^X!jpAPbHA$Rsn zB-k=12Xp2TZ0U_?Eb)Oi^37OU13=}p=bF%sEWd9;!{1J1D=aU7X7z=Iz5>>kVr$>+ z@@GC{7(-N^F9J-#8)U8nFt5 z*_k4jcK_%*aw)Vt0To(Os^*g=G+Q~Uk_Kd5th$hZYR~*5l!$mtQf99+1^h5kRW0rn zke+*K^g^)p0J#LS;SV4fFM?jn8VUxb>*+!~sx3-u3`$>#xl;NmxEPg;0KPua zqOE8IG!8ACV#JMjymP_vHG|;T8ndZGf+g!5mW4z0YqS^Ep8(@xg!xP&gSfAWn+|En ztKTM6?J;i{$#L0Ne?|-FwG8OB46_g@!$B=;rJ=A?;g%_UDAa5PEnmE=Cts|qQ!T?s z3vbgEC-1$G7rRUi>v$(fSosi-8JaWcipTW+Hs8)IPuGMM+m?gx3<={PW|b5?t%042 z#SL{GTD>sj6h-~WdATzQ(r&ZDYR4HvpG;or;D(qi_eq!(-2RM(v?M*v@+kh37yXj_ z&TN|(VOmas%u}M=d)`{YSpJ`m<^TB{;GxMNo(J&{=-Yjal^?yVl-Z-@D=t0v4!`u3 z`?ZBdMd{ILl;IKup^>yDA(6c6C|z%$6{TX;!%gDy$NGQSzkurU<@E7_K39dL!dL6q zc8>u-N7c~B`G_9Rw&9e*9^9ayaGS0{6UT!%CvVH67xa7`{CZ&r-$Vf7=ZS@O^2jxS z_#w)bb7)JHa*7K)0~$p@(Z!x@S9zB_)nM3mb7R78$ydy-2+9Qr!QG6nVME6*hU@U;bZpYw&B(Mp zR%^PfdO{DosB!m)Lr+z*WZX$ojD%SODW2iPYUo~grxUE#0;r&o${kAiB=ll?9^E6G z3Gn=R!To1$EylR?jnLfo#o3HJh&97Ggbw#N*CHm#gVD5t_UXZ8b+!Bkh~dh&b|Zs8 zdq-s-FH=XQsZN!cS}FGeBnd>zHH18)dsl#U&uVZ4;{1FAOAOU=XB6UUwqE1X|AcbY zFScalEw-rNr`LO11slYVI99`Ac4>FnTq;Gug3t_FHie%6ZY@7+eJbKm@Eja;cj-U5 z?oyN8)GF6e>;7o?db>3Lzc#jKa&@*f`q1&V+;o@|TVQx@gT*?*BgpTXQVpN&#o_|e z_PxA#S;2x17%kgEFCeP=td$Nc$}`Au@jpeOfS_~+BNb`{*N6<%e86<=u=B9AIUW}h z#>^xb=lf~8q1|xlhoD@|78^Ns{5;y-C&x2UL$cBkn@2@M@cT%tSoU_q{CGLR0_8N? zlBa3KLJC+Ow4$hj*h>l7%332a?YZFaM7c?P`&Uifn4%@xwHdZ393X&gue&xYS{@`h zu)PS!ZXW^6@m#?`*JdrvIc(!*v1XTpju=4w{23&og=V1nyVeAMOQL%W5pvY*!zO?7gklpGD& zX2Q5y7OQM*bh#uzBwwnK{1E09Ek$>1VrYmi@AhB^UqQr_OD8}$LV3(gcjXyb`73zL zC=^8b9ognD$_v8Agp6Q{_~G@P>Ke?9dS`+RS}SLsw~APmwHjA>Td+_@q0G$sQKcBI zK}EJnN>I`GFvqOkEQc-_ORwLreU`jw7l2!GYs9VEU>u#QVi9{tj_r=+XU(KOcjkUziK(}-Ze)$qL{tRUNfLcdY2?q-dNd;gt@9vp1LcspC2k5v(*f` zlTe}5iEYJ+CRbUq%6CaflqkE?mMOXO9s?(EheB}6g_*RY;0W0ZAp$$4#OZ@D-dn1_ zsCr*e5rlz|P{hgJ*g&)JFUjMMlfAw9fuN53Gbc|cr$ddcO@T1310e{Lbs2tiL~-TM zgz@v8P7CTwOA7+vQ3*Pjp*!TI+jj#9x`zwIVC)y36Gf2Wm!vvkqMjwqCK^*NMcDIZLQ&oRzG&gJ4*QV6%$XCxVs(TFBKUY`p;>q8U=*g1LbDN(OA3W*$#QTsFlnNYH zy#!9PyLzgk>*dw`E4)G(2!f1P9?}RWxWw_Da@DYs&NU!S-=F42k!Ar_e!_ZOZYVL@ z%gt!_HIcLh0J$f!+fzWNM4YZY=z{vD9Uc}`ZgGG8fF8F7Go>z(_&Yz1CbB9>7#3(x zSs7~2dyB^0Yyp{+91HM@W6%kx!B{smLwhKothW&}k1C)nvF4t4bFX2V zrG=9m7W0#73)Vr>i%6SCX+mzT$~|}QiG!}i^W!oAKdqMk!n8);@7%U8J(}0>TF|e= zd2>!JDsf&pZ)bEGigcCvM#aE*;qPQB*Gapay9VzYUhPermVX1}O~e<^!QG&r0hc&! zobJ4e*8rBHVeWJ%^`l0MRTLGDy4i)jnWX_chdaG#kzTH&zoOPpu;Ai6!WsfD(JI}R zb9TcoO&ID^Cn)tJu>QqlLI_-T6`W*v;Q#vpWM| z-O&E3{)D!Rx26%qTQeHsZCUbsNa4bs_XwAMt^7TD{aWjh(|i9C?za+suO~hTI8S^) zI_Qg}B3UO8sp8lBh}=iXCJrGt%W6#yT8V~in2V->*B7RM*B457J*Hc>b+iZ@$_a;Q z+3_#{{+K%JeIxEr^1LAkXYT_15o^2&k{o+F6e3n&G5)sqVb1LyA(*w4l(A0KXRcEnlR=0*%L2}$Rb~`6bf#qe zM>+HZy6*=!IFogCNO{RHiueN!N@O3Z!ObuLd|x4`eruS+L_zy{2NoEtMAIAaJOG+44(Mykwo{%`igXtm1;TLDwg0;YxorWONC ztsR83b+M^e3vzah^0*ZyW&Ye`s6i5WVEK~zC5GR6S&U@L7P{I{6n%p?j{oj6p&`}7 zh)4s>*jIT>QY?(KaU6(fm@LxuzeKcrra0G$#bV7=jVQVIc|2PRKs2d=mJ@zNZo9=I z<~84Kkr=-g&>h-JC6Z(;)=05g^bmHthoGy9bR=N_`lv^wU3EYi zEy97fk5KJeX{%T(Zj%U(2BbJjB_xFDF8|pI*s&_# zbkaPYTxgiOv)DYjpk9+CGl7-eqc~;e$1N;OuH7>D3gWnz`nhaI{RzEZ0A`BgwlfyQ zLAG4H>vt`VsIdjm3m<{!F;(ap0fLYrYY| zv7T))HE1A7V(2SomL3_re6y8Dy29c;Vr<-3IfKl~&ERCYiIfz%`q-dQD{%z%H@B~9 z&NsKSI{`s4C&_233Is(vEJpaEpg5oesVXt%c!^iC3XxrehSIDN9hD%sH;8=?-bH0a#t{HMV0BcB`2c7nHs6oQ)93XlIuZO3WJWvb>@$ za8ZqQd@#;p{-vQvbZ0D_Q$E&Es#u?G2Y6=EtR^dH{ ze2LcYT4psKT2+p}WJCF~+QU5(Px0`vetx|pjcSr$-D47Xe4o2`BsW3o3*pMDJcveW z6bCjTuerOu>89c#+KHNLc4>1oo-+{!PU9XPz}g&v{6KY0z39UA*>Dp*U1}lpgSoxF z^rfBsd~G~L!!v>U)Ft>Qh}wr_;O73En$7w*VK35oh*IrED#bSIrI-`3wRmjX{xuVj zBg#~k>L&+)xAwbyJSu8!PPdk}W-`BzdIN_H!rBR>U2G~UJc(l`U+On|j?rqQzDK(* z6Z#5bzvjxj=8n78rg#|b!21!t?z>EgQH-Roqn#_dtLxOUwz}GqplWQ@H6DEu>0XQY zz$0XpNGa)99 zuU#$e%>OkJ^5^YeGa*`?(j@gvWC2s&YSLz4X{zQ=Ki9^7bi@jTR8d*T0LI1jt z>?NmpZWFE&n=yA|wV0#I@KKH-6+~?(gS45>`Gh|;{YWh-hzC2`5%=u+pbs#(kqrF( z?}Lqhj&}T?I)7IrsaNHEu4S@1i>K>-zyMgH2~AkAPjnN`GILW z|FcI&n(RxgMQjz@jo;|?3#gwHrT@GfFNfAm3Y|`C#FOE=rGY8C=0bKh`GDpWM{;Z? zux_Wn;?y#DCi5!vQKoCFNtM({_FiEZ9#-AqNz0&bfT}#_lPs5U$S?gh1pD_HPwWuv zzhD0tiB(tr_b>l_77sfH`qw22hyuR+*HGv`zxwy_HSDn7Uso?MSOt9bzl`qv^ErPX z$HES~{dEmry>RsHpAY!^xD$42>#s}w+P}?k{qu`|pAW)%{$JN4y#KG+sDD22??Hz3 zy}vGDVAk=^t@v};>aQWAe?H~!zWwjZk{3RI%K!QEZwvq3tItQa{`tVad(Xcwi(KU2 bANco2sVn0G=DT$1I`GE=7}vZaioN@PF(JqX literal 0 HcmV?d00001 diff --git a/kurt-utility/src/val/resources/FolderFilesReferenced/r03/r03.xlsx:Zone.Identifier b/kurt-utility/src/val/resources/FolderFilesReferenced/r03/r03.xlsx:Zone.Identifier new file mode 100644 index 0000000..a45e1ac --- /dev/null +++ b/kurt-utility/src/val/resources/FolderFilesReferenced/r03/r03.xlsx:Zone.Identifier @@ -0,0 +1,2 @@ +[ZoneTransfer] +ZoneId=3 diff --git a/kurt-utility/src/val/resources/FolderFilesReferenced/r07/r07.xlsx b/kurt-utility/src/val/resources/FolderFilesReferenced/r07/r07.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..ba07df7c3aa9637dc185173ed274b794184aec74 GIT binary patch literal 17954 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 Vj{@9>fPfDEJqPc3$d-Vg{U6t2(To59 literal 0 HcmV?d00001 diff --git a/kurt-utility/src/val/resources/FolderFilesReferenced/r07/r07.xlsx:Zone.Identifier b/kurt-utility/src/val/resources/FolderFilesReferenced/r07/r07.xlsx:Zone.Identifier new file mode 100644 index 0000000..a45e1ac --- /dev/null +++ b/kurt-utility/src/val/resources/FolderFilesReferenced/r07/r07.xlsx:Zone.Identifier @@ -0,0 +1,2 @@ +[ZoneTransfer] +ZoneId=3 diff --git a/kurt-utility/src/val/resources/FolderFilesReferenced/r10/r10.xlsx b/kurt-utility/src/val/resources/FolderFilesReferenced/r10/r10.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..db9071190f93c85943d350b2b69dcc384d6864eb GIT binary patch literal 5610 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 Shk-$G@vy&`-8lZZIR6EOD~hH7 literal 0 HcmV?d00001 diff --git a/kurt-utility/src/val/resources/FolderFilesReferenced/r10/r10.xlsx:Zone.Identifier b/kurt-utility/src/val/resources/FolderFilesReferenced/r10/r10.xlsx:Zone.Identifier new file mode 100644 index 0000000..a45e1ac --- /dev/null +++ b/kurt-utility/src/val/resources/FolderFilesReferenced/r10/r10.xlsx:Zone.Identifier @@ -0,0 +1,2 @@ +[ZoneTransfer] +ZoneId=3 diff --git a/kurt-utility/src/val/resources/FolderFilesReferenced/r11/r11.xlsx b/kurt-utility/src/val/resources/FolderFilesReferenced/r11/r11.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..451eaa71f6ec99d635564e764f73df96c6b152e0 GIT binary patch literal 5774 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 Z+o{wP(XZ)4Lc+TKSY10t1SB_S{{oS<#Vh~- literal 0 HcmV?d00001 diff --git a/kurt-utility/src/val/resources/FolderFilesReferenced/r11/r11.xlsx:Zone.Identifier b/kurt-utility/src/val/resources/FolderFilesReferenced/r11/r11.xlsx:Zone.Identifier new file mode 100644 index 0000000..a45e1ac --- /dev/null +++ b/kurt-utility/src/val/resources/FolderFilesReferenced/r11/r11.xlsx:Zone.Identifier @@ -0,0 +1,2 @@ +[ZoneTransfer] +ZoneId=3 diff --git a/kurt-utility/src/val/resources/FolderFilesReferenced/r13/r13_cr.xlsx b/kurt-utility/src/val/resources/FolderFilesReferenced/r13/r13_cr.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..e819f96f91173036a0bc83de96ab9c4955f5f7b1 GIT binary patch literal 6548 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 Z{56%DBIc!hXlU4%FRM#}OGbXR`WKBoZ)^Yn literal 0 HcmV?d00001 diff --git a/kurt-utility/src/val/resources/FolderFilesReferenced/r13/r13_cr.xlsx:Zone.Identifier b/kurt-utility/src/val/resources/FolderFilesReferenced/r13/r13_cr.xlsx:Zone.Identifier new file mode 100644 index 0000000..a45e1ac --- /dev/null +++ b/kurt-utility/src/val/resources/FolderFilesReferenced/r13/r13_cr.xlsx:Zone.Identifier @@ -0,0 +1,2 @@ +[ZoneTransfer] +ZoneId=3 diff --git a/kurt-utility/src/val/resources/FolderFilesReferenced/r13/r13_fpp.xlsx b/kurt-utility/src/val/resources/FolderFilesReferenced/r13/r13_fpp.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..e97c06606d7c7f0ce962997c696298e632d9ef45 GIT binary patch literal 4869 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 literal 0 HcmV?d00001 diff --git a/kurt-utility/src/val/resources/FolderFilesReferenced/r13/r13_fpp.xlsx:Zone.Identifier b/kurt-utility/src/val/resources/FolderFilesReferenced/r13/r13_fpp.xlsx:Zone.Identifier new file mode 100644 index 0000000..a45e1ac --- /dev/null +++ b/kurt-utility/src/val/resources/FolderFilesReferenced/r13/r13_fpp.xlsx:Zone.Identifier @@ -0,0 +1,2 @@ +[ZoneTransfer] +ZoneId=3 diff --git a/kurt-utility/src/val/resources/FolderFilesReferenced/r15/r15.pdf b/kurt-utility/src/val/resources/FolderFilesReferenced/r15/r15.pdf new file mode 100644 index 0000000000000000000000000000000000000000..c699ce7063bcc6a868d3a8df91d5f5ccc3ccabe2 GIT binary patch literal 13349 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 literal 0 HcmV?d00001 diff --git a/kurt-utility/src/val/resources/FolderFilesReferenced/r17/r17.pdf b/kurt-utility/src/val/resources/FolderFilesReferenced/r17/r17.pdf new file mode 100644 index 0000000000000000000000000000000000000000..21cc721a4437ed4c1ae9911086988f526f5eaf45 GIT binary patch literal 19217 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 MvOhAP*q`M3FU2dt?EnA( literal 0 HcmV?d00001 diff --git a/kurt-utility/src/val/resources/FolderFilesReferenced/r19/r19.xlsx:Zone.Identifier b/kurt-utility/src/val/resources/FolderFilesReferenced/r19/r19.xlsx:Zone.Identifier new file mode 100644 index 0000000..a45e1ac --- /dev/null +++ b/kurt-utility/src/val/resources/FolderFilesReferenced/r19/r19.xlsx:Zone.Identifier @@ -0,0 +1,2 @@ +[ZoneTransfer] +ZoneId=3 diff --git a/kurt-utility/src/val/resources/FolderFilesReferenced/r20/r20.pdf b/kurt-utility/src/val/resources/FolderFilesReferenced/r20/r20.pdf new file mode 100644 index 0000000000000000000000000000000000000000..6e080cf6989ec1e2c5f504456b7b9838b837c765 GIT binary patch literal 18548 zcmeHvXIK==*6xtAieyPc&P;?M=Nu#_NfHJaau_5_Qb0tMoP&S@k_07)fG9}>6a+!Z zNt7fRMnL!mxBG1O_Jn)xJwMKOADU;F?p155YOSiSu6K34#igsHA_NhJlXA_@y%{8h z0l`2ITW3-!DUe}+ClX|;W9y8xLxU7OTs^!EJZ%Ee#Eak)1Vi9(I4h61v=~%M z7zT%)WP(FNLPAbPPESEW4`pLwgZ|scaVvn57$66Df``Knz@@~&qr^FG2e4x6Nr3bH z0Q@*`aPja72#JVENXf7YwdVl1ICyxt_;>^a`1n}u5NtXCpOWA_8$_OvO3#Lf-HRF; zo^Y3#L!tUPjsCzoC(PD6f`pWoj-KHH7dH;OK;M_Cfnz@$(M|jJ$R|DmvyyY+_P!N@`kqMrJ`_(Y^b{C8ZB)9zCwDt8aMH z_@b@7qqFN}_p7&qL+^%1-hUXKnVp;exbW%o;?l+YkI2T0iX9qGOs$Y`xB58=2TXsR#@2g) zl$H}d!?kf@+IP$T&kT$Bzq0IahW%mJD1aOf2itgflmJ=4-acDALgL3a-h4^Rd)u_8Tc4+u z_c9%-QOw^ucSQo4H!`-YFF#kI-yV)g^P^t{j!y0MALWk(uWu$B6jy(G(PYQ7ijXvW zOl+(ptDR6Ttf~?dd~2n<|Mts+*m@gZp?0k_J>tp&Nu->&bcT+v^z9)Qd79`V%$oX8 zwlarE`NXh=+u<>wi)P3(pi;fGOTDn>%=uw*6{NCYJAZhh`n0k7hDmhfio|X@<9(SC zR?LX_hK|lV-?L}s8iT$2@O?a)b+Q&b#V+3wQ2~F0J{s zjBJ>nEgo*uE@1Ya%F@U2J=2fz{;6s?_P3&p?#xr}+}H6TC|5DRQ5XgGYEdDTg;_ic z-(I5_?F#UjdAi6GaYcXqaZ!xgYZ-$Gl4F2Nt^i%9I?v5RYsVSM01bK9sHIIgSascD zQ;<9B-qvVJEyL$KeKhTwf>6$c`U$ja=DYykwr_;`#EjNiA~o&2(3@>P8W(tV-*ro`$X?#p0fd>pp|B_3*rXQnS!$ zh0t4SjVY1lBCjUL=qc+S7Z{D6y(``sz?u_K@(80Ho~CsS7zxVTD9hy^+;(BTj=)oh z6S}t90cCzYb|WF6hiRAEJA5M4ZBcfcs^%EbdhHl+p`LuhLUlo&Uo9Gw5P7!OBmtwT zw9fS@N{DB8p;}u$F4rkd7Xog3Xi?&IJB_({86oF{o{CKv^LL*4I5?lJx>;wewu{^h zjp3WXHq=gG3c(xi2mRKUEY$|aCgcT*Cr#(cO_qo>+BaI7j{(Gc*T1+Ix>{-;WCi<9 zPIUF-PF)W$SloL?aVTG~bcP|-lx9H>Lt?krDbIr0zN<3hGhv^?cB?4m9fw}3gBTz% zNlCv;%0*CLFrl9RrT5wX*tQLefpH9#aW0)1d*TaK6)QzP1^Ftb^-nRic|?psC3Aj* z9tg20#e*kxb;JCj*Td-#Ylu5Y5%NA$!on3RbLTB}s3A$W-ZtpvX=NsZk>o|^0`N^z zgXK2}b7pm-*C$Y$Yq%Tu3E;N&E3)L0p&X;lFr8z-9k;4)UOMx9BK8ECyajh&6y!Rs z<_9csjr*?HNhJ}Z5v2a>k-O?NyI0iJj-8ifsuDe!D zak5 zTrEp98}pH*O6(0v^j5Ffp!vF3(%j3d_pxNY4jQcIH!I0oQQYt9wnj;xm7WumkjCWp zSvq9@GK)*xJ1MiGC9jm>L$Y8G;?4_a(?giT+BT~U3K|Bh-}~={p+ij6pAAVV3TOCv zAekRW2w27;(-TPxDiJJs{_*}@!DjtZl(WniNot?$^fa^V?yCgYsF_)>u{LkZy>T}3P=2P_s>isdp=sDXF4s;g^~>wZhE`9q^Tc!O?2oVVj4es*+>i9L zD_Ro1M3OOUZsK??4@BB}<}A@>)un=X2U+oyW5lzwto=$)ik#uT~ z{aWo^(~8vsq3dUw_)9(mRxLxQD`9?e3uQU>MHyXB?{YNKj%`Gur6*~8{Ia|0Jhb9T29d2+}zlY2? z!k#)8Q+D{n!p+`oDz{WU%G_yZ}@-TudP3ww4l z=@a>5^7muD27!oxf1jnPxZ0qRf0?KGXE&Re`4p<0yE;Xhqy=&FA)Wo+ko}#49DuMr&;p1RAYDE0z|4)?BMpy02&~h4@5p$x%k} z!83}FFP)?3UVrl1`G6&0^$nZTv!m&ua7{|cu2RR49M}|H~Ey3m|TLhzg}LLRKLx3TRg5+@UiH+S&x5I-R<0b!hdDcu zMjO2uuS#nUKpf1GRCMg}6&(fU6p05%-a9LQURLEM`_2~c4K_jkpcTA`h;j2`byFpA za>N_kjPem%u309l_5m6}Wx_JfIF`bE`!sps2$0vd;q=Y&nA~q-T}Ba(h_8gYaa=89 z)58eU0~E_WNgS(2g(YR{r!(j3rw>_TYVmJ%)I56W8RF0cJCo@k`u^a3CR3-na4b9$ z15$Y`!!eA)xu{HB3ucE4UPE4U9f2xbP#{%*bth3%dqTw!7IvQ*;5mVAEoVztJ(qLK z2~OZvcy`J~E{Sy;mPNsC1pPW0*7&YFj8Ggf-S{rd9Dj?rpbW=|nWAKk+^Lxt108sf ze2t%;q}T+Ene8I;O5+ZH3B6-}EdTL=YmqINyFmlHsLN1J%ExWDS2ZKAYPM38O9hZ3 zk1RhVzAxAFGdAXW)!j>Pv&zJ3WU;2})uw$%rDmE?PgbddOz=g`u8LQK*-f$X2i1b3 z%7Wb+%X9(!(2uL)wMOMNM6gEAm{+|a5ifnqNJM-bUr4v2I9iG`UGNXG%i_DMIc4WQ zDM7|8;C>!Fb$+rzbnlNfG2e>b`ep>i!L-VpwJQ+RwmEfy(l?%Q>t*LHQdoWxs-)K{ z_Iur%3n#~$NFYXeH^L4+Fi*G3Ha`!T@>Q`c{xkf9X%FBV=VpBNj5}n z_ksqO+lTk*%A83HFq(6ZoaK6*@u16U3lKxZ$ZWflnZJn}f1KoqiWu2TN&Q{b)Z^y! zBCOWWx41hzsX||DMr+fj7$nEcFjU37$0VoiK_5_FFA;my+?Ywx&X%l{+Ed1D)jf>j z^tgIA?8$NZKIFaLg`y+7GZ&j$Co}n`h1qBy(kh=ho(AJ8vj`Qs`Vf@9pIA)9t*R(9 zV*8X$VGq^vdYI6rnW$ox!B@qZQc)pGf>g+Z3W~T*}f!4=dU9e4Pod2S&!8q1+t7z!M0qf0CcKhn)cu4KxQ~AvO?Xi1bGT ze}l>jKfV=ze5+gjgs-vL{9I3LMk?64V5KS$AoP1>RG>ikZ)IQ;wUPEH8wC%4b1+sU zA}#_HgF`Jr`W|TPU=0)p%gCHK>11#h!=|4i`+tG;Pm%qfBNnH~{!eKC6xp95`%`3p zitJC3{VB5lUxn<&|Cs#!j_ko;=s!pHeI}YdW1{C;woF#~UdQ!?;q%>SsXqUa*Ehwq zAgDA*PEAcd`YZ!}^5bW9UEpU0WJ@+*DK#p`GvXaM1#wpD4_3YXlv~4nh=?)ax2M$I zC(L9!XjjA5h|U!oQ=5;ZlCAX__{6s^ptH?AqR)uo&t~}Ub04*3H{*3}te$bZ7>I8n zr5Q3r=AkU(cUkwvPUV9gnWfQ5#r`czwow9itzh)j&Px12Khs;+o+rMep>*+}LhAxA zayE4C{w%>#!hT^4IB#okz4Ie6^BiF!L;Hd?mo!o(TI!^Oh<#P5;J&S#c2c7x~Q$uEy!U^EwMieg}3NjbvqC zLI#<{o$}Ns@Y7hHJTk9hFEdoN{q+|{H)5TQ@Ur^+3!H;(^V6SWl5OM!8vF@DzYRBu z+;8pRw;fCN1?W?dnccs{OFyKUn{u<`)s||;5h>wYV?4S|^PP4%)`BV$Yx+vE+~&IK z=oXev|KdJOkJAd1`khGSBtm&IVz$bWt*hjUuB&%B5CYW9`h7;!MJ^D0EdXw--I+b$NV`rRMkYnXC^F`|_A(g0>FedpaGRsSl zg|+?>iZjJk^;G;EE5#l+-x2Sb5)IJZk?yXqWL4#U5{{yH+epe}?dnwAmu1~nHUJEM z-n$;5A>S-&Z@~BP)lOEOey_>9GO?MI2+0uJ(YW$Y5_bBA+R-?v3kBy=5_yH6EXp(p za7JqlF&#y%D9w|l!gKiTJcD8^yo+MeU*oAx)(vEUY@uk1yUHJ?N#j$S~a)|Y*gJ2qy@IZq~vGgpsl@@o)yziUyKiF*cUu_Be&Tn zX1Ek3=@wzBh^#4qE>;*l>E7W<4J@+T+v2FrJh(8_#)h`rGbp+Erg3o4`$pa z%Z#9Q*d}HDGIz7^sxnAU{~D4ppI1nNCF>ggv;|YPj|~8yH(M7tO(=Y%O&hrunOBIj z)#{5E!yO5}5X|y^T|St9iPFhg_2%{D$m zrcDQ9d~LFBw))_R~XUw5Q7KK$_GwUr-+wB>#2uh3F z(^5?h7p#>{@;cdVaUVJEAAdU=d~v?STE!vWPH!YkCRPO@cW7;aYXgs+#&>sB(D?$! z-IF`KEBn~Oq4iiKcf+q$Lg5Cht5N8E28j)!2vRno$KUYx4+lTw6n&Gr*0X*|s{J9( zBCBOv+DPGs*rCwj=KULPW8xjJEj@9^*yBH2Wb_Q|e8~B{NbCOM<~lc1-i!-%ZZoTO zNDG5DF3(G)_Wia(g9Irrt?o=nXjY!J)Am1ARV1 za?}~{nr_c0JC?~mz5=11I?G|TV9Feex%ztUym|52jhZk&Rr;th8YF>%c9-#O>dX2s zB+Run$iD<{wSFqw$pncFPb6$m;@Xb_Mn2p=R1Xur7RnVYly0^8wL0>hbDrr{IamL~ z)=^u|IG8pUu}V*dUl|TXn8WOa=}#5L?xVWh$q#OW+BpC zyO7^qQ}p~=a_q%zH)o);fSf59zDdJr=5*I;I5yt>S~7a<=nWqMr%>Ayc;>a^x_v-$MqTkv7LlH#?L|4>rW7VFX%O~Z@r@cqG zG2Yo@_4MmihyGjLaUXe~62U@KMuI#14>qHDM-340T%WLw-K|Ktc@S=g=_e}Q&SVZc zz0dhxs^V(8`SDIo-+J@OUd44JOE+eOX{5cX+iJkyHh3h=3!^o-a#GkM-k_O__$8{M z)w<$_)@EvtJy5suv>{^D~RArd+_DY7G8>WoSFdifsTqKjrJ zg^iapMyxdFm8#VfEV_3*nV89^5~$tfwsH(gvbh<#wl7*4F(>n4Q7J3>Ko-v>#DvxCRNG6cuJFsOd`ebT>jNSmFH{AL zg>b(^cnfFMPdMuDn7%8Wx{}vT>)R57mCx#KhBA&B3uQi@Con!2M&)$0DrU`fuc=;h ztBJZk@at5-hTU_v*$ws?_M0u&qqS2n8XTSNwRYn!ZF2pn>96L<1%kQk$tBFbm81V+ zkUI&qb8ug8H(HURO^aC;oVXmA>#6l}P|)fHZ(pKdF6}vC$Hl}?v=)6f-8OwaxJN=@ zzchmT+reA3(8+OyN)0vRo63A&l11;_9LlxJ_A)E4fv550>9G6u2g=}$RWq%5713Rz z>>J2oUq1$P%Wr~y4VpksUcmo&HvEU8Cf^@7|4!Hh3j7|Q_-~AxoUB+lU4HP70wzD? zr*V_hxXEeUbdj7c?+KO(+4X;a9BKi$THA#KjeEVxk_LzfbFVS8r#f`}EKu@HQ z>ZdM~9kn!1${ZECf%$Zk;(?8)-IzfmbO2C~Me~cU>eivMgmq^(sRMZ;Xv4DOa!dL> z1nPX%TjeuIBe_lu-eJUY#7B~<*O;jW!4HQLbDDa%0$<-P7pVnMe&Sj?Q-+bS^XjO& zxHcC|;E^{iD&?jt3hncDou$O<2HtD% zH9Wq=KsNp6R+`njhuTTOOY zzXtf>H!#|EAqWFL~pl`sJoMV@-Gq z<8tcfu>pyJ1DuLIMd|(Sg4v7d%rTQZr2Ao}1tT+H7m{uLo){Tj3L&87=YuhF*4QYU zWlLY7v7sxPPsurJG|dA{IrYIwDbdQS!m{JZ``r@L(#S6?U9QrO*L=_J-6d6zGKHkr|G43W2GQLCJRDb(= zbh@9c;yVb~S)|Ea2)5Rl|8ltE%Q4CWmn((?y#+aoz#2gvigEUtHFAM){ zifjFIo?3jFQe=CvIsel%>G#(>&~Fm)>h9-`DLb(|SC7E>QET6>HwIdW;!Vl*_~1MXbH z4I6^u_CK$y6LQ0Nj*SZJ?Rry*Fvf6+m3t;BsJJ(Z)YJ>*rEk8LZLixmQ>QvI>?Qy` zt`}nEyVPW3W3GQ?F2@9<;z^pQ=+`I~D= zH}FBx&vu%b=cY2(O9h5~-0@)-N%~WfQV96RmGyHy%Z`fdzQINF3Cm;VxsryD{o7t_ z7Nt75)~*PxWvs7aQv>FOZbVVYlyYHh)J zCvptS8WwIF*WyOQ z{MpuaAB%CCbXB6<36f)?TZ9iU;#|coxkVD|{Nw>C;UhX!i>>k|*J}^6;2eiVX9`u_ z;+gw8V-^;n$TGz@M+7gQkK=)dnZhKQbuJ$s%_*Y;0x&4W+31V(5m(YA%{WuUa8go{ zMtQgSkA+R97Rc`l=JJ#iZeRE^q8yl16ABEf&b>GL{zA`;Oml^)k=WDd4e(SO<;SyK zx8KZqeb%p%8A|Qg@hV3qREmFPm@D^)6^qup#Hk$oD1!HywvVv{_%+b+q5V73Bg+kB zsc~@as~s2Kbg4JBB|x*@Pe!?uMlQU|Mgm`@=A3JJ-|A=A2Eh&JzFw3IZ-`%(&0gdy zP}>SLdw$HC*!e8$@5GOO+IrzX6+ilS$ty4*zY&JM%aq-*J6oXK9kH8XxXZiyp#FCK`|cSh%ZMO<@N|9(l>M5okb;M+ z{r^Mezk3l&CsH>wHROc~Lxd50f6$wJutX$ZEC~t@(nQ(&{N`)mcW(lJ^B3?pk68Xu zU+7P9&xkPbG!uITTqF-N4&Z=|uG3i|0@R>W>- zg7)y{)v)pLM0)EZJw3d!RntP*dfRvh0IwjueNZ0mKoMb4VF=&JU1#rWhxFz}eW#0k zZyum+01#pbGd1J`X?xf!VR>D=N)k{oL<|grh-3Fwfj}VwUqK*3n=|4D|uIGN@DNru%E z$F}XCWMHTW0^1CKl0gu#U&;U@5ZDs`tOtgJ5m?Xu>9=4}QP^MgupT)X82+q>5EuLF zZ?Rf%YzO$09z+y@_-maZP?-2HdT??0Uwr^UfJJ{P0|6HQRS$yo@L$SBV7>K=4E~F~ z5QON-o%rWEBShiYVdF0{#Lx9Zd)uH~k=`f!`sjOjpn>0S1$~gZ63|=*efr z-_qInK99E}G(NGl(?|bXvC9HBq-E{PO5cyUpQ)&HFgY z(K^loZ^UzKD%%scCTP3Z@4G46@PP&6Q@f$C!w(X3v#rmfE1Xr|Xx#U@dgWWk$3Y+I z{HJda^4!zC1a>Wm*ZC2IY1PyC;d1o^L!Yw;mJSo{!||RHv46+5oYEIMw0puE-;qet zVs@xG?&09#qUChEM6XfF=;37CipVKYVk42p_JMai$OLU-Y-(+T}pMMnG?iU3@DU^YRPa?vtVM-iE<+Au5`Fg|xlu0!Ed0iJ87 zGJT-K1ItKpGBQ(Y;%=JF1lt{EeR~%8>HZj!@NioJTyfDN! zvydYNZ&l3EuLSGKwQP0SVdV4GI`uBR-jtP|;Ih%uO8-7kO^+_bmrw&7WZkg6T&(QZ zM{tKMj$c1pDJ+}~l%lbZNxBPtEJFh_o|axHG9UGFKXoy=BT*jpbr=lI8E_r&N1aFr z<#f6QHIe1iPW!FM9UqUErYHijLWVt4B9lcqlQZzO*jOyN4Pp&u#dC_J?wRMuN>ffQMUt(A{|d+=5jcUo=y_*i&pJgtTzFlpVh z$-h%?wv^0y{K?*j(%JjtHFJ#x)`_!J&QF!}Os8lY$n>K=zefT)0zryKmo$`g%wp>E z*xIHm47ft&=pij>Ipp|0cqWgv1nqk+_Bz~M@ZU}!^L^1YaerzP;`U$dU=o;U`OxRq8;0~iV!m5VnsKT(q zIBnYgRu|i~6e$N@8?ysJK>j^cwAN_l58`MmaeWn3HS0$QZua!;*he$Ysh?RnvrDH2u1&78}Yj)zzayIQ7EYUWxc5vY|w<{(EftbD|iSSM(A2HAx2k5rruqGEF%7^nOKIXc`{rd*mqRO1%1}z?-4e+7N@mx=H?7O|RCe&F?8u2(34{ZW=hYhz1bqr~d#@0!J=kUyVY|68 zcjwjMsNw7OTQEwvD=zbJ0uzV{=KV0GH(Fn33s^t;DWED-hZ38j>hag$-2%4v{DHPI zSurlN)#R++>S}KBf|jb24I{mO_3gWW~S$o0TK} zYi88py75Y_!Ory$Gw!|v;X)W{8R5&at4wm;wswa`pxuhNZif0)d=`zUp-1{!MGtRH z+R6{sgjJ_^x6rSsNv9rQ!|9)(A`QvgB-kWcYhfz5w9op55mMsFuAMKj$}1Eb`K_+h z;MtyJT#Nt+~7M$N|+o_eR-BO_zN@g$nY-i# zFusad8GgX4k1V?rT*H%en>VU(djPMZq1S18Y5a#<>g1kdgP*r=ZBzHq8i{FzfBI@3 z-5KtVp0|`l(3qc~Ir#7O{R$fQzsUEKaPb4>1fgIetof`$JE!!}FuuqZOEm+0DH(1h zhC#Ct{q~xgJWA}&p6@@r>WU5fTDI0&74&5ulOYE=)^EH3nbeQi5Z=zxvo*0&O9rd+ zl#Q0lBFXc_U1&$66(gTgPgYU9qoNpD6Y|pT(`K5x-kxyc1#HrMe}L&fm5!`0Yz=au zjD##CkM`xpOFQ|qq;NHMu$h}4hMoGeWbTDyzB1I`Nu>L{0Xj>NtXePVIePn4elB`Cv#ZRXHlBooG`OO5bxM5GCa#>}pz&qe zss^1U_>VY{|34hg5okBMZM1ZgXaq(g#?8#Cn1RCuH}BpD*vb;P@bxx zul&ualuv}b|LyG+W~Lu}GL{|_G{anF5pyp%R0s4}HYPirQFxM?SNUm2@f&O@qOl0P z48cWI<4gTp@SXB<9b>m0+nWWtTlBYZTI%^y-2$PRaDjp*nynpC{87@xD|2ZMY^*jn z$woczrAZ6KSkq)Q^7CKXl3nI`}i# za^(U;S|YZm7Edl`?O4y0;Z zo^)%6-fr|-%t*bL?t5U#8s+b!K4HZ%mcPZ>uim#%2^OW#xdn5ipF>@z%euu@7t~`S z8sFKozhU?4+IL-nKsjdis z7+3_gGhl;JZg&yK|rN^dxtY>F=Y^Hp*F-eU#-$k3@v0b#H;47yQ zH32^pY@_O`vATIxX0zpkRU`A9m`dT;qLF~Hg%^Dgb5#0s+BJW(qB^y~SV;&PDfdYPVhQ8?CmVJB6`e(2?O!G;A z8g{TK(7Ycbg9os8Ik*mBE(HWj0uVold#0B{s%~UPG+nv`2AG!uG8g~?nC2aTULgPs zh@8d*-vwld16DWzBTxq!hnS{Fu8+*1+iL=F%p}<;Cuo$M|MpD;2 z0i#8!OD2k?NP>^{GhQ`5Z2KChH7+j}bgZPgyn~D}LIw9HdHcGrnG8n^GQX}sWz*6b z)C;h!*69ty#`R99R`|q|=%qJvn&pGj)ginATVWeHj+$fy-%{zvPCvd84PC=2l5o7WM|ZwmS)Yt!bt? z@oU{*Qs>XdVVm-A+)yX1PQ~L5GUTU*vQwBjvQQAriBcp~Kf&v4=AbZh7NVGi-k_Lm z^5Z|tnOf`QR$C2XBS*#)wN!&p`@w&VtXf5N=FB=i4@j> z$?pecez6^!L*({hQmVE+98#p->GRbH$C*=icU4}h_xo8-68D~MR15_di^1)==S&G3 zD|`ogUFg0jm|=o}fEC7c@rkM4}rChh}D(V%dcGUA z&ZN<*%V2ulr#m%s2xRuCF;TVcjrs4sW#wk!W$$GBe_iYE<$2%I>y;&Fp(l!12+)wVah4_P$Qa&|2p$5e zt>MIji6Y4x8@W7=c2@&NcGa~SpLeHCv;+#~Mw^<699-Y3>DjuZLb)5uCt!G(gybh2 zNoA}?C6|$E(O8rd8FAXaYzL{Z-Q#I%lyJNK;kd+%%w1zYpRj}42cnxxHv0YVI^*y5^G`Y#6UiF9{j>MZHx{y0))et5s00bO6R%-J+Du|)Lf$DD zJ3Hr&zOMC`ILr{ydowBOr$w|>8>wR^qc|<@=v}hl+D!8*38L`+rZ|FfmU&P(%3%y{ zl7A(N3xmtLTS$%XSeyORjS9B9y|yA6lQME0yu4wIbcHFythmKzZP;?$#9ABGSe`^b z=D8?Qn9?&#k#F}$>rnPFONdLEddGyIz#oX9LB#rC$2!`Y+?f?{O|l z#xp^FZdqu){ug=vdw`3Q>`Ymn8!7fLI`enOiyG#P`R8_kcKjdo+wTD{9xop?t-iNTopbiy=hUTB5|?CVXW_g`H#ybWbM-zo z8?~L$ldFP)tZE+irmR|uMo&zQoms`~tnD0C?G24hS;b9VEsaf8q#m-Wx)?dbPm-}Q zG&f~^XzA>vWa=npXJc(CmScLw5g@Jg)=ob zC#$5TwX>-stGJk&xT&$7iK(!#le43#q0QBkfs=8R>#~wEk|>uhqo7;@{zEw#MiE27 zymAHO3OXhR1_l-u=2aZRYdF~0I5+VL@CYf$s3gdKnEB9UTn~INJyK90lzL zI{s~T(JKVXh8Q#sgdES_e89Z(Ft3J4rE87$zLBFp)>UE>(wk&-cj*}z?{RW*^YHTV zi-}7}N=eJes;a4LXljAAjZI9=%q=XRI61qxy19FJ20RZ83Vsn18W|NG6C3yTT|6`; zH7z|O^W&%dg2JNWlG3vB+PeCN#-`?$*6yC(pMCuUgF_ROQ@^KYX6NP?);Bh{ws&B= zd;9QpT|z-cEDQJ>v9Q0b>jto{%V=n*Xc+KyUApWB{EvDA4gEIz6?{=;3_}M38jfd} zgb&|*$g9D+b6;hR$jGtlDlskR1l>A(X{Rgu?=8&#e`{su3%gj?5DE_JCBS&7H&8@S zVEYWvr&ndM8q{qRYHnHSJ;1X!Aq3}f$4-|szL6tureq}Q-7@7P+`mGoEP?W0{ZB-m zpL&BcpPc5hOrxK|Hr?&tN*K3X{J1}UY_h1M8+-EY@r`soft|z(6kN%NFAdB;&PU1R zN!R+k`nBG<5(nx2x~fzHc?4;G%ORU_@7t6sKL@0Lcu_@kDqE%g8Bd%W=`!`u80^RK z`+o1WjcC=3yxH2X#`McP0^mYS4Mh?8H(4xFk}tf&ms);AG#`YP7`iamKZ;Yv%z+A+ zK5!Izr|2RS(Mu^x6r8%dD$|=Nafd5wq)*4@@C2oasMp>jN9JRbOiDg3ejkpcsRXG0 z-m^%VaSfSu&ES9~{++kC(uMn}cKi9(6%~KF;Nd+e_jYVYbFwQ7x*coy3RmO>>Tq&X zu@w4;Csi1a8J1nbFHdzU5kG$ZF7dvb5$ffyJ1CQBk_*$nU|Q3!++(GaOu~cIU;nBqfN=p-S?q$bFsaXIrb+hMGK_CMxFX{asbo3R7Q5cL=NcW1XN_B{PvU z%Fu@$>YGmpc*u%c2Q6$oxSv;i_|?mn3br{EQ*?9gbvseL9EgMVP05I}b-)%EQTuk% zJ7pIav|F1c?XOuJ`fu)sZc+ute=YY-^P2El9ciW*rK4YI{wf`?(K+5!DYc$TB_jE4 zwym`3SS+J0JJ6{|q=XZ)e--RE{?IR6x;!S}F<0y8FzJorLa6!>-Uq%$52_@O%z|C{ zXK{~CQ2Mz|YF^=w&D1@fRie98QLqk)5>V>slEM;rMLq2sd=Kbv`xErR?LlyA>Z zP{>Mf)^((2MDIxl@4gAZ`>y$BS5AD5ZZ?RSzHcT^Ui4+MMVt~lTiq9(Ooxa#ipoWv z2Nup_p>KxWpG-{m{7#hGDAthPG2QTc!8igKYC9zcz0>j24}EQ2>8{}sQKpPht=~AB z3mCHX>s6H}D44Lo726bRUAcnua+#pVGeBS0LX$0)-+RpXYsP&0H?h?y0E2gq#@-2;{1-x&EW4qgyw}ceM{B~m`SNuHVn!$H-QaPEF20>k@{;u9JukFZ9QFt`0fNZyUXhM6+3Q4m^O=?38I-3p ze;0FjE4xh!Fl1-^u(nyfL7MP3>BXBka+^6JpM3*LtCv3o!Kn)lF@1;F-gcOcWO#3V z$e-42(&LkV$z<=*5C{vmi{ zl0pHisBF8fl5%HX(!)?1tiMWCxyeYeCV-=vrL6caFoJL$FW^vgqEfF-Bfs=(pY6+J z<43V89XX}n?6L7Nr`Bi+ed&i6__xyo+>BEfShTU;O+MB%e-2^2`VAKkVWS|yk#K%IdR&~ z%frx~8T0$rkGt2Ghpk#=BbC-mwErpeP*-7W7OMdxU+;k0)9LUD=3UQr=tK}}`G0_5Qqoc42e*D~9pq}=QS zMMGs)m^EF|n@5?g_MhLhVBA5?(;iuS_3Rp~&Wo8<`-?qRbm9HR<~i?v>X+jmYnp|( zhm^&P1#dM_;coljPn@6>jFML3D+7f3A!Vx5(yCH~%@O|$_F z4Zi!00UG+?zsgB}|J?6n@T#e;2@-Ar|AK=)t_$#o#A`fUyk{Uy(%R73^lvcDJ+Vlm z&2fm0aO8lggJu4*R54rQa_H0H?v{Y3U}t_^2H)#0hbZ8VDZ7d^{VpqfhKL}uE9H4~ z&d!}>QvI52S{7Oc_JYC5hGySiZhjkQ=6w}R&2jjxl-=6xnPsKORV zIe!f&Xo1tT=K?|!!&|?&z5qqYs>aYZKcSK~1>Zv7I4RquWa;>I#fs+^iyaTC@cRH; zbJAV0t#LOIw=1Y8-PKpe$6g);h}{ykN-=XS8jtKy;ogv#7o?P)u~q9}8RV43H5q?p z<4Mlk@4Oe;FhV=8=iGRQN{A|8V%uN)%iuk~5{Zy0N7`tyULIUn3(Q*Tgf;oByC0!tCZy>AFr ztmMv}deeiJ5Q<-27-|Vq>#&sRW@!7Q({V5USUe^Gsv;5V|F)YzdH!LGW6dKRr#GRG z7Z_=+DDQ#YN{ISh{eMlTFaDS{)7~-jmkZ{v%bnA8YjPP`-k;J+pH;c}&fCh%p1w^4 zH$>3CDy*N`zZcuEqn~oqAc3pPHSm6!MTUf{}2t5_YvmZ!@n>VFq5-P4;*v zlWqA48}llSy4qMY;gsk?1(Zf4hITIClObPy^yObY;jx)C!^Ng{^MmfxKjPwOgCQDL zI621r@2jzjj|3lucMXRYx9cdaI>hIyWo_Rzt-kb|h~qzS9QF&xk#e+iu|H!^r@yd@ zss72CSk)X2ZJq259ZhYGJ%oi>mEivZ*bs0D6@X^hIs?BsQNvwP1wp}-;N(ip(8!5Z zl~u*m$m*whL51|&5D{$*)n&PEMqZYuEWIocVknmSWIW(AlXHLIGbyE8R{p*=+Y z6hr=$(fxzg0hjr6p1_49fw=%jCE2MtPA4PDLCuNy4&Xz1Qxi+Whj#9d*?>b_d|cGL zoE*BWDt695kf7#c6BdR?7kEtJ1wQ|mQ2rMb^It;wSEBqcq5KQU{FhMvODO*(l>ZXS ze+lKkg!2C@Ldkal{*Z){or{Z;<9|*mE0c8H$eZ4zuWmCf*qX7t__(l;)iGKIm2R%% z!)J_oAK~M=bNTM=TNQ_|MSqO$m3Wm6>F34VxT(u{=>-qXeVNYn7nYaY?<99Dg?cJc zHyV;r%GdEeH`Y2iNq~(VE+^QrR=tb6{d~%PeJ5cv%+B|u-F7!(t2#a67RKIO7;ws> zTMt`!U4!D-;byhYVdqw!->peU*MTmKj;Sw?MVzVnSOpFjw-2fx)%8Twt+wSxpB(L{ z{qE^&mTG`>wyAx}-CeTO?s!#k`}@?O`)^OzI$OxX&3Q4~Ka~iM zU2YH_)tJ7I`{v5V&Sv}1jESDvgo%X=NKT*M5o~c-KM2BV7nBjf+M#-XYAw#I`{dw6 z>trwXsi02(iaT#YFxxBhgMetRqx3Ah+_B07PVYlYcRvp=7bl-R+ug(Y{W|@ilEwVY z`D!vbte#_QH`1L6`(l9@j^py^491ORkr?XZ$4t*02B?%wBCcoW##J9~wYBd*(Z3c4 zOwew$h(1Wah-*Y9@zr9R$EIbrb!fP9&(`Oa6|?rKi7rxD1g?`eC+-QiAZ4HA6B(b(la-`y!YD6nK+vv+;llVJ;4Ki=rc_#96%cO7pSo6t>Q z7(3d_#G>%a*9VcnHP_I!MeN(45>wcPk69f)Hf*bx!o-&*2lM+C>p$Cl#;vnu!L9S< zro6(!WA~$wjUos>kzKZ>SsEs0ZE!@dA^ECQrHFuk%GyR8kEY0&UUopEUpjX8;M&ME zB-rn0xn>|+|Mo90wmBy~ArZfgx~Y@HxNV!`X;!~nkNNbeomTlp10%2L#>+DnUL%e_ zbgtCI*^q_NYI9au?_uKx*Hz{YbGDmL;eNH(6ge47_&iY&K{fg-`P#|Ou%@*(YCN_pC1s7tg_ls-vTI*X z&Xupi4uT1*J|4Dnf!X}x!D;R%w*uCGD!-n{D*Il$>SxU7{_?}#^t*n)AEMA9i(fkA>{?R=T|-WpnDma%skO9?C=y66yBO#>eHl?UmempI)o{H zy0W-!WlIv<;BMFzq|r-E#KnuuVqww@9rM&*G=0@+u!P2Dd9OZsHbcV zGuhpiz&CFX;jh4=K0hpP!&8YbvhAdiS^4a zB>n84Nct_azLqK+Y#qHgV99~ljj8MEG#PDxS)&@mK5ryHEtuiJu0CNP*(eYA7Vr3W z)vp@T&rC?X=6kXZ1e{MDwd~fV{clFyi3#&U;pa~F+46s~U!6)F(OB)r;(ZD>t2C`B z^Hp{68EKmAVA5Ls>e#+#%RsjJ6@LGz?U$h{u$j7^IW|^U_1<&i^0uF&UcL-OyYriU zZH_uCKC5NNYsDMWe9u3+AA~e6e&M#8fxzA$Vs(vvo1shyR_9%S86xW30P& zm9K6;{!z~MLQ@9XK>YK=9>3V?_MGK@Mx|_qLt zFtC91K}RjhT*v#b@^jel7knQwT{XXf(&CS@>zek}Ef0lZ^=RfDeP*Sgo-;}We~~v& zGmL^Pn=esi6_1*2DNsUB*lYg1n$D*I7q;<8GQDOpg<$8F(Ti;>YrrXNLY2Kvp z@uTIvoaqG8Dm#$HwF!_vJ@`7MK&y%t{{%()yOqye?ySQ4B@9{_#OnOD;74}cqdNI6 z%tY4x1)6*EnrRG)4JeMpS023jNT@KnTu@(d!y1w&@t!X&wi~a*$hFIJ%cx8_TT_8sziw;TI~EObLTb;*GebS_&a*ZemsI6>xV6S5$a>ZpE+Gx-9rl8 zqr)4$F54{Kzx}8;EEoQ``5kgkTz@=ovB)B1DoiuS^mkIp724P$IlV*q?^5DwO};G zd}={g?}LZCE|oZH@uH`9AL?-3K#?BY#f$mN_;%5?E$=a-+dgJWR+#2D1Y7*qw0f4Y z&1avxX^99wEy1@rOjML({0(h!Q?{Tgt+LO!)XY{WsWxT}zN zjIH8LbO+*yq%Ph{t2^<7cV2DwufGtklv=SL6`bUKCp1~gM z(P49#`tXpjittO?4R%;nGAHFHtE+G4z6<1)n0o37ZhI42S$ zV@eX~B^Wr%iXd&a%(y53w^_0VaOlkYj^$5nwqg8gXvfm?dl%zjw68sJL0Df3Nn1GC zkrZp2#5LUnoh>YpGv70Y@RB&@E!KP{^lf#1QQ(dr-uOl@VJOSdL3pKVO5eMj0dAUFOF-6o%KgEQ*vt+6vwpcI_-*1pa#Wt?3EH*LX?nxELdl%%*hPO>IAcH@@EuG_ ztN60Q#(T^EyQ8w{Ac(}LHiBMto{?;C8Z<+ab@;G_Rc%eqQ8^G6Y|g6h?I)ag!XDDl zl&hC?vbGGHl@}3OR`t;iW(%{N0X>RJ8?n9b?vslX^9gw3fXQ|7-umJmm1U85ZRLrC zi&T-N1Z1Iy%pZ)yYHsMhG~$}@e6zMqTRFHtoha#(;yk9Asb|4@V{}@QNqeQ;BPR8W z`|v%%BrwVE;EP6YQz&uvoSKiU2piLde* zANQlnuA5EYx@II1^P^@0GdK%~smOo`Uo;R9;cixl za5IJNzq^_0#jr%An`HxTCSW0vvCwlC8)I!$4M!8vWSE{DcDwQRZ&tp#v#j0qasLlL z`v~_l38p8Y$3;-p?RArTLK1gGT4;Q0T3MqHAEJwNhmw6&VG$$1e}* zqwb)28;Ne1UyyM1S^svelI8ws3VzYp^|Ug{hTP;f6IbJyXcA~@@Eq1N( zGB*)!2bN+M^lEO)Jx_T^_l*uCz)DroNpLHz$}!0URzd_E>h-%|%ZU-;!F!+lQ)*66 z{!4Z<{hay1DnC@ACu2LH;6;*&s4ECRqxPPwkb6wJ;!SKI7QXM|ZL^w+AG}A|$ST;X z*-~YKKUE5Dpo`C*bOgbJ;W#1~Y5;fRJQ%hNCPBNQRtGNWif3Saz&cMg1*aG9epp;q> z70J!#1gLMl6V7Hzlt81y#;5JS3of+Br~RC{ek)>KdEaheIo=O{$nwHacO_e(fdr{q z65*x=@R9M46#r(Ze85mt)qaNu{j($_vvob26Fig~v25!~G#9LjIh*kODWvu&QPt3PFHwvQT~O+xIXxT0oV~(A$TRO(W|!YqzFO~( zA{hzDT+dnl+ISHu5tf6ItFpzYdb?v1i<3;s!$$kQT!Z~#ZIpM+;+;3{zfx)N(C>aM z)q7F=-o@~`d!%?6^CyTJ@K~kYC2d%qW%wn`C=enW2B60f;WPATVCptx`QiRk*{+N; z7$`j`qoEDQis$A)VH9YQ4XZ*~5Jx<9VcVFXY1_x;RL}S?hBcQ0!?aL-#e^=TamqCK zB&clxUxPH7$xm0%*Mul)8Hw;Q2jTi7!^BB;PLYpuo8H=XykWeu#J`(Sr}ExXCXqKV zK4C~mf_84M8~ok99099^Z6!|fM}^l>1yh_D^MB_52|Ry`*UfLpxA=1o4pLzM$1bL% z-9Xw&Y;U@|ZrZjQ;rdB9`%a?77AN2vbP$* zp|eZ|MEq_j>r;Mx#H}h!hG?x64;(C)C;$O$0(6-gd>uug()jjn`Q^-L+twFB1@7c8 z8}qbpC4Kj|qpI#u4G>V)HvrY9Mmt8FAQNT{Rq$bOAKAZhVh}q1ipBoN>G~CGFLB7nzupK!d9bX>L8Si09 zn|JKp?|rXWZmBx~qG15PruNF!l4he9#rGzwPWJDlA1NHQCw7PiHNU}V)Or-5@QP-a zGrArAfje7FGW5+K*q#bY_?n(y&1{sdb}(<4g)DJu%RY#hC3`XOgGxCPQKVeD#RedX zu5rqmjO9$p)03rm!{%g&Q=6`Ui21+ED560mbCuWl(h`sXuQ7W29U?8IC7cI5A0Xht z1Bf#MFl%=zg4`Z29ql{@CVU3WlJr1m`kE*)-SRiP?1>`+x_C9LQlh|X?ZLU5ao6_0 z-jb=TySocyWA9Cs|Lb-TI?fk`IG<;t9lhX({s2lJ@7ZmEk!3hMIcdA%(4NRV(Ug&>tw7>I8Zn_!-Q;=Lfn0NCfz7R=BhD|Kg_dV@%PLoF;#=Zc{ldq!p{(Sd zLPm-SP&&`8Rms73GJU@eYzw;!&q6zjqgiAO@#u1tADPxqGG>u$OVI!})+}5CR}}$=>rcaO3lLH5 z)tNelR8$Vqg+5DpPjQ%~?opk)@a9)Lf$=n+92uZ6BlL1-<96|k-zEarp&>SVk z7mg1?p5DJqtxAu0Y{uY^4bAvVl;&Q9zs$k_e~HE9z4H{Ah!6*M@83bew*gi}jN+yX zb!A+h!1wW0Tm-JhTX4gqu9&dAUFNk8v@xPO+e7DMxQ1^3Fu9MsBU1Fo6#$c`onmr2 z0F&!NJ6F%J0=|#g)F~IHDigmp3X7;d>bc`-qU3wiF-&F4QaD>6k&d!MGBR*PWuPKQ zGf=i29%|~-ZeFUN#D9c6tAU@Extz|OHrL|~h3nOT_5+N zU)jgH^WLc}E4`E|0T5x}2(Y+j&O0diwg~IQK>1Y)86+}hRDt9|)AMo(!GcZG0Gyy2 zD%=jYj5zMlK%Ruo)wF@_arGy{rg!VX94ZoQGjNl-~ND^N+? zfz#bN0R-J;FD-)v=o)3xq0eSY}UvY5_;M z(;4=Glro7_g5e2m^{tGLG7S5)RGn$vs+=29pvf~7e&<7Gjo021-YiL7!(PMQ+D5}> zhCGn8J-F~KrX_JTrk(pm6wv8kTzh5K7uRJVgb9!=+J#kGG2s6UxF~jc! zg5)`IfH)~Q-#be;*BIOQ;l$~+25{&s-83SIQ@(;)yJXnu$yA9AOVI7P2FDc1ldd*? zWwHKr0-sRDMGW&B0xkYa1Jpqe>EXC8RPi0A1F<5ci?`k?DjrP#>L53Tz$Z3>aMHIY zWU3>Jp#SqOaUl!Nf}?hN zQwg|yx9afQwk*arNOF5+gwIu`5C{F25elzq2)Sb072&p0O#csTC8x-MJCD^s95q+q zrLD>vh9XOh)|_msFI|yC5+GZF$lRQ-P?v^inaG-+c|C#_hYUS}cCMTUywAlx6C*&t zqy4l7e9*IU7Vsnnd*A_2udsXNJm5vb!vhfTWxJU|h$7J4pvROA9@q+mJ5r^a2DX*CEJ6^nyN0TeO zVEM_F(qaGZT7zX;M&{5=-@9EO0VzUB%@&e^vmBKXmFdz|a>QSeL4=M_?*@93T(#$L z-ovL?lZErN00*TRm~lC9sN+99^oN76|jG83G8E}N$tDYjSTlw^4rhRN13A^9MToRu$`8Fh<4|U)uJ@8WQz4mk0OW7MheVAtKm5G7#d9DdO7_(_{ z*-+WsE;!@rzVW>k5RiNr1x_JcoCW}Z8G!59$6i7S;c2;AF^aO_oOH_nq1%V`jwKDF zcGWH&@=RCFPI=^)?gXCdev$`iPO5h~-^OIrSR{TbYH3-5^}$wh*HhoCR=nvMw(*U~ z5Q-Xm%x5jSc)6lb6|NT9`gSsnoD(FIPNZ7&>l~CU4~5)?su8j zhsi)<`dRA58Sb{jp z9_X|vSFT3EGt-ceDPcWW&{cBkFelu?EXw_D)!MEe-EK3bLV}FWE8qZW7{Geg&VmX3Cx!3CAtM(6&r0?7a3Wd@?UO@(VaB;=uRlnT+9}S)=ZbEp>7s}I6K98r zU(;I!?gmuR3ZOlYTKw6-gYtpZi=MifNP_u?zs$;r+K3eiG0t)NXrCeNA)9;T0OJAJ zv0e&Xb3ihlzq$)jIiEx_9^Jn)o{q9}#=}(kam`Ejk{Umc>BBm(;5Er9wQP9>v+9zU z`oPyiT;&v2*=&7T#S6x;n`kU_Np<3ByNtpXW?_ll@*lAz9S-=emOz#U84=Rzg|jRT z7M}vRj`K%_*2}f^l!jh7g7nT(bPTc2rCvS+!}&w1`(xamOY3Rc@l}MU9hD!mzs}Q6 zVVp@ok}_44}F<^%6-oCRivDN35VO`n=(BAloJ5H^i`yCw-BBDC^A~PN=Xzd%nQS8J{=0%U zj2HlNn`-Vh{GA^M03b))lMr6=fwoNn?6f-kL$=|Z=|zGBOw$704t@utsYALpUcc|@ zVEk+5@s(BrfcES6ic6Nj2S)VZ*AyONEl`R608Pf7XvXX2>-9IoQ!2QV-qB4S?*`Jt z?v+SQu9eEvAJu?v!16G)Nv;^u!?n468S#w43vCXH)aC|y&a^oVXM{FKc%fwzBGH@C zg*FF8YI94cx$_SRoZw;@4pN&70kpZM0tYaz4SpB>g$(|4C~wVL!Jqa9mv7S^?+RX< z?Yki={4EcmY@S33ayo3s-_O=hS?c6-WVU$bfGHbf`1wVA&P)f7p?XCt!ed z;B4Fa9FPvkUN(NzPDuRjYxinA_$h2%d0;u=C|MCmK4A%C2_yw$33zbWUCMb1yE|6_ z(tKWJT6%}5G9@OQSDA#6u=_tvH1I0Z(mO=$0_i({!0wA-wABdMy)U$^;<>c;`h92F zxqe`ktHlfG2OC~wB6}Wz9=}RXT>ORqOg)W8-p>AnH5qx<#NNX5jZuHED@m_eu2uQ$ z?f$esKIrfCwcf`@_xU7mg>8Q0VT(T|IKH9wy-Ovz+9z(LAV+PmN(UI|`mfEb_r>8u z$wXW4xGzLhB5VvG3uypZ$ZR_?{VWUdw06L=kXuSj`gv%1eg8BIK@PLt^UD58WD!! zdFfB;`j>j{-o-E|oIn6lk6bTHnvn1K05JD6w0&*(!w(w;|KIprzVpNJ6(cKMdBJj9 zdqNjzdtC{RwkPocw9V2r3v=iAyWj&5SUtxO=2I6vyCp;;AJ$xSb5UcEo^O$erUj%z zPKC=bX>psALK$($K+jpRu-H2IVHw{gb1Bik?h!yUrA+>Y;XRpJMlh$ZNh3`MiR(ftaZ7-CvKR>gfsYAk zo>2IG<_e_2Mx~ZOGN04wsxsuWp{O_mya32bA?GKZ6_8GEjQodYz=U5A7$N2b93#ky zunyn7;bR2X7l4ob(ZJcvf#y#5v>}=60v*AnB3UQ>6Bw_2^b{Abot^;TY@N{gt`=o- zXi)y(?ftKmcnCfOpXO_QhP}Y6zQ3w(%)`f!J^+iWDqaUaX^l7Y zrGi-vPf+e=^!v_=H@(;iAZ6SkPH^Te>2yz$0OprnDs_?SP&=lie)wvI^4S+PX%jtVq**KMwHqDdz z6U=krIqd%(b*_RWSHF_KnlxFcn%8e{>2SM^xNMfdR@;d;>;XVoTNXfsl-Y|CA5=n4jq8&Z=6F1xq2ni1~_ZoV7voV zAJzfZ>TaV}K-Mr{dcrT+MZe!nv!W>Jz`v3O{MGSTNt<*ji8f8*#?MX$el9=_3T<6> zivHlU;eubpvR|xkzE=n}K(wkHAl*s(f}`#6w`h|jUFrq@r-%OFM4*dmrE`KwHa5Xi z0ZHY`=pD9D;kFDH^n$kr9kpnK1NNIG$RNV-J)80q+&MTR61*-Ox+mVwTrxKtXW@Y=RoL2kq4!6Q(Jd zbyoL771}bK(F!<#5|LtSl>(d=rN+bpfC*V%?v~H5?Wpz{U|4WWX<*=IhIHe7Z@o}| zj8ih9z(s&XZle~w)$OQV(xO@6Ng05Rt7{9J(mn@!9KLMi)4TQayQD*9t#9~P=p>!6Tl_{ZPI33;9PMDgU&c%Rfs<`NtBjBqFQ^nCKLU!|y(_ z3aO6_g43rl`%hirV%R)V{*eUaA6GW`9dHROc=6su)PHGk=3zM?c`Ntsw(#(HkxFDt z_r%wM(NyxOrISf#PfIY*#Hpb-cD@y8qF{ z(;!cjncoG{N7q3EjYJR0FHOJ>>)&2b`gnlE1&1D(p;j!)dKtfyw1!{RcqQ1FEoK=1(aS0oq#&!fAh1>#AubO#7k4 zN#*A(cHnMDpf+6ic7br*ngk__r8vCrH{&kQ7F?=Y6Vx|7l%`+dE^;Srf3nU-B)VAp zew{Xi__3Nu(cG4gtUO!jaHn#q5560I46*KTZjX;P;NU3I#Ax3pk;-@Z1^O;UqHow~ zFafHtDEMxO3^k9?8~@-B-IXb$kui>ic? ziFjx^EPNpLDObFxPy8Z+*C#UJ^;hk!dEtN7C!PTPD9df;ik-nte(r}pVX|BEfWm~R z@0uu=FlFiXe-=#}MWlbS*-NoDfS|hhP3WHTu!POMt_)b=nV_mWoO9g{U`_ad{Cy9u zkRezTPYP&()@sG)zBX{^?5Q1uKYpt_E%%g*$e2%0{%a$O2wVa81Vr=;jJG_IqZFcx zrw7c%Of<2<$($2+ZRn+$Mo8P1iyE|Z?Tv6EcMRz(vzXGC@H}OK)WGTZkCM;9xHwV+ z--6dB5G`Ms$UKEyAzTArK&U=F7j#G*$)Y^}p@ClvJHH<= z*5S`8D>o5-hm2w&6sYbo@vEOX(qEfSkb&ec@BxSVKd$bLs$o{;pxjGK;DAnmC^1qT zvicFP@YRPy=2Y?Q+Jp2X&f{Sa1k! z|E&cNph_Kn-g}eVR2{4=9l^8*+P%q&CFkXhko$1DFZVFb7U@R8mmT#p0Lkv^iid&H zu&fOp&c1a*-}Md}_ek`KH~WzwZQhBHLDh+(cS0F9XJGtIB#(e8&~YNoWOJ@QN{_-t z7eMx=B2}9WiN&~*1XY;-OaHN!&%id_)ugY!l0 z$QtQ4uP)+WHX{CYte?ieKMdw{G0X(1K0tteuFggW{^C7x$ke%HS8Uw`kQJ;*#opa* zZ-XCy)PFD7UZ9cx>`WH zuIr0}Y;&8owA+(+cU{B4YsKkEVx?r$CMWJ+x8)hG1fb4*zppOz6s}~Mbigcira|a@JLpV_Hd3Vy&dZYvWfdu{vApUTmo{M2$kq%S@ z$ai8ECtwrE%DMXx+XmNG0q&!XXgp3n{6f{AP$ro-7v-aE#T&*ZOI+W)If;>athp1ztCOgoh{vig=r^>L(kxt;u^m+KBE>}X)zSiPVCkZ#L?$P~vBjqz zeXE7nj_#JuO1&wn?A-xQZ^$^)T$hG%1HGMU36e5vt$-?MLk7}jw@ra+rqk-JZrO$l z$pzlu1lX)E1n6V!hM&9@03h!|%1SNU-Z>FZFg;)~XQ<-(IcvIAFZO|;0tk5x8IORF zm(giKK3OEwo<-0!y*MWhnZ6TPYR&&fK17E8)dx(n3Hoq})1G7guK8V{iquOQ3Uq9> zAgdIN@Qy96AR6q;24G~B;&f__N+tk!SVZ`|DtysaI1)gobUsotx;RO$Y&dpB>b(Ly z24=AXd>`en)mRloHMWm56lgi-8dl*2@LhL^1tGW-mg4cN=!DD!@*AF>j2TWbdE6-` z{{UceUzINUy)%6%9MCQh{i}$|`R-tkIncLS?K=p?_wj_Q8}KvGz`e|YMT?$XnZ0nl zb2{bgVREd@iI1h#pv7TBYH%QP?R1{kDJzQ8{*LkBvxJKehk(Goqz+Vd5H|;vdKd}A z>7EQ{$k6d`Cj-SKGO;&-gUF)!J$TXlbS4<5Gg%s-WC@goqwwuy;B683jd5R5GvoX$ ztFua8wS*`p1x3jSc4z<{c6RKGkZY|9M%_kj^X4~_o~%wpD&d!Oh?ctGJ4Y6SzRrj2b4$%HT!-vJAXr$oZCowj&Xgyj7@AgWLvfregrnS%o zPV4xMIE`egSihCIcx!aWg?M!WxEN2TOsR*XC4M0bsC_IiaOkIFaS)0st^2LHLWt{Y-APg@1aN8gAiS_^O^nJKjAnU;_#dYO!dvEEB3gnu z0SPyAf6<<->dx90dW!q^uwohT&Co1KmX+$(0v{IDSn^-TsZ+Z&MqLhzrt^gP$2Tij zWn}zDjmigkA$PpKP!iVJIN{g|ykiLgpZqFXCKKAR7i9}3>*V|5kgt=WOSI3em)1xL z!kn?6N({KA7$oP|CjztiDj6oEb^ZH9BOeA&@>1;YEWedu_i%i#FVt`A!dV-$s|W?G z<|}_%IS&M&*O1#LI@wRP$jWr=o6AkPWhHn@So?{0rqxo~V$NJIO+>AE6Ev|%R}k~;^v@nP(q7`JKI!P`9wZqeoYPSVottDE%re zAMm64;73xiaeQ)_lSfXl*E7C)(Ch=V)Wn?xUq_BMetFZr)E@6wi#28jxMB%5u%OgW zwB{?`c3RUV7xyDx7Puc?ZrCE)8OyP;^o!maOEnq>xOc)DQHjHZZjNBQgk<)-;1W`r zb+p7Qx$J}q?s(QL-LuSN+Q03t?oo)*#Phb!*r+gk5U*3cnB7aLp~*u_V{#KUVY&qt zpY7Zc9*BOTSn6&dqB z+?&~t171HZ(X9K7r)f8;pM0%z)Q3zsHP`J3wv{KM?@M+(w%q=6e^5mKB>(vH;^P>ImhbD~R1ADUQCI0b#ye{bW>cCxN)fXDD(1shf;caM4RH|Xbz*gR(u z`AT7X;;BwUmScz2IlVnpH$7yt55wyG*}m*|jmmFm?icPV>xtFw+PdrR=1+U4BH!=B zopw2+xKwsQ!wE6p4i<-pT|5pPN_DE6x7&wf4ED)RN~?|*n>v{~6Bf6{P8_0ym+I{I zHuuqweSx=V=Vzu4#*E4iC{?U0N9rE#T<`c@+D%1aXCHjq!VfF@WBv&q?pK)YKljq& zxp?*Y|In5|@RzCoSGELVr-tvn^Z($MKzLu^zWWP|C7yT|J@Vl z-#vl;-4p2FJ%Rq+6X@SPf&RbR6NnwYn-PPsPuAMUs`hsF6FhD{#tNNM)pUBc2!K}kTHl!SHv4rAyZ>LV*wXQ(1 zj;d`n`s83g`*)khZ}9rMsZ82_Xl`=)^kM0(TEXN9sT^~jrJaw-Z-l2;SjP^hrcbJ> zyH~id)ILI{N8m zjT5X9KTdZAIzmO?aMrDun((HqS)%nGp+ zIX2xj)FtLRGB;*49D=Ok)(Mk$xMip`>c?(?Zu{*9bG$g|j{nBHgoinZ3f*?u-i#0# z%ho(Fb9Zy|J2*OUHQJSU+=Dvltiw7xGFz0-$PG=OCm9hk0d@tletA$(N8Z^up&t}B zQ4#ievF-E3p#9#6A5dl9-@uDw%?)l7sq#54cM)T~!;oIIzJ7Qewpo7ov$}t^@^Nh| zuqhD#&qBLYzHCOhuI(TX4i`zThhz6NZ6q{(gUWczTwwsDi~uxWqnn9Hy0 z=c*#GDbOacDbNIbQ=qZ+$s-=S-dt#>EadPRuqn{3E%op5a(y_}3#Eivg#%jZ&!~)k ze}hF_@#R&RU7Q|WjoVyP8@CflCwW6&uc_V0#q->C4 zm+J_J1&iofzPzz0ut||=+n7BsIc2474<{r-z<$EkcfZ<=r*2i)=kWO0dpAyBKhJUm z($u8i)+gtD;E}{*mD7{=Rl&0Niw-@r@QZjk!YY+uv1h+EqKzNfoBlMC5%D<=w&wU}x^)qJEqoCse?lQ6O(XF-`W1RLlbG;J@jQRDp`?>H9 zfu`SRR^Im6UBu>Ets@`_)!$wKR7tN8L(S+m@}5Sr)&79D`&D9a&SzFB)@6 z?6&P2eLDH$+hCDAgN7Z4Nw!TN%cRRxN!ha$5w@+{9-GrUt9ZCwhS_0Ica!{McYQ9+ z)lh-1+gh^=Wu*jNwVc4OkKcS5Z{T}wl#?#8nAKD_rAlI6q8GziY2~!tCgQ8frIkD8 zRFMa2ycNd1WCVQMTDXJPzP@loOuUKbJ)Ih}}H=p_1rZH}>; zT~3ddhf~td{Opa05uNH^)w$(muNr0lT%jnEV(^H18tFx`RuRt9ALO%?rlirbh|->&HlO@ z5d5LjAZ`6nbVTUZw7xuT9)_{z)N$o#xu84sEA~;l$Q!o#RhRg|2aC1ic7fty*S4L5 z^fHzRD`n-cH!Pb2TgxO`FiKYd%~dKzP`0qk*NJhSVk|o@tdKpJcF!RU1d~57n?SMH zXQe{lzoG;y5Km+HK8eDCjqzY7U5(ENHPcC0R{3qir9XPBMzw*hfe_>7E~R)6eL-6b z<4J1ROz~w(>X6#kZ@VA8S|+)8wSYm?um)`}@1u8+<6Yj)0z<+3o{iB7~&*|#QMpJ5Z5XfM#R zyY8T8^Rp%^3lL}Z_4S0Ry}eu*SC3NMj*BwE5SE|(4Io){EjIPyytMdb&*03%OCMAS z%^ZNuFYc@XdK#UXNVmYsn1neM0ar9jM zTJA~{O-zu+JZ1rJ<>2nq*2|@ZHM*U8)17`Xz->fr29cx8=XCpclyu^E&fkfI)>XkapBxzwo6>{cQdH}fdav38J*XcKqxY^CxD$sr ze$Y!8{_g28bkca=CuaLjTItx3}qo2=tu%?!@EFKY7cr~>xEknk~VWjRUkv;~BRhf5obF0{-grgRc5I#a zutIN(Q6!u1JCr&Q9o{hqyp7jEEy4N(%)KZ9**LASHXc5g*h9DS{qUVt?YEStGWO~- zJ!^J&lNwhrm@xH=!Rw{Poxrb)o~oIJK&c9N+Qg@{zIDiJb@37l8W9$?Z#j+`5&Fa` zT45G22pZO`X_YNwpUmJWzJ!wLB`7-sO@ep6PXh0D-Df=DH*Bwj$S^Tqtatt{{6!*& zHDS?mj|pK?tl~UI0q-AsDk%4!b<72Tqm#ZExB@Ra1S-QzKgdkSv}M0!tiKNj#x*A*pmpcM}JOzrU_>;>O7t+~9}5(dNkHKJa%XM^@0Yv6D5>0* z4{visyeK(C4{BxA+Qc^X{Xiqa5vuJzrdL@>nXmEHeRF05Z>*}+IzLpnCxhz+m@xf+ zu=n0kQKU_{IIdZYfMY^HMS_ALA|TNKiYOToZ~;*S$s$pbE=pEW0Z~ahh=WRyAgCmX z2GSx*8iIf%36e8->+SBDL3h9NyZ8L=IrrXkzWrmrZ)duP?tZ(fo~pO%d0w2p*VEH} z@T)`CZY?xC2abYlD|-3|4|I>L;7IbX^EOYx4!)+#7Wv||b6i7vUhckp*5|R_)h25r zo&fg+W=(&7EK||3`_b`9sgnLI6f@zbGO4DzWfcLJmJ4Fd#9)~D0aYpMiX%48mmRa>Y3^woK+^pdC`p`BZIK&I6cG%RJLiYJEE28d%U)z z_52tAA=|qBW=3kx2bBW;_@cT~QXdTIVB6@1bLXQTM?8ehx6y7bSSw@9Moycdy;M6U zj5;UzB2$UTg8iRVbh^oQOb&=x=HEY>vshoC?NfIjlgWlZxH@>^9E_HI{YzWRCPpTe z49(N}2S~j4bR`blwaO^Xyu^B3Z%rUFrHvh<;yVy&4!g1Kt@~ccmeOwoHgctCYo%CL z`OAL68yqLjkvi7JO?ZjqsNFXFqv#^cxpCRz@8F;@GTi{8hH99 z8&~aE0dJCV8!Xh;(@n5Y;Y&E`Z*66L zDRAl>3~^vh!e>45$kU#CbJW_`?HJs4Kh}G!rKRof52#_cirqy0R-Wg9PRT2T)%d&u+>zwY@jaIM9kl3pnE;c;2tCG zz8R+eC%Kky7h0d?qbiE2HEJ{0$(lp_dk+8$n)<7mZ`~?*JZhuIqd^BMu#?QEIdx;w zO0J1FtiQRu{eup?&`G!AVc8(Rf)Q!)oF$9R&iB`=f1xtDo#m z(OUkl$@xy=MR#tNz%Z?EkKS^xt=?3z2!hmKc#zVl0G=sYkm8rZgOofYNF@_N3i0>g z5Kpld4^oKshX_*q1gJo?KfeYk#%b?g;Xx|c|9kwfTfOQH?DA<=b%L7IZ(X+F=nnIV z%^mrfasrj2KJ8BYlhRRDn@rSi=6UWLeCsUmv?u&oNfN`rg7a41^h~3WbcI|E6g1&iqX10;5JX( zyZU4X>3QcK7=yj1(6yBL$-BB<9SI3jmosZ$4sVPnR}S-UHX>2PH$@$*tzBx-H}j_+ z;^`uugCC$I1g_B3IKr4N9%o)t&-@5&lI(!iQC+qxFHSSX4d3)?>fVS?jhD2T32&sB zTU`{H%5q;|vk|K%FsApYLNFdH#|D$h7t9Wl3%zN>u;f=W*Ma{`h83g#K{K{Sq=j4p z>zSw+{m*4J{$(i=S4#5c-I8I&?d$dL_Ju~t0c@euzJqs<68<&AUGnp^&5wd_| zX{JePX8J#vLx?LsAHH1Y%2Jq$y?Ufk6j-&=#8*rPLtiT44}bc5Ew}ULbx~cBsQhDJ z2oM9A*a8z;QgGY-7wwIKF(Drr4?r3o0P3o%e3<6`pi#6l)j>(_Uf~@2nV;5&1m8T# zq5jR!urQf30*|pVvB}`40MY-rQKW7VR#l>5D?438Fl*I3ZefQH43Pb=s~_EG z>@QN*F*92F^^w+R>lhjAt=BgqZRZoX$MrnzP;*20(mPtBfm^#TTYm=VKzRv3JLbjd zVCg*^{_{R%7koLVOND|by!@vXcbYekAiO~t@zD*2lkN)i zuJp?7b}_|x_AqpA`L+e2^G(wSclMQ69HZ(6U{q|JCFGuK3scVaI`XlH?~zIZw{=4s zd7PWV0Wh;%9@EovZSR=Ju6R*s4Tq!jy)=lhL0X8J~Vmx!M7w5+>( zFk>Gp_w(}`6h|^yz+k~Em<`*bXzQlhU^C z`V4PJ!Z+b&y1;t$A(dEu;YvnmAjW~RtL+c4j^ zFzX(vOlJEJozH1sil4~c>KOt~x_jGIN=Y2W=`q5#W&H($&zfJpMtz`?c>-%L77e$z z9KA(?Bsb;AXSVfT+0e04=UHY`>@cYaR>a06{l@6`18#+u(wqSW?~DDEh83dDnwH6s6{1*Q8$ zP;z4grPoAIYN7|F_w{&C>VR<_!WrKuR>$ohL5Xo1mSg~mun+hiZ@#~}f0EAf0_LuuAi9<0o=nepYcjnK=0hr#gx~}zBAJ#-o&Q*eQmG@AO0|rKlZ7u@ z09rIZ1xnAaXd+91^s=+AfUG)dMyp3;6sY;4IX;b1{-7-;18f^_v}TGW-7jo`F}^bu z9aD-ted0+HeI;jXvjS`&Jl%4}!V@nkA`NI&iSU$$+my;EJv>=tppoVIvB3;$PmRFC zQ!;u_@$i&}hbNWM-@{W7R_!y)>^GM z&_;^Ez4fOdPdLxMh-1LFj$}TybFI5IeSvgRdzrhTBq5DT5=ZRe9K0kE#CHlSNyzU+ zT);#L<_lhu=vf0LiEnEntbZ>_9D$O=kgseyP;TKRiMW+xUPn+#q9Iab$r;irjHY=0 zgD>0q7(B(Ymw+rN*#-WU{@16xuRYg-NeiDv9kKri+$PsP_U-}ZTV2Tm@d4Sr)vtlu z}x9)Jv0Vw@ub_VEi-fp}OIQFWPY@_+i`kW|_;jmt_9b&-9r2{(bV|D`(f4?>$Z@ zL(2`to+_Zm@@oPrqA3^10)6eJEhAY{S}<^j5?A?Fx3_~RWN}Js1$<91cMTw`j+w1E zK=Oh7RNB#Ih^Hm9`P|D`V82DPcwI}9F9MoqhKW8v6RRkgUnOpHR9VNUqe(W71nKW% z?BK=87a7@AlAczyg=Tq zA0Ee0M?QqyIr*3nE1a;=HFXP)QMRH~}ow09XX54J*Oq-t1xbCX9vA9Pb~_>$}$-%1{~&}dygjv|x=58_$yHFD)3Eem%429fr$GAY2}P%eQnTm_9k=!Q|{bAU4B%%^U-pbD9;Lrt^n0AKS}Q zUCy#9$D-AS;qTCDf2Cq;%V43F!a}vW-5aa4o-u8j%!rDBS*sN(d`FCO5d{}e1Kf`u zmlynK64hzvCVlT85sViin5(UW!#-(Oj{%<{Blo!M^#;;EE5EdTxiE3DX2s?6NddC0 z6bFCZ;AbyRKkMmxa`2l&)&Z@J!0e4VN%_-1k&|4bl(D{b;*Y-7iHUk1Cj&Gm%pj49 zf#NsERQl6fwq?WeLgrn2zbjA%5&BTE5tDtGoXHAAYV%%dOkj}!Jr^%3hr)!*bI+ytkw!NqFNs3#)4)0omuKCCTL-O?T?0u7`Cp zR|rhzB{2cDsunAYpqQ3iMMtU)ZI49GER_{U>P>W{E?NgXLr`35gZVbxxD+?`7GR6? z0Z4`5UQy;QS_hdsRF{Ha8t7N+`o=hq)Kj3ue2i(8LX_jq-Yt`EgUa;U#bvB^adg;h zVua0IcH+s1w{CFsi_!8@TS-c`0YPU_YB!nT%aSSmTJ_>wK1co?FV2Er6hDaqa1pa_gt}6Nf z#}I>z4DT>uP}%>$5RB6V?%^1s0#e*}L%UP`;jz+T#HiuBgWdomDkyE$n!^*{!hWwq zY@JNy3sZKK|+TogR zFqFw%Ec0%9k?fxEl2wl-st@mLqvf*mLiRpD(I+8{ycn9$eL_p04pPlY7PH~7h<4h(rMl# zJaAgT!7_UuMY3w~59cL54XN1$%62K(n=4*IX7^fX_wBFUq{`?$N7lIO1(%Y`d7Cgk zCrFnV8-=$!EAy!GO&79PHVK-Pn^IG&gagj7k*?p)(iPy=tCl(#V}%DuVCB>{%=0h0 z|8-3Y#VV%y=?TcCJ$N<9 z5;y!g)gUUp8YD1u#%L651Wv16p5nandeJ4lu=^z@Hcm_?LVe{c?JUJyWt$I+{djRd zOJ6uFt3l%m@T`-U`jIw0i>kHzE*8V%+cLUmS-NWDaW#yNlkwXpjDvfm9sULOX!R2C~@-)a~@$v$5 z;vu6PNR(=?M!!#%I#skXr!AjCO>Gwr@MI$`2a4N6yJaP>vc067tBo6VdvgO*Fc@Mb zwb6DhIG@T0W|~5Q_3{9@E7WydG^~onMBOdVb0A4rifuHmJN}_Y3U&{xZ{#yc2>}=o z?td>d_IKLf#qI$WL%KlaMBsro2fpdhJ<_{f%$=|H-{0Vc3N+&Y}F;=Dorzvb>D#eHN;Gd3gicz9%zZG|K0p&)D~3s{ll> z0VxwYv#Yf5Dwp7!$SkD>l+$YR=}0go+rTRc91Z5`R9R*73ZUumz<$b<5DR&(AoxZM ztBA;9&p735*ef=3v~Zu@KU(^tA8}rJ0?_@m@CS|IPF^lEcjg}j%NzJ z+I5EnC++7TZe}lc*kLzUFSe29fRXddVk2rOpP+4)OYio^Dz0!qvM!wYFB`cU0ea4% ziHQbTFrGBx5QOt+5PQVx>y}wmk65cA1`Md3_!eEdat;+9IL5t{>Z77VQ&Mo2T-q+{ zGeNe-()$saN7aiH29*6(GGH23H@wl(jdV_x7skv}&c`$`vJEQS7RG!lc{KH&Jf-2c z+Jhwv)E+QiU0Us-IA4vyd}}gLv*E^2h8P)WZc`gav;B__FO^O9nF<1tKB?#Muc1Xs z%vWEsYUr`im~U6_NH6C*H1(}(0nQ;bmP+Qr`!ifI4k6fn0-L%OGXM15Elh*+c)iHb#FpOAvONgOIq$e9dm^jW8ryo_ z_hL0xO>cUv-;{9xJyXv(_Whz|^988a5X;G-px8b#56&8VtFZPQsqE$ns>hIZV^8u? ztrQDUKeRFnboW8KionN6R24F@||7^gk1#ck+;e6RK!3vu)S zXl*Jz)$Iq<0M7-*wjJTIoiP;`n=aky;0Rd59)OB@_v8hOwSziSiN%>) z2Y=6P-fYEV`~K%t!U2AutE%EKQ4h}ZR8M{p#_U=>lBNdj9=HMJUWrErB|x&+k~S8V-e_AkASHTCa*G|0XHatD>|Mc+qL;doNKKV*7HRoXhVb z^V`ntISSNUzp+I`qIxTzlu>Sv&bBfyO;i|?i4tLh!VqY-e6YxWP|MHZX!wqQQi~Ic zLhWp;qTz!lC}*9;bJlRO<}f{H6>-FK)=P|>^(+yfA{jYr5)QG;hUn-*#F0qO{*klJ zIqd?TvvxwxYUbm_iyjOO=$TR1)(zJJQhsH1l{sK>)?vp zQ59iiy0-0tt;5Ll;Ij`rlgp#3)|;sN=6P;Oejc{WwtB={&1{@7pxam6kpXc#7x0*G zdRmGdOxx(Q4qG+`byZ7LSH)XXuvV`jz6`9cdSoYRa3QK+&A9nkvZ7Wm)(G$4>#E97 zS55Ilyb!cjuho=19z>1rt-4|H?tmk}KGXbicc~?7{`jWA{u6hEHWZwzw``GpVAV3K zgP?dl4#kxbM?V3@qyB7Iigl*!p?9Y2Pq3z9{X^b#`{6$6bOzfjUQWMU#e_b*p0ME` z1~liqFOFxhRy;A(iuVFtJk7^_tGTAYZ0c#u8Xv7_`4W9YLkOa~QT2eUkO#0G6&ih_ zKm4P5knE@DY{_Z}TS`{yezIBgALagj4FrXpuF~Exh(Fv^73dpU%rRlX`cnV%U^S0q zFC8D>Hix7?yw>mN=VT%R5!hh6s?!1A)lWT>AY5XXZ+98ZPW7=XCBMihpO z2oG?0hu4uoHJ#K>@NT`4BFmr?56a#-NS%+n>|NqewtN(@;yc$LZ*db2E7*r>3NIY7 znt~}ygbQO|fk0 zqZaS*0JP-D?U`nQ>jOPC<_I@1tVo)K_WXAH!JZ!v==Nbu8NVj6M?dGe4vmgZud_$K4wnJJeBFGI0RgDMskn13-Fa}e;=V2p`MSrf5&plgjtZa#T3nUbsb3R8fyZlEsQq{^?dSv<1&xd11BLH-j~%4zrjRUHmA;H#rzFUeS)WMXxY z2nfD9xCqF~hr|t{qU{}`md%g5HMBa(#Ofg0nO~|7h;{~^3p(wh6}~zSusWN|DKmXF zxQYqUN3NT^d08u@v-ae>AQe_Jl`rD8TNF9BN*CxLQP&YZ!m)l;;c#b(x+R%(E=75G zgDj>nQKG67Oy5B=W_{V85Oj=a8T#``irlK!OP06&Wh>|%u5mpp5pBL9Mw<`b0jJG} zouduG8oP^z7S^vfFx;DUw8C^U6*eC}v67AlzN9|7aG`9tU@-z%&u75R1+`#K$f?ls)Ta&0K>XswSDOFsfR=3|jf!t2N#W0kj+X++SxOshI@O4t=3wvx{Q_qXyc6 zDq?U+;O7Ov&!g_3AgnuxyED}ex`Xz5dwQi1;#5uCfVxL{4gg0r?P^@}V{Z8({>K{4 zC;PGAVWo&f=x%SBEa^YNPFC%`Exw%B$2mNH*}$tN;qG^fbb0Tk)=11uKhpdzqtCL{ zwtIPAe9!~dvNxS|E)nHulh0fhxPju@2yUP@8GY#UA3B~_8gz&C?>C)Pw}^MHZvb($ z-@g{dyP5YPsJu)_`i$Ablt-yhkyTFcDa)>`-tOs!N@&OwFXyh8))k!>&wOlXmGmQ* z^qz-H5&O?lGGFF#XeQmq9Cp~wJCtq9Mp4H~=d?|m7Tu7vprkHR4>sb-U4DtQoO-&m zM3{O&u*hUzC#$2htVe9_Faop;uMzBo1dB}{x>j?LsyzN|h)bb)&C zpFFwWYTkG$=Q_B5NYrvrt%g1*x73E7+6PPd>a0gsg*;5NtGoWN{1bogezvx|M}@^l z&lv@omenV((6X}#`b*`&n7!QU!raodj-#WNe>{+qQ`P?XnqmPvppn3J#B%Nry>*TH z`7CPGy~->9?rMwdTSS&fJ1=dSR3Bd9UQ_ea?CHxcxu`puZ~o%*7YsUW88?;JKKq8_ zrPAiH;cJW4rIij-B@&h!X!ougGgO#*ZT}~W`&7_S>!#4ciTLz9R^yrV%wmro2Z|pT zZ|h*SRjs-zTrYO^0`(|msmaVM3+mpLeO;bhKo-PaBk?q~GGUqfro=%TRnmfe^%B7N zb2NIX>C7ve*1dhbAjjsj$#kW)G{0zb94GJx6=lfiuKsqRHNf_{P+^&#i_HkMdxPpq z{*67rDD*k>LRFyP4LLQ}y3I-XQcU{Uy)9s~X413dC^LBY~j9O!}hlXThN}IxZ%_#r$Qo&Q!4oQd*x4A-anMI@T}z{U%~OS$0SvY zkI!nqmDA76w7%f7t76pt*sVhq=T=_7=~nAuXR2@5`kb2@wD7=6aSkgd2Nr`ozqE|W zL!lI_FrLs37E9H!KlTOdw!bZT@6ap$qpd{1ReEm60=a=l{_*niF44wAA{YO$~8|GnKvN-Iw3! z%T4w-7r&$Cxa)@gG#wwb)ye6GV}>$9hG#h&-CzH-cbdBYerI!s(~qW^si`ons`93$ zhQ=ngI74v>PDRdZ18#LQ$p?;hwtUZ7QEuQqHj0KyIongRx!G6cd&tD(Ob&MEGG|wg?qV!&w!l6FL-sT423i`nx8J02ilU;V^Rg9gSoAX!{jN6Xo=QJ&M67TMq z?r)n4fSiL>Gk3S^ux_1&MHB#615u5(bGfp3Z*>gZ@hxH2JfDiE|#){CTv0n6Q85{g*K4 zzl1@ms$U#dt=j*_?PBQyJDbuDuj?e|}fV$AcvEjsoq$#04L+BY9=3jOi6|Ermi{9u4HYwUG5UAA{d8&#edvFFLg z{T!R2m|k`tZD>mYx}cg>p`4KshO$%nDW&~3T|dKQt=Ydt3(3h$mD*5@Hu@BEM$HW6 z{5hLAoOF3}%f&a;zZaLazR;Dk-&7?eHQnA`8P(A|Ri4lJF){e3$Bf3HnZ>uG106#m zA>Vh(x<0sDIb*V9$XT-Qb!6#_+9xiDCvRoQ$xU?({mjhCaJhVWXu@&)f=s=~tiAix zZ0nbq>Wpro{Ln0whg`Kl+K^2ba=JD%RR9Ut1(^|SSI!q1ug`#rJ} zNq%&0;retXIpZ*s~ZK3N)cC(E^q~nq;OtN zTY9&lYrRjequqm>>wjEpD1Yv1=ioXrD@4gLsBzxtos)QZ%w{5JmxoiVLv3W=t1GJI zVpDDQ`2m6DjnASKI74K|S%pj{MLJU?EOw=sjO$LtyjKc1tG%{g|N3&bDZc&&4@rHY zF~^K>Z^QYsePUU@Zm&o!@5&n@RV@C>sB8$A9U0#cm5}ZBI^p&Hj8{?y4`0>R>{9Ey z{iq`E;$PhGn_m~|$@Sj@UK{3AT^rk{g(EwpUABr1*w=pNZRvG7;bXLCosW^!rd9Jp z!^F?)-CKF6>_IVb1*O^D4k5+kTtU%|k$t)9uf|7bCn;0i4u6ja+8>hK?BO~>X%^3s zULQ8H^V*SBi`>hoCp*e7OH2h`)-`Mw%ASdD|D-(CN}~$;qy2n_^}h4Fu6{iiR+l=pN;gUCw_X{uT|XQ3SLMvOP0h~Qk5?NSAgZ7#oGNJO97YwCO;81` z;Jp5zn9nW7F=OivLA^va_$5}(91UBgL!z%V3_T>>FSxfjOUk)i>g&wY-b`-L$eg{A z>+Ha0jGl6TcazRaj+S%!2aBcB8S#ewNyRS(x*su#$E5^z z4|Vnm0auWvN`8AqvHeTgJ=&Wo+u5S2EH_%^t#99lb#cem1-ODIEwFB%`Xsqf zR`OK&CXR;S?xE4{(k2dea)aKwN5B=7ot60Dxp-m3`E_x2BY)QWoi{@N8Lyc9wXoKU z&J~oXA71Km;?r6gUW{!H^12085mMak=J1nOP{q_m4LH|YfP*1b9TOyYT>*6x1I zCx1*$yc>Cx^!=%a-@+da>u)4Ve|$aJCSh2v$n+*OBr9%UZ&j%wnzg=g|RSJ0!VtjsuGBi(N#~$FS~H<)%RAp7zO+*|T3t9RzryM#RiAU++jAOHr{+cn#Pn*g;w`!vcI8a}A=*ZeWtMJr! z-+LwJEfy}03$%0+|M9#pk*XtoX<>KJ$%K7!D->FTLXAt$krpI0Xni+ubKbbQy=`D! z)C*PB*L4=Fp z?;CKB4<|@zIK9=vH3jsjZCf z&3Lt`C_UtdU>}D^l--_QRmWEQG8+Un*B=_;))>37m7(mK6wVRBp1%9C;(nk!jk^uQh(;tV5KO^xKv1m>H_lyzUO@+lx~=?;3VcU2Pfn=b=!`RlZH$V z*2l3=&dbOp)mtTv727myGJgq@RInkj1MK9c#=U?LmKl z%?n?X_mLoE0g6T)u=PXexz+B$_1w_j56CdhX(VBsrs#p`RZ64XAbWpGYfa~v8`=;u zU31_A2s*f0f!HdyqK9g0`n3ULj*cL+8JiJ44c>-SnvODWkrj0M9Ps}NvMkK9QTA9P z>MwdzpsDB#gy{x3o65Y?JJy8??b0iWgpTBhW&tuNR&8}nvD#Acrg6;Q; zwe;tr7={UalqZ+z9cTiYC!H7yG&Rmu8I@3>AeyJ2uiKjb=!flG&TxeuZsz2(S6>O* zqY?6_ff9NLH9mC~he`5+R{t5+Pyj4=oI8PM}GC zR!c6T)836HN#%aW0atT_jb)meTXNqEOa|K@I!sJ4efnE*xSA2B42a^_o6qT8}{K$}>$_L8lYvhYl>_8@D86l62Snh*n zx_gC87fFlWrV&epgr^7-Z5k8P+85VtUh~>C!g|L4K@08iT+Vn}JRQ2Gh?s5@R zqg&Fut#7tQuQML?+fj@Uf1&YZ*d^VabGmJvlE))Y!$H3tncrAX$&*$4%x2ySn1DE? zRF!>LbV|1?XKXNZy$J7wcHyH}P9SAO?tV4yXHyhq?#XYFRjW(RIPYW5KUfuT6G~wUKqjR7b062H=yLhXl@cam@~YPLCC;*BR0vR!dK-bG?t|JMi?J(v|LF!xD7SYnXBIa z!!Y7!o+aFN}Z4J81=knPx z&bw#{=OHJz2Ao{l)x*P2p=T7=mE?ZOqnmnxh5JVAK=*{|cFDrXD)zFix9%)F@Tq_g zzVT%912Ln!@ERTo>Uu;u|BY9-KuBl8>yBaU*CQj{UrjUS&94~O!<`~6QC=is#4EWLx`WHkFeZ-&0>z$pKJZAbeL7ATBVSH7 zt{}q{gqGV!Y2Os*(d$K948kf)BzN~j9p(iNIR1heb>2a>)1UmhZ*;DQ2I222ch1{h z|4w0rxzVSf!!xxHhK-U{$k-r+KQwWhu3`G%$)r=Y83rMiV{Je9<^3LP(5v)|+SK|v zO<8kd)I}?ZQ6#2SSlf^4yQBf}olj8sqR-y0C)5Qbur_#dHm zjR=2eD4kHdMr=EPALjJeGfv~i)vh@vWuU*_-Z|r8`D?n0s70cVgfQ=cLDvgxwJ5(x zo9Xq$Sb)R{|Nye}6Jp0lbHzc9FATaZk8dcFs&aKDJiVhK4c9KXXOI0%? zmnD{V@6(4F%Ca*s!G9?@{=PBvp&r?(k7L+<%=5V{a51on22YS|b4h=wS^2xvb^1f^ zgx&^EtWy|wassQ*8eyVs`IPIBFEBcVI~po$Ji2g;)F zVm-tv0Q}J+&$sV*Vkf!|+y9akEbD#lgCMHh% zf=8aed7eS!5kpjf2^UCffr$PiH+ILGtUY!#x9Pst-*H|swXE= z*G{5d)KAcHiJ24XMFn%p{knz{Yef;GbPl=E*Xxtj$@LN-P3{lU}aQheI?FL8Ta6e z)d8a97w-B>Y+@2~^ubhMu`4?!AHIfZgA|@0Nuy<8S!22Y+E8)3M{TGn@&y~_3A9;zOKgYs*;vGTHY2i4}ipSP%?Ei25IIbxZCYSc#Ja z>543=+mDk3u|AeS^2wUOMnIEKCYM_hV4D(~D>Zeta*D;>K-FTgsh@MoqqB$7+1|jS zJp9y+7Uj0-VQ8D{fVMfOf-Mk5O1DgA0(vWBaWc93?v54zbpQzxC>9;EcR?UwdrPUJ z&92CCtY;2B;S1kBTC(JdD83*9-Lc7E(#xGCt?!ZoQ7~7PIJW%3Z9@TZi($^3o;7>j ztgw+oj|+F#AJ`{5IW?R)dwHdg)jK9jjV3`V3hZm zj>?0d{D*)nh9O3drd|*DANj1qn5O(CiT$=_uXE^+Y$?t%gY5C<=`U@yZ2{GZ-c3Lc zl>9+((k-fLYuVQDI}2@-Uo(3Zb-P%^f}A&wATGQeMOu{-&IN+zr=FE!2NU|dNp8$u zevrtfgHokkfJzggROu#i&JHP6@>VJ#_9HyOSIokdDm^Zf5f55ar@gzbZO@MSck53h z{IF6L!w(&6fuo3yAF2rakU+-|HFY?C_%wp~3Y4rSJL1XeYep2UBCM$zyN5aWp^S0b z9cvsvWMNI+Yuyu|sT;37)TUW6k3j9gK)p58qj}J=HoQPMJqL&%CjU`;IEj``A*%bI zwTEwO_d3gk&s>;I?(GOid_PM~*T{bG9IyFg#SEHu+G<_+3*=j5bVV8EMZ*2QM?R;i zg<+$(Tf!Ckxta6MR-_5WfoVA-)56JtFzA5Dfe>`?(|*Ii-_HpA4ZorqgdO|~{x0SK zsmk^>a4Fr3P1i_$@a)mqY|R{q6ky-ToLdbFu*8hAcHpbpa@C<(`KZQiPQZK9Vj`z2 z(_)gdZ&3^~E*PPt8P}uOdf6iz>UfXws&|uZrW~wcnM|;n!iyLJOMu;Y>TX~%-N1A! zCMeFKV#EH3|M=0|bpo7Dql z{@+KSD{HGI!H;YZ2`>B;n6-=PXV#DjZRb;D94Z4S9;+nd#g_ok== z6OgJATLd{!pr!ph+oep=4TT~3P@6sN>ZC|6-2E&}eb^kj@Yfgic0h0U1R?&ai^N|Q zn7Bdw)zAqq=OLD8qMTQam-9?vN|7k%O-SN?Q2<8`bIN&)(-hP3avnx5eHC$Q(-I}) z@-+U(5S}(bc;b#;f5>vy&y<4brF9o*VA8MRh2xzIfL{7+tvOr7U3_5g7bvd&`RjnH zbd+Jgs#H{ti^pusmvaHy_Rkpd*JkPb%MGff4$*Y0H=52T*}zhzZL>R_Ijk z3#8m2fhB=i)F-zts5q0?o^XaQo&(9?1rm@9u6iQS%MIgur}dr!Qzvof_r*V8lSl9? zvcN432YXx~%^BabP*|ZKgk1`)b{F)DAGoEVb~hRP8ftgTH{Qt46idASvc=kEV|-_d z`(qYLwDzB)Ch@N}VL7ccp3}x7r%L3s?sptnu)#1*plp%|U{WM4c>9T{1tAt`qHG6R z-B?OH$E6XT@aaFwc5_a%Bg%Gb!JHOjwAd#l0+uL|xZfvR?I?kDGD9%J$S!#U_43zR zcy5e(>(lj|5nKv8%>}|<0v|QT*R)OU!&Z;nk3zxI2N%kH^52;G!yr7z?UKi(i2%c4 zX=xh`G=T2lm*N|1d;o_1pD>2~A?A{8WlvA==pu40V1d&A@&qvhSS&GJBmKd%za~rB z%NHWlONdaK0V)l&2qkgO7DXtZN^HuXcxSV*2({{GB*|gwI%UYDn!GOJqiWYuC{mr5 z@kpwVtGGO!Z1B1NWfySELpQ!|fl4x$l$gKfqjd;av{6cYBmzt;&a;1i`MNZ2UFd+> zFu8nkd(5j%fiAn{Qw)|*p+rh65=*2AI{oV{qjqf8avw4dVbDTlf(|V{WVB+?Vh3;= z{RS-%pFR#P6bJim0R_;!&;0mNbBe4V>5I%g=J;NTnHdr4XN5Qtg!(DI4~-9aayM`X zkW@S$udCoo-Z0kvv+nZBx~J3h)#5pf3IvZk5$Z!s`wxzzCtlqx6_bgK#vGp@*6sv1mQmZ*%To{2o_ zui$G9TfnOJ>!GP<+^Y7ASVL6>sP(6<5z}DSDU|E{YFFLzEA+##f-+%O+pa=Q1x@s= zjS^YaA`mGPZR=azE}EiJ-#4cqVeMoR@#+TJ&WM#diu_*`K7~a1zhA_!asQ`F_&-e7 zdj0;gJSN2|-2YKv$dvE`9|-@)_7DHZIPLvQ-2Z*{`yQWq_19W>n$UHyt1fx)e-RR6 z&gn?hn~_CLVOdlJWKmTxcJDsgT`n(gVjTcC^!2<7Z zJ2YfpaMJ&=Gz1ZTfonJ)zD(yeh1D7aR3B6pZ06NbHqC-dQ` zEQvDXvwNMD55sN*y>PU>C0p2EU)2EO-C?MQGbq9B+%`scvbr0uX|3QZ3#jEQ!)g;f z5qNEa4_+A!P_;%T73CHoPZvQTY7>bBo`5KdcG#dc@r@8EM`YhbZNiNZn!k%bi8-|i z#%YhKa909M92*gTMr+gw;Pqw%DiU)S;J(A^n-xZcCGhYSH@ajTxpRdE1GcRj-y=UWM;KJGSyr8ttObhb-+p_hWPqgsdJJDjo4{6l_ zDxOwpkt=`D)2gGN@w7_i2i^At5NXwS1~4TPXdDfZ6B)&4!p30s9Bgb3cSaZEv`Bby2{>^zrLDB_X=B{^3Dh`xS=q60hr|w?%5xTp|GCL&MYLi>;~Z4sgss#LKoxN? zh5j!qr33}OsettSwu!ch{)T|2sGkEpPKkyQduJL=DP5Ht3v?G~CUYHkbj)BVS71R4 zDOW(y+9(ZV-z&bDtaX1v4_Z1Iy~`GNT;tVN_o69RnC=E*4WwL=+}>Co6Y_-a+iy8T zBt`-wYths>CUddabT1R0~O4lsBU1kB?SU$L$O8cgW4S` z#g#fhZn`b#6?=S3>fTd@{A>qUrynO_7%=JtKqbI{d%dMU2Hb;5&{S-h+d;z2@CY!O=z;{U92v5aKzOuvn%5W!sO$ik*NJlWBa2 z=+RGNUva-ru;MQOAE>KvgY#73>+&4zOFQh#1vsUU%B?eN_uehlh5<=zr1^G~F}ggW zMDaW}_n7uTT;j>$*Rt^n;czd^Eyfn>Z1^V(+FZA&a_}ASvAM%&2 zrtG~2L_@|0oCO;1=H-FsI|-iek^-e0c|J|PWZ|sW&dVMvRHvNmLa48b&0k>omCtyY z;#*T0*(%C5qWIZOL!dTx!B3#=1Pa1VU_H5f3=9hW>06t-3t}z=pq;=Un%;-7D_lkX z__v8;z**;w1cz~j;LVg;!JAYBCZusNQ7$Oy#qfM3gy%yf#)Rj4O?W=Ut&Dp<`>_xV z`IU{)b6^oCJO`fm2lC7Q^?ifAj7}1^mvL%%g5mjENy}!y^I5C6I@t$M9T7{ho}EO% zekBsD&RM>qBfN^X0UPJg7r$3c_BDJl$hisYWAYO&gM&G8SO!nIVd zgFx%FTdNMgASCxPMi>nV84Y$Yf%J5;yz=s4X>?&}?kiAwX+bG8IUNNhJF}Qx`n_{E zVnK;F=Pcp^_@RT!>A$AA+K}dAHc3x&xxN3*YQF4Hnd+sPjf_sASx%B(p_v@#)lYe+ z`?>iA{bN0}A#DhLpr&OV6}=p|zk_07cydOvlCpLo?#AX?4w0?CuZ3(C_BW87{QF09 zHkwS~l{>Ay=&kM|rpNW%7W(&?q+fvSfqmC$F6v>5xD{~JT)1pM!slOJo(L|I*fsQMXrE1?Bq&USyQ904&?!%x)05# znVf?X`Rm|_2vj0Jwo@701hLUv5N7Ok>sp}8A&&e}=sK_6Ho`f#}WoJ$2kWH@^Gp$Z>L---F}i%0Bvj z;PbTC{njeZXILPq<*BfM4RkE2EhqPMp`=zo4@fg;H~j(CD}RhON4aUIt4@CCc$Q%p z(~R6(iI83(QG~T*-Rq_-R$<225nR~vXH7wZPvWP3{#LHCmWn+aO`WZd@1X)ukeMY} zb@29qdUmT8Yf<<>YXK0Wy$<5mV~?J!m8Z18m@)_(+yp6#=RvsEOLHYSvjzK;xtJUs z@Zz{A1IG1bfhm zERXs09p(C7M_$d&)3EI~XQAqWNuTv`jXb1Fhys9CBxh{dim6{6`yter<_w&7m36tg z*C2zGOtTL|T;D5bRb;a5YT)_?aIi$W1(9@P^)^~YtCMQAth@ahF9+CTJI3C<1Oo?b zAMYY?p!z5T@%jTo*oW^1ar@@ZxW>j(Q57P}dV3b_rl)X#<&-ug- zZ1Z^)rBdX+*r#*Ig%N{VwXO%M+-g}32w`PK#|RA}tfBRwaPE^|(Ku8sWSA|Hv%bt* z+%z;)P_DVh-c8R!B0yM)RPa8{ddFw|>Qe`yQ3ng88-4x|L*=|fx!YvbsY+I|6&>UB zY}SjaRU^(TJphd@Vo>jiUTtEB8XE~vY@9d2byTw!h!wZ4cl;3r!e%HATv;oc(lz`e!M5Sda2Zb}pK zkg(BAiT9L~FXr<0(On+bDW`g@H}4(Y<=u&wGLBJzu0hm8guhwbr<|aL8+JKRdk~Z& z=2Y|MoM#E=c`bZ&o?jNmj&qE!|HxBkf-txGz`rJ3~uB_KSrEFf9xvTRos9%2jGa40FvjFNFI(+o=W-zH$ z(IGC38>gaL3eX7cK+s`F#Z#aW`lXon99a~`XhkbJxDrK&kw_6{C^|?*+g_(zVYEqF>FhgWRGzFW#S$Mek1$_`VYF zPhq%ZKcd2bn74?XCv{@y2{DrWvh#!pyNK|0iP(ACfp(tMeoc@@X$g{4Y(eQ0{q2*( z^ad5!5(IezUPX03fOK>wu3uJ23sz|2M|op-RMw_!InKsEGqa^HdrY)ARLX@TTu*C# zEweUUl9_-b2|P$G>S=%=b>!-iIC2^dNi++1^6IYUut;}r{u?hQ!rmUHlQDyPNh-1{$RKZ+ru7D{v`bZ8b+p#_zV; z8tNc13Ls56yQQp!0VI^&Ha_nRayMpat=M5rN;y&AgBm7zu@GZZ3p3OkN}^ulN6fzvrBG5wErq*fu+&6oPGbpfHYzwR&8my3ThTX9;=F;)2Dy3Zag4T$?&$EAfXa!jaO1T3iB^S&|XAq1Qe7ATY8w0h4Gb2r#mS}tBix0`9PE`X5I}Zh>UkuXoOZu1 zn5;TP2YXWK`dh$`ee7Tg61#$uF&qN2-@ZZI|>0ix}y;%=@Iha z_qwgVhYWa=(SuS&o9 zV#+VQ!T<7fVPH+B^WMzy=F-9mYWnv;pY>xC)=NI}ob7m_GhS}0`AuQi4o{X(5ry6bkHafgFK*&MHZG3vR zo6=34YM%5Mcb+-->h;XPPy^*T&~c<2dgpk|P{IQ9r^?gE#Jdh<$6a18Yk(*?X1n^@ zsWa)#`6K={1S>7IP?>vW-3e5M-r{8E>8o zXuO@jwA-L&I`hC5d&hw$pC5*Dm&fuao)`PLRfU$!Sl1*Zp3WH`F3zcU+sE?e&5UsU z&$c)6qV@Hxkj<4~W;%-=apF{?5*CwS=P zylqO5T`AY-K0AC&;Ct27&re1?&i_KPv4=58_`i!}1I;G>uaIo);o6PJEdFmK*$^Y1 z&Z*tlJ?ZG`!T*X0!yW3QXK8cBeA#Ys+A-+=XbAo5F%q<6FjABMaL_*bL1^D7bf3i|{9{Av$;g_i4I&Ju;M&?0Hfy%6+fp!Wc7PX3&oy&V^J zY49@B9<9inHN!5IO9X$Lu+{n>eOygz+%OQm@2}7$WS2s$uhB;d3nkk^N=w6L35C*w zY>$g!u@|JZxV(a)AD0D9x!e35EDuJ)YmDbXZ91*v5y0T zD|01Q#1q@c2Gg?N;ZtUlJ*<9aVyC|DR@LX&ZbHW8=B?zyaV0!`rQ&b6xa9nDRZV1+ z@71XPI-jV>1!qz(_`k&rfCARB7mV&QlRx8P!wUwEkB{*b7;OX%V}VheCzlG0OR!`^ zfq@f#j!EG(nP0?lWgK-|i5aQp`ZQOP94X?Y6l$(nYUAemz=EA)nw#;xq9UJG!p^mT zb>{30tmkuHVmQ-Gn5EG#IKWAJme1)kE#S1C*9#8dgg2+q?=g+Dv5k>BYaE4bb-Q8T zu043C>!uB%gBDwDv;+i+wNSwuZ`aolyjFGHd2SlgE)6%zg}RfXbD{}+{k^&!y2#|; d-{pP(8>y+N&yG2yJarj3EBxZ(;{BHoi$CLrLOlQg literal 0 HcmV?d00001 diff --git a/kurt-utility/src/val/resources/FolderFilesReferenced/r23/r23.zip b/kurt-utility/src/val/resources/FolderFilesReferenced/r23/r23.zip new file mode 100644 index 0000000000000000000000000000000000000000..12d35717fca85a6b3e3c853227a188fa687385c7 GIT binary patch literal 4181 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 R`$mv|a^Rn;PWA8Ye*qs&Nech~ literal 0 HcmV?d00001 diff --git a/kurt-utility/src/val/resources/FolderFilesReferenced/r25/r25.zip b/kurt-utility/src/val/resources/FolderFilesReferenced/r25/r25.zip new file mode 100644 index 0000000000000000000000000000000000000000..003402ed32bc768d11afd9c448bedf01fa11baf7 GIT binary patch literal 364055 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

    mIyN;$ugI4Zt3hQ#HKln^sx4#? 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 vrw$KI=)jfa)gXDdVVv@ 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

  • B9IksXV-v2bm<<8RcKjy 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 eyvY1j=T4ZC%|0o6`v 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⩔3s&C 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�#Mf&k@w8>X=jKG$3RkC21Kr!V3vH(Oj!h5dTRV*wpD!) zo}DbP;|fUm(EBDE&{r5FV&zRAK2`|40^pX0N8D{oA_RgW0t13V0)W3H$-#gAi(6#< zsK-CJ<8q{?`x?HH`#Y8EKdsgrGc=KjV6ZjKp^A((8;&lxjgP{iZzG6lW_Nq5(C9SW zV-(x}2_~A>aEa}|)&nb6TBOVzjjhk7v<~!r|-a^*urb1(*rubmGp!WG|j*eJas6viQ+gJ((u` zkUh5XAviOdqI`d98p_Z0i^K+#o^IM}-+QTsr0S9oxg>%nzO;ZZH_Fd1aY zLnv#ccyBbcj7CNB00z?*wL&s0=vP=b2w^EYgQ>NyZ6iP53awh}$WQX6>;aUpP4|k? zh0LM&Q8(@djK>}O;<#DbuiMA0Il|5SdKaV4x0b2dZS;7&R zL`9GFCjU(PlXtQCx+EV*){d`@nHiCVrJrI;+Ie5ED_6m7k^oOYu)o_*+(gLFc^*qXI3(j?t2U==8dNqfd|TcAk!xv1 z<&qH=v~lW8GKxOJZZ2(^Ram;#d#hk(P5PtmdFpW)R^KjhWb?hfa1H+H(#JEVZ5Le` z2JF0d1s42>4XAqrX!rPC@OSU+HJ3*7cfLyqx&`5X|8l^tm(EF6i0id^i^e^3MA;J| zQ&WPsWl??@?c(b?Oj?5PO*}%Cj@DkJS=Eeep^L(Mtt~IABkHmow#0e%PcRVOrjIke zpq4W0JyrL=iiaD`i*0KV$)(6r0`{2`QEk2#XbD9%R_u5Uol^xOG0L4_pS&H*ls-XP zcf-p;pb0k*;7!?Wr-Y7BuBfUCQ5+Iqf!#X;nUkcuTC7%*%YIk0V5Zj*PqRF`j;tnn z6Bu%#zb#?Rb}hP z7Gg1mb*5kYm@LKBLuWM75y@0|ov#QEf@`xJ3&|M5+44p{JolP`b90Zf#>tr!p)PPQWy>yWuRQOYp z1PuCurzTxamr#P0;$UE`l2Uw+BMYD0>^qMulz zqGgj}l5Gq8ER2Av(I(e+u~VMz`9Qv}UHv0_9HWrNs3CwlBOB11^g1}t#l#~(*fA+G z5p)-e6?<7tKPh&wGcrP?as9g=N%3>axDa1Eo3SM^>L63bHOk&KmCU0#E@7xU;RwV zr;pSnpkq@)4nhqzP<-gJ{}Ss95{CQit$XDv9S-w1&(N=1%UQ9Z{AL)uK)kA;ex~DS zjFL$(F6YUp2!LsEgFLz!6i|inmmvWe&MUZcY*of*KxtK_(u`elz6E`Si2HH}RRFx% z#p_p5*pViW84T5y->05aRoum36Wxsdy(p(f?j+WyadAN#HoDlh`Xnx`bE_@{{5}-@ z#@88lyW6dEw0dTezmMmvX%FeaaexWMTk*#slP729Gy z3m(_8iHJq1Tup0H=1Cle9(*<9rsphOKbmn524h1{v?EP9)vhEE`bZ$3AR;+BB)O*I zqwXCCC%#FLbUj*?a86J!Ai50-r1v>#E7O{k$m=piiKm~sUa7kX%ZcL1u6L1=5&u() zJmuDU{TZ@^UpaWqO5SIWxnw<9*xq>dXuGF_K3(R6tM%|n!B)z!les%XxtO!kN9$XH zzy<_I?cL@(zZ#l{QE<79eO7&xBtlCXFrAx>2_e6o>D!H8=df*zW-QU0DdU4|pA1!C zVZ!Cupkb`Ek>_WrVtYyb1+=&#`2eBc;_+F{a~h9&=L?xs9|{52R>>&CK6}0vXnF+c zoHoI{!senQsqgEVvMyfjJQ_ecJbVO#c^Q{(F=kgRYto7g#2^*&Wtv*Pj2lf#NtK#~ z%6Hy=(h+WHe}s0ru024rma9>VsxEuc+zGy$PbM4|S|%Kf%pkt@bxRU#CX8g*J6QU@ zUaDu)+Tf%>NYT2^zyG>@Y_!z+(JH0!c;ee~VyrH)bg7iQ=uER5dBoC)J%U(LH{dDS3Z;a1?a}uNs<7@72y$yM9{S<@VRKE36J8 zRF#)Ep`+e!P6o#+Fyo_{f`^-uEBBz$KJj6s7zDO)Vn-tS&C)dWcs;We1kIQk6=jlL%uD+?bRm1Kv_eHUX9g%1~q6ja75k#ZfpTez$! z99q&M{BG0Nv+)XeQ*+sgj9T$2Ak77yCoz4h78VTquESL6wxlE6i!$w4dQVc)#T&~kYq93ZgdNOvQOqRc=msGvhB zIz*uUOZpF3I|uJ}Lm*Jknun1!-G)bcT)TMt;t6j6FqK|ydC5<{05_e(*~aruB?OPo3fPxgkT&8ic#d+NXR15Y z)V=(ng7)G0gRD#){A%fn1EFh-CVaw_;D-XcCN-_5?nq-A8Z)&pogMJEoo=u&kX7@+ z;F1j$9M=X86r_HA9&$D55QNjSya`}AqRN``VC~D?dRU~X0=4B(VI-zHNE3uRBYAgQ zFngJLn7ChJyvHGSegC(eT3d(b`JftwtH%y(&~At9a{1CvT*7Knu0F^61jcPI@EDW1 z?!FD0RhX7(u}XBiN5gTewwFdqV9147y7Im^N&m0QeYctd@WDHmTp!7S{;@-Yw2eo zx$&v-)y>iEeGc7Zn5C#Tr-Ou@|$>Jxu#~j zx9sa*AnBXSv!+xi76xU#Rx20dOkr*fJvP6-frI18c{FeZ~6% zrA;$BfkytCPybERw)MK)6y(dRGn}L>eeufp{r3z<=)R6UbT7{lCU>D8h3BaFP#T_W z2PeZa(P2#cokrVxIn+l0|<``crJGZ?9HTt`f$uz z$oMe*uMLMtwTb)6Z<@guUp|lLx`j{{(T5tB1;ppyC>tHI*vf^Fd2*S=rM_MO0(FK> zx?G8zjdx%%#!WD(JyS`{gc$|W(oDmt&VpTugPnl+IQxTTa->c5g|f_3X=nDgbklSzcqN&oX~HXm}qlSUjS&Ls0IVS!SpM*p0tmO_ozxWj%F~gnjSzsh z!oqm5Gt`h6!LW#CvF1(mvsk95JCQ_F5yxp1x2S3z9E8MZ*_)|Y=Qva5__jOabo?G{ zlwJ*Sn%o!4>bKi^u|ovc9%&VbEX_?;6{&wgV!4bgQS(44MeQKc5&GH`RTCiGgt!<} zMLf+!hFr^Kk_jEy6+Y*t*;x7cYJ)C2N6v+CUF(r zF7-LCHEn-ziP%_4Jb=&^kw(|BB^kVzAXm4cu1c&hCeso6aM{{kc}!jAeYN>I_sC*a zGzW2Fp{CTJwSG7Bf)aoV&P|wtT?#4&`i){UC<#sTwb8{%f(0Wwg>=CxW*}&7g?HdD zQt|ENKIbnw?_AL)F@8$~(Oh}s;iIxCM#=^Mg8v4AuI1SOZH}Dw8Z&kVxQHv*sC5y< z=H>2L@i8(u+U1qRj4z~Fd2cD!dW%}az|xH|OskTHIa(*$3!&YyAXK-;9@Xsrz|;&U zqOM2MsrkV}lbgxR-U7OX^LvqJm{@yi0!Z`e6{o%w>n!jH>J!Z_R`or)SQ}$QqbMIO zM)XzH2&62uZpJNB;qpYP6uDD;6P#70^*JQY)?Ul!@{}@(2loy5&X$1&F_l#`iHFAe zT4r+5Fe2Z!v6U20#EH$uB=ncixLQBjQ!u|R=(qn^*K2zYYL2l>rDY{Qj{C&7Rm1kfHU$mI+$x?ykP50sk3Zk2}yhR|g87 z9b8`C1k!ZmZEf>y4s;LQr45>daNN!SIF=Z2{s4ChO5Z@B6-#c(?t?~lm}o$){P5>p z7qRT%)w~+OXteu0BZ?>JgeUhx0YYCr^)4WW*Wmix9xT+-nA99woNU-t+I#p5CJR%N zE}!Y9Eajhdxp-1XZaEJ!nJvdHma8KXK_;W#$Lzzwv`SI6;rB_LUK^B?vDo%nx4`S_ zKk3}RTsDYbzXRC7zcCMBN-WUHKIC5wT{6*+pU<1Uh`kuUR4hn8hGpR&nYh25XET-9 zSM(+R=sqRVKdEm%NU7t#_lU7?JJg;%+;8gb{l7zhlrMCaOShrC6u4A9n74*M@sp38 zgSq4EPxLS|c0Zc5@7t5JrXMSH4PigwD?hjQr;863YVgB8($zk%kBp`ttW<`He-A5r zxWC(pzOYk?&vg-dc||OuA7V4ta|@GYpI5Fx%frK;y%3vN>11DM(Akd=Ch#M*h75_qzXzc8QME&^rmRO z2G2_gyb8=Z6+;JyLfKf-J+YPYFO&KP)T9&{ys+92Ipwwm?H4<#VW}%yJUG z6EZgaH+P;TNwGp+&m4co*(X%GoQ__2BT5-##_3ISijSuRa3v|jij6(-YHL_k1PNI-!P zx`g3R@WfczTUCUyJ9giN<<=a~qpxd~5ZvaHh;g4$I@|aZIdk%XlsuXwg<+Z~f;UcYdX}yjt}#j5?hkK|R~wlb z$2`j-F~i9Axz9ej2~&ALA`%*jM+K%U1d5YP-;hqV)@aQ_u(7#y!XW}e;`$(W9?

    vSz)<)v3iMt18n{K+h* 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 literal 0 HcmV?d00001 diff --git a/kurt-utility/src/val/resources/reporting.properties b/kurt-utility/src/val/resources/reporting.properties new file mode 100644 index 0000000..672408a --- /dev/null +++ b/kurt-utility/src/val/resources/reporting.properties @@ -0,0 +1,200 @@ +# Plateforme VAL +#com.capgemini.report.teamcenter.url=http://10.67.208.184:6666/tcval/ +#com.capgemini.report.fsc.clientip=http://10.69.165.177:4544/ +#com.capgemini.report.fsc.cachedir=http://10.69.165.177:4544/ +#com.capgemini.report.fsc.assignedURI=http://tc10.69.165.177:4544/ +#com.capgemini.report.fsc.bootstrapURI=http://10.69.165.177:4544/ + +# Plateforme 36 ReportsVal dédiée +com.capgemini.report.teamcenter.url=http://10.24.192.36:80/tc/ +com.capgemini.report.fsc.clientip=http://10.69.165.201:4544/ +com.capgemini.report.fsc.cachedir=http://10.69.165.201:4544/ +com.capgemini.report.fsc.assignedURI=http://10.69.165.201:4544/ +com.capgemini.report.fsc.bootstrapURI=http://10.69.165.201:4544/ + +# Plateforme MIG +#com.capgemini.report.teamcenter.url=http://10.24.192.23:5555/tcmig/ +#com.capgemini.report.fsc.clientip=http://10.69.165.198:4544/ +#com.capgemini.report.fsc.cachedir=http://10.69.165.198:4544/ +#com.capgemini.report.fsc.assignedURI=http://10.69.165.198:4544/ +#com.capgemini.report.fsc.bootstrapURI=http://10.69.165.198:4544/ + +# Authentication to Teamcenter +com.capgemini.report.teamcenter.session.login=infodba +com.capgemini.report.teamcenter.session.password=infodba + +# Authentication: Connection to the ActiveDirectory and domain name +com.capgemini.report.authent.provider.url=LDAP://snecmadc.snecma.local +com.capgemini.report.authent.provider.port=389 +com.capgemini.report.authent.domain=snecma.local + +# Authentication: Technical account informations +com.capgemini.report.authent.tech.organisationalunit=TechnicalAccounts +com.capgemini.report.authent.tech.login=sa-bind +com.capgemini.report.authent.tech.password=SNECMA1234** + +# Authentication: User informations +com.capgemini.report.authent.user.organisationalunit=Snecma.Utilisateurs +com.capgemini.report.authent.user.attributes.email=mail +com.capgemini.report.authent.user.attributes.login=sAMAccountName +com.capgemini.report.authent.user.attributes.firstName=givenName +com.capgemini.report.authent.user.attributes.lastname=sn + +# Authentication: Admin informations +com.capgemini.report.authent.admin.organisationalunit=Snecma.Utilisateurs +com.capgemini.report.authent.admin.group=ReportAdmin + +# SMTP server configuration +com.capgemini.report.common.MailHelper.defaultSmtpHost=${email.server}> +com.capgemini.report.common.MailHelper.defaultSmtpPort=25 +com.capgemini.report.common.MailHelper.defaultExpeditorMail=reporting.tool@capgemini.com +com.capgemini.report.common.MailHelper.defaultExpeditorPassword= +# Default recipient eMail addresses (comma-separated) +com.capgemini.report.common.MailHelper.defaultDestinatorMail=${email.defaultDestinatorMail} + +# Printing locations +com.capgemini.report.location.default.input=D:/Users/jpaulino/Documents/PV_Snecma/Reports/kurt/kurt-utility/src/val/resources/FolderFilesReferenced/ +com.capgemini.report.location.default.output=D:/kurt/compare/FolderFilesGenerated/ +com.capgemini.report.location.default.extract.folder.r23=D:/kurt/compare/FolderFilesGenerated/r23 +com.capgemini.report.location.default.extract.folder.r24=D:/kurt/compare/FolderFilesGenerated/r24 + +com.capgemini.report.location.scheduling.output=C:/kurt/Jasper/scheduling/output/ +com.capgemini.report.location.scheduling.history.output=C:/kurt/Jasper/scheduling/history/ +com.capgemini.report.download.URL=${download.URL} + +# Configuration resolution parameters +com.capgemini.report.common.bom.revisionRule.default=\ DMA Configuration Interface +com.capgemini.report.common.bom.revisionRule.REPORT_R01=\ DMA Configuration Interface + +com.capgemini.report.common.bom.revisionRule.REPORT_R03=\ DMA Configuration Interface +com.capgemini.report.common.bom.revisionRule.REPORT_R05=\ DMA Configuration Interface +com.capgemini.report.common.bom.revisionRule.REPORT_R06=\ DMA Configuration Interface +com.capgemini.report.common.bom.revisionRule.REPORT_R07=\ DMA Configuration Rapport PU +com.capgemini.report.common.bom.revisionRule.REPORT_R10=\ DMA Configuration Validated +com.capgemini.report.common.bom.revisionRule.REPORT_R11=\ DMA Configuration Mockup Best So Far +com.capgemini.report.common.bom.revisionRule.REPORT_R13=\ DMA Configuration Interface +com.capgemini.report.common.bom.revisionRule.REPORT_R15=\ DMA Configuration Interface +com.capgemini.report.common.bom.revisionRule.REPORT_W15=\ DMA Configuration Interface +com.capgemini.report.common.bom.revisionRule.REPORT_R16=\ DMA Configuration Validated +com.capgemini.report.common.bom.revisionRule.REPORT_R17=\ DMA Configuration Interface +com.capgemini.report.common.bom.revisionRule.REPORT_R19=\ DMA Configuration Interface +com.capgemini.report.common.bom.revisionRule.REPORT_R20=\ DMA Configuration Interface +com.capgemini.report.common.bom.revisionRule.REPORT_R21=\ DMA Configuration Interface +com.capgemini.report.common.bom.revisionRule.REPORT_R22=\ DMA Configuration Interface +com.capgemini.report.common.bom.revisionRule.REPORT_W22=\ DMA Configuration Interface +com.capgemini.report.common.bom.revisionRule.REPORT_R23=\ DMA Configuration Rapport PU +com.capgemini.report.common.bom.revisionRule.REPORT_R24=\ DMA Configuration Validated +com.capgemini.report.common.bom.revisionRule.REPORT_R25=\ DMA Configuration Descriptif R25 +com.capgemini.report.common.bom.revisionRule.REPORT_R26=\ DMA Configuration Interface + + +# Teamcenter limit for retrieving records from a saved query +com.capgemini.report.teamcenter.queries.methods.maxQuery=50 +com.capgemini.report.teamcenter.queries.methods.paging=25 + +com.capgemini.report.jsp.defaultPaging=12 + +# List of Product types available (comma-separated, like '120,238,410,700,80C,80E,850,8LM,900,970', without the ''): +com.capgemini.report.product.list=120,238,410,700,80C,80E,850,8LM,900,970 + +# Report titles +com.capgemini.report.title.REPORT_R01=BOM assemblage PU +com.capgemini.report.title.REPORT_R03=BOM fabrication date +com.capgemini.report.title.REPORT_R05=BOM Multi récepteursPU +com.capgemini.report.title.REPORT_R06=Statut Def et Indus PU +com.capgemini.report.title.REPORT_R07=Comparaison BOM PU +com.capgemini.report.title.REPORT_R10=Documents associés générique +com.capgemini.report.title.REPORT_R11=Mise en maquette et cohérence +com.capgemini.report.title.REPORT_R13=Etat avancement processus +com.capgemini.report.title.REPORT_R15=Fiche article +com.capgemini.report.title.REPORT_W15=Fiche article +com.capgemini.report.title.REPORT_R16=Fiche générique +com.capgemini.report.title.REPORT_R17=Liste documents associés article +com.capgemini.report.title.REPORT_R19=Cas utilisation document +com.capgemini.report.title.REPORT_R20=Gel de UNIT +com.capgemini.report.title.REPORT_R21=Compare Net +com.capgemini.report.title.REPORT_R22=BOM fabrication date PDF eDOC +com.capgemini.report.title.REPORT_W22=BOM fabrication date PDF eDOC +com.capgemini.report.title.REPORT_R23=Bom assemblage PU(s) +com.capgemini.report.title.REPORT_R24=Fiche(s) générique(s) +com.capgemini.report.title.REPORT_R25=Liste des documents des génériques +com.capgemini.report.title.REPORT_R26=Cas d'emploi d'un article + + +# Report priorities (1=High, 2=Medium, 3=Low) +com.capgemini.report.priority.REPORT_R01=2 +com.capgemini.report.priority.REPORT_R03=1 +com.capgemini.report.priority.REPORT_R05=3 +com.capgemini.report.priority.REPORT_R06=3 +com.capgemini.report.priority.REPORT_R07=3 +com.capgemini.report.priority.REPORT_R10=3 +com.capgemini.report.priority.REPORT_R11=2 +com.capgemini.report.priority.REPORT_R13=2 +com.capgemini.report.priority.REPORT_R15=1 +com.capgemini.report.priority.REPORT_W15=1 +com.capgemini.report.priority.REPORT_R16=1 +com.capgemini.report.priority.REPORT_R17=1 +com.capgemini.report.priority.REPORT_R19=1 +com.capgemini.report.priority.REPORT_R20=2 +com.capgemini.report.priority.REPORT_R21=3 +com.capgemini.report.priority.REPORT_R22=1 +com.capgemini.report.priority.REPORT_W22=1 +com.capgemini.report.priority.REPORT_R23=2 +com.capgemini.report.priority.REPORT_R24=1 +com.capgemini.report.priority.REPORT_R25=1 +com.capgemini.report.priority.REPORT_R26=1 + + +# Report launch type parameters (immediate or delayed) +com.capgemini.report.common.launch.launchType.default=immediate +com.capgemini.report.common.launch.launchType.REPORT_R01=immediate +com.capgemini.report.common.launch.launchType.REPORT_R03=immediate +com.capgemini.report.common.launch.launchType.REPORT_R05=immediate +com.capgemini.report.common.launch.launchType.REPORT_R06=immediate +com.capgemini.report.common.launch.launchType.REPORT_R07=immediate +com.capgemini.report.common.launch.launchType.REPORT_R10=immediate +com.capgemini.report.common.launch.launchType.REPORT_R11=immediate +com.capgemini.report.common.launch.launchType.REPORT_R13=immediate +com.capgemini.report.common.launch.launchType.REPORT_R15=immediate +com.capgemini.report.common.launch.launchType.REPORT_W15=immediate +com.capgemini.report.common.launch.launchType.REPORT_R16=immediate +com.capgemini.report.common.launch.launchType.REPORT_R17=immediate +com.capgemini.report.common.launch.launchType.REPORT_R19=immediate +com.capgemini.report.common.launch.launchType.REPORT_R20=immediate +com.capgemini.report.common.launch.launchType.REPORT_R21=immediate +com.capgemini.report.common.launch.launchType.REPORT_R22=immediate +com.capgemini.report.common.launch.launchType.REPORT_W22=immediate +com.capgemini.report.common.launch.launchType.REPORT_R23=immediate +com.capgemini.report.common.launch.launchType.REPORT_R24=immediate +com.capgemini.report.common.launch.launchType.REPORT_R25=immediate +com.capgemini.report.common.launch.launchType.REPORT_R26=immediate + + +# Report delayed hour (HH:mm) +com.capgemini.report.common.launch.delayed.hour=16:03 + +# Purge hour (HH:mm) +com.capgemini.report.common.launch.purge.hour=11:01 + +# Number days for purge on report and scheduling report +com.capgemini.report.nb.days=60 +com.capgemini.report.nb.days.scheduling=60 + +# Technical settings for memory monitoring +com.capgemini.report.MngMemMonitor.maxTraceCount=50 +com.capgemini.report.MngMemMonitor.frequency=10 + +#com.capgemini.report.devmode=${devmode} +#com.capgemini.report.valmode=${valmode} +com.capgemini.report.devmode=true +com.capgemini.report.valmode=true +com.capgemini.report.cleanup=false + +# PIC FTP accesses for uploading generated files +com.capgemini.report.FTPUtility.host=${ftp.pic.host} +com.capgemini.report.FTPUtility.port=${ftp.pic.port} +com.capgemini.report.FTPUtility.login=${ftp.pic.login} +com.capgemini.report.FTPUtility.password=${ftp.pic.password} +com.capgemini.report.FTPUtility.targetFolder=${ftp.pic.targetFolder} +com.capgemini.report.optimized.folder.R23=C:/kurt/input/R23 +com.capgemini.report.optimized.folder.R24=C:/kurt/input/R24 diff --git a/kurt-utility/src/val/resources/testng.xml b/kurt-utility/src/val/resources/testng.xml new file mode 100644 index 0000000..701d5f8 --- /dev/null +++ b/kurt-utility/src/val/resources/testng.xml @@ -0,0 +1,694 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-utility/src/val/resources/testng.yaml b/kurt-utility/src/val/resources/testng.yaml new file mode 100644 index 0000000..f05c161 --- /dev/null +++ b/kurt-utility/src/val/resources/testng.yaml @@ -0,0 +1,179 @@ +name: Validation Test Suite +threadCount: 4 + +tests: + - name: test01 + parameters: + productID: 65A1 + unit: 20 + monomulti: Mono + generic: + genericAssemb: + effectivityDate: 01-01-2015 + refFile: r01.xlsx + classes: + - com.capgemini.reports.definition.r01report.Test_R01 + + - name: test03 + parameters: + partId: 307-084-738-0 + partRev: A + refFile: r03.xlsx + classes: + - com.capgemini.reports.definition.r03report.Test_R03 + + - name: test07 + parameters: + productID: 35R0 + unit1: 30 + unit2: 60 + generic: N24 + genericAssemb: + refFile: r07.xlsx + classes: + - com.capgemini.reports.definition.r07report.Test_R07 + + - name: test10 + parameters: + productID: ZZ01 + unit: 1 + monomulti: Mono + effectivity: 14-07-2014 + generic: A10 + genericAssemb: + refFile: r10.xlsx + classes: + - com.capgemini.reports.definition.r10report.Test_R10 + + - name: test11 + parameters: + productID: SS01 + unit: 1 + monomulti: Mono + effectivity: 15-09-2015 + generic: A11 + vueMont: + refFile: r11.xlsx + classes: + - com.capgemini.reports.definition.r11report.Test_R11 + + - name: test13_cr + parameters: + objectType: CR + beginDate: 01-10-2015 + endDate: 27-10-2015 + refFile: r13_cr.xlsx + classes: + - com.capgemini.reports.definition.r13report.Test_CrR13 + + - name: test13_fpp + parameters: + objectType: FPP + beginDate: 01-10-2015 + endDate: 27-10-2015 + refFile: r13_fpp.xlsx + classes: + - com.capgemini.reports.definition.r13report.Test_FppR13 + + - name: test15 + parameters: + language: Francais + partId: 307-084-738-0 + partRevision: A + refFile: r15.pdf + classes: + - com.capgemini.reports.definition.r15report.Test_R15 + + - name: test16 + parameters: + product: 29R0 + unitStr: 245 + idTopGeneric: C25 + typeImpression: Def_certifiee + language: Francais + refFile: r16.pdf + classes: + - com.capgemini.reports.definition.r16report.Test_R16 + + - name: test17 + parameters: + partId: 307-098-542-0 + partRevision: A + language: Francais + refFile: r17.pdf + classes: + - com.capgemini.reports.definition.r17report.Test_R17 + + - name: test19 + parameters: + docId: 00065451 + revision: --A + typeObject: DocDrawing Revision + refFile: r19.xlsx + classes: + - com.capgemini.reports.definition.r19report.Test_R19 + + - name: test20 + parameters: + prodIDBefore: R201 + prodIDAfter: R201 + unitBefore: 1 + unitAfter: 5 + matricule: Moteurs n°204-209 + listModif: '-' + classe: 1 + majMin: Mineur + conjoint: CONJOINT + refFile: r20.pdf + classes: + - com.capgemini.reports.definition.r20report.Test_R20 + + - name: test21 + parameters: + generic: E24 + genericAssemb: 24E + productID: 30E0 + unit: 20 + effectivity: 01-01-2015 + refFile: r21.xlsx + classes: + - com.capgemini.reports.definition.r21report.Test_R21 + + - name: test22 + parameters: + partID: 307-084-738-0 + partRevisionID: A + refFile: r22.pdf + classes: + - com.capgemini.reports.definition.r22report.Test_R22 + + - name: test23 + parameters: + productID: RP23 + genericTech: + genericMontage: + monomulti: Multi + EffectivityDate: 05-01-2017 + refFile: r23.zip + classes: + - com.capgemini.reports.definition.r23report.Test_R23 + + - name: test24 + parameters: + productID: RP24 + unit: 10 + typeImpr: Def_realisation + language: Anglais + refFile: r24.zip + classes: + - com.capgemini.reports.definition.r24report.Test_R24 + + - name: test25 + parameters: + productID: 35R0 + unit: + typeImpression: Définition certifiée + language: Francais + refFile: r25.zip + classes: + - com.capgemini.reports.definition.r25report.Test_R25 \ No newline at end of file diff --git a/kurt-web/pom.xml b/kurt-web/pom.xml new file mode 100644 index 0000000..43efeb9 --- /dev/null +++ b/kurt-web/pom.xml @@ -0,0 +1,136 @@ + + + 4.0.0 + kurt-web + war + kurt-web + + + com.capgemini.reports + kurt + 1.32.9 + + + + + com.capgemini.reports + kurt-ejb + 1.32.9 + + + + junit + junit + test + + + org.mockito + mockito-core + test + + + + org.slf4j + slf4j-api + + + + org.projectlombok + lombok + + + + org.json + json + + + + org.jboss.spec.javax.annotation + jboss-annotations-api_1.1_spec + + + + + org.jboss.spec.javax.servlet + jboss-servlet-api_3.0_spec + + + + + + + + + org.springframework + spring-test + 2.5 + test + + + org.springframework + spring-core + 4.1.1.RELEASE + test + + + + + + org.hibernate + hibernate-entitymanager + 4.0.1.Final + + + org.hibernate + hibernate-validator + 4.2.0.Final + + + org.hibernate + hibernate-core + 4.0.1.Final + + + + com.hp.gagawa + gagawa + 1.0.1 + + + + + org.jboss.netty + netty + provided + + + com.capgemini + spnegobasic + 1.0.0 + + + + + + + + org.apache.maven.plugins + maven-war-plugin + + true + + + true + src/main/webapp + + index.jsp + + + + + + + + + + diff --git a/kurt-web/src/main/java/com/capgemini/reports/DispatcherServlet.java b/kurt-web/src/main/java/com/capgemini/reports/DispatcherServlet.java new file mode 100644 index 0000000..cb360f2 --- /dev/null +++ b/kurt-web/src/main/java/com/capgemini/reports/DispatcherServlet.java @@ -0,0 +1,91 @@ +package com.capgemini.reports; + +import com.capgemini.reports.formatting.ErrorPageTemplate; +import lombok.extern.slf4j.Slf4j; + +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.Locale; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** Forwards the request to the report's own jsp. */ +@Slf4j +@WebServlet("/dispatcherServlet") +public class DispatcherServlet extends HttpServlet { + + private static final long serialVersionUID = 490514018643346053L; + + /** + * URL pattern.
    + * There are 3 matching possibilities: + *
      + *
    1. "REPORT_R" followed by an optional "B" for RB01 reports followed by a two-digit number "XX"
    2. + *
    3. An optional series of all-alpha words preceded by whitespace like "_Document_Revision"
    4. + *
    5. "&" separator then anything that isn't a whitespace, then the end of the string
    6. + *
    + * + * So these work: + *
      + *
    • REPORT_R01
    • + *
    • REPORT_R20
    • + *
    • REPORT_R19
    • + *
    • REPORT_R15_A
    • + *
    • REPORT_R15_B
    • + *
    • REPORT_R19_Document_Revision
    • + *
    • REPORT_R19_Document
    • + *
    • REPORT_R19_Document_Revision
    • + *
    • REPORT_R19&truc=machin
    • + *
    • REPORT_RB05
    • + *
    • REPORT_RB01
    • + *
    + * And these don't: + *
      + *
    • REPORT_R011
    • + *
    • RAPORT_R01
    • + *
    • REPORT_RB1
    • + *
    • REPORT_RB6
    • + *
    • REPORT_R15A
    • + *
    • REPORT_R19_Document-Revision
    • + *
    + */ + private static final String URL_PATTERN = "(REPORT_RB?[0-9][0-9])(_[A-Za-z]+)*(&[\\S]*)?$"; + + /** + * Forwards the request to the appropriate web page. + * + * @param aRequest The user request + * @param aResponse The expected response + * @throws ServletException + * @throws IOException + * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) + */ + @Override + protected void doGet(final HttpServletRequest aRequest, final HttpServletResponse aResponse) throws ServletException, IOException { + ServletContext context = getServletContext(); + + String theUrl = aRequest.getQueryString(); + Pattern pattern = Pattern.compile(URL_PATTERN); + Matcher matcher = pattern.matcher(theUrl); + if (matcher.find()) { + final String reportId = matcher.group(1); // Group 0 is the whole string, group 1 is REPORT_RXX + String target = "/index.jsp?rd_id=" + reportId.toLowerCase(Locale.FRENCH); + RequestDispatcher dispatcher = context.getRequestDispatcher(target); + // Will go to each report's report_rXX.html + dispatcher.forward(aRequest, aResponse); + } + else { + String theErrorTitle = "Unable to download file"; + String theErroMessage = "Could not extract target report of the form \"" + URL_PATTERN + "\" in request URL parameters"; + log.error(theErrorTitle + ": " + theErroMessage + " = " + theUrl); + ErrorPageTemplate theErrorTemplate = new ErrorPageTemplate(theErrorTitle, theErroMessage); + aResponse.getWriter().write(theErrorTemplate.generateCode()); + } + } +} diff --git a/kurt-web/src/main/java/com/capgemini/reports/auto/AbstractAutoLaunchServlet.java b/kurt-web/src/main/java/com/capgemini/reports/auto/AbstractAutoLaunchServlet.java new file mode 100644 index 0000000..8022522 --- /dev/null +++ b/kurt-web/src/main/java/com/capgemini/reports/auto/AbstractAutoLaunchServlet.java @@ -0,0 +1,160 @@ +package com.capgemini.reports.auto; + +import com.capgemini.framework.common.SettingsHelper; +import com.capgemini.framework.common.TeamcenterDateFormatter; +import com.capgemini.framework.common.activedirectory.ActiveDirectory; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.reports.database.DataBaseReportHelper; +import com.capgemini.reports.database.HibernateUtil; +import com.capgemini.reports.database.javabean.DbReport; +import com.capgemini.reports.database.javabean.DbUser; +import com.capgemini.reports.database.javabean.DbUser.UserData; +import com.capgemini.reports.database.manager.MngCriteriaVal.CriteriaValue; +import com.capgemini.reports.database.manager.MngUser; +import com.capgemini.reports.exceptions.InsufficientParametersException; +import com.capgemini.reports.exceptions.InvalidActiveDirectorySearchException; +import com.capgemini.reports.exceptions.InvalidInputException; +import com.capgemini.reports.exceptions.NoConnectionToActiveDirectoryException; +import com.capgemini.reports.execution.AbstractExecutionReport; +import com.capgemini.reports.logging.ReportLoggerHelper; +import com.capgemini.reports.queuing.EmbeddedServer; +import lombok.extern.slf4j.Slf4j; +import org.hibernate.HibernateException; +import org.hibernate.Session; +import org.hibernate.SessionFactory; + +import javax.jms.JMSException; +import javax.naming.NamingException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.List; + +/** + * An abstract {@link HttpServlet} for classes that launch a report from an automatic Workflow request.
    + * This servlet expects the Tc workflow owner to be passed as parameter: http:\\[URL]?[parameters]&userID=toto[&...] + * + * @param the exact {@link AbstractExecutionReport} report type + */ +@Slf4j +public abstract class AbstractAutoLaunchServlet> extends HttpServlet { + + private static final long serialVersionUID = -8586399099581830304L; + + private static final String URL_PARAMETER_OWNER_LOGIN = "userID"; + + private static final boolean DEV_MODE = SettingsHelper.isDevMode(); + + @Override + protected void doGet(final HttpServletRequest aRequest, final HttpServletResponse aResponse) throws IOException { + String relaunchURL = makeRelaunchURL(aRequest); + SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); + Session session = sessionFactory.openSession(); + try { + // Register owner + final DbUser dbUser = retrieveUserInAdAndDb(session, aRequest); + + // Generate the report definition + T report = processFunctionalParams(aRequest); + + // Prepare execution roadmap + setupSchedulingStrategy(relaunchURL, report); + + // Prepare the report execution parameters + List launchData = report.getLaunchData(); + String reportCode = report.getReportIdentifier().getReportCode(); + log.info("Server received a request to perform a {} report from WKF, owned by user {} with parameters: {}", reportCode, dbUser.getLogin(), + launchData); + + // Register current time as the posting time + report.setPostingTime(TeamcenterDateFormatter.getCurrentTime()); + + // Post the report into the queues + EmbeddedServer.produce(report); + + // Record the report launch in the database, and log this + DbReport theReportEntry = DataBaseReportHelper.registerLaunch(report, dbUser); + + // Log the report request (AFTER the email is sent, so that the report knows its startTime) + ReportLoggerHelper.logRequest(dbUser, theReportEntry, report); + // Normal processing termination, return success code + aResponse.setStatus(HttpServletResponse.SC_NO_CONTENT); // Successful, but no content to return + } + catch (KurtException | JMSException | NamingException e) { + aResponse.setStatus(HttpServletResponse.SC_BAD_REQUEST); // 400 Bad Request + aResponse.getWriter().write(e.getMessage()); + log.warn(e.getMessage(), e); + } + finally { + try { + session.close(); + } + catch (HibernateException e) { + log.error(e.getMessage(), e); + } + } + } + + protected abstract void setupSchedulingStrategy(String relaunchURL, T report); + + private String makeRelaunchURL(HttpServletRequest aRequest) { + StringBuffer requestURL = aRequest.getRequestURL(); + String queryString = aRequest.getQueryString(); + String fullURL; + if (queryString == null) { + fullURL = requestURL.toString(); + } + else { + fullURL = requestURL.append('?').append(queryString).toString(); + } + return fullURL; + } + + @Override + protected void doPost(final HttpServletRequest aRequest, final HttpServletResponse aResponse) throws IOException { + doGet(aRequest, aResponse); + } + + /** + * Retrieve/update the DB User.
    + * Steps followed: + *
      + *
    1. fetch the user UID in the URL
    2. + *
    3. Obtain the TC object 'User' with this UID
    4. + *
    5. Read user login from Tc user
    6. + *
    7. Request ActiveDirectory for Data about this login (email, names etc.)
    8. + *
    9. Fetch/Update/Create the user in the DB accordingly.
    10. + *
    + */ + private DbUser retrieveUserInAdAndDb(Session session, final HttpServletRequest aRequest) throws InsufficientParametersException, + NoConnectionToActiveDirectoryException, InvalidActiveDirectorySearchException, InvalidInputException { + // Parse user ID + String ownerLogin = aRequest.getParameter(URL_PARAMETER_OWNER_LOGIN); + if (ownerLogin == null || ownerLogin.isEmpty()) { + throw new InsufficientParametersException("No user UID was provided in URL"); + } + + // Find this same login in the ActiveDirectory + UserData adUser; + if (DEV_MODE) { + adUser = ActiveDirectory.getGuestUser(); + } + else { + adUser = ActiveDirectory.obtainUserData(ownerLogin); + } + + // Find / update / create corresponding user in DB + return new MngUser().fetchOrUpdateOrCreateUser(session, adUser); + } + + /** + * Generates a report according the the request. + * + * @param aRequest the {@link HttpServletRequest} + * @return a report Execution + * @throws InsufficientParametersException + */ + protected abstract T processFunctionalParams(final HttpServletRequest aRequest) throws InsufficientParametersException; + +} diff --git a/kurt-web/src/main/java/com/capgemini/reports/common/AbstractKurtServlet.java b/kurt-web/src/main/java/com/capgemini/reports/common/AbstractKurtServlet.java new file mode 100644 index 0000000..cbc4857 --- /dev/null +++ b/kurt-web/src/main/java/com/capgemini/reports/common/AbstractKurtServlet.java @@ -0,0 +1,165 @@ +package com.capgemini.reports.common; + +import com.capgemini.framework.common.MapHelper; +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.exceptions.NoTeamcenterConnectionException; +import com.capgemini.framework.teamcenter.exceptions.runtime.ConnectionLostException; +import com.capgemini.reports.exceptions.DuplicateReportEntryFound; +import com.capgemini.reports.exceptions.InvalidInputException; +import com.capgemini.reports.exceptions.InvalidUserInputException; +import lombok.extern.slf4j.Slf4j; +import org.json.JSONObject; +import org.quartz.SchedulerException; + +import javax.jms.JMSException; +import javax.naming.NamingException; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; + +/** Abstract class providing a framework for all servlets communicating with the application. **/ +@Slf4j +public abstract class AbstractKurtServlet extends HttpServlet { + private static final long serialVersionUID = 7233193093588056531L; + + private static final String CONTENT_TYPE_JSON = "application/json"; + + /** + * Receives user input, forwards to the actual implementation in .
    + * If the report could not be posted in the queue, then the resulting {@link JMSException} will be caught here, and a standardized failure message will be sent back to the server. + * + * @param request the user request + * @param response the response (a JSON object) + * @throws ServletException + * @throws IOException + * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) + */ + @Override + protected void doPost(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException { + // Parse server request parameters + processParams(request); + + JSONObject computedResponse; + try (TcSession session = new TcSession()) { + session.login(); + computedResponse = perform(request, session); + response.setContentType(CONTENT_TYPE_JSON); + response.getWriter().write(computedResponse.toString()); + } catch (DuplicateReportEntryFound e) { + // The user is requesting a report with specific criteria, but a similar request has been made recently. + log.debug("A Previous similar report execution request has been found, adding user to wishlist for this report.", e); + response.setContentType(CONTENT_TYPE_JSON); + response.getWriter().write(ServletMessageHelper.successMessage(e.getErrorMessageForUser()).toString()); + } catch (InvalidUserInputException e) { + // A nice error message will be sent to the user to tell him what he did wrong + log.error(e.getMessage(), e); + response.setContentType(CONTENT_TYPE_JSON); + response.getWriter().write(ServletMessageHelper.errorMessage(e).toString()); + } catch (NamingException e) { + // Error due to miscommunication with the JMS queuing system + log.error(ServletMessageHelper.POSTING_ERROR_MESSAGE_EN, e); + response.getWriter().write(ServletMessageHelper.errorMessage(e).toString()); + } catch (JMSException e) { + // Error due to miscommunication with the JMS queuing system + log.error(ServletMessageHelper.POSTING_ERROR_MESSAGE_EN, e); + response.getWriter().write(ServletMessageHelper.errorMessage(e).toString()); + } catch (SchedulerException e) { + // Error due to miscommunication with the scheduler system + log.error("Error caught while trying to delay the report.", e); + response.getWriter().write(ServletMessageHelper.errorMessage(e).toString()); + } catch (NoTeamcenterConnectionException e) { + // Error due to miscommunication with the Teamcenter servers + log.error("Unable to connect to the Teamcenter server", e); + response.getWriter().write(ServletMessageHelper.errorMessage(e).toString()); + } catch (ConnectionLostException e) { + // Runtime exception, happens when connection is suddenly lost and not recovered despite attempts to do so + log.error("Connection lost to Teamcenter server", e); + response.getWriter().write(ServletMessageHelper.errorMessage(e).toString()); + } + } + + /** + * Forwarder of GET access to POST. + * + * @param request the user request + * @param response the response (a JSON object) + * @throws ServletException + * @throws IOException + * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) + */ + @Override + protected void doGet(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException { + doPost(request, response); + } + + /** + * Parsing method for JSP request parameters. + * + * @param aRequest + */ + private void processParams(final HttpServletRequest aRequest) { + if (!log.isDebugEnabled()) { + return; + } + // Parse headers + Map theParsingMap = new HashMap<>(); + Enumeration headerEnum = aRequest.getHeaderNames(); + while (headerEnum.hasMoreElements()) { + String currentHeader = headerEnum.nextElement(); + Object attribute = aRequest.getAttribute(currentHeader); + String currentValue = attribute == null ? "" : attribute.toString(); + theParsingMap.put(currentHeader, currentValue); + } + log.debug("Request headers: " + MapHelper.toString(theParsingMap)); + + // Parse attributes + theParsingMap = new HashMap<>(); + Enumeration attNameEnum = aRequest.getAttributeNames(); + while (attNameEnum.hasMoreElements()) { + String currentAtt = attNameEnum.nextElement(); + Object attribute = aRequest.getAttribute(currentAtt); + String currentValue = attribute == null ? "" : attribute.toString(); + theParsingMap.put(currentAtt, currentValue); + } + log.debug("Request attributes: " + MapHelper.toString(theParsingMap)); + + // Parse parameters + theParsingMap = new HashMap<>(); + Map parameterMap = aRequest.getParameterMap(); + for (Entry entry : parameterMap.entrySet()) { + String[] currentParamArray = entry.getValue(); + if (currentParamArray.length == 1) { + theParsingMap.put(entry.getKey(), currentParamArray[0]); + } else { + for (int i = 0; i < currentParamArray.length; i++) { + theParsingMap.put(entry.getKey() + "[" + i + "]", currentParamArray[i]); + } + } + } + log.debug("Request parameters: " + MapHelper.toString(theParsingMap)); + } + + /** + * This method will perform the job of the application.
    + * This method may throw a {@link InvalidInputException} with a nice failure message to the user.
    + * This method may throw any {@link KurtException} but, the user will receive a standardized failure message. + * + * @param request the request + * + * @return A {@link JSONObject} containing the response + * + * @throws JMSException can be thrown if the job could not be posted into the queues. + * @throws NamingException can be thrown when the required Queue could not be found + * @throws InvalidInputException when the user gave bad inputs. The exceptions should contain a nice error message, which will be sent to the user. + * @throws KurtException when some bug occurred. A generic error message will be sent to the user. + */ + protected abstract JSONObject perform(final HttpServletRequest request, final TcSession session) + throws JMSException, InvalidUserInputException, NamingException, SchedulerException; +} diff --git a/kurt-web/src/main/java/com/capgemini/reports/common/AbstractSubmitServlet.java b/kurt-web/src/main/java/com/capgemini/reports/common/AbstractSubmitServlet.java new file mode 100644 index 0000000..ed471b3 --- /dev/null +++ b/kurt-web/src/main/java/com/capgemini/reports/common/AbstractSubmitServlet.java @@ -0,0 +1,177 @@ +package com.capgemini.reports.common; + +import com.capgemini.framework.common.StringHelper; +import com.capgemini.framework.common.TeamcenterDateFormatter; +import com.capgemini.framework.common.activedirectory.ActiveDirectory; +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.reports.checkdata.CheckingDataHelper; +import com.capgemini.reports.database.DataBaseReportHelper; +import com.capgemini.reports.database.HibernateUtil; +import com.capgemini.reports.database.javabean.DbReport; +import com.capgemini.reports.database.javabean.DbUser; +import com.capgemini.reports.database.javabean.DbUser.UserData; +import com.capgemini.reports.database.manager.MngCriteriaVal.CriteriaValue; +import com.capgemini.reports.database.manager.MngReport; +import com.capgemini.reports.database.manager.MngReport.RunningReportEntry; +import com.capgemini.reports.database.manager.MngReportOwner; +import com.capgemini.reports.database.manager.MngUser; +import com.capgemini.reports.exceptions.*; +import com.capgemini.reports.execution.AbstractExecutionReport; +import com.capgemini.reports.execution.posting.DelayedPostingStategy; +import com.capgemini.reports.execution.posting.ImmediatePostingStrategy; +import com.capgemini.reports.logging.ReportLoggerHelper; +import com.capgemini.reports.quartz.SchedulerServer; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.json.JSONObject; +import org.quartz.SchedulerException; + +import javax.ejb.EJB; +import javax.jms.JMSException; +import javax.naming.NamingException; +import javax.servlet.http.HttpServletRequest; +import java.util.List; + +/** + * Abstract class providing the framework for submitting and checking the necessary parameters to produce a report. + * + * @param the sub-class of AbstractExecutionReport that this servlet will generate + */ +@Slf4j +public abstract class AbstractSubmitServlet> extends AbstractKurtServlet { + private static final long serialVersionUID = -9065306729627250134L; + + @Getter + @EJB + protected SchedulerServer schedulingServer; + + @Override + protected JSONObject perform(final HttpServletRequest request, final TcSession tcSession) throws JMSException, + InvalidUserInputException, NamingException, SchedulerException { + // Identify the user using the LDAP + UserData adUser = identifyUser(request); + + // Prepare the report execution parameters + AbstractExecutionReport report = prepareReport(request); + List launchData = report.getLaunchData(); + String reportCode = report.getReportIdentifier().getReportCode(); + + SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); + Session session = sessionFactory.openSession(); + try { + // Find / update / create corresponding user in DB + DbUser dbUser = new MngUser().fetchOrUpdateOrCreateUser(session, adUser); + log.info("Server received a request to perform a {} report from user {} with parameters: {}", reportCode, dbUser.getLogin(), launchData); + + // Verify that the report has not been already requested not too long ago + List duplicates = new MngReport().searchQueuedReportsWithCriteria(session, report.getReportIdentifier(), launchData); + if (!duplicates.isEmpty()) { + // Previous report execution detected: this report is a duplicate + if (userOwnsOneReport(dbUser, duplicates)) { + // Forbidding same user to submit report twice + throw new DuplicateReportEntryFound(); + } + RunningReportEntry dupe = duplicates.get(0); + // Subscribing user to existing report execution + new MngReportOwner().subscribe(session, dbUser, dupe); + if (dbUser.getEmail() == null || dbUser.getEmail().isEmpty()) { + // This user does not have an email Address, send a warning email to the user + log.warn("Cet utilisateur abonné au résultat de ce rapport n’a pas d’adresse mail : {} {}", report.getReportIdentifier().getReportName(), dbUser.getLogin()); + } + throw new DuplicateReportEntryFound(dupe.getSafeName()); + } + + // Do a quick Check. If it fails, the exception thrown will carry a message to the user's webpage + log.debug("Report {} is not a duplicate, Beginning quick checks...", reportCode); + try { + CheckingDataHelper.doQuickCheck(tcSession, report); + } + catch (FileLoadingException e) { + log.error("Policy file could not be read", e); + return ServletMessageHelper.errorMessage(e); + } + log.debug("All quick checks have passed for {}", reportCode); + + // Register current time as the posting time + report.setPostingTime(TeamcenterDateFormatter.getCurrentTime()); + + // Perform the requested strategy: post immediately, or wait some delay + switch (report.getLaunchType()) { + case DELAYED: + new DelayedPostingStategy(schedulingServer).handleRequest(report); + break; + case IMMEDIATE: + new ImmediatePostingStrategy().handleRequest(report); + break; + default: + final String msg = + StringHelper.concatToString("Unable to perform the SUBMIT request, the execution strategy ", report.getLaunchType() + .toString(), " is unknwon for report ", report.getReportTechnicalUid()); + throw new UnsupportedOperationException(msg); + } + + // Record the report launch in the database, and log this + DbReport theReportEntry = DataBaseReportHelper.registerLaunch(report, dbUser); + + // Log the report request (AFTER the email is sent, so that the report knows its startTime) + ReportLoggerHelper.logRequest(dbUser, theReportEntry, report); + + // Return a success message + return sendSuccessMsg(report); + } + finally { + session.close(); + } + } + + private JSONObject sendSuccessMsg(final AbstractExecutionReport report) { + switch (report.getLaunchType()) { + case DELAYED: + // Return a nice success message to the user + return ServletMessageHelper.successMessage("Le rapport \"" + report.getReportIdentifier().getReportTitle() + + "\" est différé"); + default: + // This case is for IMMEDIATE type + return ServletMessageHelper.successMessage("Le rapport \"" + report.getReportIdentifier().getReportTitle() + + "\" a bien été soumis"); + } + } + + private boolean userOwnsOneReport(final DbUser dbUser, final List duplicates) { + for (RunningReportEntry report : duplicates) { + if (dbUser.getLogin() != null && dbUser.getLogin().equals(report.getLogin())) { + return true; + } + } + return false; + } + + private UserData identifyUser(final HttpServletRequest request) { + // Obtain userName, and user email through authentication + String userName = request.getRemoteUser(); + try { + return ActiveDirectory.obtainUserData(userName); + } + catch (NoConnectionToActiveDirectoryException e) { + log.warn("Could not connect to the AD to authenticate the user, using GUEST", e); + } + catch (InvalidInputException e) { + log.warn("AD Could not authenticate the user, using GUEST", e); + } + catch (InvalidActiveDirectorySearchException e) { + log.warn("Could not perform a search on the AD, using GUEST", e); + } + // Guest user when authentication failed + return ActiveDirectory.getGuestUser(); + } + + /** + * Provide the {@link AbstractExecutionReport} with the parameters. + * + * @param request the client request. + * @return the report execution, with its parameters checked, to be posted in the queues. + */ + public abstract T prepareReport(final HttpServletRequest request); +} diff --git a/kurt-web/src/main/java/com/capgemini/reports/common/AbstractSubmitServletForItemRevision.java b/kurt-web/src/main/java/com/capgemini/reports/common/AbstractSubmitServletForItemRevision.java new file mode 100644 index 0000000..d93cd53 --- /dev/null +++ b/kurt-web/src/main/java/com/capgemini/reports/common/AbstractSubmitServletForItemRevision.java @@ -0,0 +1,35 @@ +package com.capgemini.reports.common; + +import com.capgemini.reports.execution.AbstractExecutionReport; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +import javax.servlet.http.HttpServletRequest; + +/** + * Abstract class providing the framework for submitting and checking the necessary parameters to produce a report on an {@link ItemRevision}. + * + * @param a subType of {@link AbstractExecutionReport} + */ +public abstract class AbstractSubmitServletForItemRevision> extends AbstractSubmitServlet { + + private static final long serialVersionUID = -3114366972057429074L; + + @Override + public T prepareReport(final HttpServletRequest request) { + // findAll parameters for KurtItemRevision + String partId = request.getParameter("num_article"); + String partRevision = request.getParameter("rev_article"); + return prepareReport(partId, partRevision, request); + } + + /** + * The main method. Builds an {@link AbstractExecutionReport} using the itemId, item Revision, and the request to eventually obtain additional parameters. + * + * @param itemId + * @param itemRev + * @param request + * @return + */ + protected abstract T prepareReport(final String itemId, final String itemRev, final HttpServletRequest request); + +} diff --git a/kurt-web/src/main/java/com/capgemini/reports/common/DownloadServlet.java b/kurt-web/src/main/java/com/capgemini/reports/common/DownloadServlet.java new file mode 100644 index 0000000..1ae9a5d --- /dev/null +++ b/kurt-web/src/main/java/com/capgemini/reports/common/DownloadServlet.java @@ -0,0 +1,127 @@ +package com.capgemini.reports.common; + +import com.capgemini.framework.common.SettingsHelper; +import com.capgemini.framework.common.StringHelper; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.reports.database.HibernateUtil; +import com.capgemini.reports.database.javabean.DbReport; +import com.capgemini.reports.database.manager.MngReport; +import com.capgemini.reports.exceptions.InsufficientParametersException; +import com.capgemini.reports.exceptions.NotFoundException; +import com.capgemini.reports.formatting.ErrorPageTemplate; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.io.IOUtils; +import org.hibernate.Session; +import org.hibernate.SessionFactory; + +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; + +/** + * JSP Servlet for downloading file content from web GUI. + */ +@Slf4j +@WebServlet("/downloadServlet") +public class DownloadServlet extends HttpServlet { + private static final long serialVersionUID = 4856158363304758345L; + + private static final String OUTPUT_FOLDER = SettingsHelper.getReportLocation(); + private static final String OUTPUT_FOLDER_SCHEDULING_HISTORY = SettingsHelper.getSchedulingHistoryLocation(); + + private static final String UNABLE_TO_DOWNLOAD_FILE = "Unable to download the file"; + + @Override + protected void doGet(final HttpServletRequest aRequest, final HttpServletResponse aResponse) throws ServletException, IOException { + SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); + Session session = sessionFactory.openSession(); + try { + // Check URL argument + String theReportUid = getMandatoryArg(aRequest, "reportUid"); + + MngReport theMngReport = new MngReport(); + DbReport theReport = theMngReport.searchByUid(theReportUid, session); + if (theReport == null) { + throw new NotFoundException("The report has not been found for uid: " + theReportUid); + } + + // Build file path + String theFilePathValue = makeFileName(theReport); + + // Secure file path + theFilePathValue = theFilePathValue.replace("..", "").replace("//", "/"); + + // Extract binary content + downloadFile(aResponse, theFilePathValue, theReport.getFileName()); + } + catch (KurtException e) { + String theErrorTitle = UNABLE_TO_DOWNLOAD_FILE; + log.error(theErrorTitle, e); + ErrorPageTemplate theErrorTemplate = new ErrorPageTemplate(theErrorTitle, e.getMessage()); + aResponse.getWriter().write(theErrorTemplate.generateCode()); + } + finally { + session.close(); + } + } + + private String makeFileName(final DbReport theReport) throws NotFoundException { + String[] split = theReport.getFileName().split("\\."); + if (split.length != 2) { + throw new NotFoundException("Could not extract file name and extension from DB: " + theReport.getFileName()); + } + String fileNameNoExtension = split[0]; + String extension = split[1]; + + // Define which folder to findAll + if (theReport.getSchedulingReportId() == null) { + return StringHelper.concatToString(OUTPUT_FOLDER, "/", fileNameNoExtension, "_", theReport.getReportUid(), ".", extension); + } + else { + return StringHelper.concatToString(OUTPUT_FOLDER_SCHEDULING_HISTORY, "/", fileNameNoExtension, ".", extension); + } + } + + /** + * Try to download a file from the output directory. + */ + private void downloadFile(final HttpServletResponse aResponse, final String aFilePathValue, final String fileName) + throws IOException, InsufficientParametersException, NotFoundException { + final File theSourceFile = new File(aFilePathValue); + if (!theSourceFile.exists() || theSourceFile.isDirectory()) { + throw new NotFoundException("The source file does not exist: " + aFilePathValue); + } + + long theFileSize = theSourceFile.length(); + if (theFileSize == 0) { + throw new NotFoundException("The source file is empty: " + aFilePathValue); + } + + try (FileInputStream input = new FileInputStream(theSourceFile); ServletOutputStream out = aResponse.getOutputStream()) { + aResponse.setContentType("application/download"); + aResponse.setHeader("Content-Disposition", "attachment;filename=\"" + fileName + "\""); + aResponse.setContentLength((int) theFileSize); + IOUtils.copy(input, out); + } + catch (IOException e) { + log.error(UNABLE_TO_DOWNLOAD_FILE, e); + } + } + + /** + * Try to findAll an argument value in the URL and return an error message in JSP when it failed. + */ + private static String getMandatoryArg(final HttpServletRequest aRequest, final String anArgName) throws ServletException, IOException, InsufficientParametersException { + String theArgValue = aRequest.getParameter(anArgName); + if (theArgValue == null) { + throw new InsufficientParametersException("Missing required argument in URL: " + anArgName); + } + return theArgValue; + } +} diff --git a/kurt-web/src/main/java/com/capgemini/reports/common/ServletMessageHelper.java b/kurt-web/src/main/java/com/capgemini/reports/common/ServletMessageHelper.java new file mode 100644 index 0000000..a40042a --- /dev/null +++ b/kurt-web/src/main/java/com/capgemini/reports/common/ServletMessageHelper.java @@ -0,0 +1,146 @@ +package com.capgemini.reports.common; + +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.exceptions.NoTeamcenterConnectionException; +import com.capgemini.framework.teamcenter.exceptions.runtime.ConnectionLostException; +import com.capgemini.reports.exceptions.InvalidInputException; +import com.capgemini.reports.exceptions.InvalidUserInputException; +import com.capgemini.reports.exceptions.UserInputErrorEnum; +import org.json.JSONObject; +import org.quartz.SchedulerException; + +import javax.jms.JMSException; +import javax.naming.NamingException; + +/** Helper class that provides several error and success messages with standardized KEYS and TOKENS that are understood by the HMI. */ +public final class ServletMessageHelper { + + private ServletMessageHelper() { + + } + + /** + * TOKEN to obtain request TcReleaseStatus from the JSON response. + */ + public static final String TOKEN_STATUS = "status"; + /** TOKEN to obtain error explanation from the JSON response when STATUS is FAILED. */ + public static final String TOKEN_ERROR = "error"; + /** TOKEN to obtain success message from the JSON response. */ + public static final String TOKEN_SUCCESS_MSG = "success"; + + /** STATUS value for the JSON response when posting is successful. */ + public static final String STATUS_SUCCESS = TOKEN_SUCCESS_MSG; + /** STATUS value for the JSON response when posting has failed. */ + public static final String STATUS_FAILED = "failed"; + /** STATUS value for the JSON response when user should be prompted before actually launching the report. */ + public static final String STATUS_PROMPT = "prompt"; + + protected static final String POSTING_ERROR_MESSAGE_EN = "Error caught while trying to submit the report into the Queue"; + protected static final String POSTING_ERROR_MESSAGE_FR = + new InvalidUserInputException(UserInputErrorEnum.INTERNAL_ERROR).getErrorMessageForUser(); + private static final String DELAY_ERROR_MESSAGE_FR = "Impossible de planifier une exécution"; + private static final String TEAMCENTER_UNAVAILABLE_EXCEPTION_MSG_FR = "Impossible de communiquer avec le serveur Teamcenter"; + private static final String TEAMCENTER_CONNECTION_LOST_EXCEPTION_MSG_FR = + "Le serveur Teamcenter a cessé de répondre, réessayez ultérieurement. Si le problème persiste, contactez l'administrateur."; + + /** + * Helper function to return standardized success messages to the client. + * + * @param msg the message + * @return the {@link JSONObject} + */ + public static JSONObject successMessage(final String msg) { + return new JSONObject().put(TOKEN_STATUS, STATUS_SUCCESS).put(TOKEN_SUCCESS_MSG, msg); + } + + /** + * Helper function for producing standardized JSON error messages to be sent to server in case a fault is found. + * + * @param msg the message + * @return the {@link JSONObject} + */ + public static JSONObject errorMessage(final String msg) { + return new JSONObject().put(TOKEN_STATUS, STATUS_FAILED).put(TOKEN_ERROR, msg); + } + + /** + * Helper function for producing standardized JSON error messages to be sent to server in case a InvalidUserInputException is triggered by a user. + * + * @param exception the {@link InvalidUserInputException} that caused the failure and contains a nice error message for the user + * @return the {@link JSONObject} containing the status and a nice error message for the user + */ + public static JSONObject errorMessage(final InvalidUserInputException exception) { + return new JSONObject().put(TOKEN_STATUS, STATUS_FAILED).put(TOKEN_ERROR, exception.getErrorMessageForUser()); + } + + /** + * Helper function for producing standardized JSON error messages to be sent to server in case a InvalidInputException occurred. + * + * @param exception the {@link InvalidInputException} that caused the failure and contains a nice error message for the user + * @return the {@link JSONObject} containing the status and a nice error message for the user + */ + public static JSONObject errorMessage(final InvalidInputException exception) { + return new JSONObject().put(TOKEN_STATUS, STATUS_FAILED).put(TOKEN_ERROR, exception.getErrorMessageForUser()); + } + + /** + * Helper function for producing standardized JSON error messages to be sent to server in case a fault is found. + * + * @param exception the generic {@link KurtException} that caused the failure + * @return the {@link JSONObject} containing the status and a generic error message + */ + public static JSONObject errorMessage(final KurtException exception) { + return new JSONObject().put(TOKEN_STATUS, STATUS_FAILED).put(TOKEN_ERROR, exception.getMessage()); + } + + /** + * Helper function for producing standardized JSON error messages to be sent to server in case a NamingException occurred. + * + * @param exception the {@link NamingException} that caused the failure + * @return the {@link JSONObject} containing the status and an error message + */ + public static JSONObject errorMessage(final NamingException exception) { + return new JSONObject().put(TOKEN_STATUS, STATUS_FAILED).put(TOKEN_ERROR, ServletMessageHelper.POSTING_ERROR_MESSAGE_FR); + } + + /** + * Helper function for producing standardized JSON error messages to be sent to server in case a JMSException occurred. + * + * @param exception the {@link JMSException} that caused the failure + * @return the {@link JSONObject} containing the status and an error message + */ + public static JSONObject errorMessage(final JMSException exception) { + return new JSONObject().put(TOKEN_STATUS, STATUS_FAILED).put(TOKEN_ERROR, ServletMessageHelper.POSTING_ERROR_MESSAGE_FR); + } + + /** + * Helper function for producing standardized JSON error messages to be sent to server in case a SchedulerException occurred. + * + * @param exception the {@link SchedulerException} that caused the failure + * @return the {@link JSONObject} containing the status and an error message + */ + public static JSONObject errorMessage(final SchedulerException exception) { + return new JSONObject().put(TOKEN_STATUS, STATUS_FAILED).put(TOKEN_ERROR, ServletMessageHelper.DELAY_ERROR_MESSAGE_FR); + } + + /** + * Helper function for producing standardized JSON error messages to be sent to server in case a NoTeamcenterConnectionException occurred. + * + * @param exception the {@link NoTeamcenterConnectionException} that caused the failure + * @return the {@link JSONObject} containing the status and an error message + */ + public static JSONObject errorMessage(final NoTeamcenterConnectionException exception) { + return new JSONObject().put(TOKEN_STATUS, STATUS_FAILED).put(TOKEN_ERROR, ServletMessageHelper.TEAMCENTER_UNAVAILABLE_EXCEPTION_MSG_FR); + } + + /** + * Helper function for producing standardized JSON error messages to be sent to server in case a ConnectionLostException occurred. + * + * @param exception the {@link ConnectionLostException} that caused the failure + * @return the {@link JSONObject} containing the status and an error message + */ + public static JSONObject errorMessage(final ConnectionLostException exception) { + return new JSONObject().put(TOKEN_STATUS, STATUS_FAILED).put(TOKEN_ERROR, ServletMessageHelper.TEAMCENTER_CONNECTION_LOST_EXCEPTION_MSG_FR); + } + +} diff --git a/kurt-web/src/main/java/com/capgemini/reports/common/TestServlet.java b/kurt-web/src/main/java/com/capgemini/reports/common/TestServlet.java new file mode 100644 index 0000000..4d9349d --- /dev/null +++ b/kurt-web/src/main/java/com/capgemini/reports/common/TestServlet.java @@ -0,0 +1,77 @@ +package com.capgemini.reports.common; + +import java.io.IOException; +import java.util.Enumeration; +import java.util.Map; +import java.util.Map.Entry; + +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import lombok.extern.slf4j.Slf4j; + +/** + * JSP Servlet for downloading file content from web GUI. + */ +@Slf4j +@WebServlet("/testServlet") +public class TestServlet extends HttpServlet { + + /** Default serial UID. **/ + private static final long serialVersionUID = 1L; + + @Override + protected void doGet(final HttpServletRequest aRequest, final HttpServletResponse aResponse) throws ServletException, IOException { + + log.info("GET RECEIVED"); + processParams(aRequest, aResponse); + } + + @Override + protected void doPost(final HttpServletRequest aRequest, final HttpServletResponse aResponse) throws ServletException, IOException { + log.info("POST RECEIVED"); + + processParams(aRequest, aResponse); + } + + + private void processParams(final HttpServletRequest aRequest, final HttpServletResponse aResponse) { + + Enumeration attNameEnum = aRequest.getAttributeNames(); + while (attNameEnum.hasMoreElements()) { + String currentAtt = attNameEnum.nextElement(); + log.info("\t - Att: " + currentAtt + "=" + aRequest.getAttribute(currentAtt)); + } + + Enumeration headerEnum = aRequest.getHeaderNames(); + while (headerEnum.hasMoreElements()) { + String currentHeader = headerEnum.nextElement(); + log.info("\t - Head: " + currentHeader + "=" + aRequest.getHeader(currentHeader)); + } + + Map parameterMap = aRequest.getParameterMap(); + + for (Entry entry : parameterMap.entrySet()) { + + String[] currentParamArray = entry.getValue(); + if (currentParamArray.length == 1) { + log.info(entry.getKey() + "=" + currentParamArray[0]); + } + else { + for (int i = 0; i < currentParamArray.length; i++) { + log.info(entry.getKey() + "[" + i + "] =" + currentParamArray[i]); + } + } + } + + try { + aResponse.getWriter().write("FINISHED"); + } + catch (IOException e) { + log.error("Error", e); + } + } +} diff --git a/kurt-web/src/main/java/com/capgemini/reports/common/obtaindata/AbstractObtainDataFromItemRevision.java b/kurt-web/src/main/java/com/capgemini/reports/common/obtaindata/AbstractObtainDataFromItemRevision.java new file mode 100644 index 0000000..6be1ee0 --- /dev/null +++ b/kurt-web/src/main/java/com/capgemini/reports/common/obtaindata/AbstractObtainDataFromItemRevision.java @@ -0,0 +1,95 @@ +package com.capgemini.reports.common.obtaindata; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.reports.exceptions.InvalidUserInputException; +import com.capgemini.reports.exceptions.NotFoundException; +import com.capgemini.reports.exceptions.UserInputErrorEnum; +import com.capgemini.reports.teamcenter.queries.DirectQuery; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import lombok.extern.slf4j.Slf4j; +import org.json.JSONObject; + +import javax.servlet.http.HttpServletRequest; + +/** + * This class is a servlet that handles requests to perform a report on an ItemRevision. + */ +@Slf4j +public abstract class AbstractObtainDataFromItemRevision extends AbstractObtainDataServlet { + private static final long serialVersionUID = 7666172651622505390L; + + @Override + protected JSONObject obtainData(final HttpServletRequest request, final TcSession session) throws InvalidUserInputException { + // Obtain the URL parameters + String objectUID = request.getParameter("dataValues"); + + ItemRevision itemRev = getItemRevisionByIUD(objectUID, session); + + String itemID = getItemID(itemRev); + String itemRevisionID = getItemRevisionID(itemRev); + String itemType = itemRev.getTypeObject().getName(); + return obtainDataFromItemRevision(itemID, itemRevisionID, itemType, session); + } + + /** + * Obtains the ItemID of the {@link ItemRevision}. Handles errors nicely. + * + * @param itemRev the Revision ID of the object + * @return the item Id + * @throws InvalidUserInputException thrown in case of internal errors: some properties might not be loaded + */ + private String getItemID(final ItemRevision itemRev) throws InvalidUserInputException { + return itemRev.get_item_id(); + } + + /** + * The main method of this class: receives and stores information on an ItemRevision. + */ + protected abstract JSONObject obtainDataFromItemRevision(final String itemID, final String itemRevisionID, final String itemType, + final TcSession session) throws InvalidUserInputException; + + + /** + * Obtains the revision ID of the {@link ItemRevision}. Handles errors nicely. + * + * @param itemRev the ItemRevision + * @return the itemRevision Id + * @throws InvalidUserInputException thrown in case of internal errors: some properties might not be loaded + */ + private String getItemRevisionID(final ItemRevision itemRev) throws InvalidUserInputException { + return itemRev.get_item_revision_id(); + } + + /** + * Verifies that the UID provided is not corrupt. + * + * @param objectUID the object UID + * @throws InvalidUserInputException thrown if the UID is corrupt (empty, or null) + */ + private void validateInputUID(final String objectUID) throws InvalidUserInputException { + if (objectUID == null) { + throw new InvalidUserInputException("dataValues uid is null"); + } + if (objectUID.isEmpty()) { + throw new InvalidUserInputException(UserInputErrorEnum.OBJECT_DOES_NOT_EXIST); + } + log.info("Server validated parameter dataValues \"{}\"", objectUID); + } + + /** + * Returns the ItemRevision matching the UID provided. Handles errors nicely. + * + * @param uid the item UID + * @param session the Tc session to make the query + * @return the {@link ItemRevision} + * @throws InvalidUserInputException thrown if the object couldn't be found + */ + private ItemRevision getItemRevisionByIUD(final String uid, final TcSession session) throws InvalidUserInputException { + validateInputUID(uid); + try { + return new DirectQuery(session).searchByUID(uid); + } catch (NotFoundException e) { + throw new InvalidUserInputException("Object not found with UID '" + uid + "'", e); + } + } +} diff --git a/kurt-web/src/main/java/com/capgemini/reports/common/obtaindata/AbstractObtainDataFromModelObject.java b/kurt-web/src/main/java/com/capgemini/reports/common/obtaindata/AbstractObtainDataFromModelObject.java new file mode 100644 index 0000000..0967cc5 --- /dev/null +++ b/kurt-web/src/main/java/com/capgemini/reports/common/obtaindata/AbstractObtainDataFromModelObject.java @@ -0,0 +1,86 @@ +package com.capgemini.reports.common.obtaindata; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.reports.exceptions.InvalidUserInputException; +import com.capgemini.reports.exceptions.NotFoundException; +import com.capgemini.reports.exceptions.UserInputErrorEnum; +import com.capgemini.reports.teamcenter.queries.DirectQuery; +import com.teamcenter.soa.client.model.ModelObject; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import org.json.JSONObject; + +import javax.servlet.http.HttpServletRequest; + +/** + * This class is a servlet that handles requests to perform a report on an ModelObject. + */ +@Slf4j +public abstract class AbstractObtainDataFromModelObject extends AbstractObtainDataServlet { + + + private static final long serialVersionUID = 7451192554668264900L; + + private static final String OBJECT_NOT_FOUND_PREFIX = "Object not found with UID '"; + private static final String OBJECT_NOT_FOUND_SUFFIX = "'"; + + @Getter + private String uid; + + @Override + protected JSONObject obtainData(final HttpServletRequest request, final TcSession session) throws InvalidUserInputException { + + // Obtain the URL parameters + uid = request.getParameter("dataValues"); + log.info("Report - search uid for {}", uid); + // findAll model object by uid + ModelObject modelObject = getModelObject(session); + + return obtainDataFromModelObject(modelObject, session); + } + + /** + * The main method of this class: receives and stores information on an ModelObject. + * + * @param modelObject + * @param session a Tc session to validate the input + * @return a {@link JSONObject} contaidning the server response that will be sent back to the browser + * @throws InvalidUserInputException thrown when user posted invalid input parameters + */ + protected abstract JSONObject obtainDataFromModelObject(final ModelObject modelObject, final TcSession session) + throws InvalidUserInputException; + + /** + * Verifies that the UID provided is not corrupt. + * + * @param objectUID + * @throws InvalidUserInputException thrown if the UID is corrupt (empty, or null) + */ + protected void validateInputUID(final String objectUID) throws InvalidUserInputException { + if (objectUID == null) { + throw new InvalidUserInputException("dataValues uid is null"); + } + if (objectUID.isEmpty()) { + throw new InvalidUserInputException(UserInputErrorEnum.OBJECT_DOES_NOT_EXIST); + } + log.info("Server validated parameter dataValues \"{}\"", objectUID); + } + + /** + * Returns the ModelObject matching the UID. Handles errors nicely. + * + * @param session the Tc session to make the query + * @return the {@link ItemRevision} + * @throws InvalidUserInputException thrown if the object couldn't be found + */ + protected ModelObject getModelObject(final TcSession session) throws InvalidUserInputException { + validateInputUID(uid); + try { + return new DirectQuery<>(session).searchByUID(uid); + } catch (NotFoundException e) { + throw new InvalidUserInputException(OBJECT_NOT_FOUND_PREFIX + uid + OBJECT_NOT_FOUND_SUFFIX, e); + } + } + +} diff --git a/kurt-web/src/main/java/com/capgemini/reports/common/obtaindata/AbstractObtainDataFromPartRevision.java b/kurt-web/src/main/java/com/capgemini/reports/common/obtaindata/AbstractObtainDataFromPartRevision.java new file mode 100644 index 0000000..bc0250c --- /dev/null +++ b/kurt-web/src/main/java/com/capgemini/reports/common/obtaindata/AbstractObtainDataFromPartRevision.java @@ -0,0 +1,38 @@ +package com.capgemini.reports.common.obtaindata; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.capgemini.reports.exceptions.InvalidUserInputException; +import com.capgemini.reports.exceptions.UserInputErrorEnum; +import org.json.JSONObject; + +/** This class is a servlet that handles requests to perform a report on a Part. */ +public abstract class AbstractObtainDataFromPartRevision extends AbstractObtainDataFromItemRevision { + + private static final long serialVersionUID = 3679669481879532713L; + + @Override + public JSONObject obtainDataFromItemRevision(final String itemID, final String itemRevisionID, final String itemType, + final TcSession session) throws InvalidUserInputException { + + if (!SnecmaObjectTypes.isPartRevision(itemType)) { + throw new InvalidUserInputException(UserInputErrorEnum.THE_SELECTED_OBJECT_IS_NOT_PERMITTED_ON_THIS_REPORT); + } + return obtainDataFromPartRevision(itemID, itemRevisionID, itemType, session); + } + + /** + * The main method of this class: receives and stores information on a Part Revision. + * + * @param partID the ID of the Part + * @param partRevisionID the revision ID of the Part + * @param partType the type of the Part + * @param session a Tc session to validate the input + * @return a {@link JSONObject} containing the server response that will be sent back to the browser + * @throws InvalidUserInputException thrown when user posted invalid input parameters + */ + public abstract JSONObject obtainDataFromPartRevision(final String partID, final String partRevisionID, final String partType, + final TcSession session) throws InvalidUserInputException; + + +} diff --git a/kurt-web/src/main/java/com/capgemini/reports/common/obtaindata/AbstractObtainDataServlet.java b/kurt-web/src/main/java/com/capgemini/reports/common/obtaindata/AbstractObtainDataServlet.java new file mode 100644 index 0000000..93f8388 --- /dev/null +++ b/kurt-web/src/main/java/com/capgemini/reports/common/obtaindata/AbstractObtainDataServlet.java @@ -0,0 +1,50 @@ +package com.capgemini.reports.common.obtaindata; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.reports.common.AbstractKurtServlet; +import com.capgemini.reports.common.ServletMessageHelper; +import com.capgemini.reports.exceptions.InvalidUserInputException; +import lombok.extern.slf4j.Slf4j; +import org.json.JSONObject; + +import javax.servlet.http.HttpServletRequest; + +/** + * Abstract class providing the framework for request of ajax client. + */ +@Slf4j +public abstract class AbstractObtainDataServlet extends AbstractKurtServlet { + + private static final long serialVersionUID = 7803067312625585174L; + + @Override + protected JSONObject perform(final HttpServletRequest request, final TcSession session) throws InvalidUserInputException { + try { + PolicyLocation policyLocation = obtainLocation(); + session.setObjectPropPolicy(policyLocation); + } catch (KurtException e) { + log.error("Unable to findAll data for request Ajax Client", e); + return ServletMessageHelper.errorMessage("Impossible de retrouver les données, merci de contacter l'administrateur système."); + } + return obtainData(request, session); + } + + /** + * The main method of this class: sets up the environment required to valdiate user input before a report execution. + * + * @param request the web request containing various user inputs + * @param session a Tc session to validate the input + * @return a {@link JSONObject} containing this server's response to the browser + * @throws InvalidUserInputException thrown when user posted invalid input parameters + */ + protected abstract JSONObject obtainData(final HttpServletRequest request, final TcSession session) throws InvalidUserInputException; + + /** + * Returns the {@link PolicyLocation} of the policy to be used to perform some validation on the user inputs. + * + * @return the {@link PolicyLocation} + */ + protected abstract PolicyLocation obtainLocation(); +} diff --git a/kurt-web/src/main/java/com/capgemini/reports/common/scheduling/AbstractGenerateScheduledTemplateServlet.java b/kurt-web/src/main/java/com/capgemini/reports/common/scheduling/AbstractGenerateScheduledTemplateServlet.java new file mode 100644 index 0000000..f4afa92 --- /dev/null +++ b/kurt-web/src/main/java/com/capgemini/reports/common/scheduling/AbstractGenerateScheduledTemplateServlet.java @@ -0,0 +1,240 @@ +package com.capgemini.reports.common.scheduling; + +import com.capgemini.framework.common.ReflectionHelper; +import com.capgemini.framework.common.activedirectory.ActiveDirectory; +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.exceptions.NoTeamcenterConnectionException; +import com.capgemini.framework.teamcenter.exceptions.runtime.ConnectionLostException; +import com.capgemini.reports.common.AbstractSubmitServlet; +import com.capgemini.reports.common.ServletMessageHelper; +import com.capgemini.reports.database.javabean.DbUser.UserData; +import com.capgemini.reports.database.javabean.enumeration.SchedulingEnum; +import com.capgemini.reports.exceptions.*; +import com.capgemini.reports.execution.AbstractExecutionReport; +import com.capgemini.reports.periodicity.PeriodFactory; +import com.capgemini.reports.periodicity.SchedulingPeriod; +import com.capgemini.reports.quartz.SchedulerServer; +import com.google.common.base.Joiner; +import com.teamcenter.schemas.soa._2006_03.exceptions.ServiceException; +import lombok.extern.slf4j.Slf4j; +import org.json.JSONObject; +import org.quartz.SchedulerException; + +import javax.ejb.EJB; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.text.ParseException; +import java.util.Map.Entry; + +/** Abstract class which contains the framework for submitting and checking the necessary parameters to produce a scheduled report. **/ +@Slf4j +public abstract class AbstractGenerateScheduledTemplateServlet extends HttpServlet { + private static final long serialVersionUID = -1942251448070464203L; + + private static final String KEY_DATE = "datepicker_planification"; + private static final String KEY_PERIOD = "period"; + + @EJB + protected SchedulerServer schedulingServer; + + // Configuration for reflection + private static final String CLASS_IMPL_PACKAGE = "com.capgemini.reports."; + private static final String PREFIX_SUBMIT_SERVLET_CLASS = "SubmitServlet"; + private static final String CONTENT_TYPE_JSON = "application/json"; + private static final String INTERNAL_ERROR_MESSAGE_FR = UserInputErrorEnum.INTERNAL_ERROR.getMsgFr(); + + // Keys to findAll data from the HttpServletRequest + private static final String KEY_REPORT_CODE = "report_code"; + private static final String KEY_PLANIFICATION_NAME = "scheduling_name"; + static final String KEY_SCHEDULING_REPORT_ID = "scheduling_report_id"; + + /** + * Forwarder of GET access to POST. + * + * @param request the user request + * @param response the response (a JSON object) + * @throws ServletException + * @throws IOException + * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) + */ + @Override + protected void doGet(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException { + doPost(request, response); + } + + @Override + protected void doPost(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException { + try (TcSession session = new TcSession()) { + session.login(); + JSONObject computedResponse = perform(request, session); + response.setContentType(CONTENT_TYPE_JSON); + response.getWriter().write(computedResponse.toString()); + } catch (DuplicateSchedulingEntryFound e) { + // Error due to miscommunication with the scheduler system + log.error("A Scheduling with the same name already exists.", e); + response.getWriter().write(ServletMessageHelper.errorMessage(e).toString()); + } catch (InvalidUserInputException e) { + // Error due to miscommunication with the scheduler system + log.error("The report parameters were invalid.", e); + response.getWriter().write(ServletMessageHelper.errorMessage(e).toString()); + } catch (SchedulerException e) { + // Error due to miscommunication with the scheduler system + log.error("Error caught while trying to schedule the report.", e); + response.getWriter().write(ServletMessageHelper.errorMessage(e).toString()); + } catch (NotSupportedException e) { + log.error("Unable to find the requested report definition.", e); + response.getWriter().write(ServletMessageHelper.errorMessage(INTERNAL_ERROR_MESSAGE_FR).toString()); + } catch (FileLoadingException e) { + log.error("Unable to read the policies file.", e); + response.getWriter().write(ServletMessageHelper.errorMessage(INTERNAL_ERROR_MESSAGE_FR).toString()); + } catch (NoTeamcenterConnectionException e) { + // Error due to miscommunication with the Teamcenter servers + log.error("Unable to connect to the Teamcenter server", e); + response.getWriter().write(ServletMessageHelper.errorMessage(e).toString()); + } catch (ConnectionLostException e) { + // Runtime exception, happens when connection is suddenly lost and not recovered despite attempts to do so + log.error("Connection lost to Teamcenter server", e); + response.getWriter().write(ServletMessageHelper.errorMessage(e).toString()); + } catch (ServiceException e) { + String msg = "Servlet could not logout the Teamcenter connection Properly, some session might still be running..."; + log.error(msg, e); + } catch (KurtException e) { + log.error("Unable to perform the request.", e); + response.getWriter().write(ServletMessageHelper.errorMessage(INTERNAL_ERROR_MESSAGE_FR).toString()); + } + } + + /** + * Perform a scheduling operation (new/update/delete).
    + * If the method is successful, returns a {@link JSONObject} success message.
    + * If the method fails in any way, an exception must be thrown. + * + * @throws NotSupportedException If the report instance could not be created (not developped yet?) + * @throws FileLoadingException If unable to load policies to perform the quick checks + * @throws InvalidUserInputException If any report parameter or scheduling parameter could not be understood + * @throws SchedulerException if a scheduling operation failed. + * @throws NotFoundException if elements potentially affected by the request could not be found (DB etc.) + * @throws InsufficientParametersException if not enough parameters or attribute were passed in the http request + */ + protected abstract JSONObject perform(final HttpServletRequest request, final TcSession session) + throws SchedulerException, NotSupportedException, InvalidUserInputException, FileLoadingException, NotFoundException, + InsufficientParametersException, DuplicateSchedulingEntryFound; + + /** Obtains the name of the planification from the {@link HttpServletRequest}. */ + String getPlanificationName(final HttpServletRequest request) { + return request.getParameter(KEY_PLANIFICATION_NAME); + } + + /** Obtains dynamically an instance of ExecutionReport to match the {@link HttpServletRequest request} parameters. */ + AbstractExecutionReport getExecutionReportImpl(final HttpServletRequest request) throws NotSupportedException { + String reportCode = request.getParameter(KEY_REPORT_CODE); + if (reportCode == null) { + String aMessage = "Unable find key [" + KEY_REPORT_CODE + "] in request parameter map: " + request.getParameterMap().toString(); + throw new NotSupportedException(aMessage); + } + // Recovery of the name of a not known class because of the package + String className = getBuilderClassName(reportCode); + + // Research and recovery of the builder class using Reflection + Object invokedObj = ReflectionHelper.newFromClassForName(className); + + if ((invokedObj == null) || (!(invokedObj instanceof AbstractSubmitServlet))) { + String aMessage = "Unable to invoke the servlet: " + className + " of the report " + reportCode; + throw new NotSupportedException(aMessage); + } else { + // Use the builder + AbstractSubmitServlet submitServlet = (AbstractSubmitServlet) invokedObj; + return submitServlet.prepareReport(request); + } + } + + /** + * Get the name of the SubmitServlet class of the appropriate report thanks to his code. + * + * @param reportCode String - the report code + * @return theClassNameBuilder String + */ + private String getBuilderClassName(final String reportCode) { + return CLASS_IMPL_PACKAGE + reportCode.replace("R", "r") + "." + PREFIX_SUBMIT_SERVLET_CLASS + reportCode; + } + + SchedulingPeriod getSchedulingData(final HttpServletRequest request) throws InvalidUserInputException { + if (log.isTraceEnabled()) { + StringBuilder result = new StringBuilder("Parsing http Request for scheduling periodicity:"); + for (Entry paramEntry : request.getParameterMap().entrySet()) { + result.append(paramEntry.getKey()).append("="); + String paramValues = Joiner.on(", ").join(paramEntry.getValue()); + result.append(paramValues).append('|'); + } + log.trace(result.toString()); + } + SchedulingEnum periodicityEnum = getPeriodicity(request); + switch (periodicityEnum) { + case DAILY: + log.trace("Daily periodicity requested"); + return PeriodFactory.daily(); + case DATE: + final String date = request.getParameter(KEY_DATE); + log.trace("Date periodicity requested: date={}", date); + try { + return PeriodFactory.day(date); + } catch (ParseException e) { + throw new InvalidUserInputException("Unable to parse date: " + date, e); + } + case DAY_IN_MONTH_VALUE: + final String dayInMonthStr = request.getParameter(SchedulingEnum.DAY_IN_MONTH_VALUE.getCriteriaName()); + log.trace("Monthly periodicity requested: day in month={}", dayInMonthStr); + try { + int dayInMonth = Integer.parseInt(dayInMonthStr); + return PeriodFactory.dayInMonth(dayInMonth); + } catch (NumberFormatException e) { + throw new InvalidUserInputException("Unable to parse day of month number (int): " + dayInMonthStr, e); + } + case WEEKEND: + final String weekend = request.getParameter(SchedulingEnum.WEEKEND.getCriteriaName()); + log.trace("Monthly periodicity requested: weekend={}", weekend); + return PeriodFactory.weekend(weekend); + case WEEKLY: + final String weekdayNum = request.getParameter(SchedulingEnum.WEEKLY.getCriteriaName()); + log.trace("Weekly periodicity requested: weekDay={}", weekdayNum); + try { + int dayInWeek = Integer.parseInt(weekdayNum); + return PeriodFactory.weekly(dayInWeek); + } catch (NumberFormatException e) { + throw new InvalidUserInputException("Unable to parse day of week number (int): " + weekdayNum, e); + } + default: + throw new InvalidUserInputException("Unable to understand periodicity value:" + request.getParameter(KEY_PERIOD)); + } + } + + private SchedulingEnum getPeriodicity(HttpServletRequest request) { + final String initialPeriodicity = request.getParameter(KEY_PERIOD); + String periodicityValue = request.getParameter(initialPeriodicity); + if (SchedulingEnum.DAY_IN_MONTH_VALUE.getCriteriaName().equals(periodicityValue)) { + return SchedulingEnum.DAY_IN_MONTH_VALUE; + } else { + return SchedulingEnum.getEnum(initialPeriodicity); + } + } + + UserData identifyUser(final HttpServletRequest request) { + // Obtain userName, and user email through authentication + String userName = request.getRemoteUser(); + try { + return ActiveDirectory.obtainUserData(userName); + } catch (NoConnectionToActiveDirectoryException e) { + log.warn("Could not connect to the AD to authenticate the user for scheduling, using GUEST", e); + } catch (InvalidInputException e) { + log.warn("AD Could not authenticate the user for scheduling, using GUEST", e); + } catch (InvalidActiveDirectorySearchException e) { + log.warn("Could not perform a search on the AD for scheduling, using GUEST", e); + } + // Guest user when authentication failed + return ActiveDirectory.getGuestUser(); + } +} diff --git a/kurt-web/src/main/java/com/capgemini/reports/common/scheduling/DeleteServletScheduling.java b/kurt-web/src/main/java/com/capgemini/reports/common/scheduling/DeleteServletScheduling.java new file mode 100644 index 0000000..db612b3 --- /dev/null +++ b/kurt-web/src/main/java/com/capgemini/reports/common/scheduling/DeleteServletScheduling.java @@ -0,0 +1,64 @@ +package com.capgemini.reports.common.scheduling; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.reports.common.ServletMessageHelper; +import com.capgemini.reports.database.HibernateUtil; +import com.capgemini.reports.database.javabean.DbSchedulingReport; +import com.capgemini.reports.database.manager.MngSchedulingReport; +import com.capgemini.reports.exceptions.InsufficientParametersException; +import com.capgemini.reports.exceptions.NotFoundException; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.json.JSONObject; +import org.quartz.SchedulerException; + +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServletRequest; + +/** + * Class providing the framework for deleting a scheduling. + */ +@WebServlet("/scheduling/delete") +public class DeleteServletScheduling extends AbstractGenerateScheduledTemplateServlet { + private static final long serialVersionUID = -8856096872281102308L; + + @Override + protected JSONObject perform(final HttpServletRequest request, final TcSession tcSession) throws SchedulerException, NotFoundException, InsufficientParametersException { + + // Obtain all parameters from the request + String schedulingReportIdStr = request.getParameter(KEY_SCHEDULING_REPORT_ID); + Long schedulingReportId; + if (schedulingReportIdStr == null) { + throw new InsufficientParametersException("No scheduling Identifier passed to DeleteServletScheduling, aborting..."); + } + try { + schedulingReportId = Long.valueOf(schedulingReportIdStr); + } + catch (NumberFormatException e) { + throw new InsufficientParametersException("Input scheduling Identifier passed to DeleteServletScheduling could not be understood: " + + schedulingReportIdStr, e); + } + + // Delete the Job and all of its triggers + schedulingServer.deleteScheduledJobAndKeys(schedulingReportId); + + // Update the DB + SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); + Session session = sessionFactory.openSession(); + try { + MngSchedulingReport mngSchedulingReport = new MngSchedulingReport(); + DbSchedulingReport report = mngSchedulingReport.searchById(session, schedulingReportId); + mngSchedulingReport.deleteSchedulingReport(schedulingReportId); + + // Return a success message + return successMessage(report.getReportCode()); + } + finally { + session.close(); + } + } + + private JSONObject successMessage(final String reportCode) { + return ServletMessageHelper.successMessage("Le rapport \"" + reportCode + "\" a bien été supprimé"); + } +} diff --git a/kurt-web/src/main/java/com/capgemini/reports/common/scheduling/ModifyServletScheduling.java b/kurt-web/src/main/java/com/capgemini/reports/common/scheduling/ModifyServletScheduling.java new file mode 100644 index 0000000..c43e6b6 --- /dev/null +++ b/kurt-web/src/main/java/com/capgemini/reports/common/scheduling/ModifyServletScheduling.java @@ -0,0 +1,90 @@ +package com.capgemini.reports.common.scheduling; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.reports.checkdata.CheckingDataHelper; +import com.capgemini.reports.common.ServletMessageHelper; +import com.capgemini.reports.database.DataBaseReportHelper; +import com.capgemini.reports.database.HibernateUtil; +import com.capgemini.reports.database.javabean.DbSchedulingReport; +import com.capgemini.reports.database.javabean.DbUser; +import com.capgemini.reports.database.javabean.DbUser.UserData; +import com.capgemini.reports.database.manager.MngSchedulingReport; +import com.capgemini.reports.database.manager.MngUser; +import com.capgemini.reports.exceptions.*; +import com.capgemini.reports.execution.AbstractExecutionReport; +import com.capgemini.reports.periodicity.SchedulingPeriod; +import lombok.extern.slf4j.Slf4j; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.json.JSONObject; +import org.quartz.SchedulerException; + +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServletRequest; + +/** + * Class providing the framework for modifying a scheduling.
    + * The old scheduled report will be destroyed and the new scheduled report will be submitted and checked.
    + */ +@Slf4j +@WebServlet("/scheduling/modify") +public class ModifyServletScheduling extends AbstractGenerateScheduledTemplateServlet { + + private static final long serialVersionUID = 3233963187725874998L; + + @Override + protected JSONObject perform(final HttpServletRequest request, final TcSession tcSession) throws SchedulerException, NotSupportedException, + InvalidUserInputException, DuplicateSchedulingEntryFound, FileLoadingException { + SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); + Session session = sessionFactory.openSession(); + try { + // Identify the requestor + UserData adUser = identifyUser(request); + final DbUser dbUser = new MngUser().fetchOrUpdateOrCreateUser(session, adUser); + + // Obtain all parameters from the request + String schedulingReportIdStr = request.getParameter(KEY_SCHEDULING_REPORT_ID); + Long schedulingReportId = Long.valueOf(schedulingReportIdStr); + String planifName = super.getPlanificationName(request); + AbstractExecutionReport report = super.getExecutionReportImpl(request); + report.setScheduling(schedulingReportId, planifName); + SchedulingPeriod period = super.getSchedulingData(request); + + checkDuplicateName(session, schedulingReportId, planifName); + + // Check the report is STILL valid + CheckingDataHelper.doQuickCheck(tcSession, report); + + // Update the DB + DataBaseReportHelper.updateScheduling(schedulingReportId, report, planifName, period, dbUser); + + // Update the functional (JobDetail) and temporal (Trigger) parameters + schedulingServer.replaceJob(schedulingReportId, report, report.getPriorityCode(), period, planifName); + + // Return a success message + return successMessage(report); + } + finally { + session.close(); + } + } + + /** + * Fails if the name has changed AND the new name is already used. + */ + private void checkDuplicateName(Session session, Long schedulingReportId, String planifName) throws DuplicateSchedulingEntryFound { + MngSchedulingReport mngScheduling = new MngSchedulingReport(); + DbSchedulingReport oldScheduling = mngScheduling.searchById(session, schedulingReportId); + if (!planifName.equals(oldScheduling.getSchedulingName())) { + // the scheduling name has changed, check that it doesn't interfere with an other one! + DbSchedulingReport potentialDuplicate = mngScheduling.searchByName(session, planifName); + if (potentialDuplicate != null) { + throw new DuplicateSchedulingEntryFound("La planification " + planifName + " existe déjà. veuillez saisir un autre nom."); + } + } + } + + private JSONObject successMessage(final AbstractExecutionReport reportImpl) { + return ServletMessageHelper.successMessage("Le rapport \"" + reportImpl.getReportIdentifier().getReportTitle() + "\" planifié est modifié"); + } +} diff --git a/kurt-web/src/main/java/com/capgemini/reports/common/scheduling/SubmitServletScheduling.java b/kurt-web/src/main/java/com/capgemini/reports/common/scheduling/SubmitServletScheduling.java new file mode 100644 index 0000000..7e017af --- /dev/null +++ b/kurt-web/src/main/java/com/capgemini/reports/common/scheduling/SubmitServletScheduling.java @@ -0,0 +1,132 @@ +package com.capgemini.reports.common.scheduling; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.reports.checkdata.CheckingDataHelper; +import com.capgemini.reports.common.ServletMessageHelper; +import com.capgemini.reports.database.DataBaseReportHelper; +import com.capgemini.reports.database.HibernateUtil; +import com.capgemini.reports.database.javabean.DbSchedulingReport; +import com.capgemini.reports.database.javabean.DbUser; +import com.capgemini.reports.database.javabean.DbUser.UserData; +import com.capgemini.reports.database.manager.MngSchedulingCriteriaVal.SchedulingCriteriaValue; +import com.capgemini.reports.database.manager.MngSchedulingReport; +import com.capgemini.reports.database.manager.MngUser; +import com.capgemini.reports.exceptions.*; +import com.capgemini.reports.execution.AbstractExecutionReport; +import com.capgemini.reports.execution.posting.SchedulingPostingStrategy; +import com.capgemini.reports.execution.strategies.ScheduledExecutionStrategy; +import com.capgemini.reports.logging.ReportLoggerHelper; +import com.capgemini.reports.periodicity.SchedulingPeriod; +import com.capgemini.reports.quartz.TriggerPreparator; +import lombok.extern.slf4j.Slf4j; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.json.JSONObject; +import org.quartz.SchedulerException; +import org.quartz.Trigger; + +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServletRequest; +import java.util.List; + +/** + * Class providing the framework for submitting a new report Scheduling request.
    + * Also checks in advance the parameters to produce the scheduled report.
    + * Note: The reports generated from a right click on a TC object cannot be scheduled.
    + * For examples : R15, R17,... + */ +@Slf4j +@WebServlet("/scheduling/submit") +public class SubmitServletScheduling extends AbstractGenerateScheduledTemplateServlet { + + private static final long serialVersionUID = -7776388563908130383L; + + /** + * Record a new Scheduling job into Quartz and the DB. + * + * @throws NotSupportedException If the report instance could not be created (not developped yet?) + * @throws FileLoadingException If unable to load policies to perform the quick checks + * @throws InvalidUserInputException If any report parameter or scheduling parameter could not be understood + * @throws SchedulerException if a scheduling operation failed. + * @throws DuplicateSchedulingEntryFound + */ + @Override + protected JSONObject perform(final HttpServletRequest request, final TcSession tcSession) + throws SchedulerException, NotSupportedException, InvalidUserInputException, FileLoadingException, DuplicateSchedulingEntryFound { + SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); + Session session = sessionFactory.openSession(); + try { + String schedulingName = getPlanificationName(request); + DbSchedulingReport previous = new MngSchedulingReport().searchByName(session, schedulingName); + if (previous != null) { + throw new DuplicateSchedulingEntryFound( + "La planification " + schedulingName + " existe déjà. veuillez saisir un autre nom."); + } + + // Get the implementation of the report by reflection thanks to his code and the request + AbstractExecutionReport reportImpl = getExecutionReportImpl(request); + + // Prepare a Session in order to perform the quick checks + String reportCode = reportImpl.getReportIdentifier().getReportCode(); + log.debug("Beginning quick checks for the report {}...", reportCode); + + // Do a quick Check. If it fails, the exception thrown will carry a message to the user's webpage + CheckingDataHelper.doQuickCheck(tcSession, reportImpl); + log.debug("All quick checks have passed for {}", reportCode); + + // Get scheduling parameters + SchedulingPeriod schedulingPeriod = getSchedulingData(request); + + // Record which admin has asked for this job + DbSchedulingReport theSchedulingEntry = recordSchedulingRequest(request, reportImpl, schedulingName, schedulingPeriod.asCriteriaValues()); + + // Get the trigger thanks to the scheduling parameters from the request + Trigger trigger; + try { + trigger = TriggerPreparator.prepareScheduledTrigger(theSchedulingEntry.getId(), reportImpl.getPriorityCode(), schedulingName, + schedulingPeriod); + } + catch (InvalidInputException e) { + throw new InvalidUserInputException("Some scheduling parameters could ntot be understood", e); + } + // Setup the scheduling parameters + log.info("Scheduling name={}, id={}", theSchedulingEntry.getSchedulingName(), theSchedulingEntry.getId()); + reportImpl.setScheduling(theSchedulingEntry.getId(), theSchedulingEntry.getSchedulingName()); + reportImpl.setExecutionStrategy(new ScheduledExecutionStrategy()); + + // POST the report + new SchedulingPostingStrategy(schedulingServer, trigger).handleRequest(reportImpl); + return successMessage(reportImpl); + } + finally { + session.close(); + } + } + + private DbSchedulingReport recordSchedulingRequest(final HttpServletRequest request, final AbstractExecutionReport reportImpl, + final String schedulingName, final List schedulingCriteriaValues) { + SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); + Session session = sessionFactory.openSession(); + try { + // Identify the user using the LDAP + UserData adUser = identifyUser(request); + + // Find / update / create corresponding user in DB if it doesn't already exist + DbUser dbUser = new MngUser().fetchOrUpdateOrCreateUser(session, adUser); + + // Record the report launch in the database + DbSchedulingReport theSchedulingEntry = DataBaseReportHelper.registerScheduledTemplate(reportImpl, dbUser, schedulingCriteriaValues, schedulingName); + + // Log the scheduling request + ReportLoggerHelper.logSchedulingRequestWaiting(session, dbUser, theSchedulingEntry, reportImpl); + return theSchedulingEntry; + } + finally { + session.close(); + } + } + + private JSONObject successMessage(final AbstractExecutionReport reportImpl) { + return ServletMessageHelper.successMessage("Le rapport \"" + reportImpl.getReportIdentifier().getReportTitle() + "\" est planifié"); + } +} diff --git a/kurt-web/src/main/java/com/capgemini/reports/common/scheduling/controller/QueueReaderServlet.java b/kurt-web/src/main/java/com/capgemini/reports/common/scheduling/controller/QueueReaderServlet.java new file mode 100644 index 0000000..5abe29c --- /dev/null +++ b/kurt-web/src/main/java/com/capgemini/reports/common/scheduling/controller/QueueReaderServlet.java @@ -0,0 +1,91 @@ +package com.capgemini.reports.common.scheduling.controller; + +import java.io.IOException; +import java.util.List; + +import javax.ejb.EJB; +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.capgemini.reports.database.HibernateUtil; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.json.JSONObject; +import org.quartz.SchedulerException; + +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.reports.common.ServletMessageHelper; +import com.capgemini.reports.database.manager.MngReport; +import com.capgemini.reports.database.manager.MngReport.RunningReportEntry; +import com.capgemini.reports.quartz.SchedulerServer; +import com.capgemini.reports.quartz.SchedulerServer.JobExecution; + +import lombok.extern.slf4j.Slf4j; + +/** + * A {@link HttpServlet} that reads data from the DB and Quartz to retrieve queue status, then forwards the data t oa JSP for pretty-printing. + */ +@Slf4j +@WebServlet("/queueReader") +public class QueueReaderServlet extends HttpServlet { + private static final long serialVersionUID = -1471984298116642565L; + + // Output attribute keys + private static final String KEY_REPORTS_IN_QUARTZ = "quartzJobList"; + private static final String KEY_REPORTS_IN_QUEUE = "waitingReports"; + + private static final String CONTENT_TYPE_JSON = "application/json"; + private static final String FORMATTING_JSP_URL = "/frames/queue.jsp"; + + @EJB + SchedulerServer quartz; + + @Override + protected void doPost(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException { + // Parse server request parameters + try { + perform(request, response); + JSONObject successMessage = ServletMessageHelper.successMessage("success"); + response.setContentType(CONTENT_TYPE_JSON); + response.getWriter().write(successMessage.toString()); + } + catch (SchedulerException e) { + // A nice error message will be sent to the user to tell him what he did wrong + log.error(e.getMessage(), e); + response.setContentType(CONTENT_TYPE_JSON); + response.getWriter().write(ServletMessageHelper.errorMessage(new KurtException("Unable to post a message", e)).toString()); + } + } + + @Override + protected void doGet(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException { + doPost(request, response); + } + + private void perform(final HttpServletRequest request, final HttpServletResponse response) + throws ServletException, IOException, SchedulerException { + SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); + Session session = sessionFactory.openSession(); + try { + // Obtain all reports currently queueing + MngReport theMngRep = new MngReport(); + List theWaitingReports = theMngRep.searchWaitingReports(session); + request.setAttribute(KEY_REPORTS_IN_QUEUE, theWaitingReports); + + // Obtain all report planification jobs stored + List tonightJobs = quartz.listAllScheduledJobsForTonight(session); + request.setAttribute(KEY_REPORTS_IN_QUARTZ, tonightJobs); + + // Add data to the request + RequestDispatcher dispatcher = getServletContext().getRequestDispatcher(FORMATTING_JSP_URL); + dispatcher.forward(request, response); + } + finally { + session.close(); + } + } +} diff --git a/kurt-web/src/main/java/com/capgemini/reports/common/scheduling/controller/SchedulingReaderServlet.java b/kurt-web/src/main/java/com/capgemini/reports/common/scheduling/controller/SchedulingReaderServlet.java new file mode 100644 index 0000000..f825fcf --- /dev/null +++ b/kurt-web/src/main/java/com/capgemini/reports/common/scheduling/controller/SchedulingReaderServlet.java @@ -0,0 +1,227 @@ +package com.capgemini.reports.common.scheduling.controller; + +import com.capgemini.reports.ReportEnum; +import com.capgemini.reports.common.ServletMessageHelper; +import com.capgemini.reports.database.HibernateUtil; +import com.capgemini.reports.database.javabean.DbReportType; +import com.capgemini.reports.database.javabean.DbSchedulingReport; +import com.capgemini.reports.database.manager.MngReportType; +import com.capgemini.reports.database.manager.MngSchedulingCriteriaVal; +import com.capgemini.reports.database.manager.MngSchedulingReport; +import com.capgemini.reports.exceptions.InvalidInputException; +import com.capgemini.reports.periodicity.SchedulingPeriod; +import com.capgemini.reports.quartz.SchedulerServer; +import com.google.common.base.Optional; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.json.JSONObject; +import org.quartz.SchedulerException; + +import javax.ejb.EJB; +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.sql.Timestamp; +import java.util.*; +import java.util.Map.Entry; + +/** + * Controller servlet used during all transactions made to show the schedulings summary page.
    + * Entry parameters: + *
      + *
    • reportCode (MANDATORY) contains a usueal report code ('R01', 'R19') or 'TOUS' to show all report schedulings.
    • + *
    • page (OPTIONAL) may contain an integer for the result page number [1..n]
    • + *
    + * This servlet correlates the DB entries and the quartz entries to produce a {@link Set} of {@link SchedulingReportEntry}.
    + * The request is enriched with this Set, and forwarded to a JSP for printing. + *

    + * Output attributes: + *

      + *
    • schedulings : contains a {@link List} of {@link SchedulingReportEntry}
    • + *
    + */ +@Slf4j +@WebServlet("/schedulingReader") +public class SchedulingReaderServlet extends HttpServlet { + private static final long serialVersionUID = -8848572431950894775L; + + private static final String FR_HUMAN_DATE = "Par date"; + private static final String FR_HUMAN_MONTHLY = "Tous les mois"; + private static final String FR_HUMAN_WEEKLY = "Toutes les semaines"; + private static final String FR_HUMAN_DAILY = "Tous les jours"; + + // Key to output attributes + private static final String KEY_SCHEDULINGS = "schedulings"; + + private static final String CONTENT_TYPE_JSON = "application/json"; + private static final String FORMATTING_JSP_URL = "/frames/all_scheduling_reports.jsp"; + + private static final String PARAM_REPORT_CODE = "reportCode"; + private static final String PARAM_PAGE = "page"; + + @EJB + SchedulerServer quartz; + + @Override + protected void doPost(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException { + // Parse server request parameters + try { + perform(request, response); + JSONObject successMessage = ServletMessageHelper.successMessage("success"); + response.setContentType(CONTENT_TYPE_JSON); + response.getWriter().write(successMessage.toString()); + } + catch (InvalidInputException e) { + // A nice error message will be sent to the user to tell him what he did wrong + log.error(e.getMessage(), e); + response.setContentType(CONTENT_TYPE_JSON); + response.getWriter().write(ServletMessageHelper.errorMessage(e).toString()); + } + catch (SchedulerException e) { + // An error message will be sent to the user to tell him an error occurred + log.error(e.getMessage(), e); + response.setContentType(CONTENT_TYPE_JSON); + response.getWriter().write(ServletMessageHelper.errorMessage(e.getMessage()).toString()); + } + } + + @Override + protected void doGet(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException { + doPost(request, response); + } + + /** + * Performs the request: obtains data then forwards to a JSP for printing. + * + * @param request the http request + * @param response the http response + * @throws ServletException if the forward to JSP action fails + * @throws IOException if the forward to JSP action fails + * @throws SchedulerException if unable to schedule the report + * @throws InvalidInputException if something went wrong while parsing TEMPORAL parameters (technical error) + */ + private void perform(final HttpServletRequest request, final HttpServletResponse response) + throws ServletException, IOException, SchedulerException, InvalidInputException { + String reportCodeParamStr = request.getParameter(PARAM_REPORT_CODE); + String pageStr = request.getParameter(PARAM_PAGE); + + // Parse page num + int page; + if (pageStr != null) { + page = Integer.parseInt(pageStr); + } + else { + page = 1; + } + + // Obtain the db data + SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); + Session session = sessionFactory.openSession(); + try { + Map dbData; + MngSchedulingReport theMngSchedRep = new MngSchedulingReport(); + if (reportCodeParamStr != null && !"TOUS".equals(reportCodeParamStr)) { + ReportEnum reportCodeParam = ReportEnum.fromCode(reportCodeParamStr); + dbData = theMngSchedRep.searchSchedulingReportByReportCode(session, reportCodeParam, page); + } + else { + dbData = theMngSchedRep.searchAllSchedulingReports(session, page); + } + + // Obtain all reports currently queueing + MngSchedulingCriteriaVal mngSchedulingCriteriaValues = new MngSchedulingCriteriaVal(); + Set schedulings = new TreeSet<>(); + for (Entry entry : dbData.entrySet()) { + DbSchedulingReport dbSchedulingReport = entry.getKey(); + String owner = entry.getValue(); + Long schedulingId = dbSchedulingReport.getId(); + // Find additional scheduling data + Optional nextFireTime = quartz.nextExecutionOfJob(schedulingId); + SchedulingPeriod period = mngSchedulingCriteriaValues.getPeriod(session, schedulingId); + String periodStr = parseToFrench(period); + + // Find authorization status + String reportEntryCode = dbSchedulingReport.getReportCode(); + ReportEnum reportEntryEnum = ReportEnum.fromCode(reportEntryCode); + DbReportType dbReporttype = new MngReportType().search(session, reportEntryEnum); + String authorized = dbReporttype.getReportAuthorized(); + boolean isReportAuthorized = "true".equalsIgnoreCase(authorized); + + // Make a line with all this data + schedulings.add(new SchedulingReportEntry(schedulingId, dbSchedulingReport.getSchedulingName(), reportEntryEnum, + dbSchedulingReport.getLastUpdate(), owner, periodStr, nextFireTime, isReportAuthorized)); + } + + // Add data to the request + request.setAttribute(KEY_SCHEDULINGS, schedulings); + // Forward to the relevant JSP + RequestDispatcher dispatcher = getServletContext().getRequestDispatcher(FORMATTING_JSP_URL); + dispatcher.forward(request, response); + } + finally { + session.close(); + } + } + + private static String parseToFrench(final SchedulingPeriod period) { + String periodStr; + switch (period.getPeriodicity()) { + case DAILY: + periodStr = FR_HUMAN_DAILY; + break; + case DATE: + periodStr = FR_HUMAN_DATE; + break; + case DAY_IN_MONTH_VALUE: + periodStr = FR_HUMAN_MONTHLY; + break; + case WEEKEND: + periodStr = FR_HUMAN_MONTHLY; + break; + case WEEKLY: + periodStr = FR_HUMAN_WEEKLY; + break; + default: + periodStr = "Unknown periodicity"; + break; + } + return periodStr; + } + + /** + * Represents a scheduling report entry. + */ + @Getter + @AllArgsConstructor + public static class SchedulingReportEntry implements Comparable { + + // Data + private final Long id; + private final String planificationName; + private final ReportEnum reportCode; + private final Timestamp lastUpdate; + private final String userResponsable; + private final String period; + private final Optional nextFireTime; + private final boolean isReportAuthorized; + + @Override + public String toString() { + return "SchedulingReportEntry [id=" + id + ", planificationName=" + planificationName + ", reportCode=" + reportCode + ", lastUpdate=" + + lastUpdate + ", userResponsable=" + userResponsable + ", period=" + period + ", nextStart=" + nextFireTime + + ", isReportAuthorized=" + isReportAuthorized + "]"; + } + + @Override + public int compareTo(final SchedulingReportEntry other) { + return this.getPlanificationName().compareTo(other.getPlanificationName()); + } + } +} diff --git a/kurt-web/src/main/java/com/capgemini/reports/common/scheduling/utilities/AbstractActionManager.java b/kurt-web/src/main/java/com/capgemini/reports/common/scheduling/utilities/AbstractActionManager.java new file mode 100644 index 0000000..cd32254 --- /dev/null +++ b/kurt-web/src/main/java/com/capgemini/reports/common/scheduling/utilities/AbstractActionManager.java @@ -0,0 +1,118 @@ +package com.capgemini.reports.common.scheduling.utilities; + +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.reports.exceptions.InsufficientParametersException; +import com.capgemini.reports.exceptions.InvalidInputException; +import lombok.extern.slf4j.Slf4j; +import org.json.JSONObject; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * Class used to perform operations on Schedulings.
    + * Example operations: + *
      + *
    • get_sub_period used to obtain the existing parameters of a scheduling when updating it from HMI
    • + *
    • save used to set activation status of a particular report
    • + *
    • is_authorised_report used to obtain activation status of a particular report
    • + *
    + */ +@Slf4j +public abstract class AbstractActionManager extends HttpServlet { + + private static final long serialVersionUID = 3744965867042379548L; + + private static final String CONTENT_TYPE_JSON = "application/json"; + + /** This key can be found in the URL. i.e. 'kurt-web/activateDeactivate?reportCode=R01&reportAuthorized=true' etc. */ + protected static final String URL_KEY_REPORT_CODE = "reportCode"; + + /** + * TOKEN to obtain request TcReleaseStatus from the JSON response. + */ + public static final String TOKEN_STATUS = "status"; + /** TOKEN to obtain error explanation from the JSON response when STATUS is FAILED. */ + public static final String TOKEN_ERROR = "error"; + /** TOKEN to obtain success message from the JSON response. */ + public static final String TOKEN_SUCCESS_MSG = "success"; + + /** STATUS value for the JSON response when posting is successful. */ + public static final String STATUS_SUCCESS = TOKEN_SUCCESS_MSG; + /** STATUS value for the JSON response when posting has failed. */ + public static final String STATUS_FAILED = "failed"; + /** STATUS value for the JSON response when user should be prompted before actually launching the report. */ + public static final String STATUS_PROMPT = "prompt"; + + @Override + protected void doGet(final HttpServletRequest aRequest, final HttpServletResponse aResponse) throws ServletException, IOException { + doPost(aRequest, aResponse); + } + + @Override + protected void doPost(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException { + try { + String json = perform(request, response).toString(); + response.getWriter().write(json); + } catch (InsufficientParametersException | InvalidInputException e) { + log.error(e.getMessage(), e); + response.setContentType(CONTENT_TYPE_JSON); + response.getWriter().write(errorMessage(e).toString()); + } + } + + protected abstract JSONObject perform(final HttpServletRequest request, final HttpServletResponse response) + throws InsufficientParametersException, InvalidInputException; + + /** + * Helper function to return standardized success messages to the client. + * + * @param msg the message + * @return the {@link JSONObject} + */ + protected static JSONObject successMessage(final String msg) { + return new JSONObject().put(TOKEN_STATUS, STATUS_SUCCESS).put(TOKEN_SUCCESS_MSG, msg); + } + + /** + * Helper function for producing standardized JSON error messages to be sent to server in case a fault is found. + * + * @param msg the message + * @return the {@link JSONObject} + */ + public static JSONObject errorMessage(final String msg) { + return new JSONObject().put(TOKEN_STATUS, STATUS_FAILED).put(TOKEN_ERROR, msg); + } + + /** + * Helper function for producing standardized JSON error messages to be sent to server in case a fault is found. + * + * @param exception the generic {@link KurtException} that caused the failure + * @return the {@link JSONObject} containing the status and a generic error message + */ + protected static JSONObject errorMessage(final KurtException exception) { + return new JSONObject().put(TOKEN_STATUS, STATUS_FAILED).put(TOKEN_ERROR, exception.getMessage()); + } + + /** + * Try to findAll an argument value in the URL and return an error message in JSP when it failed. + * + * @param aRequest the {@link HttpServletRequest} + * @param anArgName the argument you're looking for + * @return the argument's value + * @throws InsufficientParametersException if the URL argument requested couldn't be found in the {@link HttpServletRequest} + */ + protected static String getMandatoryArg(final HttpServletRequest aRequest, final String anArgName) throws InsufficientParametersException { + String theArgValue = aRequest.getParameter(anArgName); + log.debug("Arg name {}\targ Value {}", anArgName, theArgValue); + if (theArgValue == null) { + String theErrorMessage = "Missing required argument in URL: " + anArgName; + throw new InsufficientParametersException(theErrorMessage); + } + return theArgValue; + } + +} diff --git a/kurt-web/src/main/java/com/capgemini/reports/common/scheduling/utilities/ReportActivationReaderServlet.java b/kurt-web/src/main/java/com/capgemini/reports/common/scheduling/utilities/ReportActivationReaderServlet.java new file mode 100644 index 0000000..bbf1bec --- /dev/null +++ b/kurt-web/src/main/java/com/capgemini/reports/common/scheduling/utilities/ReportActivationReaderServlet.java @@ -0,0 +1,58 @@ +package com.capgemini.reports.common.scheduling.utilities; + +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.reports.database.HibernateUtil; +import com.capgemini.reports.database.manager.MngReportType; +import com.capgemini.reports.exceptions.InsufficientParametersException; +import com.capgemini.reports.exceptions.InvalidInputException; +import lombok.extern.slf4j.Slf4j; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.json.JSONObject; + +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * Servlet handling requests to read activation status of the report in DB.
    + * Receives http requests with URL parameters: + *
      + *
    • reportCode={REPORT_CODE}
    • + *
    + * Example:
    + * {@code kurt-web/reportActivation?reportCode=R01} + */ +@Slf4j +@WebServlet("/reportActivation") +public class ReportActivationReaderServlet extends AbstractActionManager { + + private static final long serialVersionUID = -3288930443279088612L; + + private static final String SUCESS_MESSAGE_IS_AUTHORIZED = "La demande a bien été prise en compte"; + private static final String ERROR_MESSAGE_IS_AUTHORIZED = "Le lancement de ce rapport n'est pas autorisé"; + + @Override + protected JSONObject perform(final HttpServletRequest request, final HttpServletResponse response) + throws InsufficientParametersException { + log.info("Start Manager scheduling Report ...."); + return isAuthorizedReport(request); + } + + private JSONObject isAuthorizedReport(final HttpServletRequest request) throws InsufficientParametersException { + SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); + Session session = sessionFactory.openSession(); + try { + MngReportType mngReportType = new MngReportType(); + if (mngReportType.isAuthorized(session, getMandatoryArg(request, URL_KEY_REPORT_CODE))) { + return successMessage(SUCESS_MESSAGE_IS_AUTHORIZED); + } + else { + return errorMessage(new KurtException(ERROR_MESSAGE_IS_AUTHORIZED)); + } + } + finally { + session.close(); + } + } +} diff --git a/kurt-web/src/main/java/com/capgemini/reports/common/scheduling/utilities/ReportActivatorServlet.java b/kurt-web/src/main/java/com/capgemini/reports/common/scheduling/utilities/ReportActivatorServlet.java new file mode 100644 index 0000000..ef776a2 --- /dev/null +++ b/kurt-web/src/main/java/com/capgemini/reports/common/scheduling/utilities/ReportActivatorServlet.java @@ -0,0 +1,53 @@ +package com.capgemini.reports.common.scheduling.utilities; + +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.json.JSONObject; + +import com.capgemini.reports.database.javabean.DbReportType; +import com.capgemini.reports.database.manager.MngReportType; +import com.capgemini.reports.exceptions.InsufficientParametersException; +import com.capgemini.reports.exceptions.InvalidInputException; + +import lombok.extern.slf4j.Slf4j; + +/** + * Servlet handling requests to chachge activation status of the report in DB.
    + * Receives http requests with URL parameters: + *
      + *
    • reportCode={REPORT_CODE}
    • + *
    • reportAuthorized={AUTHORIZATION}
    • + *
    + * Example:
    + * {@code kurt-web/activateDeactivate?reportCode=R01&reportAuthorized=true} + */ +@Slf4j +@WebServlet("/activateDeactivate") +public class ReportActivatorServlet extends AbstractActionManager { + + private static final long serialVersionUID = 403605177414500576L; + + private static final String URL_KEY_REPORT_AUTHORIZED = "reportAuthorized"; + + @Override + protected JSONObject perform(final HttpServletRequest request, final HttpServletResponse response) + throws InsufficientParametersException, InvalidInputException { + log.info("Start Manager scheduling Report ...."); + return enableDisableAuthorizedReport(request); + } + + /*Save or Unsaved scheduling report */ + private JSONObject enableDisableAuthorizedReport(final HttpServletRequest request) throws InsufficientParametersException { + String reportCode = getMandatoryArg(request, URL_KEY_REPORT_CODE); + String reportAuthorized = getMandatoryArg(request, URL_KEY_REPORT_AUTHORIZED); + + log.info("Update {} activation with value {}", reportCode, reportAuthorized); + + DbReportType dbReportType = new MngReportType().setReportActivation(reportCode, reportAuthorized); + + return successMessage("La modification a bien été prise en compte pour le rapport " + dbReportType.getTitle()); + } + +} diff --git a/kurt-web/src/main/java/com/capgemini/reports/common/scheduling/utilities/SchedulingPeriodReaderServlet.java b/kurt-web/src/main/java/com/capgemini/reports/common/scheduling/utilities/SchedulingPeriodReaderServlet.java new file mode 100644 index 0000000..d897a49 --- /dev/null +++ b/kurt-web/src/main/java/com/capgemini/reports/common/scheduling/utilities/SchedulingPeriodReaderServlet.java @@ -0,0 +1,70 @@ +package com.capgemini.reports.common.scheduling.utilities; + +import com.capgemini.reports.common.scheduling.view.SchedulingParametersReader; +import com.capgemini.reports.database.HibernateUtil; +import com.capgemini.reports.database.javabean.enumeration.SchedulingEnum; +import com.capgemini.reports.database.manager.MngSchedulingCriteriaVal; +import com.capgemini.reports.exceptions.InsufficientParametersException; +import com.capgemini.reports.exceptions.InvalidInputException; +import com.capgemini.reports.periodicity.PeriodFactory; +import com.capgemini.reports.periodicity.SchedulingPeriod; +import lombok.extern.slf4j.Slf4j; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.json.JSONObject; + +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * Servlet handling requests for periodicity data.
    + * Receives http requests with URL parameters: + *
      + *
    • subPeriod={SUB_PERIOD} The period that is currently selected (daily/weekly/monthly/date)
    • + *
    • isUpdate={BOOLEAN} True if an existing scheduling is being update (existing values should be retreived in DB), false if it is a brand new scheduling.
    • + *
    • id={ID} (OPTIONAL) the identifier of the updating report, only present if isUpdate is true
    • + *
    + */ +@Slf4j +@WebServlet("/getScheduling") +public class SchedulingPeriodReaderServlet extends AbstractActionManager { + private static final long serialVersionUID = 6495163507120953894L; + private static final String SUCESS_MESSAGE = ""; // No need for a message to the user, it is sufficient to simply update the page + + @Override + protected JSONObject perform(final HttpServletRequest request, final HttpServletResponse response) + throws InsufficientParametersException, InvalidInputException { + log.info("Start Manager scheduling Report ...."); + return getSubPeriod(request); + } + + /* Return sub period of current period */ + private JSONObject getSubPeriod(final HttpServletRequest request) throws InsufficientParametersException, InvalidInputException { + String subPeriod = getMandatoryArg(request, "subPeriod"); + String isUpdateStr = getMandatoryArg(request, "isUpdate"); + Boolean isUpdate = Boolean.valueOf(isUpdateStr); + SchedulingPeriod period; + if (isUpdate) { + String schedulingIdStr = getMandatoryArg(request, "id"); + Long schedulingId = Long.valueOf(schedulingIdStr); + SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); + Session session = sessionFactory.openSession(); + try { + period = new MngSchedulingCriteriaVal().getPeriod(session, schedulingId); + } + finally { + session.close(); + } + } + else { + period = PeriodFactory.daily(); + } + log.info("subPeriod {} active={} id={}", subPeriod, isUpdate, period.toString()); + SchedulingEnum periodicity = SchedulingEnum.getEnum(subPeriod); + String content = new SchedulingParametersReader().getSubPeriod(periodicity, period, isUpdate); + log.info("Content [" + content + "]"); + + return successMessage(SUCESS_MESSAGE).put("content", content); + } +} diff --git a/kurt-web/src/main/java/com/capgemini/reports/common/scheduling/view/NewSchedulingFormatter.java b/kurt-web/src/main/java/com/capgemini/reports/common/scheduling/view/NewSchedulingFormatter.java new file mode 100644 index 0000000..e6093ea --- /dev/null +++ b/kurt-web/src/main/java/com/capgemini/reports/common/scheduling/view/NewSchedulingFormatter.java @@ -0,0 +1,37 @@ +package com.capgemini.reports.common.scheduling.view; + +import com.capgemini.framework.common.StringHelper; +import com.capgemini.reports.database.javabean.enumeration.SchedulingEnum; +import com.hp.gagawa.java.elements.Div; + +/** This formatter page can display an empty scheduling data page. It is used in the 'new scheduling' page. */ +public class NewSchedulingFormatter extends SchedulingFormatter { + + + /** + * Builds the html content that will show the page, in html. + * + * @return the page contents (html) + */ + public String showNewReportSchedulingPage() { + // Parent + Div parent = new Div(); + parent.setId("div_temporal"); + + // scheduling name + Div containerSchedulingName = getSchedulingName(StringHelper.EMPTY); + parent.appendChild(containerSchedulingName); + + // period + Div containerPeriod = getPeriod(SchedulingEnum.DAILY, null).setId("div_container_period").setCSSClass(SUB_TITLE_PLANIFICATION); + parent.appendChild(containerPeriod); + + Div containerSubPeriod = new Div(); + containerSubPeriod.setId("div_container_subPeriod").setStyle(MARGIN_TOP_10PX).setCSSClass(SUB_TITLE_SUB_PERIOD); + parent.appendChild(containerSubPeriod); + + return parent.write(); + } + + +} diff --git a/kurt-web/src/main/java/com/capgemini/reports/common/scheduling/view/SchedulingFormatter.java b/kurt-web/src/main/java/com/capgemini/reports/common/scheduling/view/SchedulingFormatter.java new file mode 100644 index 0000000..ef044d8 --- /dev/null +++ b/kurt-web/src/main/java/com/capgemini/reports/common/scheduling/view/SchedulingFormatter.java @@ -0,0 +1,306 @@ +package com.capgemini.reports.common.scheduling.view; + +import com.capgemini.framework.common.StringHelper; +import com.capgemini.framework.common.TeamcenterDateFormatter; +import com.capgemini.reports.database.HibernateUtil; +import com.capgemini.reports.database.javabean.enumeration.SchedulingEnum; +import com.capgemini.reports.database.manager.MngSchedulingCriteriaVal; +import com.capgemini.reports.periodicity.*; +import com.capgemini.reports.periodicity.SchedulingPeriod.PeriodVisitor; +import com.hp.gagawa.java.elements.*; +import lombok.Getter; +import org.hibernate.Session; +import org.hibernate.SessionFactory; + +import java.text.SimpleDateFormat; + +/** + * Formatting class for schedulings. Can extract scheduling data from the DB, and format it into html {@link Div}s and {@link Input}s.
    + * Implements the {@link PeriodVisitor} interface, to analyze a {@link SchedulingPeriod} and show it as a html {@link Div}. + */ +@Getter +public class SchedulingFormatter implements PeriodVisitor
    { + + // Period keys + private static final String PERIOD_DAY_IN_MONTH_VALUE = SchedulingEnum.DAY_IN_MONTH_VALUE.getCriteriaName(); + private static final String PERIOD_WEEKEND = SchedulingEnum.WEEKEND.getCriteriaName(); + private static final String PERIOD_WEEKLY = SchedulingEnum.WEEKLY.getCriteriaName(); + + // Period Values + private static final String KEY_DAY_IN_MONTH_VALUE = PERIOD_DAY_IN_MONTH_VALUE; // This one is both a Periodicity value and a key + private static final String KEY_END_OF_MONTH = WeekendPeriod.END_MONTH.getStrMonthType(); + private static final String KEY_FIRST_WE = WeekendPeriod.FIRST_WEEK_END.getStrMonthType(); + private static final String KEY_SECOND_WE = WeekendPeriod.SECOND_WEEK_END.getStrMonthType(); + private static final String KEY_THIRD_WE = WeekendPeriod.THIRD_WEEK_END.getStrMonthType(); + private static final String KEY_FOURTH_WE = WeekendPeriod.FOURTH_WEEK_END.getStrMonthType(); + private static final String KEY_FIFTH_WE = WeekendPeriod.FIFTH_WEEK_END.getStrMonthType(); + + // Error message + private static final String MESSAGE_REPORT_NOT_AUTHORIZED = "Ce rapport n'est pas disponible, car il est planifié"; + + // html Positioning + protected static final String MARGIN_TOP_10PX = " margin-top: 10px; "; + private static final String MARGIN_BOTTOM_20PX = " margin-bottom: 10px; "; + private static final String P_STYLE_SUBPERIOD = "display:inline;margin-right:10px; "; + private static final String DATEPICKER_KEY = "datepicker_planification"; + + // html constants + private static final String TYPE_TEXT = "text"; + private static final String TYPE_RADIO = "radio"; + private static final String EVENT_ON_CLICK = "onclick"; + private static final String CHECKED = "checked"; + + // CSS constants + private static final String CSS_CLASS_RADIO_INPUT = "radioInput"; + + // Translation to french + private static final String TEXT_ALL_DAYS = "Tous les jours"; + private static final String TEXT_ALL_WEEK = "Toutes les semaines"; + private static final String TEXT_ALL_MONTH = "Tous les mois"; + private static final String TEXT_BY_DATE = "Date"; + + // Weekdays in french + private static final String MONDAY_FR = "Lundi"; + private static final String TUESDAY_FR = "Mardi"; + private static final String WEDNESDAY_FR = "Mercredi"; + private static final String THURSDAY_FR = "Jeudi"; + private static final String FRIDAY_FR = "Vendredi"; + + // Weekday Nums + private static final int MONDAY_NUM = 1; + private static final int TUESDAY_NUM = 2; + private static final int WEDNESDAY_NUM = 3; + private static final int THURSDAY_NUM = 4; + private static final int FRIDAY_NUM = 5; + + // Weekends in french + private static final String FR_DAY_IN_MONTH = "Jour dans le mois"; + private static final String FR_END_OF_MONTH = "Fin du mois"; + private static final String FR_FIRST_WE = "1er Week-End"; + private static final String FR_SECOND_WE = "2nd Week-End"; + private static final String FR_THIRD_WE = "3ème Week-End"; + private static final String FR_FOURTH_WE = "4ème Week-End"; + private static final String FR_FIFTH_WE = "5ème Week-End"; + + // Javascript functions + protected static final String SUB_TITLE_PLANIFICATION = "subTitle_planification"; + private static final String SUB_TITLE_PLANIFICATION_REQUIRED = "subTitle_planification_Required"; + protected static final String SUB_TITLE_SUB_PERIOD = "subTitle_sub_period"; + + /* */ + Div getPeriod(final SchedulingEnum thePeriod, final Long identifier) { + // TEXT period + P paragraph = new P(); + paragraph.setStyle("margin-left: 20px; display:inline; margin-right:30px;").setCSSClass(SUB_TITLE_PLANIFICATION_REQUIRED) + .appendText("Période* : "); + // period + Div period = makePeriod(thePeriod, identifier); + return new Div().setStyle(MARGIN_TOP_10PX).setAlign("left").appendChild(paragraph).appendChild(period); + } + + + /*Make bloc period */ + private Div makePeriod(final SchedulingEnum thePeriod, final Long identifier) { + String name = "period"; + + Div containerPeriod = new Div(); + containerPeriod.setStyle("margin-left: 80px; margin-top: 10px;display:inline;").setId("div_period"); + SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); + Session session = sessionFactory.openSession(); + try { + String activePeriod = identifier == null ? "" : new MngSchedulingCriteriaVal().getPeriodOfSchedulingReportById(session, identifier).getName(); + + // Construct all the Radio Buttons + boolean isDaily = thePeriod == SchedulingEnum.DAILY; + boolean isWeekly = thePeriod == SchedulingEnum.WEEKLY; + boolean isMonthly = thePeriod == SchedulingEnum.WEEKEND || thePeriod == SchedulingEnum.DAY_IN_MONTH_VALUE; + boolean isDate = thePeriod == SchedulingEnum.DATE; + + Input daily = inputRadio(name, SchedulingEnum.DAILY, isDaily, EVENT_ON_CLICK, + makeJsFunctionGetSubPeriod(SchedulingEnum.DAILY, identifier, activePeriod)); + + Input weekly = inputRadio(name, SchedulingEnum.WEEKLY, isWeekly, EVENT_ON_CLICK, + makeJsFunctionGetSubPeriod(SchedulingEnum.WEEKLY, identifier, activePeriod)); + + Input monthly = inputRadio(name, SchedulingEnum.WEEKEND, isMonthly, EVENT_ON_CLICK, + makeJsFunctionGetSubPeriod(SchedulingEnum.WEEKEND, identifier, activePeriod)).setId("div_period_monthly"); + + Input date = inputRadio(name, SchedulingEnum.DATE, isDate, EVENT_ON_CLICK, + makeJsFunctionGetSubPeriod(SchedulingEnum.DATE, identifier, activePeriod)).setId("div_period_date"); + + // Construct the Div orderly + containerPeriod.appendChild(daily).appendChild(new P().setStyle(P_STYLE_SUBPERIOD).appendText(TEXT_ALL_DAYS)); + containerPeriod.appendChild(weekly).appendChild(new P().setStyle(P_STYLE_SUBPERIOD).appendText(TEXT_ALL_WEEK)); + containerPeriod.appendChild(monthly).appendChild(new P().setStyle(P_STYLE_SUBPERIOD).appendText(TEXT_ALL_MONTH)); + containerPeriod.appendChild(date).appendChild(new P().setStyle(P_STYLE_SUBPERIOD).appendText(TEXT_BY_DATE)); + + return containerPeriod; + } + finally { + session.close(); + } + } + + /* Function for period */ + private String makeJsFunctionGetSubPeriod(final SchedulingEnum period, final Long identifier, final String activePeriod) { + return "getSubPeriod('" + period.toString() + "', '" + identifier + "', '" + period.getCriteriaName().equals(activePeriod) + "');"; + } + + Div getSchedulingName(final String theScheduligName) { + String schedulingName = "scheduling_name"; + Label labelSchedulingName = makeLabel(schedulingName, "margin-left: 20px; margin-right: 140px;", "Nom* :") + .setCSSClass(SUB_TITLE_PLANIFICATION + " " + SUB_TITLE_PLANIFICATION_REQUIRED); + Input inputSchedulingName = inputText(schedulingName, theScheduligName).setStyle("width:380px;height:20px;").setId(schedulingName); + return new Div().setId("div_scheduling_name").setAlign("left").appendChild(labelSchedulingName).appendChild(inputSchedulingName); + } + + private Label makeLabel(final String forName, final String style, final String text) { + return new Label().setFor(forName).setStyle(style).appendChild(new Text(text)); + } + + /** + * Creates an {@link Input} of type Radio Button. + */ + private static Input inputRadio(final String name, final String value, final boolean checked) { + Input radio = new Input(); + radio.setCSSClass(CSS_CLASS_RADIO_INPUT).setName(name).setType(TYPE_RADIO).setValue(value); + if (checked) { + radio.setAttribute(CHECKED, CHECKED); + } + return radio; + } + + /** + * Creates an {@link Input} of type Radio Button.
    + * Example: if checked is true and event in onclick
    + * <input class="radioInput" type="radio" name=${NAME} value=${VALUE} onclick=${FUNCTION}> + */ + private static Input inputRadio(final String name, final SchedulingEnum value, final boolean checked, final String typeEvent, + final String functionOnEvent) { + Input radio = new Input(); + radio.setCSSClass(CSS_CLASS_RADIO_INPUT).setType(TYPE_RADIO).setName(name).setValue(value.getCriteriaName()).setAttribute(typeEvent, + functionOnEvent); + if (checked) { + radio.setAttribute(CHECKED, CHECKED); + } + return radio; + } + + /** + * Creates an {@link Input} of type "text".
    + * Example:
    + * <input type="text" name=${NAME} value=${VALUE}> + * + * @param name the name of the input + * @param value the value inside the input + * @return a text {@link Input} + */ + private static Input inputText(final String name, final String value) { + return new Input().setType(TYPE_TEXT).setName(name).setValue(value); + } + + @Override + public Div visit(final DayInMonth theDayInMonth) { + // Build the 'day_in_month' radio and input. + Input dayInMonth = inputRadio(PERIOD_WEEKEND, KEY_DAY_IN_MONTH_VALUE, true); // True because this is DAY_IN_MONTH period + Input dayInMonthValue = inputText(PERIOD_DAY_IN_MONTH_VALUE, theDayInMonth.getDayInMonth().toString()).setMaxlength("2") + .setId("dayInMonthValue").setStyle("width:24px;height:20px;margin-right:10px;"); + + // Even if DayInMonth is selected, each weekend button must also be constructed (unchecked), as both are accessible via the same radio button + + Input endOfMonth = inputRadio(PERIOD_WEEKEND, KEY_END_OF_MONTH, false); // False because this is DAY_IN_MONTH PERIOD + Input firstWE = inputRadio(PERIOD_WEEKEND, KEY_FIRST_WE, false); // False because this is DAY_IN_MONTH PERIOD + Input secondWE = inputRadio(PERIOD_WEEKEND, KEY_SECOND_WE, false); // False because this is DAY_IN_MONTH PERIOD + Input thirdWE = inputRadio(PERIOD_WEEKEND, KEY_THIRD_WE, false); // False because this is DAY_IN_MONTH PERIOD + Input fourthWE = inputRadio(PERIOD_WEEKEND, KEY_FOURTH_WE, false); // False because this is DAY_IN_MONTH PERIOD + Input fifthWE = inputRadio(PERIOD_WEEKEND, KEY_FIFTH_WE, false); // False because this is DAY_IN_MONTH PERIOD + + + // Make a Div and (orderly) add the radio buttons to it + Div containerWeekEnd = new Div(); + containerWeekEnd.setStyle("margin-left: 18px; display:inline;").setId("div_weekend"); + containerWeekEnd.appendChild(dayInMonth).appendChild(new P().setStyle("display:inline; ").appendText(FR_DAY_IN_MONTH)); + containerWeekEnd.appendChild(dayInMonthValue); + containerWeekEnd.appendChild(endOfMonth).appendChild(new P().setStyle(P_STYLE_SUBPERIOD).appendText(FR_END_OF_MONTH)); + containerWeekEnd.appendChild(firstWE).appendChild(new P().setStyle(P_STYLE_SUBPERIOD).appendText(FR_FIRST_WE)); + containerWeekEnd.appendChild(secondWE).appendChild(new P().setStyle(P_STYLE_SUBPERIOD).appendText(FR_SECOND_WE)); + containerWeekEnd.appendChild(thirdWE).appendChild(new P().setStyle(P_STYLE_SUBPERIOD).appendText(FR_THIRD_WE)); + containerWeekEnd.appendChild(fourthWE).appendChild(new P().setStyle(P_STYLE_SUBPERIOD).appendText(FR_FOURTH_WE)); + containerWeekEnd.appendChild(fifthWE).appendChild(new P().setStyle(P_STYLE_SUBPERIOD).appendText(FR_FIFTH_WE)); + + return containerWeekEnd; + } + + @Override + public Div visit(final WeekendPeriod weekend) { + // Build the 'day_in_month' radio and input. Even if WeekEnd Period is selected, then day_of_month must also be constructed (blank), as both are accessible via the same radio button + Input dayInMonth = inputRadio(PERIOD_WEEKEND, KEY_DAY_IN_MONTH_VALUE, false); // False because this is WEEKEND PERIOD + Input dayInMonthValue = inputText(PERIOD_DAY_IN_MONTH_VALUE, StringHelper.EMPTY).setMaxlength("2").setId("dayInMonthValue") + .setStyle("width:24px;height:20px;margin-right:10px;"); // Initialize day in month to empty (this is WEEKEND PERIOD) + + // Build the 'weekend' radio buttons. Only the provided weekend will be checked. + Input endOfMonth = inputRadio(PERIOD_WEEKEND, KEY_END_OF_MONTH, weekend == WeekendPeriod.END_MONTH); + Input firstWE = inputRadio(PERIOD_WEEKEND, KEY_FIRST_WE, weekend == WeekendPeriod.FIRST_WEEK_END); + Input secondWE = inputRadio(PERIOD_WEEKEND, KEY_SECOND_WE, weekend == WeekendPeriod.SECOND_WEEK_END); + Input thirdWE = inputRadio(PERIOD_WEEKEND, KEY_THIRD_WE, weekend == WeekendPeriod.THIRD_WEEK_END); + Input fourthWE = inputRadio(PERIOD_WEEKEND, KEY_FOURTH_WE, weekend == WeekendPeriod.FOURTH_WEEK_END); + Input fifthWE = inputRadio(PERIOD_WEEKEND, KEY_FIFTH_WE, weekend == WeekendPeriod.FIFTH_WEEK_END); + + // Make a Div and (orderly) add the radio buttons to it + Div containerWeekEnd = new Div(); + containerWeekEnd.setStyle("margin-left: 18px; display:inline;").setId("div_weekend"); + containerWeekEnd.appendChild(dayInMonth).appendChild(new P().setStyle("display:inline; ").appendText(FR_DAY_IN_MONTH)); + containerWeekEnd.appendChild(dayInMonthValue); + containerWeekEnd.appendChild(endOfMonth).appendChild(new P().setStyle(P_STYLE_SUBPERIOD).appendText(FR_END_OF_MONTH)); + containerWeekEnd.appendChild(firstWE).appendChild(new P().setStyle(P_STYLE_SUBPERIOD).appendText(FR_FIRST_WE)); + containerWeekEnd.appendChild(secondWE).appendChild(new P().setStyle(P_STYLE_SUBPERIOD).appendText(FR_SECOND_WE)); + containerWeekEnd.appendChild(thirdWE).appendChild(new P().setStyle(P_STYLE_SUBPERIOD).appendText(FR_THIRD_WE)); + containerWeekEnd.appendChild(fourthWE).appendChild(new P().setStyle(P_STYLE_SUBPERIOD).appendText(FR_FOURTH_WE)); + containerWeekEnd.appendChild(fifthWE).appendChild(new P().setStyle(P_STYLE_SUBPERIOD).appendText(FR_FIFTH_WE)); + + return containerWeekEnd; + } + + @Override + public Div visit(final SpecificDay specificDay) { + // TEXT date + Label labelSchedulingName = makeLabel(DATEPICKER_KEY, "margin-left: 20px; margin-right: 50px; ", "Date de planification"); + String dateStr = new SimpleDateFormat(TeamcenterDateFormatter.DD_MM_YYYY).format(specificDay.getDay()); + Input inputSchedulingName = inputText(DATEPICKER_KEY, dateStr).setId(DATEPICKER_KEY).setStyle("cursor:hand;width:80px;height:20px;"); + + Div flowElement = new Div(); + flowElement.setCSSClass("flow-element").appendChild(new Div().setId("container_planification")); + return new Div().setId("div_date").setStyle(MARGIN_TOP_10PX).appendChild(labelSchedulingName).appendChild(inputSchedulingName) + .appendChild(flowElement); + } + + @Override + public Div visit(final WeeklyPeriod dayInWeek) { + Input monday = inputRadio(PERIOD_WEEKLY, String.valueOf(MONDAY_NUM), dayInWeek.getDayInWeek() == MONDAY_NUM); + Input tuesday = inputRadio(PERIOD_WEEKLY, String.valueOf(TUESDAY_NUM), dayInWeek.getDayInWeek() == TUESDAY_NUM); + Input wednesday = inputRadio(PERIOD_WEEKLY, String.valueOf(WEDNESDAY_NUM), dayInWeek.getDayInWeek() == WEDNESDAY_NUM); + Input thursday = inputRadio(PERIOD_WEEKLY, String.valueOf(THURSDAY_NUM), dayInWeek.getDayInWeek() == THURSDAY_NUM); + Input friday = inputRadio(PERIOD_WEEKLY, String.valueOf(FRIDAY_NUM), dayInWeek.getDayInWeek() == FRIDAY_NUM); + + // Put it all (orderly) in a
    container + Div containerDaily = new Div(); + containerDaily.setStyle("margin-left: 200px; display:inline;").setId("div_weekly"); + containerDaily.appendChild(monday).appendChild(new P().setStyle(P_STYLE_SUBPERIOD).appendText(MONDAY_FR)); + containerDaily.appendChild(tuesday).appendChild(new P().setStyle(P_STYLE_SUBPERIOD).appendText(TUESDAY_FR)); + containerDaily.appendChild(wednesday).appendChild(new P().setStyle(P_STYLE_SUBPERIOD).appendText(WEDNESDAY_FR)); + containerDaily.appendChild(thursday).appendChild(new P().setStyle(P_STYLE_SUBPERIOD).appendText(THURSDAY_FR)); + containerDaily.appendChild(friday).appendChild(new P().setStyle(P_STYLE_SUBPERIOD).appendText(FRIDAY_FR)); + + return containerDaily; + } + + @Override + public Div visit(final DailyPeriod uselessParam) { + // TEXT period

    + P paragraph = new P(); + paragraph.setStyle("margin-left: 210px; display:inline; margin-right:30px;").appendText("Tous les jours"); + // period

    + return new Div().setStyle(MARGIN_TOP_10PX).setAlign("left").appendChild(paragraph); + } + +} diff --git a/kurt-web/src/main/java/com/capgemini/reports/common/scheduling/view/SchedulingParametersReader.java b/kurt-web/src/main/java/com/capgemini/reports/common/scheduling/view/SchedulingParametersReader.java new file mode 100644 index 0000000..87c6a75 --- /dev/null +++ b/kurt-web/src/main/java/com/capgemini/reports/common/scheduling/view/SchedulingParametersReader.java @@ -0,0 +1,56 @@ +package com.capgemini.reports.common.scheduling.view; + +import com.capgemini.reports.database.javabean.enumeration.SchedulingEnum; +import com.capgemini.reports.periodicity.*; + +/** This class can interrogate the DB and show sub-period parameters either loaded with DB data, or empty. */ +public class SchedulingParametersReader extends SchedulingFormatter { + + private static final WeeklyPeriod DEFAUT_VALUE_OF_WEEKLY = PeriodFactory.weekly(1); + private static final DayInMonth DEFAUT_VALUE_OF_WEEKEND = PeriodFactory.dayInMonth(1); + private static final DailyPeriod DEFAULT_VALUE_OF_DAILY = PeriodFactory.daily(); + + /** + * Return html code representing all the sub period data, pre-fileld or not. + * + * @param currentlySelectedSubPeriod the requested sup-period to display. (weekly / weekend...) + * @param existingUpdatePeriodFromDB optional, is present if isUpdate is true. + * @param isUpdate a boolean, true if a report scheduling is being update + * @return content sub period + */ + public String getSubPeriod(final SchedulingEnum currentlySelectedSubPeriod, final SchedulingPeriod existingUpdatePeriodFromDB, + final boolean isUpdate) { + if (isUpdate && existingUpdatePeriodFromDB.getPeriodicity() == currentlySelectedSubPeriod) { + return existingUpdatePeriodFromDB.accept(this).write(); + } else { + return getSubPeriodForNewScheduling(currentlySelectedSubPeriod); + } + } + + /** + * Return content of sub period. + * + * @param subPeriod + * @return content sub period + */ + private String getSubPeriodForNewScheduling(final SchedulingEnum subPeriod) { + final String result; + switch (subPeriod) { + case DAILY: + result = this.visit(DEFAULT_VALUE_OF_DAILY).write(); + break; + case WEEKLY: + result = this.visit(DEFAUT_VALUE_OF_WEEKLY).write(); + break; + case WEEKEND: + result = this.visit(DEFAUT_VALUE_OF_WEEKEND).write(); + break; + case DATE: + result = this.visit(PeriodFactory.today()).write(); + break; + default: + throw new UnsupportedOperationException("Unable to understand scheduling sub-period of type " + subPeriod); + } + return result; + } +} diff --git a/kurt-web/src/main/java/com/capgemini/reports/common/scheduling/view/UpdateSchedulingFormatter.java b/kurt-web/src/main/java/com/capgemini/reports/common/scheduling/view/UpdateSchedulingFormatter.java new file mode 100644 index 0000000..c65bc3b --- /dev/null +++ b/kurt-web/src/main/java/com/capgemini/reports/common/scheduling/view/UpdateSchedulingFormatter.java @@ -0,0 +1,79 @@ +package com.capgemini.reports.common.scheduling.view; + +import com.capgemini.reports.database.HibernateUtil; +import com.capgemini.reports.database.javabean.DbSchedulingCriteriaVal; +import com.capgemini.reports.database.javabean.DbSchedulingReport; +import com.capgemini.reports.database.manager.MngSchedulingCriteriaVal; +import com.capgemini.reports.database.manager.MngSchedulingReport; +import com.capgemini.reports.exceptions.InvalidInputException; +import com.capgemini.reports.periodicity.SchedulingPeriod; +import com.hp.gagawa.java.elements.Div; +import com.hp.gagawa.java.elements.Input; + +import lombok.Getter; +import org.hibernate.Session; +import org.hibernate.SessionFactory; + +/** + * This formatter page can display the existing scheduling data of a SchedulingReport from the DB. It is used in the 'update scheduling' page. + */ +@Getter +public class UpdateSchedulingFormatter extends SchedulingFormatter { + + private final Long reportId; + + /** + * Builds a formatter instance, that can display the 'update scheduling' page of the provided Scheduling Report ID. + * + * @param reportId the id of a {@link DbSchedulingReport} from the DB + */ + public UpdateSchedulingFormatter(final Long reportId) { + super(); + this.reportId = reportId; + } + + /** + * Builds the html content that will show the scheduling's parameters, in html. + */ + public String showReportUpdatePage() throws InvalidInputException { + SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); + Session session = sessionFactory.openSession(); + try { + final String uncheckedSchedulingName = new MngSchedulingReport().searchById(session, reportId).getSchedulingName(); + String theSchedulingName = uncheckedSchedulingName == null ? "" : uncheckedSchedulingName; + + SchedulingPeriod thePeriodicity = new MngSchedulingCriteriaVal().getPeriod(session, reportId); + + // hidden id of scheduling report + Input hidden = new Input().setType("hidden").setName("id").setValue(String.valueOf(reportId)); + + // scheduling name + Div containerSchedulingName = getSchedulingName(theSchedulingName); + + // Period (daily / weekly / weekend / date) + Div containerPeriod = getPeriod(thePeriodicity.getPeriodicity(), reportId).setId("div_container_period").setCSSClass(SUB_TITLE_PLANIFICATION); + + // Sub period (day in week / weekend num / day in month / date + Div containerSubPeriod = new Div(); + containerSubPeriod.setId("div_container_subPeriod").setStyle(MARGIN_TOP_10PX).setCSSClass(SUB_TITLE_SUB_PERIOD); + + // Active subPeriod + Div containerAllSubPeriods = thePeriodicity.accept(this); + + containerSubPeriod.appendChild(containerAllSubPeriods); + + // Parent + Div parent = new Div(); + parent.setId("div_temporal"); + parent.appendChild(hidden); + parent.appendChild(containerSchedulingName); + parent.appendChild(containerPeriod); + parent.appendChild(containerSubPeriod); + + return parent.write(); + } + finally { + session.close(); + } + } +} diff --git a/kurt-web/src/main/java/com/capgemini/reports/formatting/AbstractTableFormatter.java b/kurt-web/src/main/java/com/capgemini/reports/formatting/AbstractTableFormatter.java new file mode 100644 index 0000000..68d0195 --- /dev/null +++ b/kurt-web/src/main/java/com/capgemini/reports/formatting/AbstractTableFormatter.java @@ -0,0 +1,99 @@ +package com.capgemini.reports.formatting; + +import com.capgemini.framework.common.FileTemplate; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.reports.database.HibernateUtil; +import com.capgemini.reports.exceptions.NothingToBeShownException; +import lombok.extern.slf4j.Slf4j; +import org.hibernate.HibernateException; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.quartz.SchedulerException; + +/** + * This abstract class allows easy creation of a js table.
    + * If no data exist or if an errror occurs during the table construction, an appropriate message is shown. + */ +@Slf4j +public abstract class AbstractTableFormatter extends FileTemplate { + + private static final String TAG_TABLE_DATA = "TABLE_DATA"; + private static final String TAG_ERROR_MESSAGE = "ERROR_MESSAGE"; + + /** + * Generates a html page displaying a table.
    + * If not elements exist in the table, shows a message that says so.
    + * If the DB could not be queried, shows an error message. + * + * @return the full html page content + */ + public String makeJsContent() { + SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); + Session session = sessionFactory.openSession(); + try { + String jsDataTable = makeTable(session); // Attempt to format all the reports into a JS table + super.setTemplateFilePath(successPageTemplateLocation()); + super.setTagValue(TAG_TABLE_DATA, jsDataTable); + this.addOptionalTags(session); + } + catch (NothingToBeShownException e) { + // This is normal behaviour: the table does not contain any matching entries. No worries + log.trace("Normal exception: nothing to show in HMI", e); + super.setTemplateFilePath(failedPageTemplateLocation()); + super.setTagValue(TAG_ERROR_MESSAGE, e.getErrorMessageForUser()); + this.addOptionalErrorTags(); + } + catch (KurtException e) { + // A Technical error occured, unable to display the screen contents + super.setTemplateFilePath(failedPageTemplateLocation()); + super.setTagValue(TAG_ERROR_MESSAGE, e.getErrorMessageForUser()); + this.addOptionalErrorTags(); + log.debug("Unable to perform user request", e); + } + catch (HibernateException e) { + super.setTemplateFilePath(failedPageTemplateLocation()); + super.setTagValue(TAG_ERROR_MESSAGE, "Impossible de communiquer avec la base de données"); + this.addOptionalErrorTags(); + log.error("A Database error occured while trying to show MyReports table", e); // This is not normal behaviour. Check query syntax, and Hibernate config + } + catch (SchedulerException e) { + super.setTemplateFilePath(failedPageTemplateLocation()); + super.setTagValue(TAG_ERROR_MESSAGE, "Impossible de communiquer avec le système de planification"); + this.addOptionalErrorTags(); + log.error("An error occurred while communicationg with Quartz", e); // This is not normal behaviour. Check Quartz setup + } + finally { + session.close(); + } + return this.generateCode(); + } + + /** + * Allows to add optional tags, if the template is a bit more complex. + */ + protected abstract void addOptionalTags(Session session); + + /** + * Allows to add optional tags, if the ERROR template is a bit more complex. + */ + protected abstract void addOptionalErrorTags(); + + /** + * Main method: builds a javascript table to be inserted into the webpage. + */ + protected abstract String makeTable(Session session) throws KurtException, SchedulerException; + + /** + * The location of the template html page, in case the data was successfully retrieved. + * + * @return the file location in src/main/resources + */ + protected abstract String successPageTemplateLocation(); + + /** + * The location of the template html page, in case the data could not be retrieved. + * + * @return the file location in src/main/resources + */ + protected abstract String failedPageTemplateLocation(); +} diff --git a/kurt-web/src/main/java/com/capgemini/reports/formatting/AllSchedulingReports.java b/kurt-web/src/main/java/com/capgemini/reports/formatting/AllSchedulingReports.java new file mode 100644 index 0000000..8e7594a --- /dev/null +++ b/kurt-web/src/main/java/com/capgemini/reports/formatting/AllSchedulingReports.java @@ -0,0 +1,289 @@ +package com.capgemini.reports.formatting; + +import com.capgemini.framework.common.SettingsHelper; +import com.capgemini.framework.common.activedirectory.ActiveDirectory; +import com.capgemini.reports.ReportEnum; +import com.capgemini.reports.common.scheduling.controller.SchedulingReaderServlet.SchedulingReportEntry; +import com.capgemini.reports.database.javabean.DbUser.UserData; +import com.capgemini.reports.database.manager.MngReportType; +import com.capgemini.reports.database.manager.MngSchedulingReport; +import com.capgemini.reports.exceptions.InvalidActiveDirectorySearchException; +import com.capgemini.reports.exceptions.InvalidInputException; +import com.capgemini.reports.exceptions.NoConnectionToActiveDirectoryException; +import com.capgemini.reports.exceptions.NothingToBeShownException; +import com.google.common.base.Optional; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang.StringEscapeUtils; +import org.hibernate.Session; + +import java.text.SimpleDateFormat; +import java.util.Collection; +import java.util.Date; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; +import java.util.Set; + +/** + * This page displays all information on report schduling. + *

    + * Top left is a filter on report codes
    + * Top right is a combobox that tells if the report selected in the filter will
    + * Below is a table listing all currently scheduled reports: + *

      + *
    1. Report Code (R01 / R20...)
    2. + *
    3. Scheduling name
    4. + *
    5. Periodicity (weekly, monthly, etc.)
    6. + *
    7. Last modification date
    8. + *
    9. Owning administrator (final a User)
    10. + *
    11. Next scheduled launch
    12. + *
    13. A button opening a popup showing the report's Functional parameters
    14. + *
    15. A button opening a page to edit the line's scheduling parameters
    16. + *
    17. A button to delete the line's schedule altogether.
    18. + *
    + */ +@Slf4j +public class AllSchedulingReports extends AbstractTableFormatter { + + + private static final boolean DEV_MODE = SettingsHelper.isDevMode(); + private static final int MAX_PAGE_SIZE = SettingsHelper.getJspPaging(); + + private static final String QUOTE_WITH_END_COMMA = "' ; "; + private static final String BUTTON_END = ""; + + private static final String TAG_SELECT_DATA = "SELECT_DATA"; + private static final String TAG_DISPLAY_BUTTONS = "DISPLAY_BUTTONS"; + private static final String TAG_ACTIF_REPORT_NAME = "ACTIF_REPORT_NAME"; + private static final String TAG_ACTIF_REPORT_VALUE = "ACTIF_REPORT_VALUE"; + private static final String TAG_ACTIF_BUTTON_VALIDATE = "ACTIF_BUTTON_VALIDATE"; + private static final String TAG_PAGING = "PAGING"; + /** + * Date Format of the form 'dd-MMMM-yyyy' which gives '08-April-2014' in US timezone. + */ + private static final String DD_MMMM_YYYY = "dd MMMM yyyy"; + private static final String SIMPLE_FORMATTER = DD_MMMM_YYYY; + + private final String theUserLogin; + + /** + * The report filter. May be null far 'all'. + */ + private final Optional reportCode; + private final String thePageParamStr; + private final Set entries; + private String paging; + + /** + * Constructs an instance of this page. Invoke {@link AllSchedulingReports#makeJsContent()} to generate it.
    + * This page displays all information on report scheduling. + *

    + * Top left is a filter on report codes
    + * Top right is a combobox that tells if the report selected in the filter will
    + * Below is a table listing all currently scheduled reports: + *

      + *
    1. Report Code (R01 / R20...)
    2. + *
    3. Scheduling name
    4. + *
    5. Periodicity (weekly, monthly, etc.)
    6. + *
    7. Last modification date
    8. + *
    9. Owning administrator (final a User)
    10. + *
    11. Next scheduled launch
    12. + *
    13. A button opening a popup showing the report's Functional parameters
    14. + *
    15. A button opening a page to edit the line's scheduling parameters
    16. + *
    17. A button to delete the line's schedule altogether.
    18. + *
    + * + * @param reportCode the {@link ReportEnum} (maybe null for ALL) + * @param thePageParamStr (optional) the page number.
    + * possible values: 1, 2, 3... + * @param theUserLogin the login of the user who requested the page + * @param entries a {@link Set} of {@link SchedulingReportEntry} obtained from the DB, that belong to the user + */ + public AllSchedulingReports(final ReportEnum reportCode, final String thePageParamStr, final String theUserLogin, + final Set entries) { + super(); + this.reportCode = Optional.fromNullable(reportCode); + this.thePageParamStr = thePageParamStr; + this.theUserLogin = theUserLogin; + this.entries = entries; + } + + private static int obtainIntegerPageParam(final String thePageParamStr) throws InvalidInputException { + if (thePageParamStr != null) { + try { + return Integer.parseInt(thePageParamStr); + } + catch (NumberFormatException e) { + throw new InvalidInputException("Numéro de page incorrect", e); + } + } + else { + return 1; + } + } + + private static long pageCount(final long schedulingReportCount) { + return (schedulingReportCount - 1) / MAX_PAGE_SIZE + 1; // Integer division + } + + @Override + protected String makeTable(Session session) throws InvalidInputException { + // Reject request if not admin nor devmode + if (!DEV_MODE) { + boolean isAdmin = false; // by default + try { + UserData userData = ActiveDirectory.obtainUserData(theUserLogin); + isAdmin = userData.isAdmin(); + } + catch (InvalidInputException e) { + log.warn("No login received, unable to authorize admin access", e); + } + catch (NoConnectionToActiveDirectoryException e) { + log.warn("Could not connect to the AD to findAll users admin report ", e); + } + catch (InvalidActiveDirectorySearchException e) { + log.warn("Could not perform a search on the AD, to findAll users admin report", e); + } + if (!isAdmin) { + String aTechnicalErrorMessage = "User \"" + theUserLogin + "\" is not an administrator but requested the scheduling page"; + String userMessage = + "L'utilisateur \"" + theUserLogin + "\" n'est pas un administrateur et ne peut accéder à la page de planification"; + throw new NothingToBeShownException(aTechnicalErrorMessage, userMessage); + } + } + + // Prepare data + MngSchedulingReport mgnSchedulingReport = new MngSchedulingReport(); + final long schedulingReportCount; + if (reportCode.isPresent()) { + schedulingReportCount = mgnSchedulingReport.countSchedulingReportsByReportCode(session, reportCode.get()); + } + else { + schedulingReportCount = mgnSchedulingReport.countAllSchedulingReport(session); + } + int thePageParam = obtainIntegerPageParam(thePageParamStr); + long pageCount = pageCount(schedulingReportCount); + + JsTableCreator reportArray = new JsTableCreator("reportArray"); + for (SchedulingReportEntry entry : entries) { + String owner = entry.getUserResponsable(); + Long schedulingId = entry.getId(); + Optional nextFireTime = entry.getNextFireTime(); + SimpleDateFormat frenchDateFormat = new SimpleDateFormat(SIMPLE_FORMATTER, Locale.FRENCH); + String nextFireTimeStr = nextFireTime.isPresent() ? frenchDateFormat.format(nextFireTime.get()) : "Jamais"; + String lastUpdate = frenchDateFormat.format(entry.getLastUpdate()); + + // Make a line in the js table + Map schedulingReportsAsMap = new HashMap<>(); + schedulingReportsAsMap.put("report_code", StringEscapeUtils.escapeJavaScript(entry.getReportCode().getReportCode())); + schedulingReportsAsMap.put("planif_name", StringEscapeUtils.escapeJavaScript(entry.getPlanificationName())); + schedulingReportsAsMap.put("period", StringEscapeUtils.escapeJavaScript(entry.getPeriod())); + schedulingReportsAsMap.put("date_maj", StringEscapeUtils.escapeJavaScript(lastUpdate)); + schedulingReportsAsMap.put("user_responsable", StringEscapeUtils.escapeJavaScript(owner)); + schedulingReportsAsMap.put("date_start", StringEscapeUtils.escapeJavaScript(nextFireTimeStr)); + schedulingReportsAsMap.put("id", StringEscapeUtils.escapeJavaScript(schedulingId.toString())); + reportArray.addLine(schedulingReportsAsMap); + } + + // Additional tags preparation + paging = makePaging(thePageParam, pageCount); + + return reportArray.toString(); + } + + /* Paging */ + private String makePaging(final int thePageParam, final long theLastPage) { + /* Manage page browsing */ + StringBuilder thePaging = new StringBuilder(); + for (int i = 1; (i <= theLastPage) && (theLastPage > 1); i++) { + if (thePaging.length() > 0) { + thePaging.append(" - "); + } + else { + thePaging.append( + "
     
    Pages: "); + } + + if (i == thePageParam) { + thePaging.append(""); + showButton.append(""); + } + else { + showButton.append(""); + } + return showButton.toString(); + } + + /** + * Return js code for an array containing 'TOUS' as well as all report types authorized for planification. + */ + private String getDatasReportType(Session session) { + MngReportType theMngReportType = new MngReportType(); + Collection theReportType = theMngReportType.getAllSchedulableReportTypes(session); + JsArrayCreator selectArray = new JsArrayCreator("selectArray"); + selectArray.addEntry("TOUS"); + selectArray.addAll(theReportType); + return selectArray.toString(); + } + + private String isSchedulingAuthorized(Session session, final ReportEnum aReportCode) { + return new MngReportType().search(session, aReportCode).getReportAuthorized(); + } + + @Override + protected void addOptionalErrorTags() { + // Nothing to do for Running Reports + } + +} diff --git a/kurt-web/src/main/java/com/capgemini/reports/formatting/ErrorPageTemplate.java b/kurt-web/src/main/java/com/capgemini/reports/formatting/ErrorPageTemplate.java new file mode 100644 index 0000000..6370727 --- /dev/null +++ b/kurt-web/src/main/java/com/capgemini/reports/formatting/ErrorPageTemplate.java @@ -0,0 +1,38 @@ +package com.capgemini.reports.formatting; + +import lombok.extern.slf4j.Slf4j; + +import com.capgemini.framework.common.FileTemplate; +import com.capgemini.framework.common.ResourceHelper; +import com.capgemini.reports.exceptions.FileLoadingException; + +/** Template loader for HTML content in order to display an error in JSP. **/ +@Slf4j +public class ErrorPageTemplate extends FileTemplate { + + /** + * Constructor. + * + * @param anErrorTitle Title of the error + * @param anErrorMessage Content message for the current error + */ + public ErrorPageTemplate(final String anErrorTitle, final String anErrorMessage) { + + super(); + + // Select the corresponding template content + try { + String theTemplateContent = ResourceHelper.getResourceContent("/html/error_jsp_page.html"); + setTemplateContent(theTemplateContent); + } + catch (FileLoadingException e) { + log.warn("Could not load the Page template", e); + } + + // Assign the expected template + + // Set tag values + setTagValue("ERROR_TITLE", anErrorTitle); + setTagValue("ERROR_MESSAGE", anErrorMessage); + } +} diff --git a/kurt-web/src/main/java/com/capgemini/reports/formatting/JsArrayCreator.java b/kurt-web/src/main/java/com/capgemini/reports/formatting/JsArrayCreator.java new file mode 100644 index 0000000..fe074f5 --- /dev/null +++ b/kurt-web/src/main/java/com/capgemini/reports/formatting/JsArrayCreator.java @@ -0,0 +1,55 @@ +package com.capgemini.reports.formatting; + +import java.util.Collection; + +/** + * Creates a js array easily.
    + * Example output:
    + * var tab = new Array();\n
    + * tab[0] = 'toto';\n
    + * tab[1] = 'tata';\n + */ +public class JsArrayCreator { + + private final StringBuilder content = new StringBuilder(); + private final String tableName; + private int lineCount; + + /** + * Creates a js array wit hthe provided name. + * + * @param tableName the name of the table + */ + public JsArrayCreator(final String tableName) { + this.tableName = tableName; + this.content.append("\n").append("var ").append(tableName).append(" = new Array();\n"); + this.lineCount = 0; + } + + /** + * Add an entry to the table (will add a new line to the array). + * + * @param entry the content + */ + public void addEntry(final String entry) { + content.append(tableName).append('[').append(lineCount).append("] = '").append(entry).append("';\n"); + lineCount++; + } + + /** + * Adds the provided beans' content to a line in the table. + * + * @param someObjects a {@link Collection} of JAVA objects, on which {@link Object#toString() toString} will be invoked + */ + public void addAll(final Collection someObjects) { + for (Object aBean : someObjects) { + addEntry(aBean.toString()); + } + } + + @Override + public String toString() { + return content.toString(); + } + +} diff --git a/kurt-web/src/main/java/com/capgemini/reports/formatting/JsTableCreator.java b/kurt-web/src/main/java/com/capgemini/reports/formatting/JsTableCreator.java new file mode 100644 index 0000000..e700fa2 --- /dev/null +++ b/kurt-web/src/main/java/com/capgemini/reports/formatting/JsTableCreator.java @@ -0,0 +1,104 @@ +package com.capgemini.reports.formatting; + +import com.capgemini.framework.common.BeanHelper; + +import java.util.Collection; +import java.util.Map; +import java.util.Map.Entry; + +/** + * Creates a Javascript table declaration, along with content. The table is 2D, with line numbers [0..n] as dimension 1, and whatever you want as dimension 2.
    + * Example output with table name 'tab', and two provided maps: + *
      + *
    • map1={key1=val1, key2=val2}
    • + *
    • map2={key1=val3, key2=val4} + *
    + * Expected output: + *

    + * var tab = new Array();
    + * tab[0] = new Array();
    + * tab[0]['key1'] = val1
    + * tab[0]['key2'] = val2
    + * tab[1] = new Array();
    + * tab[1]['key1'] = val3
    + * tab[1]['key2'] = val4
    + *

    + * Note: keys may not even be coherent between lines. + */ +public class JsTableCreator { + + final StringBuilder content = new StringBuilder(); + final String tableName; + int lineCount; + + /** + * Creates a js table, with the provided name. The table is 2D, with line numbers as dimension 1, and whatever you want as dimension 2. + * + * @param tableName the table name. + */ + public JsTableCreator(final String tableName) { + this.tableName = tableName; + this.content.append("\nvar ").append(tableName).append(" = new Array();\n"); + this.lineCount = 0; + } + + /** + * Adds a line showing for each map key, the associated value. + * + * @param lineContent the {@link Map} + */ + public void addLine(final Map lineContent) { + content.append('\n'); + String thisLine = "\t" + tableName + "[" + lineCount + "]"; + content.append(thisLine).append(" = new Array();\n"); + for (Entry entry : lineContent.entrySet()) { + content.append(thisLine).append("['").append(entry.getKey()).append("'] = '").append(entry.getValue()).append("';\n"); + } + lineCount++; + } + + /** + * Adds the provided bean's content to a line in the table. + * + * @param aJavaBean JAVA bean + */ + public void addBean(final Object aJavaBean) { + Map theAttMap = BeanHelper.toStringMap(aJavaBean); + addLine(theAttMap); + } + + /** + * Adds a line formed by the bean's contents, as well as the map's content. + * + * @param map the map + * @param aJavaBean the bean + */ + public void addLineAndBean(final Map map, final Object aJavaBean) { + content.append('\n'); + String thisLine = "\t" + tableName + "[" + lineCount + "]"; + content.append(thisLine).append(" = new Array();\n"); + Map lineContent = BeanHelper.toStringMap(aJavaBean); + lineContent.putAll(map); + for (Entry entry : lineContent.entrySet()) { + content.append(thisLine).append("['").append(entry.getKey()).append("'] = '").append(entry.getValue()).append("';\n"); + } + lineCount++; + } + + /** + * Adds the provided beans' content to a line in the table. + * + * @param someJavaBeans a {@link Collection} of JAVA beans + */ + public void addAllBean(final Collection someJavaBeans) { + for (Object aBean : someJavaBeans) { + addBean(aBean); + } + } + + @Override + public String toString() { + return content.toString(); + } + +} diff --git a/kurt-web/src/main/java/com/capgemini/reports/formatting/MyReports.java b/kurt-web/src/main/java/com/capgemini/reports/formatting/MyReports.java new file mode 100644 index 0000000..f862881 --- /dev/null +++ b/kurt-web/src/main/java/com/capgemini/reports/formatting/MyReports.java @@ -0,0 +1,133 @@ +package com.capgemini.reports.formatting; + +import com.capgemini.framework.common.SettingsHelper; +import com.capgemini.framework.common.StringHelper; +import com.capgemini.reports.database.manager.MngReport; +import com.capgemini.reports.database.manager.MngReport.RunningReportEntry; +import com.capgemini.reports.exceptions.InvalidInputException; +import com.capgemini.reports.exceptions.NothingToBeShownException; +import org.hibernate.Session; + +import java.util.List; + +/** This class can generate an html page showing every reports currently running or waiting to be executed that are owned by the logged-in user. */ +public class MyReports extends AbstractTableFormatter { + // User input + private final String thePageParamStr; + + // Last entries: to be put in additional Tags + private String paging; + private long reportCount; + private final String theUserLogin; + + private static final String BUTTON_END = ""; + + /** + * Create the some user's 'My Reports' page, passing the page number to be shown as (String) parameter. + * + * @param thePageParamStr the page number + * @param userLogin the login of the user who wants to know the status of his reports + */ + public MyReports(final String thePageParamStr, final String userLogin) { + super(); + this.thePageParamStr = thePageParamStr; + this.theUserLogin = userLogin == null ? "Invité(e)" : userLogin; + } + + @Override + protected String makeTable(Session session) throws InvalidInputException { + // Prepare data + MngReport theMngRep = new MngReport(); + this.reportCount = theMngRep.countUserReports(session, theUserLogin); + int thePageParam = obtainIntegerPageParam(thePageParamStr); + long pageCount = pageCount(reportCount); + + StringBuilder theTableJsCode = new StringBuilder("var reportArray = new Array();\n"); + + // Access the user reports for the current page + int theLineCount = 0; + List theUserReports = theMngRep.searchUserReports(session, theUserLogin, thePageParam); + if (theUserReports.isEmpty()) { + throw new NothingToBeShownException("No previous report executions", "Aucun rapport executé"); + } + + for (RunningReportEntry currentReport : theUserReports) { + String table = "\treportArray[" + theLineCount + "]"; + theTableJsCode.append(StringHelper.toJs(table, currentReport.getReport())); + theTableJsCode.append(table).append("['requestDate'] = '").append(currentReport.getRequestDate()).append("';"); + theLineCount++; + } + + // Additional tags preparation + paging = makePaging(thePageParam, pageCount); + + return theTableJsCode.toString(); + } + + protected static int obtainIntegerPageParam(final String thePageParamStr) throws InvalidInputException { + if (thePageParamStr != null) { + try { + return Integer.parseInt(thePageParamStr); + } catch (NumberFormatException e) { + throw new InvalidInputException("Numéro de page incorrect", e); + } + } + return 1; + } + + protected static long pageCount(final long theUserReportCount) { + int theMaxPageSize = SettingsHelper.getJspPaging(); + return (theUserReportCount - 1) / theMaxPageSize + 1; // Integer division + } + + protected static String makePaging(final int thePageParam, final long theLastPage) { + /* Manage page browsing */ + StringBuilder thePaging = new StringBuilder(); + if (theLastPage > 1) { + for (int i = 1; i <= theLastPage; i++) { + if (thePaging.length() > 0) { + thePaging.append(" - "); + } else { + thePaging.append("
     
    Pages: "); + } + + if (i != thePageParam) { + thePaging + .append(" + + + + + \ No newline at end of file diff --git a/kurt-web/src/main/resources/html/myReports/my_reports_success.html b/kurt-web/src/main/resources/html/myReports/my_reports_success.html new file mode 100644 index 0000000..98bfe41 --- /dev/null +++ b/kurt-web/src/main/resources/html/myReports/my_reports_success.html @@ -0,0 +1,46 @@ + + + + Mes rapports - [[USER_LOGIN]] + + + + + + + + +

    Mes rapports - [[USER_LOGIN]] : [[USER_REPORT_COUNT]] rapport(s)

    + + + Rafraichir +

    + +
    +
    + + + + + + + + + + +
    Code du rapportDate de demandeDate de lancementDate de finInfosStatut
    + + [[PAGING]] + +

    + + +
    + + + \ No newline at end of file diff --git a/kurt-web/src/main/resources/html/queueStatus/queue_status_failed.html b/kurt-web/src/main/resources/html/queueStatus/queue_status_failed.html new file mode 100644 index 0000000..0344a0f --- /dev/null +++ b/kurt-web/src/main/resources/html/queueStatus/queue_status_failed.html @@ -0,0 +1,31 @@ + + + + + + + + + Rapports en attente + + + + + + + + Rafraichir + +

    Rapports en attente

    + +
    +
    + [[ERROR_MESSAGE]] +

    + +
    + + + \ No newline at end of file diff --git a/kurt-web/src/main/resources/html/queueStatus/queue_status_success.html b/kurt-web/src/main/resources/html/queueStatus/queue_status_success.html new file mode 100644 index 0000000..935b626 --- /dev/null +++ b/kurt-web/src/main/resources/html/queueStatus/queue_status_success.html @@ -0,0 +1,36 @@ + + + + + + + + + Rapports en attente + + + + + + + + + Rafraichir + +

    Rapports en attente

    + +
    +
    + + +

    + +
    + + + \ No newline at end of file diff --git a/kurt-web/src/main/resources/html/runningReports/running_reports_failed.html b/kurt-web/src/main/resources/html/runningReports/running_reports_failed.html new file mode 100644 index 0000000..fb8d68c --- /dev/null +++ b/kurt-web/src/main/resources/html/runningReports/running_reports_failed.html @@ -0,0 +1,40 @@ + + + + Rapports en cours + + + + + + + + +

    Rapports en cours

    + +
    Auto-refresh:
    + +
    +
    + [[ERROR_MESSAGE]] +

    + +
    + + + + + \ No newline at end of file diff --git a/kurt-web/src/main/resources/html/runningReports/running_reports_success.html b/kurt-web/src/main/resources/html/runningReports/running_reports_success.html new file mode 100644 index 0000000..8c97146 --- /dev/null +++ b/kurt-web/src/main/resources/html/runningReports/running_reports_success.html @@ -0,0 +1,54 @@ + + + + Rapports en cours + + + + + + + + + + +

    Rapports en cours

    + +
    Auto-refresh:
    + +
    +
    + + + + + + + + + + + +
    Code du rapportPrioritéUtilisateurDate de demandeDate de lancementInfosStatut
    +
    + + + + + \ No newline at end of file diff --git a/kurt-web/src/main/resources/html/schedulingReports/schedulingReports_error.html b/kurt-web/src/main/resources/html/schedulingReports/schedulingReports_error.html new file mode 100644 index 0000000..d24ff7e --- /dev/null +++ b/kurt-web/src/main/resources/html/schedulingReports/schedulingReports_error.html @@ -0,0 +1,31 @@ + + + + + Planification des rapports + + + + + + + + +
    +

    Planification des rapports

    +
    +
    + + +
    +
    + [[ERROR_MESSAGE]] +

    + + + +
    +
    + + + \ No newline at end of file diff --git a/kurt-web/src/main/resources/html/schedulingReports/schedulingReports_success.html b/kurt-web/src/main/resources/html/schedulingReports/schedulingReports_success.html new file mode 100644 index 0000000..736b814 --- /dev/null +++ b/kurt-web/src/main/resources/html/schedulingReports/schedulingReports_success.html @@ -0,0 +1,132 @@ + + + + + Planification des rapports + + + + + + + + + + + + + + + + + + + +
    +

    Planification des rapports

    +
    +
    +
    + + + + + + + + + + + + + +
    +

    Filtrer les rapports

    +
    +

    Autoriser le lancement du rapport affiché en + immediat ou différé

    +
    + + + + +
    +
    + +
    +
    +
    + + + + + +
    +

    Rapport(s) planifié(s)

    +
    +
    + + + + + + + + + + + + + + + + +
    RapportNom planificationPériodeDernière modificationAdmin. responsableDate prochain lancementInfosModifierSupprimer
    +
    +
    +[[PAGING]] + + + [[DISPLAY_BUTTONS]] + +
    + + \ No newline at end of file diff --git a/kurt-web/src/main/webapp/WEB-INF/beans.xml b/kurt-web/src/main/webapp/WEB-INF/beans.xml new file mode 100644 index 0000000..3738086 --- /dev/null +++ b/kurt-web/src/main/webapp/WEB-INF/beans.xml @@ -0,0 +1,27 @@ + + + + + + diff --git a/kurt-web/src/main/webapp/WEB-INF/ejb-jar.xml b/kurt-web/src/main/webapp/WEB-INF/ejb-jar.xml new file mode 100644 index 0000000..ebea87c --- /dev/null +++ b/kurt-web/src/main/webapp/WEB-INF/ejb-jar.xml @@ -0,0 +1,26 @@ + + + Deployment descriptor + + + + jobConsumer + com.capgemini.reports.queuing.consumer.ReportConsumer + javax.jms.MessageListener + javax.jms.Queue + + + minSession + 15 + + + maxSession + 15 + + + + + + diff --git a/kurt-web/src/main/webapp/WEB-INF/web.xml b/kurt-web/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000..59926b1 --- /dev/null +++ b/kurt-web/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,58 @@ + + +Servlet 3.0 Web Application + + + + + \ No newline at end of file diff --git a/kurt-web/src/main/webapp/css/dialog.css b/kurt-web/src/main/webapp/css/dialog.css new file mode 100644 index 0000000..acc9abb --- /dev/null +++ b/kurt-web/src/main/webapp/css/dialog.css @@ -0,0 +1,66 @@ +/* DIALOG PART */ +/***************/ +#dialog { + position: absolute; + width: 600px; + left: 50%; + top: 300px; + margin-left: -300px; + padding: 0px; + z-index: 200; + background: #fff; + filter: progid:DXImageTransform.Microsoft.Shadow(Strength=4, Direction=135, Color='#333355'); + box-shadow: 1px 1px 5px #555; +} + +#dialog-header { + display: block; + height: 24px; + background: #fff url(../ihm/dialog.gif) repeat-x; + padding-right: -4px; +} + +#dialog-title { + float: left; + height: 24px; + font-weight: bold; + font-family: Verdana; + font-size: 12px; + padding: 4px; + color: #fff; + border-left: 1px solid #DCEFFC; +} + +#dialog-content { + padding: 6px; + color: #15142B; + font-size: 13px; + font-family: Verdana; + text-align: center; + font-weight: bold; +} + +#dialog-mask { + position: absolute; + top: 0; + left: 0; + min-height: 100%; + width: 100%; + background: #BBBBCC; + opacity: .5; + filter: alpha(opacity=50); + z-index: 100 +} + +#diag-btclose { + float: right; + margin-left: -2px; + width: 18px; + height: 18px; + margin-top: 4px; +} + +#diag-btcloseX { + margin-left: -4px; + font-weight: bold; +} \ No newline at end of file diff --git a/kurt-web/src/main/webapp/css/kurt-style-frame.css b/kurt-web/src/main/webapp/css/kurt-style-frame.css new file mode 100644 index 0000000..c168bf3 --- /dev/null +++ b/kurt-web/src/main/webapp/css/kurt-style-frame.css @@ -0,0 +1,177 @@ +body{ + background-color:#FFFFFF; + margin:10px; + font-family:Verdana; + font-size:11px; +} + +strong{ + color:#78718F; +} + +td{ + font-family:Verdana; + font-size:11px; +} + +td.tdFieldTitle{ + width:210px; + font-weight:bold; + color:#7D8490; + font-size:12px; + padding-left:20px; + text-align:left; +} +td.tdFieldTitleScheduling{ + font-weight:bold; + color:#7D8490; + font-size:12px; + padding-left:20px; + text-align:left; +} +td.tdFieldTitle_align_right{ + width:210px; + font-weight:bold; + color:#7D8490; + font-size:12px; + padding-left:20px; + text-align:right; +} +td.delimitedPart{ + font-size:14px; + color:#787599; +} + +td.required{ + color:#CC0000; +} + +th.reportTable +{ + height:18px; + font-size:12px; + color:#3E3E5C; + background-image:url('../ihm/left-bar-action-back-hover.png'); + background-repeat:repeat-x; + border-bottom:3px double #E1E8ED; +} + +th.reportTableScheduling +{ + height:12px; + font-size:12px; + color:#3E3E5C; + background-image:url('../ihm/left-bar-action-back-hover.png'); + background-repeat:repeat-x; + border-bottom:3px double #E1E8ED; +} + +td.reportTable +{ + border-bottom:1px solid #E1E8ED; + text-align:center; +} + +input{ + width:310px; + height:21px; + color:#3E567D; + font-family:Verdana; + font-size:11px; + padding:3px; + border:1px solid #CCC7D1; + background-image:url('../ihm/input-back.png'); + background-repeat:repeat-x; + border-radius:2px; +} + +input.radioInput{ + width:16px; + height:12px; + font-size:10px; + border:none; + background:none; +} + +input.checkform{ + width:16px; + height:12px; + font-size:10px; + border:none; + background:none; +} + +label { + margin-left: 85px; +} + + +select{ + size:1; + align:center; + width:316px; + height:26px; + color:#3E567D; + font-family:Verdana; + font-size:11px; + padding:3px; + border:1px solid #CCC7D1; + background-image:url('../ihm/input-back.png'); + background-repeat:repeat-x; + border-radius:2px; +} + +select.basicSelect{ + size:1; + width:100px; + height:26px; + color:#3E567D; + font-family:Verdana; + font-size:11px; + padding:3px; + border:1px solid #CCC7D1; + background-image:none; + background-repeat:none; + border-radius:2px; +} + +textarea { + width:310px; + height:60px; + color:#3E567D; + font-family:Verdana; + font-size:11px; + padding:3px; + border:1px solid #CCC7D1; + background-image:url('../ihm/input-back.png'); + background-repeat:repeat-x; + border-radius:2px; +} + +.formButton{ + height:22px; + margin-top:3px; + width:200px; + border:2px solid #DDDDFF; + cursor:hand; + font-weight:bold; + color:#3E6571; + background-image:url('../ihm/button-back.png'); + background-repeat:repeat-x; +} + +h1{ + font-family:Verdana; + font-size:15px; + font-weight:bold; + color:#411E56; + padding-bottom:6px; + border-bottom:double 3px #E7F0FD; +} +.title_H1_with_no_bottom_border{ + font-family:Verdana; + font-size:15px; + font-weight:bold; + color:#411E56; + padding-bottom:6px; +} diff --git a/kurt-web/src/main/webapp/css/kurt-style.css b/kurt-web/src/main/webapp/css/kurt-style.css new file mode 100644 index 0000000..d7c7a4a --- /dev/null +++ b/kurt-web/src/main/webapp/css/kurt-style.css @@ -0,0 +1,114 @@ +BODY{ + background-color:#FCFFFF; + background-image:url('../ihm/left-bar_260.png'); + background-repeat:repeat-y; + margin:0; + font-family:Verdana; + font-size:12px; +} + +#body_frame{ + background-image:url('../ihm/left-bar_160.png'); + background-repeat:repeat-y; + background-color:#FCFFFF; + margin:0; + font-family:Verdana; + font-size:12px; +} + +#titleImg{ + background-image:url('../ihm/generateur-rapports-teamcenter.png'); + position:absolute; + top:0px; + left:50%; + width:280px; + height:49px; +} + +#snecmaImg{ + background-image:url('../ihm/title.png'); + position:absolute; + top:0px; + left:0px; + width:523px; + height:50px; +} + +#topBarImg{ + background-image:url('../ihm/top-bar.png'); + height:50px; +} + +#actionLeftBar{ + border:1px solid #E8E8FF; + background-color:#FFFFFF; + position:absolute; + left:8px; + top:58px; + width:240px; + padding:2px; + border-radius:3px; +} + +#actionLeftBarTitle{ + background-image:url('../ihm/left-bar-top.png'); + height:18px; + font-weight:bold; + color:#FFFFFF; + padding:4px; +} + +.actionLeftBarActionBack{ + border:1px solid #EAFEFE; + background-image:url('../ihm/left-bar-action-back.png'); + margin-top:2px; + height:21px; + display:block; + text-decoration:none; + color:#8888BB; + font-weight:bold; + font-size:13px; +} + +.actionLeftBarActionBack:hover{ + color:#00AA00; + background-image:url('../ihm/left-bar-action-back-hover.png'); + border:1px solid #E0FFF0; +} + +#subFrame{ + border:1px solid #E8E8FF; + background-color:#FFFFFF; + left:250px; + top:58px; + padding:2px; + width:90%; + height:100%; + border-radius:15px; + box-shadow:1px 1px 4px 1px #FBFAFF; + margin-left:80px; +} + +#footer{ + position:absolute; + margin-top:-20px; + left:20%; + top:100%; + color:#AAAACC; + font-size:10px; +} +.table_period{ + border-spacing: 15px; +} +.width_60{ + width: 60px; +} +.width_140{ + width: 140px; +} +.width_160{ + width: 160px; +} +.width_180{ + width: 180px; +} \ No newline at end of file diff --git a/kurt-web/src/main/webapp/css/pikaday.css b/kurt-web/src/main/webapp/css/pikaday.css new file mode 100644 index 0000000..e855673 --- /dev/null +++ b/kurt-web/src/main/webapp/css/pikaday.css @@ -0,0 +1,194 @@ +@charset "UTF-8"; + +.pika-single { + z-index: 9999; + display: block; + position: relative; + color: #333; + background: #fff; + border: 1px solid #ccc; + border-bottom-color: #bbb; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; +} + +.pika-single:before, +.pika-single:after { + content: " "; + display: table; +} +.pika-single:after { clear: both } +.pika-single { *zoom: 1 } + +.pika-single.is-hidden { + display: none; +} + +.pika-single.is-bound { + position: absolute; + box-shadow: 0 5px 15px -5px rgba(0,0,0,.5); +} + +.pika-lendar { + float: left; + width: 240px; + margin: 8px; +} + +.pika-title { + position: relative; + text-align: center; +} + +.pika-label { + display: inline-block; + *display: inline; + position: relative; + z-index: 9999; + overflow: hidden; + margin: 0; + padding: 5px 3px; + font-size: 14px; + line-height: 20px; + font-weight: bold; + background-color: #fff; +} +.pika-title select { + cursor: pointer; + position: absolute; + z-index: 9998; + margin: 0; + left: 0; + top: 5px; + filter: alpha(opacity=0); + opacity: 0; +} + +.pika-prev, +.pika-next { + display: block; + cursor: pointer; + position: relative; + outline: none; + border: 0; + padding: 0; + width: 20px; + height: 30px; + /* hide text using text-indent trick, using width value (it's enough) */ + text-indent: 20px; + white-space: nowrap; + overflow: hidden; + background-color: transparent; + background-position: center center; + background-repeat: no-repeat; + background-size: 75% 75%; + opacity: .5; + *position: absolute; + *top: 0; +} + +.pika-prev:hover, +.pika-next:hover { + opacity: 1; +} + +.pika-prev, +.is-rtl .pika-next { + float: left; + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAeCAYAAAAsEj5rAAAAUklEQVR42u3VMQoAIBADQf8Pgj+OD9hG2CtONJB2ymQkKe0HbwAP0xucDiQWARITIDEBEnMgMQ8S8+AqBIl6kKgHiXqQqAeJepBo/z38J/U0uAHlaBkBl9I4GwAAAABJRU5ErkJggg=='); + *left: 0; +} + +.pika-next, +.is-rtl .pika-prev { + float: right; + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAeCAYAAAAsEj5rAAAAU0lEQVR42u3VOwoAMAgE0dwfAnNjU26bYkBCFGwfiL9VVWoO+BJ4Gf3gtsEKKoFBNTCoCAYVwaAiGNQGMUHMkjGbgjk2mIONuXo0nC8XnCf1JXgArVIZAQh5TKYAAAAASUVORK5CYII='); + *right: 0; +} + +.pika-prev.is-disabled, +.pika-next.is-disabled { + cursor: default; + opacity: .2; +} + +.pika-select { + display: inline-block; + *display: inline; +} + +.pika-table { + width: 100%; + border-collapse: collapse; + border-spacing: 0; + border: 0; +} + +.pika-table th, +.pika-table td { + width: 14.285714285714286%; + padding: 0; +} + +.pika-table th { + color: #999; + font-size: 12px; + line-height: 25px; + font-weight: bold; + text-align: center; +} + +.pika-button { + cursor: pointer; + display: block; + box-sizing: border-box; + -moz-box-sizing: border-box; + outline: none; + border: 0; + margin: 0; + width: 100%; + padding: 5px; + color: #666; + font-size: 12px; + line-height: 15px; + text-align: right; + background: #f5f5f5; +} + +.pika-week { + font-size: 11px; + color: #999; +} + +.is-today .pika-button { + color: #33aaff; + font-weight: bold; +} + +.is-selected .pika-button { + color: #fff; + font-weight: bold; + background: #33aaff; + box-shadow: inset 0 1px 3px #178fe5; + border-radius: 3px; +} + +.is-disabled .pika-button { + pointer-events: none; + cursor: default; + color: #999; + opacity: .3; +} + +.pika-button:hover { + color: #fff !important; + background: #ff8000 !important; + box-shadow: none !important; + border-radius: 3px !important; +} + +/* styling for abbr */ +.pika-table abbr { + border-bottom: none; + cursor: help; +} + diff --git a/kurt-web/src/main/webapp/css/scheduling.css b/kurt-web/src/main/webapp/css/scheduling.css new file mode 100644 index 0000000..3670f32 --- /dev/null +++ b/kurt-web/src/main/webapp/css/scheduling.css @@ -0,0 +1,29 @@ + + +.title_planification{ + border-bottom :2px solid #9ec8de; + margin-bottom : 14px; + margin-top:40px; + width:800px; + font-weight:bold; + color:#7D8490; + font-size:12px; + padding-left:20px; + text-align:left; +} +.subTitle_planification{ + font-weight:bold; + color:#7D8490; + font-size:12px; + text-align:left; +} +.subTitle_sub_period{ + font-weight:bold; + color:#7D8490; + font-size:12px; + text-align:left; +} +.subTitle_planification_Required { + color: #CC0000; + font-weight: bold; +} \ No newline at end of file diff --git a/kurt-web/src/main/webapp/frames/all_scheduling_reports.jsp b/kurt-web/src/main/webapp/frames/all_scheduling_reports.jsp new file mode 100644 index 0000000..3bad050 --- /dev/null +++ b/kurt-web/src/main/webapp/frames/all_scheduling_reports.jsp @@ -0,0 +1,57 @@ +<%@page import="com.capgemini.reports.ReportEnum"%> +<%@page import="com.capgemini.reports.common.scheduling.controller.SchedulingReaderServlet.SchedulingReportEntry"%> +<%@page import="com.capgemini.reports.formatting.AllSchedulingReports" %> +<%@page import="java.util.List" %> +<%@page import="java.util.Set" %> +<%! final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger("com.capgemini.reports.all_scheduling_reports.jsp"); %> + +<% +response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1 +response.setHeader("Pragma", "no-cache"); // HTTP 1.0 +response.setDateHeader("Expires", 0); // Proxies +%> + + +<% + String reportCode = request.getParameter("reportCode"); + List allReports = ReportEnum.getListReportCode(); + ReportEnum reportEnum = allReports.contains(reportCode) ? ReportEnum.fromCode(reportCode) : null; + String pageNum = request.getParameter("page"); + String userLogin = request.getRemoteUser(); + Set entries = (Set) request.getAttribute("schedulings"); + + log.trace("reportCode = " + reportCode); + log.trace("reportEnum = " + (reportEnum==null ? "(null)" : reportEnum.toString())); + log.trace("page = " + pageNum); + log.trace("userLogin = " + userLogin); + log.trace("entries = " + entries.toString()); +%> +<%= new AllSchedulingReports(reportEnum, pageNum, userLogin, entries).makeJsContent() %> + diff --git a/kurt-web/src/main/webapp/frames/criteria.jsp b/kurt-web/src/main/webapp/frames/criteria.jsp new file mode 100644 index 0000000..c93ec4f --- /dev/null +++ b/kurt-web/src/main/webapp/frames/criteria.jsp @@ -0,0 +1,65 @@ +<%@page import="com.capgemini.framework.common.StringHelper" %> +<%@page import="com.capgemini.reports.database.HibernateUtil"%> +<%@page import="com.capgemini.reports.database.manager.MngCriteriaVal"%> +<%@page import="com.capgemini.reports.database.manager.MngCriteriaVal.CriteriaValue" %> +<%@page import="java.util.List"%> +<%! final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger("com.capgemini.criteria.jsp"); %> +<% + /* This part requests in the DB all the criteria relative to a report, whose uid is pass as URL parameter. */ + String theJsCriteriaArray = StringHelper.EMPTY; + String theErrorMessage = StringHelper.EMPTY; + String theReportUid = request.getParameter("reportUid"); + + try { + StringBuilder theJsCode = new StringBuilder(); + int theLineCount = 0; + List theReportCriteriaList = new MngCriteriaVal().searchCriteriasByReportUID(theReportUid); + for (CriteriaValue currentCriteria: theReportCriteriaList) { + if (currentCriteria != null){ + String theName = StringHelper.toHtml(currentCriteria.getName()); + String theValue = StringHelper.toHtml(currentCriteria.getValue()); + theJsCode.append("\tcriteriaArray[").append(theLineCount).append("] = new Array();\n"); + theJsCode.append("\tcriteriaArray[").append(theLineCount).append("]['name'] = '").append(theName).append("';\n"); + theJsCode.append("\tcriteriaArray[").append(theLineCount).append("]['value'] = '").append(theValue == null || theValue.isEmpty() || "null".equals(theValue) ? "-" : theValue).append("';\n"); + theLineCount++; + } + } + theJsCriteriaArray = theJsCode.toString(); + } + catch (Exception e) { + log.error("Impossible d'afficher les crit�res: " + e.getMessage()); + } +%> + + + + + + + + + Critères du rapport + + + + + +
    +
    + + + + + + +
    NomValeur
    + <%= theErrorMessage %> +
    +
    + + \ No newline at end of file diff --git a/kurt-web/src/main/webapp/frames/mem_monitoring.jsp b/kurt-web/src/main/webapp/frames/mem_monitoring.jsp new file mode 100644 index 0000000..3248169 --- /dev/null +++ b/kurt-web/src/main/webapp/frames/mem_monitoring.jsp @@ -0,0 +1,79 @@ +<% + +response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1 +response.setHeader("Pragma", "no-cache"); // HTTP 1.0 +response.setDateHeader("Expires", 0); // Proxies +%> +<%@page import="com.capgemini.framework.common.MemoryHelper" %> +<%@page import="com.capgemini.framework.common.SettingsHelper" %> +<%@page import="com.capgemini.reports.database.javabean.DbMemMonitor"%> +<%@page import="com.capgemini.reports.database.manager.MngMemMonitor"%> +<%@page import="java.util.List" %> +<% + + /* Retreive parameter */ + String theMonitoring = MemoryHelper.monitorMemory(); + Integer theMsFrequency = SettingsHelper.getInteger("MngMemMonitor.frequency") * 1000; + + /* Browse last memory traces */ + Double theMaxMemory = 0D; + int theIndexCount = 0; + StringBuilder theJsArray = new StringBuilder(); + MngMemMonitor theMemMonitor = new MngMemMonitor(); + List theMonitorList = theMemMonitor.searchMemMonitor(); + for (DbMemMonitor currentMonitor : theMonitorList){ + + /* Store max memory estimation */ + if (currentMonitor.getMaxMemory() > theMaxMemory){ + theMaxMemory = currentMonitor.getMaxMemory(); + } + + theJsArray.append("\t\tmemArray[").append(theIndexCount).append("] = new Array();\n"); + theJsArray.append("\t\tmemArray[").append(theIndexCount).append("]['freeMem'] = ").append(currentMonitor.getUsedMemory()).append(";\n"); + theJsArray.append("\t\tmemArray[").append(theIndexCount).append("]['monitorDate'] = '").append(currentMonitor.getMonitorDate()).append("';\n"); + theIndexCount ++; + } + +%> + + + Suivi mémoire + + + + + +

    Suivi mémoire

    + +
    +
    + +
    px;border-bottom:2px solid #DDDDFF;border-left:1px solid #EEEEFF;"> + +
    + +
    + <%= theMonitoring %> +
    + +
    + + + + \ No newline at end of file diff --git a/kurt-web/src/main/webapp/frames/my_reports.jsp b/kurt-web/src/main/webapp/frames/my_reports.jsp new file mode 100644 index 0000000..96ce462 --- /dev/null +++ b/kurt-web/src/main/webapp/frames/my_reports.jsp @@ -0,0 +1,9 @@ +<%@page import="com.capgemini.reports.formatting.MyReports" %> + +<% + response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1 + response.setHeader("Pragma", "no-cache"); // HTTP 1.0 + response.setDateHeader("Expires", 0); // Proxies +%> + +<%= new MyReports(request.getParameter("page"), request.getRemoteUser()).makeJsContent() %> \ No newline at end of file diff --git a/kurt-web/src/main/webapp/frames/queue.jsp b/kurt-web/src/main/webapp/frames/queue.jsp new file mode 100644 index 0000000..49fc12c --- /dev/null +++ b/kurt-web/src/main/webapp/frames/queue.jsp @@ -0,0 +1,26 @@ +<%@page import="com.capgemini.reports.database.manager.MngReport.RunningReportEntry"%> +<%@page import="com.capgemini.reports.quartz.SchedulerServer.JobExecution"%> +<%@page import="com.capgemini.reports.formatting.QueueStatus"%> +<%@page import="java.util.List"%> + +<% +response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1 +response.setHeader("Pragma", "no-cache"); // HTTP 1.0 +response.setDateHeader("Expires", 0); // Proxies +%> + + + +<% + List theWaitingReports = (List) request.getAttribute("waitingReports"); + List tonightJobs = (List) request.getAttribute("quartzJobList"); +%> +<%= new QueueStatus(theWaitingReports, tonightJobs).makeJsContent() %> \ No newline at end of file diff --git a/kurt-web/src/main/webapp/frames/report_not_authorized_message.jsp b/kurt-web/src/main/webapp/frames/report_not_authorized_message.jsp new file mode 100644 index 0000000..638b03a --- /dev/null +++ b/kurt-web/src/main/webapp/frames/report_not_authorized_message.jsp @@ -0,0 +1 @@ +

    Ce rapport n'est pas disponible, car il est planifié...

    \ No newline at end of file diff --git a/kurt-web/src/main/webapp/frames/running_reports.jsp b/kurt-web/src/main/webapp/frames/running_reports.jsp new file mode 100644 index 0000000..85edac5 --- /dev/null +++ b/kurt-web/src/main/webapp/frames/running_reports.jsp @@ -0,0 +1,9 @@ +<%@page import="com.capgemini.reports.formatting.RunningReports"%> + +<% +response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1 +response.setHeader("Pragma", "no-cache"); // HTTP 1.0 +response.setDateHeader("Expires", 0); // Proxies +%> + +<%= new RunningReports().makeJsContent() %> \ No newline at end of file diff --git a/kurt-web/src/main/webapp/frames/scheduling_criteria.jsp b/kurt-web/src/main/webapp/frames/scheduling_criteria.jsp new file mode 100644 index 0000000..3b0e2a9 --- /dev/null +++ b/kurt-web/src/main/webapp/frames/scheduling_criteria.jsp @@ -0,0 +1,67 @@ +<%@page import="com.capgemini.framework.common.StringHelper" %> +<%@page import="com.capgemini.reports.database.HibernateUtil" %> +<%@page import="com.capgemini.reports.database.manager.MngSchedulingCriteriaVal" %> +<%@page import="java.util.List" %> +<%! final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger("com.capgemini.scheduling_criteria.jsp"); %> +<% + /* This part requests in the DB all the criteria relative to a report, whose uid is pass as URL parameter. */ + String theJsCriteriaArray = StringHelper.EMPTY; + String theErrorMessage = StringHelper.EMPTY; + String theReportId = request.getParameter("reportId"); + + try { + StringBuilder theJsCode = new StringBuilder(); + int theLineCount = 0; + List theReportCriteriaList = new MngSchedulingCriteriaVal().searchFunctional(Long.valueOf(theReportId)); + + for (MngSchedulingCriteriaVal.SchedulingCriteriaValue currentCriteria : theReportCriteriaList) { + if (currentCriteria != null) { + String theName = StringHelper.toHtml(currentCriteria.getName()); + String theValue = StringHelper.toHtml(currentCriteria.getValue()); + theJsCode.append("\tcriteriaArray[").append(theLineCount).append("] = new Array();\n"); + theJsCode.append("\tcriteriaArray[").append(theLineCount).append("]['name'] = '").append(theName).append("';\n"); + theJsCode.append("\tcriteriaArray[").append(theLineCount).append("]['value'] = '").append(theValue == null || theValue.isEmpty() || "null".equals(theValue) ? "-" : theValue).append("';\n"); + theLineCount++; + } + } + + theJsCriteriaArray = theJsCode.toString(); + } + catch (Exception e) { + log.error("Impossible d'afficher les crit�res: " + e.getMessage()); + } +%> + + + + + + + + + Critères du rapport et de la planification + + + + + + +
    +
    + + + + + + +
    NomValeur
    + <%= theErrorMessage %> +
    +
    + + \ No newline at end of file diff --git a/kurt-web/src/main/webapp/frames/scheduling_delete.jsp b/kurt-web/src/main/webapp/frames/scheduling_delete.jsp new file mode 100644 index 0000000..2d6983d --- /dev/null +++ b/kurt-web/src/main/webapp/frames/scheduling_delete.jsp @@ -0,0 +1,68 @@ +<%@page import="com.capgemini.reports.database.manager.MngSchedulingReport"%> +<%@page import="com.capgemini.reports.database.manager.MngSchedulingCriteriaVal"%> +<%@page import="com.capgemini.reports.database.manager.MngCriteriaVal.CriteriaValue"%> +<%@page import="com.capgemini.reports.database.HibernateUtil"%> +<%@page import="com.capgemini.reports.database.javabean.DbCriteriaVal"%> +<%@page import="com.capgemini.reports.database.manager.MngCriteriaVal"%> +<%@page import="com.capgemini.framework.common.StringHelper"%> +<%@page import="com.capgemini.framework.common.SettingsHelper"%> +<%@page import="com.capgemini.framework.common.BeanHelper"%> +<%@page import="com.capgemini.framework.common.StringHelper"%> +<%@page import="com.capgemini.reports.database.manager.MngReport"%> +<%@page import="java.util.List"%> +<%! org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger("com.capgemini.report.scheduling_delete.jsp"); %> +<% + // This is a pop-up content to check if the user REALLY wants to destroy a scheduling + /* This part requests in the DB all the criteria relative to a report, whose uid is pass as URL parameter. */ + String theJsCriteriaArray = StringHelper.EMPTY; + String theErrorMessage = StringHelper.EMPTY; + String theReportId = request.getParameter("reportId"); + String curReportNumber = request.getParameter("activeReportCode"); + String planifName = request.getParameter("planif_name"); + +%> + + + + + + + + + + + + Suppression + + + + + + + + +
    +
    + + +
    + Confirmez vous la suppression de la planification [ <%=planifName%> ] ? +
    + +
    + + + + + +
    + +
    +
    + + \ No newline at end of file diff --git a/kurt-web/src/main/webapp/frames/scheduling_new.jsp b/kurt-web/src/main/webapp/frames/scheduling_new.jsp new file mode 100644 index 0000000..270ce12 --- /dev/null +++ b/kurt-web/src/main/webapp/frames/scheduling_new.jsp @@ -0,0 +1,122 @@ +<%@page import="com.capgemini.reports.ReportEnum"%> +<%@page import="java.util.Arrays"%> +<%@page import="java.util.Collections"%> +<%@page import="java.util.ArrayList"%> +<%@page import="java.util.List"%> +<%@page import="java.util.Map"%> +<%@page import="java.util.HashMap"%> +<%@page import="com.capgemini.framework.common.StringHelper"%> +<%@page import="com.capgemini.framework.common.SettingsHelper"%> +<%@page import="com.capgemini.reports.database.manager.MngSchedulingReport"%> +<%@page import="com.capgemini.reports.database.javabean.enumeration.SchedulingEnum"%> +<%@page import="com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum"%> +<%@page import="com.capgemini.reports.database.manager.MngSchedulingCriteriaVal"%> +<%@page import="com.capgemini.reports.common.scheduling.view.NewSchedulingFormatter"%> +<%@page import="com.capgemini.reports.common.scheduling.view.UpdateSchedulingFormatter"%> + +<% + response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1 + response.setHeader("Pragma", "no-cache"); // HTTP 1.0 + response.setDateHeader("Expires", 0); // Proxies + + + boolean isDevMode = SettingsHelper.isDevMode(); + + String selectedFilter = request.getParameter("activeSchedulingList"); + String curReportNumber = selectedFilter.equals("TOUS") ? selectedFilter : "R" + selectedFilter; + + ReportEnum reportEntryEnum = ReportEnum.fromCode(curReportNumber); + String reportTitleCanonicalName = curReportNumber.concat(" - ").concat( reportEntryEnum.getReportTitle() ); + + String jspURL = "template_r" + selectedFilter + ".jsp"; + String reportCode = "R" + selectedFilter ; +%> + + + + Planification - + + + + + + + + + + + + + + + + + + + + + + + + + +
    +

    Planification <%=reportTitleCanonicalName%> (Création)

    + +
    +
    + +
    +
    +
    +

    Définition du Rapport

    +
    +
    + + <%-- --%> + + + + + + + + +
    +
    +
    + +
    +
    + + +
    +

    Critères de Planification du Rapport

    +
    + +
    + + <%=new NewSchedulingFormatter().showNewReportSchedulingPage()%> + + +
    +
    + + +
    + + +
    + + +
    +
    + + diff --git a/kurt-web/src/main/webapp/frames/scheduling_update.jsp b/kurt-web/src/main/webapp/frames/scheduling_update.jsp new file mode 100644 index 0000000..186c3a8 --- /dev/null +++ b/kurt-web/src/main/webapp/frames/scheduling_update.jsp @@ -0,0 +1,127 @@ +<%@page import="com.capgemini.framework.common.SettingsHelper" %> +<%@page import="com.capgemini.reports.ReportEnum"%> +<%@page import="com.capgemini.reports.common.scheduling.view.UpdateSchedulingFormatter"%> +<%! final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger("com.capgemini.report.scheduling_update.jsp"); %> +<% + //// + response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1 + response.setHeader("Pragma", "no-cache"); // HTTP 1.0 + response.setDateHeader("Expires", 0); // Proxies + + + boolean isDevMode = SettingsHelper.isDevMode(); + // Useless? + String tempCurrentReportNumber = request.getParameter("activeSchedulingList"); + + String idStr = request.getParameter("id"); + Long idLong = Long.valueOf(idStr); + String curReportCode = request.getParameter("reportCode"); + String curReportNumber = curReportCode.replace("R", ""); + + ReportEnum reportEntryEnum = ReportEnum.fromCode(curReportCode); + String reportTitleCanonicalName = curReportCode.concat(" - ").concat( reportEntryEnum.getReportTitle() ); + + String jspReportToCall = "template_r" + curReportNumber + ".jsp"; + + log.trace("devMode = " + isDevMode); + log.trace("tempRepNumber = " + tempCurrentReportNumber); + log.trace("idStr = " + idStr); + log.trace("curReportCode = " + curReportCode); + log.trace("curReportNumber = " + curReportNumber); + log.trace("jspReportToCall = " + jspReportToCall); + log.trace("idLong = " + idLong); + + String theSchedulingName = ""; + String thePeriod = ""; + String theDaily = ""; + String theWeekly = ""; + String theMonthly = ""; + String theWeekEnd = ""; + String theDate = ""; + String theMonthlyValue = ""; +%> + + + + +Planification - + + + + + + + + + + + + + + + + + + + + + + + + +
    +

    Planification <%=reportTitleCanonicalName%> (Modification)

    + +
    +
    + +
    +
    + +
    +

    Définition du Rapport

    +
    + +
    +
    + + + + + + +
    +
    +
    + +
    + + +
    + <%--

    Planification du Rapport R<%=curReportCode%>

    --%> +

    Critères de la planification

    +
    + +
    + + <%=new UpdateSchedulingFormatter(idLong).showReportUpdatePage()%> + +
    +
    + +
    + + +
    + + +
    +
    + + diff --git a/kurt-web/src/main/webapp/frames/statistics_per_report.jsp b/kurt-web/src/main/webapp/frames/statistics_per_report.jsp new file mode 100644 index 0000000..043a8ce --- /dev/null +++ b/kurt-web/src/main/webapp/frames/statistics_per_report.jsp @@ -0,0 +1,104 @@ +<%@page import="com.capgemini.framework.common.DateHelper" %> +<%@page import="com.capgemini.reports.ReportEnum" %> +<%@page import="com.capgemini.reports.database.stats.GenJspStats" %> +<% + /* Retreive parameter */ + String theStartPeriod = DateHelper.getDate(); + String theEndPeriod = DateHelper.getDate(); + if ((request.getParameter("startPeriod") != null) && (request.getParameter("endPeriod") != null)) { + theStartPeriod = String.valueOf(request.getParameter("startPeriod")); + theEndPeriod = String.valueOf(request.getParameter("endPeriod")); + } + String theJsStatArray1 = GenJspStats.generateTimingsTableAsJS(theStartPeriod, theEndPeriod); + int nbReports = ReportEnum.values().length; +%> + + + + + + + + + Statistiques par rapport + + + + + + + + + + + + +
    +

    Statistiques par rapport

    + +
    +
    + + + + + + + + + +
    +
    +
    +
    +
    +
    / + +
    +
    +
    +
    +
    + +
    +
    +
    +
    + +
    +
    + + + + + + + + + + + +
    Code du rapportNombre d'ex�cutionsErreurs de saisieErreurs techniquesDur�e minimaleDur�e moyenneDur�e maximale
    + +

    + + +

    + + +
    +
    + + + \ No newline at end of file diff --git a/kurt-web/src/main/webapp/frames/statistics_per_user.jsp b/kurt-web/src/main/webapp/frames/statistics_per_user.jsp new file mode 100644 index 0000000..1c9a9e8 --- /dev/null +++ b/kurt-web/src/main/webapp/frames/statistics_per_user.jsp @@ -0,0 +1,100 @@ +<%@page import="com.capgemini.framework.common.DateHelper" %> +<%@page import="com.capgemini.reports.ReportEnum" %> +<%@page import="com.capgemini.reports.database.stats.GenJspStats" %> +<% + /* Retreive parameter */ + String theStartPeriod = DateHelper.getDate(); + String theEndPeriod = DateHelper.getDate(); + if ((request.getParameter("startPeriod") != null) && (request.getParameter("endPeriod") != null)) { + theStartPeriod = String.valueOf(request.getParameter("startPeriod")); + theEndPeriod = String.valueOf(request.getParameter("endPeriod")); + } + String theJsStatArray2 = GenJspStats.generateLaunchCountTableAsJS(theStartPeriod, theEndPeriod); + int nbReports = ReportEnum.values().length; +%> + + + + + + + + + Statistiques par utilisateur + + + + + + + + + + + + +
    +

    Statistiques par utilisateur

    + +
    +
    + + + + + + + + + +
    +
    +
    +
    +
    +
    / + +
    +
    +
    +
    +
    + +
    +
    +
    +
    + +
    +
    + + + + <% for (ReportEnum value : ReportEnum.values()) { %> + + <% } %> + + + + +
    Utilisateur<%=value.getReportCode() %> + Global
    +



    + + +
    +
    + + + \ No newline at end of file diff --git a/kurt-web/src/main/webapp/frames/submitNewReport.jsp b/kurt-web/src/main/webapp/frames/submitNewReport.jsp new file mode 100644 index 0000000..cb9105d --- /dev/null +++ b/kurt-web/src/main/webapp/frames/submitNewReport.jsp @@ -0,0 +1,101 @@ +<%@page import="com.capgemini.framework.common.SettingsHelper" %> +<%@page import="com.capgemini.reports.ReportEnum" %> +<%@page import="com.capgemini.reports.database.manager.MngReportType" %> +<%@ page import="org.hibernate.SessionFactory" %> +<%@ page import="com.capgemini.reports.database.HibernateUtil" %> +<%@ page import="org.hibernate.Session" %> +<%! final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger("com.capgemini.reports.submitNewReport.jsp"); %> +<% + + response.setHeader("Pragma", "no-cache"); + response.setHeader("Cache-Control", "no-cache"); + response.setDateHeader("Expires", 0); + + String reportNameRaw = request.getParameter("rd_id"); // May contain comments appended by '_' like : 'REPORT_R19_Document' + if (reportNameRaw == null) { + reportNameRaw = "REPORT_R01"; + } + String reportCode = reportNameRaw.split("_")[1]; // Report Code like 'R19' + ReportEnum reportEnum = ReportEnum.fromCode(reportCode); + String theReportTitle = reportEnum.getReportTitle(); + boolean authorized = new MngReportType().isAuthorized(reportEnum); + boolean isDevMode = SettingsHelper.isDevMode(); + + String targetTemplate = "template_" + reportCode.toLowerCase() + ".jsp"; + + log.trace("reportCode : " + reportCode); + log.trace("reportEnum : " + reportEnum.toString()); + log.trace("TargetTemplate: " + targetTemplate); + log.trace("isDevMode: " + isDevMode); +%> + + + + + + + + + + + + + + <%if (isDevMode) {%> + + <%}%> + + <%= theReportTitle %> + + + + + + + + + + + + +

    <%=reportCode%> - <%= theReportTitle %> +

    +
    +
    +
    +
    + +<%if (!authorized) {%> +
    +

    Ce rapport n'est pas autorisé

    +
    +<% } %> + +
    +
    +
    + <%-- Imports the report's template JSP in a form --%> + <%-- Activates content fields in the report template IF it is authorized for immediate execution --%> + + + + +
    +
    +
    +
    +
    + <% if (authorized) { %> + + <% } %> + +
    +
    +
    +
    + + \ No newline at end of file diff --git a/kurt-web/src/main/webapp/frames/template_r01.jsp b/kurt-web/src/main/webapp/frames/template_r01.jsp new file mode 100644 index 0000000..9e7d782 --- /dev/null +++ b/kurt-web/src/main/webapp/frames/template_r01.jsp @@ -0,0 +1,164 @@ +<%@page import="com.capgemini.framework.common.SettingsHelper"%> +<%@page import="com.capgemini.framework.common.StringHelper" %> +<%@page import="com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum"%> +<%@page import="com.capgemini.reports.database.manager.MngSchedulingCriteriaVal"%> +<%@page import="java.util.Map"%> +<%! final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger("com.capgemini.report.template_r01.jsp"); %> +<% + /* + * Available request parameters: + * "isUpdateReport" (boolean) Is this a submission of a NEW report or an UPDATE? + * "idReport" (long) Report Id in case of an UPDATE request + */ + boolean isDevMode = SettingsHelper.isDevMode(); + boolean isUpdate = Boolean.valueOf(request.getParameter("isUpdateReport")); + Long reportID = isUpdate ? Long.valueOf(request.getParameter("idReport")) : new Long(-1); + + log.info("**********************"); + log.info("isDevMode = " + isDevMode); + log.info("isUpdate = " + isUpdate); + log.info("reportID = " + reportID); + + // Default values in each field. May contain nothing / existing values / development values + String theDefaultGen = ""; + String theDefaultGenMont = ""; + String theDefaultProduct = ""; + String theDefaultUnit = ""; + String theDefaultDate = ""; + String theMonoMulti = "MONO" ; + String isSuperModelBOM = Boolean.FALSE.toString(); + + if (isDevMode){ // Devmode default values + theDefaultGen = ""; + theDefaultGenMont = "24E"; + theDefaultProduct = "30E0"; + theDefaultUnit = "20"; + theDefaultDate = "01-01-2015"; + } + + if( isUpdate){ // Existing values to reload from DB + Map theFunctionalCriteriaValues = new MngSchedulingCriteriaVal().getFunctionalMap(reportID); + + theDefaultGen = StringHelper.replaceNullByEmpty( theFunctionalCriteriaValues.get(ReportCriteriaEnum.GENERIC) ); + theDefaultGenMont = StringHelper.replaceNullByEmpty( theFunctionalCriteriaValues.get(ReportCriteriaEnum.GENERIC_ASSEMB) ); + theDefaultProduct = StringHelper.replaceNullByEmpty( theFunctionalCriteriaValues.get(ReportCriteriaEnum.PRODUCT) ); + theDefaultUnit = StringHelper.replaceNullByEmpty( theFunctionalCriteriaValues.get(ReportCriteriaEnum.UNIT) ); + theDefaultDate = StringHelper.replaceNullByEmpty( theFunctionalCriteriaValues.get(ReportCriteriaEnum.EFFECTIVITY_DATE) ); + theMonoMulti = StringHelper.replaceNullByEmpty( theFunctionalCriteriaValues.get(ReportCriteriaEnum.MONO_MULTI) ); + isSuperModelBOM = StringHelper.replaceNullByEmpty( theFunctionalCriteriaValues.get(ReportCriteriaEnum.SUPERMODEL) ); + log.info("theDefaultGen = " + theDefaultGen); + log.info("theDefaultGenMont = " + theDefaultGenMont); + log.info("theDefaultProduct = " + theDefaultProduct); + log.info("theDefaultUnit = " + theDefaultUnit); + log.info("theDefaultDate = " + theDefaultDate); + log.info("theMonoMulti = " + theMonoMulti); + } +%> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Niveau : +
    + /> Mono + /> Multi + + /> +
    +
    +
    +
    Générique "Vue Technique" : + +
    Générique "Vue montage" : + +
    Produit* : + +
    Unit* : + +
    Date d'effectivité : + + +
    +
    +
    +
    +
    +
    + +
    + + + diff --git a/kurt-web/src/main/webapp/frames/template_r03.jsp b/kurt-web/src/main/webapp/frames/template_r03.jsp new file mode 100644 index 0000000..900462b --- /dev/null +++ b/kurt-web/src/main/webapp/frames/template_r03.jsp @@ -0,0 +1,82 @@ +<%@page import="com.capgemini.framework.common.SettingsHelper"%> + + + + + + + + + + + + + + + + + + +
    N° d'article* :
    Révision* : + + +
    +
    + +
    + + + + + + \ No newline at end of file diff --git a/kurt-web/src/main/webapp/frames/template_r07.jsp b/kurt-web/src/main/webapp/frames/template_r07.jsp new file mode 100644 index 0000000..5485b64 --- /dev/null +++ b/kurt-web/src/main/webapp/frames/template_r07.jsp @@ -0,0 +1,172 @@ +<%@page import="com.capgemini.framework.common.SettingsHelper"%> +<%@page import="com.capgemini.framework.common.StringHelper" %> +<%@page import="com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum" %> +<%@page import="com.capgemini.reports.database.manager.MngSchedulingCriteriaVal"%> +<%@page import="java.util.Map"%> +<% + /* + * Available request parameters: + * "isUpdateReport" (boolean) Is this a submission of a NEW report or an UPDATE? + * "idReport" (long) Report Id in case of an UPDATE request + */ + boolean isDevMode = SettingsHelper.isDevMode(); + boolean isUpdate = Boolean.valueOf(request.getParameter("isUpdateReport")); + Long reportID = isUpdate ? Long.valueOf(request.getParameter("idReport")) : new Long(-1); + + /* Conf 1*/ + String theDefaultGen1 = ""; + String theDefaultGenMont1 = ""; + String theDefaultProduct1 = ""; + String theDefaultUnit1 = ""; + + /* Conf 2*/ + String theDefaultGen2 = ""; + String theDefaultGenMont2 = ""; + String theDefaultProduct2 = ""; + String theDefaultUnit2 = ""; + + if (isDevMode){ // Default values for development environment only + theDefaultGen1 = ""; + theDefaultGenMont1 = ""; + theDefaultProduct1 = "ZZ07"; + theDefaultUnit1 = "10"; + theDefaultGen2 = ""; + theDefaultGenMont2 = ""; + theDefaultProduct2 = "ZZ07"; + theDefaultUnit2 = "20"; + } + + if( isUpdate ){ // Recall existing data from DB + Map theFunctionalCriteriaValues = new MngSchedulingCriteriaVal().getFunctionalMap(reportID); + + theDefaultGen1 = StringHelper.replaceNullByEmpty( theFunctionalCriteriaValues.get(ReportCriteriaEnum.GENERIC)); + theDefaultGenMont1 = StringHelper.replaceNullByEmpty( theFunctionalCriteriaValues.get(ReportCriteriaEnum.GENERIC_ASSEMB)); + theDefaultProduct1 = StringHelper.replaceNullByEmpty( theFunctionalCriteriaValues.get(ReportCriteriaEnum.PRODUCT)); + theDefaultUnit1 = StringHelper.replaceNullByEmpty( theFunctionalCriteriaValues.get(ReportCriteriaEnum.UNIT_CONFIGURATION_1)); + theDefaultUnit2 = StringHelper.replaceNullByEmpty( theFunctionalCriteriaValues.get(ReportCriteriaEnum.UNIT_CONFIGURATION_2)); + theDefaultGen2 = theDefaultGen1; // Same both conf + theDefaultGenMont2 = theDefaultGenMont1; // Same both conf + theDefaultProduct2 = theDefaultProduct1; // Same both conf + } +%> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Informations de la configuration 1 :Informations de la configuration 2 :
    +
    +
    Générique "Vue Technique" 1 :Générique "Vue Technique" 2 (non modifiable) :
    Générique "Vue Montage" 1 :Générique "Vue Montage" 2 (non modifiable) :
    Produit 1* :Produit 2 (non modifiable) :
    Unit 1* :Unit 2* :
    +
    +
    +
    +
    + +
    + + + \ No newline at end of file diff --git a/kurt-web/src/main/webapp/frames/template_r10.jsp b/kurt-web/src/main/webapp/frames/template_r10.jsp new file mode 100644 index 0000000..8604cb2 --- /dev/null +++ b/kurt-web/src/main/webapp/frames/template_r10.jsp @@ -0,0 +1,136 @@ +<%@page import="com.capgemini.framework.common.SettingsHelper"%> +<%@page import="com.capgemini.framework.common.StringHelper" %> +<%@page import="com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum"%> +<%@page import="com.capgemini.reports.database.manager.MngSchedulingCriteriaVal" %> +<%@page import="java.util.Map"%> +<% + /* + * Available request parameters: + * "isUpdateReport" (boolean) Is this a submission of a NEW report or an UPDATE? + * "idReport" (long) Report Id in case of an UPDATE request + */ + boolean isDevMode = SettingsHelper.isDevMode(); + boolean isUpdate = Boolean.valueOf(request.getParameter("isUpdateReport")); + Long reportID = isUpdate ? Long.valueOf(request.getParameter("idReport")) : new Long(-1); + + /* Default values for development environment only */ + String theDefaultGen = ""; + String theDefaultGenMont = ""; + String theDefaultProduct = ""; + String theDefaultUnit = ""; + String theDefaultDate = ""; + String theMonoMulti = "MONO"; + + if( isDevMode ){ + theDefaultGen = "A10"; + theDefaultProduct = "ZZ01"; + theDefaultUnit = "1"; + theDefaultDate = "14-07-2014"; + } + + if( isUpdate){ // Existing values to reload from DB + Map theFunctionalCriteriaValues = new MngSchedulingCriteriaVal().getFunctionalMap(reportID); + + theDefaultGen = StringHelper.replaceNullByEmpty( theFunctionalCriteriaValues.get(ReportCriteriaEnum.GENERIC)); + theDefaultGenMont = StringHelper.replaceNullByEmpty( theFunctionalCriteriaValues.get(ReportCriteriaEnum.GENERIC_ASSEMB)); + theDefaultProduct = StringHelper.replaceNullByEmpty( theFunctionalCriteriaValues.get(ReportCriteriaEnum.PRODUCT)); + theDefaultUnit = StringHelper.replaceNullByEmpty( theFunctionalCriteriaValues.get(ReportCriteriaEnum.UNIT)); + theDefaultDate = StringHelper.replaceNullByEmpty( theFunctionalCriteriaValues.get(ReportCriteriaEnum.EFFECTIVITY_DATE)); + theMonoMulti = StringHelper.replaceNullByEmpty( theFunctionalCriteriaValues.get(ReportCriteriaEnum.MONO_MULTI)); + } +%> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Niveau : +
    + /> Mono + /> Multi +
    +
    +
    +
    Générique "Vue Technique" : + +
    Générique "Vue montage" : + +
    Produit* : + +
    Unit* : + +
    Date d'effectivité : + + +
    +
    +
    +
    + +
    +
    + +
    + + + + \ No newline at end of file diff --git a/kurt-web/src/main/webapp/frames/template_r11.jsp b/kurt-web/src/main/webapp/frames/template_r11.jsp new file mode 100644 index 0000000..022c989 --- /dev/null +++ b/kurt-web/src/main/webapp/frames/template_r11.jsp @@ -0,0 +1,118 @@ +<%@page import="com.capgemini.framework.common.DateHelper" %> +<%@page import="com.capgemini.framework.common.SettingsHelper" %> +<%@page import="com.capgemini.framework.common.StringHelper"%> +<%@page import="com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum" + import="com.capgemini.reports.database.manager.MngSchedulingCriteriaVal" %> +<%@page import="java.util.Map"%> +<% + /* + * Available request parameters: + * "isUpdateReport" (boolean) Is this a submission of a NEW report or an UPDATE? + * "idReport" (long) Report Id in case of an UPDATE request + */ + boolean isDevMode = SettingsHelper.isDevMode(); + boolean isUpdate = Boolean.valueOf(request.getParameter("isUpdateReport")); + Long reportID = isUpdate ? Long.valueOf(request.getParameter("idReport")) : new Long(-1); + + // Default values in each field. May contain nothing / existing values / development values + String theDefaultGen = ""; + String theDefaultProduct = ""; + String theDefaultUnit = ""; + String theDefaultDate = ""; + String theMonoMulti = "MONO" ; + + if (isDevMode){ // Devmode default values + theDefaultGen = "C25"; + theDefaultProduct = "29R0"; + theDefaultUnit = "245"; + theDefaultDate = DateHelper.getDate(); // Today + } + if( isUpdate){ // Existing values to reload from DB + Map theFunctionalCriteriaValues = new MngSchedulingCriteriaVal().getFunctionalMap(reportID); + + theDefaultGen = StringHelper.replaceNullByEmpty( theFunctionalCriteriaValues.get(ReportCriteriaEnum.GENERIC_ASSEMB)); + theDefaultProduct = StringHelper.replaceNullByEmpty( theFunctionalCriteriaValues.get(ReportCriteriaEnum.PRODUCT)); + theDefaultUnit = StringHelper.replaceNullByEmpty( theFunctionalCriteriaValues.get(ReportCriteriaEnum.UNIT)); + theDefaultDate = StringHelper.replaceNullByEmpty( theFunctionalCriteriaValues.get(ReportCriteriaEnum.EFFECTIVITY_DATE)); + theMonoMulti = StringHelper.replaceNullByEmpty( theFunctionalCriteriaValues.get(ReportCriteriaEnum.MONO_MULTI)); + } +%> + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Niveau : +
    + /> Mono + /> Multi +
    +
    +
    +
    Générique "Vue Technique" : + +
    Produit* : + +
    Unit* : + +
    Date d'effectivité* : + + +
    +
    +
    +
    + +

    + +
    + + + \ No newline at end of file diff --git a/kurt-web/src/main/webapp/frames/template_r13.jsp b/kurt-web/src/main/webapp/frames/template_r13.jsp new file mode 100644 index 0000000..abdf297 --- /dev/null +++ b/kurt-web/src/main/webapp/frames/template_r13.jsp @@ -0,0 +1,140 @@ +<%@page import="com.capgemini.framework.common.SettingsHelper"%> +<%@page import="com.capgemini.framework.common.StringHelper" %> +<%@page import="com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum"%> +<%@page import="com.capgemini.reports.database.manager.MngSchedulingCriteriaVal"%> +<%@page import="java.util.Map"%> +<% + /* + * Available request parameters: + * "isUpdateReport" (boolean) Is this a submission of a NEW report or an UPDATE? + * "idReport" (long) Report Id in case of an UPDATE request + */ + boolean isDevMode = SettingsHelper.isDevMode(); + boolean isUpdate = Boolean.valueOf(request.getParameter("isUpdateReport")); + Long reportID = isUpdate ? Long.valueOf(request.getParameter("idReport")) : new Long(-1); + + // Default values in each field. May contain nothing / existing values / development values + String theDefaultDateDebut = ""; + String theDefaultDateFin = ""; + String theTypeOject = ""; + + if (isDevMode){ // Devmode default values + theDefaultDateDebut = ""; + theDefaultDateFin = ""; + } + + if( isUpdate){ // Existing values to reload from DB + Map theFunctionalCriteriaValues = new MngSchedulingCriteriaVal().getFunctionalMap(reportID); + + theDefaultDateDebut = StringHelper.replaceNullByEmpty( theFunctionalCriteriaValues.get(ReportCriteriaEnum.DATE_DEBUT)); + theDefaultDateFin = StringHelper.replaceNullByEmpty( theFunctionalCriteriaValues.get(ReportCriteriaEnum.DATE_FIN)); + theTypeOject = StringHelper.replaceNullByEmpty( theFunctionalCriteriaValues.get(ReportCriteriaEnum.TYPE_OBJET)); + } +%> + + +<%! private String isCRorFPP(final String theTypeOject) { + String selectedCR = ""; + String selectedFPP = ""; + StringBuilder buildSelect = new StringBuilder(); + if("CR".equals(theTypeOject)){ + selectedCR ="selected=\"selected\""; + }else{ + selectedFPP ="selected=\"selected\""; + } + buildSelect.append(""); + buildSelect.append(""); + return buildSelect.toString(); + } +%> + + + + + + + + + + + + + + + + + + +
    Date début : + + +
    +
    +
    +
    + +
    Date fin : + + +
    +
    +
    +
    + +
    Type objet* : + +

    + +
    + + + + \ No newline at end of file diff --git a/kurt-web/src/main/webapp/frames/template_r15.jsp b/kurt-web/src/main/webapp/frames/template_r15.jsp new file mode 100644 index 0000000..60f7dad --- /dev/null +++ b/kurt-web/src/main/webapp/frames/template_r15.jsp @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + +
    N° d'article* : + +
    Révision* : + +
    Langue* : + + +
    +
    + +
    + + + + \ No newline at end of file diff --git a/kurt-web/src/main/webapp/frames/template_r16.jsp b/kurt-web/src/main/webapp/frames/template_r16.jsp new file mode 100644 index 0000000..66766c7 --- /dev/null +++ b/kurt-web/src/main/webapp/frames/template_r16.jsp @@ -0,0 +1,148 @@ +<%@page import="com.capgemini.framework.common.SettingsHelper"%> +<%@page import="com.capgemini.framework.common.StringHelper" %> +<%@page import="com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum"%> +<%@page import="com.capgemini.reports.database.manager.MngSchedulingCriteriaVal"%> +<%@page import="java.util.Map"%> +<% + /* + * Available request parameters: + * "isUpdateReport" (boolean) Is this a submission of a NEW report or an UPDATE? + * "idReport" (long) Report Id in case of an UPDATE request + */ + boolean isDevMode = SettingsHelper.isDevMode(); + boolean isUpdate = Boolean.valueOf(request.getParameter("isUpdateReport")); + Long reportID = isUpdate ? Long.valueOf(request.getParameter("idReport")) : new Long(-1); + + // Default values in each field. May contain nothing / existing values / development values + String theDefaultGen = ""; + String theDefaultProduct = ""; + String theDefaultUnit = ""; + String theDefaultLanguage= ""; + String theDefaultPrinterType= ""; + + if (isDevMode){ // Devmode default values + theDefaultGen = "C25"; + theDefaultProduct = "29R0"; + theDefaultUnit = "245"; + } + + if( isUpdate ){ // Existing values to reload from DB + Map theFunctionalCriteriaValues = new MngSchedulingCriteriaVal().getFunctionalMap(reportID); + + theDefaultGen = StringHelper.replaceNullByEmpty( theFunctionalCriteriaValues.get(ReportCriteriaEnum.GENERIC_ASSEMB)); + theDefaultProduct = StringHelper.replaceNullByEmpty( theFunctionalCriteriaValues.get(ReportCriteriaEnum.PRODUCT)); + theDefaultUnit = StringHelper.replaceNullByEmpty( theFunctionalCriteriaValues.get(ReportCriteriaEnum.UNIT)); + theDefaultLanguage = StringHelper.replaceNullByEmpty( theFunctionalCriteriaValues.get(ReportCriteriaEnum.LANGUAGE)); + theDefaultPrinterType = StringHelper.replaceNullByEmpty( theFunctionalCriteriaValues.get(ReportCriteriaEnum.TYPE_IMPRESSION)); + } +%> + +<%! private String getSelectedLanguage(final String language){ + String selectedFR = ""; + String selectedEN = ""; + StringBuilder buildSelect = new StringBuilder(); + if("Francais".equals(language)){ + selectedFR ="selected=\"selected\""; + }else{ + selectedEN ="selected=\"selected\""; + } + buildSelect.append(""); + buildSelect.append(""); + return buildSelect.toString(); + } + + private String getPrinterType(final String printerType){ + String selectedDefCertifie = ""; + String selectedDefRealisation = ""; + StringBuilder buildSelect = new StringBuilder(); + if("Def_certifiee".equals(printerType)){ + selectedDefCertifie ="selected=\"selected\""; + }else{ + selectedDefRealisation ="selected=\"selected\""; + } + buildSelect.append(""); + buildSelect.append(""); + return buildSelect.toString(); + } +%> + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Générique* : + +
    Produit* : + +
    Unit* : + +
    Type d'impression : + +
    Langue : + +
    +
    + +
    + + + \ No newline at end of file diff --git a/kurt-web/src/main/webapp/frames/template_r17.jsp b/kurt-web/src/main/webapp/frames/template_r17.jsp new file mode 100644 index 0000000..adc41af --- /dev/null +++ b/kurt-web/src/main/webapp/frames/template_r17.jsp @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + +
    N° d'article* : + +
    Révision* : + +
    Langue* : + + +
    +
    + +
    + + + + + diff --git a/kurt-web/src/main/webapp/frames/template_r19.jsp b/kurt-web/src/main/webapp/frames/template_r19.jsp new file mode 100644 index 0000000..f4c2101 --- /dev/null +++ b/kurt-web/src/main/webapp/frames/template_r19.jsp @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + +
    N° Document* : + +
    Révision* : + +

    + +
    + + + + + + + diff --git a/kurt-web/src/main/webapp/frames/template_r20.jsp b/kurt-web/src/main/webapp/frames/template_r20.jsp new file mode 100644 index 0000000..bbeead5 --- /dev/null +++ b/kurt-web/src/main/webapp/frames/template_r20.jsp @@ -0,0 +1,375 @@ +<%@page import="com.capgemini.framework.common.SettingsHelper"%> +<%@page import="com.capgemini.framework.common.StringHelper" %> +<%@page import="com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum"%> +<%@page import="com.capgemini.reports.database.manager.MngSchedulingCriteriaVal"%> +<%@page import="java.util.Map"%> +<% + /* + * Available request parameters: + * "isUpdateReport" (boolean) Is this a submission of a NEW report or an UPDATE? + * "idReport" (long) Report Id in case of an UPDATE request + */ + boolean isDevMode = SettingsHelper.isDevMode(); + boolean isUpdate = Boolean.valueOf(request.getParameter("isUpdateReport")); + Long reportID = isUpdate ? Long.valueOf(request.getParameter("idReport")) : new Long(-1); + + /* Default values for development environment only */ + String theDefaultProductBefore = ""; + String theDefaultProductAfter = ""; + String theDefaultUnitAfter=""; + String theDefaultUnitBefore=""; + String theDefaultMatricule=""; + String theDefaultLMR="-"; + String theDefaultClasse =""; + String theDefaultMajorMinor=""; + String theDefaultUniqueConjoint =""; + + if (isDevMode){ // Devmode default values + theDefaultProductAfter = "97R0"; + theDefaultUnitAfter = "550"; + theDefaultUnitBefore = "520"; + theDefaultMatricule = "GE90 M10 MOTEUR ASSEMBLE"; + theDefaultLMR = "-"; + } + + if( isUpdate){ // Existing values to reload from DB + Map theFunctionalCriteriaValues = new MngSchedulingCriteriaVal().getFunctionalMap(reportID); + + // Product + theDefaultProductBefore = StringHelper.replaceNullByEmpty( theFunctionalCriteriaValues.get(ReportCriteriaEnum.PRODUCT_BEFORE)); + theDefaultProductAfter = StringHelper.replaceNullByEmpty( theFunctionalCriteriaValues.get(ReportCriteriaEnum.PRODUCT_AFTER)); + theDefaultMatricule = StringHelper.replaceNullByEmpty( theFunctionalCriteriaValues.get(ReportCriteriaEnum.MATRICULE)); + //Unit + theDefaultUnitAfter = StringHelper.replaceNullByEmpty( theFunctionalCriteriaValues.get(ReportCriteriaEnum.UNIT_AFTER)); + theDefaultUnitBefore = StringHelper.replaceNullByEmpty( theFunctionalCriteriaValues.get(ReportCriteriaEnum.UNIT_BEFORE)); + // Overall + theDefaultClasse = StringHelper.replaceNullByEmpty( theFunctionalCriteriaValues.get(ReportCriteriaEnum.CLASSE)); + theDefaultMajorMinor = StringHelper.replaceNullByEmpty( theFunctionalCriteriaValues.get(ReportCriteriaEnum.MAJOR_MINOR)); + theDefaultUniqueConjoint = StringHelper.replaceNullByEmpty( theFunctionalCriteriaValues.get(ReportCriteriaEnum.CONJOINT_UNIQUE)); + // LMR + theDefaultLMR = StringHelper.replaceNullByEmpty( theFunctionalCriteriaValues.get(ReportCriteriaEnum.LMR)); + } +%> + + +<%! private String getSelectedClasse(final String theClasse){ + String selectedClasseOne = ""; + String selectedClasseTwo = ""; + StringBuilder buildSelect = new StringBuilder(); + if("1".equals(theClasse)){ + selectedClasseOne ="selected=\"selected\""; + }else{ + selectedClasseTwo ="selected=\"selected\""; + } + buildSelect.append(""); + buildSelect.append(""); + + return buildSelect.toString(); + } + + private String getSelectedMajorMinor(final String theMajorMinor){ + String selectedMajor = ""; + String selectedMinor = ""; + StringBuilder buildSelect = new StringBuilder(); + if("Majeur".equals(theMajorMinor)){ + selectedMajor ="selected=\"selected\""; + }else{ + selectedMinor ="selected=\"selected\""; + } + buildSelect.append(""); + buildSelect.append(""); + + return buildSelect.toString(); + } + + private String getSelectedUniqueConjoint(final String theUniqueConjoint){ + String selectedUnique = ""; + String selectedConjoint = ""; + StringBuilder buildSelect = new StringBuilder(); + if("Conjoint".equals(theUniqueConjoint)){ + selectedConjoint = "selected=\"selected\""; + }else{ + selectedUnique = "selected=\"selected\""; + } + buildSelect.append(""); + buildSelect.append(""); + + return buildSelect.toString(); + } + + /* generate js Array*/ + private String generateArrayLMRs(final String theLMRsList){ + String[] lmrList = StringHelper.splitWithoutDelim(";", theLMRsList); + StringBuilder theTableCode = new StringBuilder("var LMRsArray = new Array();\n"); + int i = 0; + for(String curLMR : lmrList ){ + theTableCode.append("LMRsArray[").append(i).append("]='").append(curLMR).append("';"); + i++; + } + return theTableCode.toString(); + } +%> + + + +<% if( isUpdate && !theDefaultLMR.contains("-")){ %> + +<% } %> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Informations de la configuration "Après" :Informations de la configuration "Avant" :
    Produit* : + + Produit (non modifiable) : + +
    Unit* : + + Unit de référence* : + +
    +
    +
    +
    Informations supplémentaires :
    +
    Matricule : + +
    Classe* : + +
    Majeur ou Mineur* : + +
    Unique ou Conjoint* : + +
    Modifications Retirées : +
    +
    + <% if( isUpdate && !theDefaultLMR.contains("-") ){ %> + + <% }else{ %> +
    + +
    + <% } %> +
    +
    + +
    + + + + +<% if( !isUpdate ){ %> + +<% } %> \ No newline at end of file diff --git a/kurt-web/src/main/webapp/frames/template_r21.jsp b/kurt-web/src/main/webapp/frames/template_r21.jsp new file mode 100644 index 0000000..85d7b2c --- /dev/null +++ b/kurt-web/src/main/webapp/frames/template_r21.jsp @@ -0,0 +1,116 @@ +<%@page import="com.capgemini.framework.common.SettingsHelper"%> +<%@page import="com.capgemini.framework.common.StringHelper" %> +<%@page import="com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum"%> +<%@page import="com.capgemini.reports.database.manager.MngSchedulingCriteriaVal"%> +<%@page import="java.util.Map"%> + +<% + /* + * Available request parameters: + * "isUpdateReport" (boolean) Is this a submission of a NEW report or an UPDATE? + * "idReport" (long) Report Id in case of an UPDATE request + */ + boolean isDevMode = SettingsHelper.isDevMode(); + boolean isUpdate = Boolean.valueOf(request.getParameter("isUpdateReport")); + Long reportID = isUpdate ? Long.valueOf(request.getParameter("idReport")) : new Long(-1); + + // Default values in each field. May contain nothing / existing values / development values + String theDefaultGen = ""; + String theDefaultGenMont = ""; + String theDefaultProduct = ""; + String theDefaultUnit = ""; + String theDefaultDate = ""; + + if (isDevMode){ // Devmode default values + theDefaultGen = "E24"; + theDefaultGenMont = "24E"; + theDefaultProduct = "30E0"; + theDefaultUnit = "20"; + theDefaultDate = "01-01-2015"; + } + + if( isUpdate){ // Existing values to reload from DB + Map theFunctionalCriteriaValues = new MngSchedulingCriteriaVal().getFunctionalMap(reportID); + + theDefaultGen = StringHelper.replaceNullByEmpty( theFunctionalCriteriaValues.get(ReportCriteriaEnum.GENERIC)); + theDefaultGenMont = StringHelper.replaceNullByEmpty( theFunctionalCriteriaValues.get(ReportCriteriaEnum.GENERIC_ASSEMB)); + theDefaultProduct = StringHelper.replaceNullByEmpty( theFunctionalCriteriaValues.get(ReportCriteriaEnum.PRODUCT)); + theDefaultUnit = StringHelper.replaceNullByEmpty( theFunctionalCriteriaValues.get(ReportCriteriaEnum.UNIT)); + theDefaultDate = StringHelper.replaceNullByEmpty( theFunctionalCriteriaValues.get(ReportCriteriaEnum.EFFECTIVITY_DATE)); + + } +%> + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Générique "Vue Technique"* : + +
    Générique "Vue montage"* : + +
    Produit* : + +
    Unit* : + +
    Date d'effectivité : + +
    +
    +
    +
    +

    + +
    + + + \ No newline at end of file diff --git a/kurt-web/src/main/webapp/frames/template_r22.jsp b/kurt-web/src/main/webapp/frames/template_r22.jsp new file mode 100644 index 0000000..ac833de --- /dev/null +++ b/kurt-web/src/main/webapp/frames/template_r22.jsp @@ -0,0 +1,85 @@ +<%@page import="com.capgemini.framework.common.SettingsHelper"%> +<%@page import="com.capgemini.framework.common.StringHelper"%> + + + + + + + + + + + + + + + + + + +
    N° d'article* : + +
    Révision* : + + +
    +
    + +
    + + + + + + diff --git a/kurt-web/src/main/webapp/frames/template_r23.jsp b/kurt-web/src/main/webapp/frames/template_r23.jsp new file mode 100644 index 0000000..93cd178 --- /dev/null +++ b/kurt-web/src/main/webapp/frames/template_r23.jsp @@ -0,0 +1,231 @@ +<%@page import="com.capgemini.framework.common.SettingsHelper" %> +<%@page import="com.capgemini.framework.common.StringHelper" %> +<%@page import="com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum" %> +<%@page import="com.capgemini.reports.database.manager.MngSchedulingCriteriaVal" %> +<%@page import="java.util.Map" %> +<%@page import="com.capgemini.framework.common.DateHelper" %> +<%! final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger("com.capgemini.report.template_r23.jsp"); %> +<% + /* + * Available request parameters: + * "isUpdateReport" (boolean) Is this a submission of a NEW report or an UPDATE? + * "idReport" (long) Report Id in case of an UPDATE request + */ + boolean isDevMode = SettingsHelper.isDevMode(); + boolean isUpdate = Boolean.valueOf(request.getParameter("isUpdateReport")); + Long reportID = isUpdate ? Long.valueOf(request.getParameter("idReport")) : new Long(-1); + + log.info("**********************"); + log.info("isDevMode = " + isDevMode); + log.info("isUpdate = " + isUpdate); + log.info("reportID = " + reportID); + + // Default values in each field. May contain nothing / existing values / development values + String theDefaultGen = ""; + String theDefaultGenMont = ""; + String theDefaultProduct = ""; + String theDefaultDate = DateHelper.getDate(); + String theMonoMulti = "MONO"; + String isSuperModelBOM = Boolean.FALSE.toString(); + String isWithFrozenUnit = Boolean.FALSE.toString(); + String theDefaultUnit = ""; + String theDefaultFromUnit = ""; + String theDefaultFrozenSinceLessThan = ""; + + if (isDevMode) { // Devmode default values + theDefaultGen = ""; + theDefaultGenMont = "24E"; + theDefaultProduct = "30E0"; + theDefaultDate = "01-01-2015"; + } + + if (isUpdate) { // Existing values to reload from DB + Map theFunctionalCriteriaValues = new MngSchedulingCriteriaVal().getFunctionalMap(reportID); + + theDefaultGen = StringHelper.replaceNullByEmpty(theFunctionalCriteriaValues.get(ReportCriteriaEnum.GENERIC)); + theDefaultGenMont = StringHelper.replaceNullByEmpty(theFunctionalCriteriaValues.get(ReportCriteriaEnum.GENERIC_ASSEMB)); + theDefaultProduct = StringHelper.replaceNullByEmpty(theFunctionalCriteriaValues.get(ReportCriteriaEnum.PRODUCT)); + theDefaultDate = StringHelper.replaceNullByEmpty(theFunctionalCriteriaValues.get(ReportCriteriaEnum.EFFECTIVITY_DATE)); + theMonoMulti = StringHelper.replaceNullByEmpty(theFunctionalCriteriaValues.get(ReportCriteriaEnum.MONO_MULTI)); + isSuperModelBOM = StringHelper.replaceNullByEmpty( theFunctionalCriteriaValues.get(ReportCriteriaEnum.SUPERMODEL) ); + isWithFrozenUnit = StringHelper.replaceNullByEmpty(theFunctionalCriteriaValues.get(ReportCriteriaEnum.WITH_FROZEN_UNIT)); + theDefaultUnit = StringHelper.replaceNullByEmpty(theFunctionalCriteriaValues.get(ReportCriteriaEnum.UNIT)); + theDefaultFromUnit = StringHelper.replaceNullByEmpty(theFunctionalCriteriaValues.get(ReportCriteriaEnum.FROM_UNIT)); + theDefaultFrozenSinceLessThan = StringHelper.replaceNullByEmpty(theFunctionalCriteriaValues.get(ReportCriteriaEnum.UNITS_FROZEN_SINCE_LESS_THAN)); + + log.info("theDefaultGen = " + theDefaultGen); + log.info("theDefaultGenMont = " + theDefaultGenMont); + log.info("theDefaultProduct = " + theDefaultProduct); + log.info("theDefaultDate = " + theDefaultDate); + log.info("theMonoMulti = " + theMonoMulti); + log.info("isWithFrozenUnit = " + isWithFrozenUnit); + log.info("theDefaultUnit = " + theDefaultUnit); + log.info("theDefaultFromUnit = " + theDefaultFromUnit); + log.info("theDefaultFrozenSinceLessThan = " + theDefaultFrozenSinceLessThan); + } +%> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Niveau : +
    + /> Mono + /> Multi + + /> + + /> +
    +
    +
    +
    Générique "Vue Technique" : + +
    Générique "Vue montage" : + +
    Produit* : + +
    Unit : + +
    A partir du Unit : + +
    Units gelés il y a moins de : + +
    Date d'effectivité : + + +
    +
    +
    +
    +
    +
    + +
    + + + diff --git a/kurt-web/src/main/webapp/frames/template_r24.jsp b/kurt-web/src/main/webapp/frames/template_r24.jsp new file mode 100644 index 0000000..15d7298 --- /dev/null +++ b/kurt-web/src/main/webapp/frames/template_r24.jsp @@ -0,0 +1,137 @@ +<%@page import="com.capgemini.framework.common.StringHelper"%> +<%@page import="com.capgemini.framework.common.SettingsHelper"%> +<%@page import="com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum"%> +<%@page import="com.capgemini.reports.database.manager.MngSchedulingCriteriaVal"%> +<%@page import="java.util.Map"%> +<% + /* + * Available request parameters: + * "isUpdateReport" (boolean) Is this a submission of a NEW report or an UPDATE? + * "idReport" (long) Report Id in case of an UPDATE request + */ + boolean isDevMode = SettingsHelper.isDevMode(); + boolean isUpdate = Boolean.valueOf(request.getParameter("isUpdateReport")); + Long reportID = isUpdate ? Long.valueOf(request.getParameter("idReport")) : new Long(-1); + + // Default values in each field. May contain nothing / existing values / development values + String theDefaultProduct = ""; + String theDefaultUnit = ""; + String theDefaultLanguage= ""; + String theDefaultPrinterType= ""; + + if (isDevMode){ // Devmode default values + theDefaultProduct = "29R0"; + theDefaultUnit = "245"; + } + + if( isUpdate ){ // Existing values to reload from DB + Map theFunctionalCriteriaValues = new MngSchedulingCriteriaVal().getFunctionalMap(reportID); + + theDefaultProduct = StringHelper.replaceNullByEmpty( theFunctionalCriteriaValues.get(ReportCriteriaEnum.PRODUCT)); + theDefaultUnit = StringHelper.replaceNullByEmpty( theFunctionalCriteriaValues.get(ReportCriteriaEnum.UNIT)); + theDefaultLanguage = StringHelper.replaceNullByEmpty( theFunctionalCriteriaValues.get(ReportCriteriaEnum.LANGUAGE)); + theDefaultPrinterType = StringHelper.replaceNullByEmpty( theFunctionalCriteriaValues.get(ReportCriteriaEnum.TYPE_IMPRESSION)); + } +%> + +<%! private String getSelectedLanguage(final String language){ + String selectedFR = ""; + String selectedEN = ""; + StringBuilder buildSelect = new StringBuilder(); + if("Francais".equals(language)){ + selectedFR ="selected=\"selected\""; + }else{ + selectedEN ="selected=\"selected\""; + } + buildSelect.append(""); + buildSelect.append(""); + return buildSelect.toString(); +} + + private String getPrinterType(final String printerType){ + String selectedDefCertifie = ""; + String selectedDefRealisation = ""; + StringBuilder buildSelect = new StringBuilder(); + if("Def_certifiee".equals(printerType)){ + selectedDefCertifie ="selected=\"selected\""; + }else{ + selectedDefRealisation ="selected=\"selected\""; + } + buildSelect.append(""); + buildSelect.append(""); + return buildSelect.toString(); + } +%> + + + + + + + + + + + + + + + + + + + + + + +
    Produit* : + +
    Unit* : + +
    Type d'impression : + +
    Langue : + +
    +
    + +
    + + + \ No newline at end of file diff --git a/kurt-web/src/main/webapp/frames/template_r25.jsp b/kurt-web/src/main/webapp/frames/template_r25.jsp new file mode 100644 index 0000000..9e2218d --- /dev/null +++ b/kurt-web/src/main/webapp/frames/template_r25.jsp @@ -0,0 +1,140 @@ +<%@page import="com.capgemini.framework.common.SettingsHelper" %> +<%@page import="com.capgemini.framework.common.StringHelper" %> +<%@page import="com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum" %> +<%@page import="com.capgemini.reports.database.manager.MngSchedulingCriteriaVal" %> +<%@page import="java.util.Map" %> +<% + /* + * Available request parameters: + * "isUpdateReport" (boolean) Is this a submission of a NEW report or an UPDATE? + * "idReport" (long) Report Id in case of an UPDATE request + */ + boolean isDevMode = SettingsHelper.isDevMode(); + boolean isUpdate = Boolean.valueOf(request.getParameter("isUpdateReport")); + Long reportID = isUpdate ? Long.valueOf(request.getParameter("idReport")) : new Long(-1); + + // Default values in each field. May contain nothing / existing values / development values + String theDefaultProduct = ""; + String theDefaultUnit = ""; + String theDefaultLanguage = ""; + String theDefaultPrinterType = ""; + + if (isDevMode) { // Devmode default values + theDefaultProduct = "29R0"; + theDefaultUnit = "245"; + } + + if (isUpdate) { // Existing values to reload from DB + Map theFunctionalCriteriaValues = new MngSchedulingCriteriaVal().getFunctionalMap(reportID); + + theDefaultProduct = StringHelper.replaceNullByEmpty(theFunctionalCriteriaValues.get(ReportCriteriaEnum.PRODUCT)); + theDefaultUnit = StringHelper.replaceNullByEmpty(theFunctionalCriteriaValues.get(ReportCriteriaEnum.UNIT)); + theDefaultLanguage = StringHelper.replaceNullByEmpty(theFunctionalCriteriaValues.get(ReportCriteriaEnum.LANGUAGE)); + theDefaultPrinterType = StringHelper.replaceNullByEmpty(theFunctionalCriteriaValues.get(ReportCriteriaEnum.TYPE_IMPRESSION)); + } +%> + +<%! private String getSelectedLanguage(final String language) { + String selectedFR = ""; + String selectedEN = ""; + StringBuilder buildSelect = new StringBuilder(); + if ("Francais".equals(language)) { + selectedFR = "selected=\"selected\""; + } + else { + selectedEN = "selected=\"selected\""; + } + buildSelect.append(""); + buildSelect.append(""); + return buildSelect.toString(); +} + + private String getPrinterType(final String printerType) { + String selectedDefCertifie = ""; + String selectedDefRealisation = ""; + StringBuilder buildSelect = new StringBuilder(); + if ("Def_certifiee".equals(printerType)) { + selectedDefCertifie = "selected=\"selected\""; + } + else { + selectedDefRealisation = "selected=\"selected\""; + } + buildSelect.append(""); + buildSelect.append(""); + return buildSelect.toString(); + } +%> + + + + + + + + + + + + + + + + + + + + + + +
    Produit* : + +
    Unit : + +
    Type d'impression : + +
    Langue : + +
    +
    + +
    + + + \ No newline at end of file diff --git a/kurt-web/src/main/webapp/frames/template_r26.jsp b/kurt-web/src/main/webapp/frames/template_r26.jsp new file mode 100644 index 0000000..02ae75e --- /dev/null +++ b/kurt-web/src/main/webapp/frames/template_r26.jsp @@ -0,0 +1,94 @@ + + +<%@ page import="com.capgemini.framework.common.SettingsHelper" %> +<%@ page import="java.util.Date" %> +<%@ page import="java.util.Calendar" %> +<%@ page import="java.text.SimpleDateFormat" %> + +<% + Date startDate = Calendar.getInstance().getTime(); + SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy"); + + String revisionRule = SettingsHelper.getPropertyWithDefaultValue("common.bom.revisionRule.REPORT_R26", SettingsHelper.getDefaultRevisionRule()); + String date = sdf.format(startDate); +%> + + + + + + + + + + + + + + + + + + + + +
    Composant* : + +
    Règle de révision : + +
    Date d'effectivité : + +
    +
    + +
    + + + + + \ No newline at end of file diff --git a/kurt-web/src/main/webapp/frames/template_r27.jsp b/kurt-web/src/main/webapp/frames/template_r27.jsp new file mode 100644 index 0000000..f8ec07e --- /dev/null +++ b/kurt-web/src/main/webapp/frames/template_r27.jsp @@ -0,0 +1,45 @@ +<%@page import="com.capgemini.framework.common.SettingsHelper"%> +<%@page import="com.capgemini.framework.common.StringHelper" %> +<%@page import="com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum"%> +<%@page import="com.capgemini.reports.database.manager.MngSchedulingCriteriaVal"%> +<%@page import="java.util.Map"%> +<%! final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger("com.capgemini.report.template_r27.jsp"); %> +<% + /* + * Available request parameters: + * "isUpdateReport" (boolean) Is this a submission of a NEW report or an UPDATE? + * "idReport" (long) Report Id in case of an UPDATE request + */ + boolean isDevMode = SettingsHelper.isDevMode(); + boolean isUpdate = Boolean.valueOf(request.getParameter("isUpdateReport")); + Long reportID = isUpdate ? Long.valueOf(request.getParameter("idReport")) : new Long(-1); + + log.info("**********************"); + log.info("isDevMode = " + isDevMode); + log.info("isUpdate = " + isUpdate); + log.info("reportID = " + reportID); + +%> + + + + + + +
    +
    + +
    + + + diff --git a/kurt-web/src/main/webapp/frames/template_r28.jsp b/kurt-web/src/main/webapp/frames/template_r28.jsp new file mode 100644 index 0000000..70e2def --- /dev/null +++ b/kurt-web/src/main/webapp/frames/template_r28.jsp @@ -0,0 +1,45 @@ +<%@page import="com.capgemini.framework.common.SettingsHelper"%> +<%@page import="com.capgemini.framework.common.StringHelper" %> +<%@page import="com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum"%> +<%@page import="com.capgemini.reports.database.manager.MngSchedulingCriteriaVal"%> +<%@page import="java.util.Map"%> +<%! final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger("com.capgemini.report.template_r28.jsp"); %> +<% + /* + * Available request parameters: + * "isUpdateReport" (boolean) Is this a submission of a NEW report or an UPDATE? + * "idReport" (long) Report Id in case of an UPDATE request + */ + boolean isDevMode = SettingsHelper.isDevMode(); + boolean isUpdate = Boolean.valueOf(request.getParameter("isUpdateReport")); + Long reportID = isUpdate ? Long.valueOf(request.getParameter("idReport")) : new Long(-1); + + log.info("**********************"); + log.info("isDevMode = " + isDevMode); + log.info("isUpdate = " + isUpdate); + log.info("reportID = " + reportID); + +%> + + + + + + +
    +
    + +
    + + + diff --git a/kurt-web/src/main/webapp/ihm/bt-error-functional.png b/kurt-web/src/main/webapp/ihm/bt-error-functional.png new file mode 100644 index 0000000000000000000000000000000000000000..dbfda229750f238e5ea15ea9c6de43b9630a5e57 GIT binary patch literal 543 zcmV+)0^t3LP)b-Q zag`tu6obp!L~)B0F04hs!e-fWL9np!FIZTLT3Lt|f`$77+}0w6){1Cgk(Djfu;K@q znfLacmk$ORL`dN9PR=>^<=&eap|wUkpV-OjRHUJl8gxYMiagMXAt_}gDkq~vtrP;U zc9@+hfgq>$t_wJl4*aF=-Vgb%v1t(G)S||f5x?FkocMZf?mH@HmlovI=)HLX+f=@H zJW%)wxc{)Sd1^sUjo#}~WT*kxgpDQf_ z=WBp>izV$c&8R?krb){CiP!g!m=3GV{oeqv0>Jz|F2%SjxZ@ zxGsL|j9QS_wUo`+tf^tGR7!93O%@RMewtR3tzslx+}~C$$Xl0~4703ZtvFdN=!tK= zjZKRB$-`mmjcxlz2)L}~=IZ2h?+;>uuTkEK0f44PUKQj>R(^sLPFCfCge;^$-(i_0001$Nklh|RW-;mF|QwNFVY zor@eWPCtGJ1ZLK@vP*Opuq>5*bADcjaX#~@(RVph(lGc?%l+5?0=Pa1eq^9E_5c6? M07*qoM6N<$f_ia+8~^|S literal 0 HcmV?d00001 diff --git a/kurt-web/src/main/webapp/ihm/bt-refresh.png b/kurt-web/src/main/webapp/ihm/bt-refresh.png new file mode 100644 index 0000000000000000000000000000000000000000..5f841381e3b14f12bc316c1dd1c16fb8ecc5ba8e GIT binary patch literal 832 zcmV-G1Hb%k7RCwB?Q^`*gQ5gTGo$1gHOABo+ z#VC}DzyTxGSV`O>=|PQA5|`-NgNc8F2XCHC^yo!A6c1uF#)x9{V44sTQw@zklrAh5 zSvo9jr=5AT`8|q=(Zqw3{N~M@Z~c7>W11%X&%@H!iTalgaEtSu%8(K=JpV5iInD z-lFJrcwlHY&LAbJpn@XnKqINdU<#6X zB&ezaAc~5{1P0$`3ZvtT)lyjru8MMNtH4=7^4U*r)+fl%9raww^{!WW*HSM;|_$ zsN{%FEEeV?GV>*-a@`&N+MVtiRzaO(D1A|(Aj@r53**pC15%mgHC@wgVD!6)c)3`F z!s;5$awwfy=252!bpvQ~5V4hkRMw2Vs+k+#MhU5KTon5eMGCaVF)5#qT3J?*G_#fi zgX#%eZ6vb%VYwjJ>I}vk}wS+cbw|C+F>^E^z z1TO7rX~J5Oqc}9(GG>A@IN8?|!ZYmdY;8pyn9GVQcpss%iUUGo(_dy1RZbz9wF>D# zZ`fY5!xh0=gfLY|l^ED}p*NH)Tfh+PkQ|>*qRmq}jT;V-=bBtBJ&q3!e{$5>Q}cXX z(mWI{HeNnggT;e&D-UA@E4b<%Fcy6tCz3>?&lg|cs??w`a0M*h_O!D1Z29wpQm3;m zAV5pAP4W9oI!p!*h23Jpf&tKR{c0$2ub-MtYKs$5hHfLnF!Tqls)w<=8o<*oK((J^ zNZtT%*EML^)Aq-jiBprt$eo+p9oP^KgdM^BV~gp=X|#Ml1Q-CtgsnbqEDV~H+MJzd|s z^YP1Hc07G_>)Lgir!F1{Qn4GcTg%?koHo<=1qRN{}nPDolOeI^o4N5I>! zU$N=L=sg~ zDx#dOA*B0N~cqPsWI(^rbbkh)DS0_H_UN0C4l_kvWIm2#Kyy6%BCh z(yIUf003&1xdx>t$*eR2ZvXxT0001Z_R$y3Iju92q*wg58};}zm(OaAH=p|y0002M zh5O5#fxp|~jc?yi@+7$`d4Q6Hl%z;WiWG??NXR{Hx%)pMd~SE0000OQI literal 0 HcmV?d00001 diff --git a/kurt-web/src/main/webapp/ihm/bt-search.png b/kurt-web/src/main/webapp/ihm/bt-search.png new file mode 100644 index 0000000000000000000000000000000000000000..c7095f2bece0c9db6ad6cc6c2a416e365da90e57 GIT binary patch literal 800 zcmV+*1K<3KP)%)q4TZxb-_u#oSC`b`Q@HF=VD4Ja$;m;LV|Q1bOw|_f8qn^G3eIt@Q{N3 z6W9SjandmcDg#wV``Xm5_HY%0F`E6dCQrTk=uva3?0^B1DFv_?cSrz9xAnG3#|IML z`mo}qR~2^L8xt5)G8Xb zrGa#ln(%J6Cz}E;feSg_(j73mzJ0!?rBTsLx~-db77FEpM&w+P$N<^|z=lcaMkLm_ z?s!W993e()5&Ls;&Rlf6u+Fi>#F%AS1|f@3qM5d(YBo!SK*aHu0Ssds@oucF$a;oh zP~Ize1n6IMv6zK*!zMJhx@Bx{ZmFH%Z7Ks43d$m;KZ)BVtp-G{00)S?0?YFpW=x9` zlh}H-DoHc4wF8 zjyc{kKqfPFdu4t;C(BBT zc)a^!ES9(#X^Q$&r%o&+o1!d_uy=Ci{rdEqbbB%QP-r}?xy}xrLr-Uib$s&LSaXE}vIszB7*oTDxgON2h=WPd1>Z&z9BAto9p% zckco~I7oG%5XiT)!vaXIJ%UnVHM-XvM?yz8Mm;GOy_+VgqR&(YJ=%g@mG`T5%2-qzXL_4W4Z z?CkOK^3KuH`}_RP(9+l1+Vb=B(A3oC=;`wF^3c=O^!4`U=jhbd*Yx)G;^pQ2{r=F@ z)!yLZ&R&Cd1q_U7p5?(gvK@9*N|<^BEr`}_Oq>+H$R&j0`aG4_F+0001#Nkl2brZWz49BT!Y-nG&)j2bATgOde%|LDMu{P*+u5 zw}mv?Y$MlAF&P&9qBRu7wiQj&;J?23pp>rYlg{wJ`Vn9Nt6mo;PjzTx00000NkvXX Hu0mjfKJOQ_ literal 0 HcmV?d00001 diff --git a/kurt-web/src/main/webapp/ihm/calendar_planification.png b/kurt-web/src/main/webapp/ihm/calendar_planification.png new file mode 100644 index 0000000000000000000000000000000000000000..f8a88b93653fb0249be8dbf8b6be7c214b012586 GIT binary patch literal 27629 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%0Dl*=Y(qTGhQ5}^K+-!?fh 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 Li6xT+7#XYq{_iib literal 0 HcmV?d00001 diff --git a/kurt-web/src/main/webapp/ihm/generateur-rapports-teamcenter.png b/kurt-web/src/main/webapp/ihm/generateur-rapports-teamcenter.png new file mode 100644 index 0000000000000000000000000000000000000000..1d6d4a3034fcf754760102014cb436fab5e1e5f1 GIT binary patch literal 21397 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 literal 0 HcmV?d00001 diff --git a/kurt-web/src/main/webapp/ihm/ico-progress.png b/kurt-web/src/main/webapp/ihm/ico-progress.png new file mode 100644 index 0000000000000000000000000000000000000000..10f765554698656c750726985ff3d83ee9eda737 GIT binary patch literal 7236 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�T$u`UK%O=_Q`|$KXK2=(e)eFH3?Z(YAPeR;WIik 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 IM6N<$f^{(Ag#Z8m literal 0 HcmV?d00001 diff --git a/kurt-web/src/main/webapp/ihm/ico-report.png b/kurt-web/src/main/webapp/ihm/ico-report.png new file mode 100644 index 0000000000000000000000000000000000000000..9ec394c4d7f7168ff1ceef391512d49c8948c100 GIT binary patch literal 737 zcmcIg+e=dc96obaIui2&u`V!hm1y@Udk|@3Q%5yKg(QlmZZ5)7V`07x)5H*>&|d1T z>>)#E=)(eWo_X24?{++%ZEmjP)U54n)3dX4TgUnv`r!LMe&5T-_v@}umSqTz2><}d zP?XCmIX|+`G(M;K=Q67}OVvtlO8{WVQgqs)#|YXCV>=Ntg3}bu41YIAaB9wm3>m>?Xl;4{8a2%hfF7J=q68JE8G{j=T7)2f z7=$q!?DKEO!8s>EF$B$Qh7F@oWSA?UE4Zr7LG=@83A;_GjOY3dvlZJbCcIq~jNPmk?dHVc)ic=DEK zO{E(m`I##@nT8v=$MZfGbfvyGcJ}dWOwK-6XP*A`edPSb^s|2Jl6m&CSX2NO^0Tn| z?AFbCZJr?jb?N0&}a;0ogs%rlO^8DoK literal 0 HcmV?d00001 diff --git a/kurt-web/src/main/webapp/ihm/ico-scheduled.png b/kurt-web/src/main/webapp/ihm/ico-scheduled.png new file mode 100644 index 0000000000000000000000000000000000000000..d981231351003e4e64cd6b7243410eacbaae576e GIT binary patch literal 824 zcmcgp{ZCQ>6n&Cy&T__9F8U=w+f;0;T=YY!;4r1B13zZ1EyanpmUAYVP}3=X^rC=x z%umpIgEUQD<|Z>YMQP|nHXbG{VGXRPfE90JZ%cTu*FVwS&OJLnoO|xw1^Hz~Nr|Tt z0RTwi6?4l;KK2g@hsd6BHo1bN_(o1C2LR?aE**aIgVZ!};dOCEbA$MS@SX_Z)Hm0O zQh80nMp3y)STAYW6kP#;xEuVE%EFjIieXrcz?DYC;_@jMY)Yd`@m%Q-p|ZXnlLd(p z1Qx}OHm7mLg8jk!<)GK=vwQt(4!35>GrZ!NU$(eC?xE3P?F*fB#@ z=v0s0;Z!al2LwL0w(k#NYDg3812F=Jr)IGTX4&-_P21iGZX#U)U2Lv17(f@z+X{s; z_!|vJFkb+bSbd9Tn?HcsJwEjSgd3!=VNwh0F%*?4GzU@K8;IH+h;(Wr7SRVIQGCBA z_7j}9I=vF<0l9n#)tmR7E~nMymQHL)CoEc>ZldLmeQ5Xq!-n9=pd6Ihe6csua0oTp zTcS{$u_M+!9}MgJAA`^m;{A?>F&v(l zTwJl>1P(4B1VLD{fE@A@t>W^s3R3>(0)ENoI>`8MJT9lQ{ZpMPiwnGlVMbp(i$xWP zPKyLo7OPRk2AI=~oK{xOI|g$)znJ}0mUgYMcTl#zzEf~CeYKjuO1ZimJ^!dSE`=_k z(IoVgTS8%zik+97EE^lW-_??F`Muy(HlMxOW%{5qaSJZwxiSS+1N0hZFDJj7lg5X5 z&oWC3)b!6E1$5*lXLS(Vg!Y)ZM<&lykBrxh*b*M-8Y^g3>iS~G6TNk77!sWpLC~D*)y8kK^?Xp#*{A50 zUsPNfyexx6QuzhhA<2h>L$V&(p!D-gsO&fdJp#HZO>mbTV8g`H+fY^BBf-_dJM~g_LbXUItLiAlt`u1!(x<$DXZd8L= zXsaz+jphV6RI-JNRhkx334xBAi3*)hR^t@4m6%5JR6c22w|Zzkm?Mp`c}KKDrfY)9 z;z_KiG@F>w>rJnY|Fx+yv46WgH4nD1S~LZ>jVpyanvLo@9o)eT5j@E6&TPe?T_o~>R0Sq^fZBGP_9eVDF^`xDE|e)@Oo7VsJmwxV zvmiubOr`34Pz@1wf(v9gXRJ)71%2R89yS|E6RP(kVZoWgYAJ?#7zY6#KID#j5H^T*z9I#q`n@Lt(&KXR*xKgl3kty5ExFcuAx$s78V!<_La#hxd z34=#%$pLR5{E%7>6{eQ(YJyV3dG#FY)cNM|Z5vtEcncn?1_%;396Jw|2$nPx<=x%g zhWn>S>R+AANch zI`_WhgD>`vUXyFSerI@(7`9Ouy5@U9H{JitVfgL7pEK{xojXWo9($7Q!IURP250yB zRabAkrfwZle%X2B*DIeMn^P?J<(Ai`1bcfy-tIvZZon7MD*9X4(7xV?! An*aa+ literal 0 HcmV?d00001 diff --git a/kurt-web/src/main/webapp/ihm/ico-user.png b/kurt-web/src/main/webapp/ihm/ico-user.png new file mode 100644 index 0000000000000000000000000000000000000000..e24ed7ad2373bf0f087b27bbb4962cc780af4cf1 GIT binary patch literal 876 zcmV-y1C#uTP)z@;o?%Qu_W%F@AY({UO#lFTB>(_`g8%^e{{R4h=l}px z2mk>USO5SzmjD14Z`WEMkN^Mz;z>k7RCwBS(@khxRTRMS|Gn?Md2c3@8Ix$5+RRLi zm`TzpbhMZtqQnoXh)}2?bfXL1q#s)mTqvk?AqtAxLUE-Vk-88S38)S$NNva1_F_JdX`0B4#l-l-1CHZ<2255*M!7w10aC!r zd&Zc2>`{^=K}0S;o}S^C*(UjX*D!#T^3FiUknF0B4BcND#B&{jR>)v?ihX$zsp;JS znsx`^@%nbmj3oBjvU&L;VJE8Nswmg#Nw@{y`=2M0&UM{#cmLjt-t=oU#}hh^k;eW%~#2n zc5>B?XxJ<39sGXp6aa}dDn%ot?*Bx%dXeR|D|E`^nfpdZkE|`s9z5{j4`Ux6-qZf- zeRbOwa(5F3-lT43KQK!}VynN%rKP{ox78SW?hrkFI@|h22Q?L+2g-5OxdljoZ;rk} z6tq9FvRyJ~NQ|Be{p0)Cy8k_j1O4a%LM5oyc9ix`z5V>$nUkA=xicq+(=@G0O-G<8 zR(2BaehIp_kcQv~H!?zFpfq$$NU3iElu}hGrAU=RBpud5o%xnV=tCHR8-VL6uC)S+ zz5QE^Om^(%_a#8bcmDYH_&e_|&!2ZdG3Vs*LkL3XMBq6AYj%Uy>M{r+g%lPL1BeaR zXjxr_Cw4#m!YdCw_2Se%VYnZJM|F|DWx_6>t|tF zBVC2w2XrHI7oa6c?8i~K>|Sf0O_OBhW}#Aw{{{fyz&kNB6@a$@0000JNRCwC#S4&F7KoG4?cYX_(Zas)M zn2mQ36hCu`xr8I)z<}Td+_-WfhzD`&%5h=h^v8Pb2!b(bNlP{+SKUZaeH$z<#Baa&mk!{gY?s z^Ro$bdA;_E083%5^)Hu;C2=I+<1bJL&*|`BpEf#03g_=j)<9~fXoOaj==80)(r zM1T!t5L^S6i!aNvU~JSBz#VN3Nt^*4NTdeX&=3R>Kzk)ZQdyQi+mD*sQF@(N1l-GN z_4sgqw`&8Z5sX8Jy6KYWx|VbAZ}DS?*ETO1m|EoEnb#9$L7R;b0%|kWir~b4dX9nc x)-{ep2=u;m^tuoH_n*^vCmab3PT)g;0RVkxoo#J=Z$SV6002ovPDHLkV1m%{-ah~U literal 0 HcmV?d00001 diff --git a/kurt-web/src/main/webapp/ihm/icone-plus.png b/kurt-web/src/main/webapp/ihm/icone-plus.png new file mode 100644 index 0000000000000000000000000000000000000000..0908e24d0cd3b90260d21742840fb031091496bf GIT binary patch literal 558 zcmV+}0@3}6P)t)in5>~w!@4YAVqCs6r*f1k`>2!_B_we z4oi{*$`lVumWn_{pdwH@0g(q_jEPRCb0q|C+SV+_0Hjp6IBykS<-B4iEY=G-=grn` z`%gPN?jAL1F1EKq7C@MjTvZKKf$f}n;31i8h0 z*x%bR&%nsS%E5l?yWj2g4c2)bkWzv#{9GJi2 z2m%F3}_6#T5URk z-{XXJ>H^x1)CxG&fXwLi&E0qrAu^>14A#~JRs<-$JjNjm!-@2pxVB0bgW){Y(ToDPKd wyyMu0K;cVAq5Hsp|2b86!iqrY1U>~A0C>Zy3SJs9x&QzG07*qoM6N<$f`rfPSpWb4 literal 0 HcmV?d00001 diff --git a/kurt-web/src/main/webapp/ihm/input-back.png b/kurt-web/src/main/webapp/ihm/input-back.png new file mode 100644 index 0000000000000000000000000000000000000000..cee152622d69b9c46e98e9df93b86c683842fcf2 GIT binary patch literal 245 zcmeAS@N?(olHy`uVBq!ia0vp^96&6>!3-qZkM=|YDVB6cUq=Rp^(V|(yIunMk|nMY zCBgY=CFO}lsSJ)O`AMk?p1FzXsX?iUDV2pMQ*D5X3<7*YT>t$2|Ks=nuRs3({QdvO zum6Ak{r~yr|JR@YfBpIY_uv0-KmY&x|Nr-&|KET8|MKHM5J(0Zb^`T!d%8G=RNU%0 z=P1-*z`=YVM00`b@BjCwWgUyV%juKX;I|`F)cAH0kNU$!p(*-Gi&)>in&s$HaV))Z rLD-d@1p-nJ_ujSIXI?i&@c={iBX)~FmW+Ra#xi)i`njxgN@xNAniFwC literal 0 HcmV?d00001 diff --git a/kurt-web/src/main/webapp/ihm/left-bar-action-back-hover.png b/kurt-web/src/main/webapp/ihm/left-bar-action-back-hover.png new file mode 100644 index 0000000000000000000000000000000000000000..15eb12adfe70e3cad280f0fdd932d0b08939f9e8 GIT binary patch literal 207 zcmeAS@N?(olHy`uVBq!ia0vp^tUxTv!3-pKreE;^QY`6?zK#qG>ra@ocD)4hB}-f* zN`mv#O3D+9QW+dm@{>{(JaZG%Q-e|yQz{EjrrH1%NeB3ZxW51W`}_ajuYZ4k@%#7Z z-{0T={{H(v2)y|H{d@kzN}w_;PZ!6Kid#9ohI|YL9843#Uj2{1^XSUK!*`fEE!g&# zsyMPKx+X}ce7mUD?Xp&U%FMfOrFnDz?_%O%m}$c_Go|CNDbN%KPgg&ebxsLQ04U~D AVgLXD literal 0 HcmV?d00001 diff --git a/kurt-web/src/main/webapp/ihm/left-bar-action-back.png b/kurt-web/src/main/webapp/ihm/left-bar-action-back.png new file mode 100644 index 0000000000000000000000000000000000000000..e92aab4330b45a9bab8eee1898918e12ec447ed3 GIT binary patch literal 206 zcmeAS@N?(olHy`uVBq!ia0vp^96&6}!3-pQX2$;kQY`6?zK#qG>ra@ocD)4hB}-f* zN`mv#O3D+9QW+dm@{>{(JaZG%Q-e|yQz{EjrrH1%NeB3Zxc>eB@AtodfByab_3!V` ze?a!%fB!+?=fA%p>;+SR$}Bxy978H@B_*^ovH7q`i!3mdXlUT%l8|t0m^yW8qbQfe wjD-!2%v=IIVhRqTiqjY`bqX}@6i_(8kWmdKI;Vst07iOBM*si- literal 0 HcmV?d00001 diff --git a/kurt-web/src/main/webapp/ihm/left-bar-top.png b/kurt-web/src/main/webapp/ihm/left-bar-top.png new file mode 100644 index 0000000000000000000000000000000000000000..391f824090a405f77a45470fc2891fb177f650cf GIT binary patch literal 261 zcmV+g0s8)lP)T$KoGz{la|bp`TtLmz`7~i zn@6nT5S^&REJjg_QuJaGjVMGCm)ON1PSM^!zD5L_$nwRcSAYQk%vuRzN(clA00000 LNkvXXu0mjf9K3!| literal 0 HcmV?d00001 diff --git a/kurt-web/src/main/webapp/ihm/left-bar.png b/kurt-web/src/main/webapp/ihm/left-bar.png new file mode 100644 index 0000000000000000000000000000000000000000..4b948864af6af2a4fdf4ecaa46eabe99789c96db GIT binary patch literal 365 zcmV-z0h0cSP){r&&= z`2TpCnic>60J=#;K~#9!?9$N=!XONV;X*fcuol+$e^^h))EMWbP80qRdP%+%TJ{Tm zB?%#+AR;qPk+Gn;Yz-An^|hR9Rm})@R5evHVk0vnwKnaeoi1nUwr=|)TX?b|*ydU8 zwyD{MJsfOKgV2?3BVc&7@$t447IB~8G}}00z<1l)P|Ch7R=34mv9p>t8}`M(sq*^x zakgc(rH9RN(rk|(>9+dD7V#M)Y!S8=F|!&I+ZXD#Zu>#oRe%8iMK^-tTeQxE00000 LNkvXXu0mjf>oB%F literal 0 HcmV?d00001 diff --git a/kurt-web/src/main/webapp/ihm/left-bar_160.png b/kurt-web/src/main/webapp/ihm/left-bar_160.png new file mode 100644 index 0000000000000000000000000000000000000000..c38259c14fca5075e734ca4d60a51040d5b09940 GIT binary patch literal 356 zcmV-q0h|7bP)000UI0{{R31eT?j0000vP)t-s`1$|+ z{Qvp-|M~d;`}+U<`~U9m|NQ^|_W1w$`~Up?|N8m=`~3g>{Qvp+|NHy@`uhL<{r~v* z|9G03761SM0b)x>L;#2d9Y_EG010qNS#tmY3ljhU3ljkVnw%H_000McNliru-wX-| zJ1zOstoHx_0I^9#K~y-)?a|Q=f-nq);ckTs*xHr8|HFF9P-4VHqgTqGWxd>&j+Wz6 zT(hJ!qa-2~r^(n*ZCit($sQ}kOtm1~S=Cj^iJjb?)cf?8q7(Sfz;p*h0M;ru;M9S` zkr2S}ff>{Q5=6WL`Afh#EfPq<>A-Qs0P?!Op|xXRwgBd0*q)UQh|MvCs@z}x47jYo zc?X72I&lBs0NN8^#@}WDGk`r}W_2d^H#&ho54-@0mRhiXXZUOY0000{Qvp+|NHy@`uhL<{r~v* z|9G03761SM0b)x>L;#2d9Y_EG010qNS#tmY3ljhU3ljkVnw%H_000McNliru-wPBC zB`&+_yZ8VA0JKR&K~zY`?bFE)gCG!q;bF5C9YEgyVLMCHEs~fXS`YIl!07P{z&6gw zj_6#L93rl~YE7w9Ykk(Zd2ahHv`Sg1LWlRhcN#hX(CQTLGRfBuo2Kgp48af#;cEnr z5%}0ah+_mMScszV4?zG%2;uYyIV0+>2|`LTqz6KbQ6Pp00>L-HGXh~K0^f!p3N&bE zL)Zi%=T`(#xSy$hBD8h{!RxEgf+FaB_(O(Z2!`;6a0C9ooG_CDbGiTk002ovPDHLk FV1fwpq+tL6 literal 0 HcmV?d00001 diff --git a/kurt-web/src/main/webapp/ihm/progress.gif b/kurt-web/src/main/webapp/ihm/progress.gif new file mode 100644 index 0000000000000000000000000000000000000000..ed3ad8481ded5d1595f93fc5953977ef36145704 GIT binary patch literal 7110 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 I7B>p~Kfr+djsO4v literal 0 HcmV?d00001 diff --git a/kurt-web/src/main/webapp/ihm/state_executing.png b/kurt-web/src/main/webapp/ihm/state_executing.png new file mode 100644 index 0000000000000000000000000000000000000000..4859e0cb2974ce80a04e9474ee51fdf194eb158d GIT binary patch literal 3400 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 a0t^5bUGJy`2LiYN0000Bq~w0&_)%H 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 literal 0 HcmV?d00001 diff --git a/kurt-web/src/main/webapp/ihm/state_wait.png b/kurt-web/src/main/webapp/ihm/state_wait.png new file mode 100644 index 0000000000000000000000000000000000000000..c87fb8b526edb02dc542a9cf9c011ddabc326659 GIT binary patch literal 3051 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 LNkvXXu0mjfpCAA2 literal 0 HcmV?d00001 diff --git a/kurt-web/src/main/webapp/ihm/top-bar.png b/kurt-web/src/main/webapp/ihm/top-bar.png new file mode 100644 index 0000000000000000000000000000000000000000..f293450824c68039293f5d053589575b74e6785c GIT binary patch literal 386 zcmV-|0e$|7P)J@g z-0#26=d;G*y2<3;X)z8_4fX*!QZ{h<<#Bq^!5GO;PQ~G()jrQYke>u0001WNklzK2bPjz(OXvnVh2EhvXarqB3+M-0Lx0dKbOF&DbPpXux6lB3hF+ivbPQcWztAT% gg|^_lhMfQd0NtElp)uuhF8}}l07*qoM6N<$f>brhr2qf` literal 0 HcmV?d00001 diff --git a/kurt-web/src/main/webapp/ihm/update.png b/kurt-web/src/main/webapp/ihm/update.png new file mode 100644 index 0000000000000000000000000000000000000000..9c7f7732d3b91def0d19f395b6bb532d4caa3341 GIT binary patch literal 7249 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 literal 0 HcmV?d00001 diff --git a/kurt-web/src/main/webapp/index.jsp b/kurt-web/src/main/webapp/index.jsp new file mode 100644 index 0000000..3fca861 --- /dev/null +++ b/kurt-web/src/main/webapp/index.jsp @@ -0,0 +1,225 @@ +<%@page import="com.capgemini.framework.common.SettingsHelper" %> +<%@page import="com.capgemini.framework.common.activedirectory.ActiveDirectory" %> +<%@page import="com.capgemini.framework.teamcenter.exceptions.KurtException" %> +<%@page import="com.capgemini.reports.database.javabean.DbUser.UserData" %> +<%@page import="java.net.InetAddress" %> +<%! final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger("com.capgemini.index.jsp"); %> +<% + response.setHeader("Pragma", "no-cache"); + response.setHeader("Cache-Control", "no-cache"); + response.setDateHeader("Expires", 0); + + String rawUserLogin = request.getRemoteUser(); + + // Useful for debug: + log.trace("Request: =" + request.toString()); + log.trace("Request: Auth Type =" + request.getAuthType()); + log.trace("Request: HeaderNames=" + request.getHeaderNames().toString()); + log.trace("Request: isSecure =" + request.isSecure()); + log.trace("Raw userName =" + rawUserLogin); + + + // Obtain user data (if the header's login is valid) + UserData userData; + try { + userData = ActiveDirectory.obtainUserData(rawUserLogin); + } catch (KurtException e) { + // Failed to authenticate the user, defaulting to Guest + log.debug("Could not authenticate the user: " + (rawUserLogin == null ? "null" : rawUserLogin), e); + userData = ActiveDirectory.getGuestUser(); + } + + // Tag for developer mode + String theDevModeInfo = ""; + boolean isDevMode = SettingsHelper.isDevMode(); + boolean isValMode = SettingsHelper.isValMode(); + if (isDevMode) { + theDevModeInfo = " - Mode DEV actif"; + } + if (isValMode) { + theDevModeInfo = theDevModeInfo + " - Mode VAL actif"; + } + + // Tag for URL to the current teamcenter target server + String theTeamcenterURL; + if (isValMode || isDevMode) { + theTeamcenterURL = " - " + SettingsHelper.getPropertyWithDefaultValue("teamcenter.url", "Unknown"); + } else { + theTeamcenterURL = ""; + } +%> + + + + + + + + + + + + + + Générateur de rapports Teamcenter + + + + + + + + + + + + + +
    +
    +
    + +
    +
    Utilisateur :
    + + <%=userData.getLogin()%> + + + <% if (isDevMode){ %> + + + <%=userData.getFirstName()%> <%=userData.getSurname()%> + + + <% } %> + + <% if(userData.isAdmin()){%> + Admin + <% } %> + +
    Actions :
    + <% if (isDevMode){ %> + + Rapport 01 + Rapport 03 + Rapport 07 + Rapport 10 + Rapport 11 + Rapport 13 + Rapport 15 + Rapport 16 + Rapport 17 + Rapport 19 + Rapport 20 + Rapport 21 + Rapport 22 + Rapport 23 + Rapport 24 + Rapport 25 + Rapport 26 + Rapport 27 + Rapport 28 + <% } %> + Mes rapports + <% if (isDevMode){ %> + + Suivi mémoire + <% } %> + + <% if(userData.isAdmin() || isDevMode){ %> + +
    Administration :
    + <% if (isDevMode) { %> + Interface JBoss + <% } %> + Rapports en + cours + Etat des queues + Statistiques par + rapport + Statistiques par + utilisateur + Planification + des rapports + <% } %> + +
    + + + + + + + + + + +
       
    + +
    + + + + + \ No newline at end of file diff --git a/kurt-web/src/main/webapp/js/criteria.js b/kurt-web/src/main/webapp/js/criteria.js new file mode 100644 index 0000000..5871a95 --- /dev/null +++ b/kurt-web/src/main/webapp/js/criteria.js @@ -0,0 +1,17 @@ +function DisplayTable() { + + var tableContent = ''; + + /* Browse each criteria */ + var criteriaCount = criteriaArray.length; + for (var i = 0; i < criteriaCount; i++) { + + /* Display columns of the current criteria */ + tableContent += ''; + tableContent += '' + criteriaArray[i]['name'] + ''; + tableContent += '' + criteriaArray[i]['value'] + ''; + tableContent += ''; + } + + document.write(tableContent); +} diff --git a/kurt-web/src/main/webapp/js/dialog_box.js b/kurt-web/src/main/webapp/js/dialog_box.js new file mode 100644 index 0000000..4a984fc --- /dev/null +++ b/kurt-web/src/main/webapp/js/dialog_box.js @@ -0,0 +1,71 @@ +/* Variable globale */ +var dialogRefresh = false; + +function GetById(id) { + return document.getElementById(id); +} + +String.prototype.startsWith = function(s) { + return (this.match("^" + s) == s); +}; + +/* calculate the current window height */ +function pageHeight() { + return window.innerHeight != null ? window.innerHeight : document.documentElement + && document.documentElement.clientHeight ? document.documentElement.clientHeight + : document.body != null ? document.body.clientHeight : null; +} + +/* calculate the current window vertical offset */ +function topPosition() { + return pageHeight() / 2 - 50; +} + +/* build-show the dialog box, populate the data and call the fadeDialog function */ +/* var t = title */ +/* var m = message */ +function Dialog(t, m) { + + /* Icone du message */ + var i = ''; + + var dialog = GetById('dialog'); + if (!dialog) { + dialog = document.createElement('DIV'); + dialog.id = 'dialog'; + dialog.innerHTML = '
     
     
    '; + dialog.style.top = topPosition(); + document.getElementsByTagName('body')[0].appendChild(dialog); + var mask = document.createElement('div'); + mask.id = 'dialog-mask'; + mask.style.height = Math.max(document.body.scrollHeight, document.body.offsetHeight) + 'px'; + document.getElementsByTagName('body')[0].appendChild(mask); + } else { + dialog.style.top = topPosition(); + dialog.style.display = ''; + GetById('dialog-mask').style.display = ''; + } + + GetById('dialog-title').innerHTML = t; + GetById('dialog-content').innerHTML = m; + GetById('dialog-table').style.backgroundImage = i; + + if (m.startsWith("\')" title="Afficher les critères" style="cursor:pointer;width:16px;height:16px;"/>\n'; + tableContent += currentError + ' ' + currentDownload + ' \n'; + tableContent += ' ' + currentStatus + '\n'; + tableContent += ''; + } + document.write(tableContent); +} + +/* Redirect to page */ +function GoPage(i) { + document.location.href = '/kurt-web/frames/my_reports.jsp?page=' + i; +} diff --git a/kurt-web/src/main/webapp/js/obtain_data.js b/kurt-web/src/main/webapp/js/obtain_data.js new file mode 100644 index 0000000..da63e1e --- /dev/null +++ b/kurt-web/src/main/webapp/js/obtain_data.js @@ -0,0 +1,27 @@ +/** + * Tool for sending an AJAX request with GET parameters for retrieving data. + */ + +/* Dedicated HttpRequest object (as global) */ +var objGetRequest = null; + +/* Main method for retrieving data in the ServerResponseForObtainData callback method */ +function ObtainData(url) { + /* Detect client browser for getting the expected HttpRequest object */ + if (window.XMLHttpRequest) + objGetRequest = new XMLHttpRequest(); + else if (window.ActiveXObject) + objGetRequest = new ActiveXObject("Microsoft.XMLHTTP"); + + /* Send AJAX form and get response */ + objGetRequest.open('post', url, true); + objGetRequest.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); + objGetRequest.onreadystatechange = ServerResponseForObtainData; + + /* Display loading bar and hide buttons */ + document.getElementById("loading").style.display = ''; + document.getElementById("btZone").style.display = 'none'; + + /* Send request and wait for response */ + objGetRequest.send(); +} diff --git a/kurt-web/src/main/webapp/js/pikaday.js b/kurt-web/src/main/webapp/js/pikaday.js new file mode 100644 index 0000000..258a000 --- /dev/null +++ b/kurt-web/src/main/webapp/js/pikaday.js @@ -0,0 +1,915 @@ +(function (root, factory) { + 'use strict'; + + var moment; + if (typeof exports === 'object') { + // CommonJS module + // Load moment.js as an optional dependency + try { + moment = require('moment'); + } catch (e) { + } + module.exports = factory(moment); + } else if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module. + define(function (req) { + // Load moment.js as an optional dependency + var id = 'moment'; + try { + moment = req(id); + } catch (e) { + } + return factory(moment); + }); + } else { + root.Pikaday = factory(root.moment); + } +}(this, function (moment) { + 'use strict'; + + /** + * feature detection and helper functions + */ + var hasMoment = typeof moment === 'function', + + hasEventListeners = !!window.addEventListener, + + document = window.document, + + sto = window.setTimeout, + + addEvent = function (el, e, callback, capture) { + if (hasEventListeners) { + el.addEventListener(e, callback, !!capture); + } else { + el.attachEvent('on' + e, callback); + } + }, + + removeEvent = function (el, e, callback, capture) { + if (hasEventListeners) { + el.removeEventListener(e, callback, !!capture); + } else { + el.detachEvent('on' + e, callback); + } + }, + + fireEvent = function (el, eventName, data) { + var ev; + + if (document.createEvent) { + ev = document.createEvent('HTMLEvents'); + ev.initEvent(eventName, true, false); + ev = extend(ev, data); + el.dispatchEvent(ev); + } else if (document.createEventObject) { + ev = document.createEventObject(); + ev = extend(ev, data); + el.fireEvent('on' + eventName, ev); + } + }, + + trim = function (str) { + return str.trim ? str.trim() : str.replace(/^\s+|\s+$/g, ''); + }, + + hasClass = function (el, cn) { + return (' ' + el.className + ' ').indexOf(' ' + cn + ' ') !== -1; + }, + + addClass = function (el, cn) { + if (!hasClass(el, cn)) { + el.className = (el.className === '') ? cn : el.className + ' ' + cn; + } + }, + + removeClass = function (el, cn) { + el.className = trim((' ' + el.className + ' ').replace(' ' + cn + ' ', ' ')); + }, + + isArray = function (obj) { + return (/Array/).test(Object.prototype.toString.call(obj)); + }, + + isDate = function (obj) { + return (/Date/).test(Object.prototype.toString.call(obj)) && !isNaN(obj.getTime()); + }, + + isLeapYear = function (year) { + // solution by Matti Virkkunen: http://stackoverflow.com/a/4881951 + return year % 4 === 0 && year % 100 !== 0 || year % 400 === 0; + }, + + getDaysInMonth = function (year, month) { + return [31, isLeapYear(year) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month]; + }, + + setToStartOfDay = function (date) { + if (isDate(date)) date.setHours(0, 0, 0, 0); + }, + + compareDates = function (a, b) { + // weak date comparison (use setToStartOfDay(date) to ensure correct result) + return a.getTime() === b.getTime(); + }, + + extend = function (to, from, overwrite) { + var prop, hasProp; + for (prop in from) { + hasProp = to[prop] !== undefined; + if (hasProp && typeof from[prop] === 'object' && from[prop] !== null && from[prop].nodeName === undefined) { + if (isDate(from[prop])) { + if (overwrite) { + to[prop] = new Date(from[prop].getTime()); + } + } + else if (isArray(from[prop])) { + if (overwrite) { + to[prop] = from[prop].slice(0); + } + } else { + to[prop] = extend({}, from[prop], overwrite); + } + } else if (overwrite || !hasProp) { + to[prop] = from[prop]; + } + } + return to; + }, + + adjustCalendar = function (calendar) { + if (calendar.month < 0) { + calendar.year -= Math.ceil(Math.abs(calendar.month) / 12); + calendar.month += 12; + } + if (calendar.month > 11) { + calendar.year += Math.floor(Math.abs(calendar.month) / 12); + calendar.month -= 12; + } + return calendar; + }, + + /** + * defaults and localisation + */ + defaults = { + + // bind the picker to a form field + field: null, + + // automatically show/hide the picker on `field` focus (default `true` if `field` is set) + bound: undefined, + + // position of the datepicker, relative to the field (default to bottom & left) + // ('bottom' & 'left' keywords are not used, 'top' & 'right' are modifier on the bottom/left position) + position: 'bottom left', + + // automatically fit in the viewport even if it means repositioning from the position option + reposition: true, + + // the default output format for `.toString()` and `field` value + format: 'DD-MM-YYYY', + + // the initial date to view when first opened + defaultDate: null, + + // make the `defaultDate` the initial selected value + setDefaultDate: false, + + // first day of week (0: Sunday, 1: Monday etc) + firstDay: 0, + + // the minimum/earliest date that can be selected + minDate: null, + // the maximum/latest date that can be selected + maxDate: null, + + // number of years either side, or array of upper/lower range + yearRange: 10, + + // show week numbers at head of row + showWeekNumber: false, + + // used internally (don't config outside) + minYear: 0, + maxYear: 9999, + minMonth: undefined, + maxMonth: undefined, + + isRTL: false, + + // Additional text to append to the year in the calendar title + yearSuffix: '', + + // Render the month after year in the calendar title + showMonthAfterYear: false, + + // how many months are visible + numberOfMonths: 1, + + // when numberOfMonths is used, this will help you to choose where the main calendar will be (default `left`, can be set to `right`) + // only used for the first display or when a selected date is not visible + mainCalendar: 'left', + + // Specify a DOM element to render the calendar in + container: undefined, + + // internationalization + i18n: { + previousMonth: 'Mois précédent', + nextMonth: 'Mois suivant', + months: ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'], + weekdays: ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi', 'Samedi'], + weekdaysShort: ['Dim', 'Lun', 'Mar', 'Mer', 'Jeu', 'Ven', 'Sam'] + }, + + // callback function + onSelect: null, + onOpen: null, + onClose: null, + onDraw: null + }, + + + /* Templating functions to abstract HTML rendering */ + renderDayName = function (opts, day, abbr) { + day += opts.firstDay; + while (day >= 7) { + day -= 7; + } + return abbr ? opts.i18n.weekdaysShort[day] : opts.i18n.weekdays[day]; + }, + + renderDay = function (d, m, y, isSelected, isToday, isDisabled, isEmpty) { + if (isEmpty) { + return ''; + } + var arr = []; + if (isDisabled) { + arr.push('is-disabled'); + } + if (isToday) { + arr.push('is-today'); + } + if (isSelected) { + arr.push('is-selected'); + } + return '' + + '' + + ''; + }, + + renderWeek = function (d, m, y) { + var onejan = new Date(y, 0, 1), + weekNum = Math.ceil((((new Date(y, m, d) - onejan) / 86400000) + onejan.getDay() + 1) / 7); + return '' + weekNum + ''; + }, + + renderRow = function (days, isRTL) { + return '' + (isRTL ? days.reverse() : days).join('') + ''; + }, + + renderBody = function (rows) { + return '' + rows.join('') + ''; + }, + + renderHead = function (opts) { + var i, arr = []; + if (opts.showWeekNumber) { + arr.push(''); + } + for (i = 0; i < 7; i++) { + arr.push('' + renderDayName(opts, i, true) + ''); + } + return '' + (opts.isRTL ? arr.reverse() : arr).join('') + ''; + }, + + renderTitle = function (instance, c, year, month, refYear) { + var i, j, arr, + opts = instance._o, + isMinYear = year === opts.minYear, + isMaxYear = year === opts.maxYear, + html = '
    ', + monthHtml, + yearHtml, + prev = true, + next = true; + + for (arr = [], i = 0; i < 12; i++) { + arr.push(''); + } + monthHtml = '
    ' + opts.i18n.months[month] + '
    '; + + if (isArray(opts.yearRange)) { + i = opts.yearRange[0]; + j = opts.yearRange[1] + 1; + } else { + i = year - opts.yearRange; + j = 1 + year + opts.yearRange; + } + + for (arr = []; i < j && i <= opts.maxYear; i++) { + if (i >= opts.minYear) { + arr.push(''); + } + } + yearHtml = '
    ' + year + opts.yearSuffix + '
    '; + + if (opts.showMonthAfterYear) { + html += yearHtml + monthHtml; + } else { + html += monthHtml + yearHtml; + } + + if (isMinYear && (month === 0 || opts.minMonth >= month)) { + prev = false; + } + + if (isMaxYear && (month === 11 || opts.maxMonth <= month)) { + next = false; + } + + if (c === 0) { + html += ''; + } + if (c === (instance._o.numberOfMonths - 1)) { + html += ''; + } + + return html += '
    '; + }, + + renderTable = function (opts, data) { + return '' + renderHead(opts) + renderBody(data) + '
    '; + }, + + + /* Pikaday constructor */ + Pikaday = function (options) { + var self = this, + opts = self.config(options); + + self._onMouseDown = function (e) { + if (!self._v) { + return; + } + e = e || window.event; + var target = e.target || e.srcElement; + if (!target) { + return; + } + + if (!hasClass(target, 'is-disabled')) { + if (hasClass(target, 'pika-button') && !hasClass(target, 'is-empty')) { + self.setDate(new Date(target.getAttribute('data-pika-year'), target.getAttribute('data-pika-month'), target.getAttribute('data-pika-day'))); + if (opts.bound) { + sto(function () { + self.hide(); + if (opts.field) { + opts.field.blur(); + } + }, 100); + } + return; + } + else if (hasClass(target, 'pika-prev')) { + self.prevMonth(); + } + else if (hasClass(target, 'pika-next')) { + self.nextMonth(); + } + } + if (!hasClass(target, 'pika-select')) { + if (e.preventDefault) { + e.preventDefault(); + } else { + e.returnValue = false; + return false; + } + } else { + self._c = true; + } + }; + + self._onChange = function (e) { + e = e || window.event; + var target = e.target || e.srcElement; + if (!target) { + return; + } + if (hasClass(target, 'pika-select-month')) { + self.gotoMonth(target.value); + } + else if (hasClass(target, 'pika-select-year')) { + self.gotoYear(target.value); + } + }; + + self._onInputChange = function (e) { + var date; + + if (e.firedBy === self) { + return; + } + if (hasMoment) { + date = moment(opts.field.value, opts.format); + date = (date && date.isValid()) ? date.toDate() : null; + } + else { + date = new Date(Date.parse(opts.field.value)); + } + self.setDate(isDate(date) ? date : null); + if (!self._v) { + self.show(); + } + }; + + self._onInputFocus = function () { + self.show(); + }; + + self._onInputClick = function () { + self.show(); + }; + + self._onInputBlur = function () { + if (!self._c) { + self._b = sto(function () { + self.hide(); + }, 50); + } + self._c = false; + }; + + self._onClick = function (e) { + e = e || window.event; + var target = e.target || e.srcElement, + pEl = target; + if (!target) { + return; + } + if (!hasEventListeners && hasClass(target, 'pika-select')) { + if (!target.onchange) { + target.setAttribute('onchange', 'return;'); + addEvent(target, 'change', self._onChange); + } + } + do { + if (pEl === opts.trigger) { + return; + } + } + while ((pEl = pEl.parentNode)); + if (self._v && pEl !== opts.trigger) { + //self.hide(); + } + }; + + self.el = document.createElement('div'); + self.el.className = 'pika-single' + (opts.isRTL ? ' is-rtl' : ''); + + addEvent(self.el, 'mousedown', self._onMouseDown, true); + addEvent(self.el, 'change', self._onChange); + + if (opts.field) { + if (opts.container) { + opts.container.appendChild(self.el); + } else if (opts.bound) { + document.body.appendChild(self.el); + } else { + opts.field.parentNode.insertBefore(self.el, opts.field.nextSibling); + } + addEvent(opts.field, 'change', self._onInputChange); + + if (!opts.defaultDate) { + if (hasMoment && opts.field.value) { + opts.defaultDate = moment(opts.field.value, opts.format).toDate(); + } else { + opts.defaultDate = new Date(Date.parse(opts.field.value)); + } + opts.setDefaultDate = true; + } + } + + var defDate = opts.defaultDate; + + if (isDate(defDate)) { + if (opts.setDefaultDate) { + self.setDate(defDate, true); + } else { + self.gotoDate(defDate); + } + } else { + self.gotoDate(new Date()); + } + + if (opts.bound) { + this.hide(); + self.el.className += ' is-bound'; + addEvent(opts.trigger, 'click', self._onInputClick); + addEvent(opts.trigger, 'focus', self._onInputFocus); + addEvent(opts.trigger, 'blur', self._onInputBlur); + } else { + this.show(); + } + }; + + Pikaday.prototype = { + + + /* Configure functionality */ + config: function (options) { + if (!this._o) { + this._o = extend({}, defaults, true); + } + + var opts = extend(this._o, options, true); + + opts.isRTL = !!opts.isRTL; + + opts.field = (opts.field && opts.field.nodeName) ? opts.field : null; + + opts.bound = !!(opts.bound !== undefined ? opts.field && opts.bound : opts.field); + + opts.trigger = (opts.trigger && opts.trigger.nodeName) ? opts.trigger : opts.field; + + var nom = parseInt(opts.numberOfMonths, 10) || 1; + opts.numberOfMonths = nom > 4 ? 4 : nom; + + if (!isDate(opts.minDate)) { + opts.minDate = false; + } + if (!isDate(opts.maxDate)) { + opts.maxDate = false; + } + if ((opts.minDate && opts.maxDate) && opts.maxDate < opts.minDate) { + opts.maxDate = opts.minDate = false; + } + if (opts.minDate) { + setToStartOfDay(opts.minDate); + opts.minYear = opts.minDate.getFullYear(); + opts.minMonth = opts.minDate.getMonth(); + } + if (opts.maxDate) { + setToStartOfDay(opts.maxDate); + opts.maxYear = opts.maxDate.getFullYear(); + opts.maxMonth = opts.maxDate.getMonth(); + } + + if (isArray(opts.yearRange)) { + var fallback = new Date().getFullYear() - 10; + opts.yearRange[0] = parseInt(opts.yearRange[0], 10) || fallback; + opts.yearRange[1] = parseInt(opts.yearRange[1], 10) || fallback; + } else { + opts.yearRange = Math.abs(parseInt(opts.yearRange, 10)) || defaults.yearRange; + if (opts.yearRange > 100) { + opts.yearRange = 100; + } + } + + return opts; + }, + + /* Return a formatted string of the current selection (using Moment.js if available) */ + toString: function (format) { + return !isDate(this._d) ? '' : hasMoment ? moment(this._d).format(format || this._o.format) : this._d.toDateString(); + }, + + /* Return a Moment.js object of the current selection (if available) */ + getMoment: function () { + return hasMoment ? moment(this._d) : null; + }, + + /* Set the current selection from a Moment.js object (if available) */ + setMoment: function (date, preventOnSelect) { + if (hasMoment && moment.isMoment(date)) { + this.setDate(date.toDate(), preventOnSelect); + } + }, + + /* Return a Date object of the current selection */ + getDate: function () { + return isDate(this._d) ? new Date(this._d.getTime()) : null; + }, + + /* Set the current selection */ + setDate: function (date, preventOnSelect) { + if (!date) { + this._d = null; + + if (this._o.field) { + this._o.field.value = ''; + fireEvent(this._o.field, 'change', {firedBy: this}); + } + + return this.draw(); + } + if (typeof date === 'string') { + date = new Date(Date.parse(date)); + } + if (!isDate(date)) { + return; + } + + var min = this._o.minDate, + max = this._o.maxDate; + + if (isDate(min) && date < min) { + date = min; + } else if (isDate(max) && date > max) { + date = max; + } + + this._d = new Date(date.getTime()); + setToStartOfDay(this._d); + this.gotoDate(this._d); + + if (this._o.field) { + this._o.field.value = this.toString(); + fireEvent(this._o.field, 'change', {firedBy: this}); + } + if (!preventOnSelect && typeof this._o.onSelect === 'function') { + this._o.onSelect.call(this, this.getDate()); + } + }, + + /* Change view to a specific date */ + gotoDate: function (date) { + var newCalendar = true; + + if (!isDate(date)) { + return; + } + + if (this.calendars) { + var firstVisibleDate = new Date(this.calendars[0].year, this.calendars[0].month, 1), + lastVisibleDate = new Date(this.calendars[this.calendars.length - 1].year, this.calendars[this.calendars.length - 1].month, 1), + visibleDate = date.getTime(); + // get the end of the month + lastVisibleDate.setMonth(lastVisibleDate.getMonth() + 1); + lastVisibleDate.setDate(lastVisibleDate.getDate() - 1); + newCalendar = (visibleDate < firstVisibleDate.getTime() || lastVisibleDate.getTime() < visibleDate); + } + + if (newCalendar) { + this.calendars = [{ + month: date.getMonth(), + year: date.getFullYear() + }]; + if (this._o.mainCalendar === 'right') { + this.calendars[0].month += 1 - this._o.numberOfMonths; + } + } + + this.adjustCalendars(); + }, + + adjustCalendars: function () { + this.calendars[0] = adjustCalendar(this.calendars[0]); + for (var c = 1; c < this._o.numberOfMonths; c++) { + this.calendars[c] = adjustCalendar({ + month: this.calendars[0].month + c, + year: this.calendars[0].year + }); + } + this.draw(); + }, + + gotoToday: function () { + this.gotoDate(new Date()); + }, + + /* Change view to a specific month (zero-index, e.g. 0: January) */ + gotoMonth: function (month) { + if (!isNaN(month)) { + this.calendars[0].month = parseInt(month, 10); + this.adjustCalendars(); + } + }, + + nextMonth: function () { + this.calendars[0].month++; + this.adjustCalendars(); + }, + + prevMonth: function () { + this.calendars[0].month--; + this.adjustCalendars(); + }, + + /* Change view to a specific full year (e.g. "2012") */ + gotoYear: function (year) { + if (!isNaN(year)) { + this.calendars[0].year = parseInt(year, 10); + this.adjustCalendars(); + } + }, + + /* Change the minDate */ + setMinDate: function (value) { + this._o.minDate = value; + }, + + /* Change the maxDate */ + setMaxDate: function (value) { + this._o.maxDate = value; + }, + + /* Refresh the HTML */ + draw: function (force) { + if (!this._v && !force) { + return; + } + var opts = this._o, + minYear = opts.minYear, + maxYear = opts.maxYear, + minMonth = opts.minMonth, + maxMonth = opts.maxMonth, + html = ''; + + if (this._y <= minYear) { + this._y = minYear; + if (!isNaN(minMonth) && this._m < minMonth) { + this._m = minMonth; + } + } + if (this._y >= maxYear) { + this._y = maxYear; + if (!isNaN(maxMonth) && this._m > maxMonth) { + this._m = maxMonth; + } + } + + for (var c = 0; c < opts.numberOfMonths; c++) { + html += '
    ' + renderTitle(this, c, this.calendars[c].year, this.calendars[c].month, this.calendars[0].year) + this.render(this.calendars[c].year, this.calendars[c].month) + '
    '; + } + + this.el.innerHTML = html; + + if (opts.bound) { + if (opts.field.type !== 'hidden') { + sto(function () { + opts.trigger.focus(); + }, 1); + } + } + + if (typeof this._o.onDraw === 'function') { + var self = this; + sto(function () { + self._o.onDraw.call(self); + }, 0); + } + }, + + adjustPosition: function () { + if (this._o.container) return; + var field = this._o.trigger, pEl = field, + width = this.el.offsetWidth, height = this.el.offsetHeight, + viewportWidth = window.innerWidth || document.documentElement.clientWidth, + viewportHeight = window.innerHeight || document.documentElement.clientHeight, + scrollTop = window.pageYOffset || document.body.scrollTop || document.documentElement.scrollTop, + left, top, clientRect; + + if (typeof field.getBoundingClientRect === 'function') { + clientRect = field.getBoundingClientRect(); + left = clientRect.left + window.pageXOffset; + top = clientRect.bottom + window.pageYOffset; + } else { + left = pEl.offsetLeft; + top = pEl.offsetTop + pEl.offsetHeight; + while ((pEl = pEl.offsetParent)) { + left += pEl.offsetLeft; + top += pEl.offsetTop; + } + } + + /* Default position is bottom & left */ + if ((this._o.reposition && left + width > viewportWidth) || + ( + this._o.position.indexOf('right') > -1 && + left - width + field.offsetWidth > 0 + ) + ) { + left = left - width + field.offsetWidth; + } + if ((this._o.reposition && top + height > viewportHeight + scrollTop) || + ( + this._o.position.indexOf('top') > -1 && + top - height - field.offsetHeight > 0 + ) + ) { + top = top - height - field.offsetHeight; + } + + this.el.style.cssText = [ + 'position: absolute', + 'left: ' + left + 'px', + 'top: ' + top + 'px' + ].join(';'); + }, + + /* Render HTML for a particular month */ + render: function (year, month) { + var opts = this._o, + now = new Date(), + days = getDaysInMonth(year, month), + before = new Date(year, month, 1).getDay(), + data = [], + row = []; + setToStartOfDay(now); + if (opts.firstDay > 0) { + before -= opts.firstDay; + if (before < 0) { + before += 7; + } + } + var cells = days + before, + after = cells; + while (after > 7) { + after -= 7; + } + cells += 7 - after; + for (var i = 0, r = 0; i < cells; i++) { + var day = new Date(year, month, 1 + (i - before)), + isDisabled = (opts.minDate && day < opts.minDate) || (opts.maxDate && day > opts.maxDate), + isSelected = isDate(this._d) ? compareDates(day, this._d) : false, + isToday = compareDates(day, now), + isEmpty = i < before || i >= (days + before); + + row.push(renderDay(1 + (i - before), month, year, isSelected, isToday, isDisabled, isEmpty)); + + if (++r === 7) { + if (opts.showWeekNumber) { + row.unshift(renderWeek(i - before, month, year)); + } + data.push(renderRow(row, opts.isRTL)); + row = []; + r = 0; + } + } + return renderTable(opts, data); + }, + + isVisible: function () { + return this._v; + }, + + show: function () { + if (!this._v) { + removeClass(this.el, 'is-hidden'); + this._v = true; + this.draw(); + if (this._o.bound) { + addEvent(document, 'click', this._onClick); + this.adjustPosition(); + } + if (typeof this._o.onOpen === 'function') { + this._o.onOpen.call(this); + } + } + }, + + hide: function () { + var v = this._v; + if (v !== false) { + if (this._o.bound) { + removeEvent(document, 'click', this._onClick); + } + this.el.style.cssText = ''; + addClass(this.el, 'is-hidden'); + this._v = false; + if (v !== undefined && typeof this._o.onClose === 'function') { + this._o.onClose.call(this); + } + } + }, + + destroy: function () { + this.hide(); + removeEvent(this.el, 'mousedown', this._onMouseDown, true); + removeEvent(this.el, 'change', this._onChange); + if (this._o.field) { + removeEvent(this._o.field, 'change', this._onInputChange); + if (this._o.bound) { + removeEvent(this._o.trigger, 'click', this._onInputClick); + removeEvent(this._o.trigger, 'focus', this._onInputFocus); + removeEvent(this._o.trigger, 'blur', this._onInputBlur); + } + } + if (this.el.parentNode) { + this.el.parentNode.removeChild(this.el); + } + } + + }; + + return Pikaday; + +})); diff --git a/kurt-web/src/main/webapp/js/post_form.js b/kurt-web/src/main/webapp/js/post_form.js new file mode 100644 index 0000000..8bf9214 --- /dev/null +++ b/kurt-web/src/main/webapp/js/post_form.js @@ -0,0 +1,60 @@ +/** + * Tool for sending an AJAX request with a POST form. Be careful: the callback function called + * "ServerResponseForPostForm" should be defined in your page. + */ + +/* Declaration de l'objet HttpRequest global */ +var objPostRequest = null; + +/* Retourne la liste des éléments HTML composant un formulaire */ +function getFormData(id) { + var formEl = ''; + var LMR = ''; + var obF = document.getElementById(id); + var elements = obF.elements; + for (var i = 0; i < obF.length; i++) { + /* LMR is for R20 report */ + if (elements[i].name === 'LMR') { + if (elements[i].value == "") + continue; + if (LMR == '') { + LMR += elements[i].name + '=' + escape(elements[i].value); + } else { + LMR += ";" + escape(elements[i].value); + } + } else if (elements[i].name + "" != "") { + /* For check-boxes and radio button only take into account of checked values */ + if ((elements[i].type === 'radio') || (elements[i].type === 'checkbox')) { + if (!elements[i].checked) { + continue; + } + } + if (formEl != '') { + formEl += "&"; + } + formEl += elements[i].name + '=' + escape(elements[i].value); + } + } + if (LMR != '') { + formEl += "&" + LMR; + } + return formEl; +} + +/* Méthode d'envoi via POST d'un formulaire */ +function PostForm(url, form) { + /* Lecture des données du formulaire */ + var data = getFormData(form); + /* Détection du navigateur pour la création de l'objet XMLHttpRequest */ + if (window.XMLHttpRequest) + objPostRequest = new XMLHttpRequest(); + else if (window.ActiveXObject) + objPostRequest = new ActiveXObject("Microsoft.XMLHTTP"); + + /* Envoi du formulaire en AJAX */ + objPostRequest.open('post', url, true); + objPostRequest.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); + objPostRequest.setRequestHeader("Content-length", data.length); + objPostRequest.onreadystatechange = ServerResponseForPostForm; + objPostRequest.send(data); +} diff --git a/kurt-web/src/main/webapp/js/queue.js b/kurt-web/src/main/webapp/js/queue.js new file mode 100644 index 0000000..d6ed80e --- /dev/null +++ b/kurt-web/src/main/webapp/js/queue.js @@ -0,0 +1,83 @@ +/* Main table for all priorities */ +function DisplayTable() { + + var tableContent = ''; + + tableContent += '
    '; + tableContent += DisplayTableByPriority("Priorité haute", 1); + tableContent += ''; + + tableContent += DisplayTableByPriority("Priorité moyenne", 2); + tableContent += ''; + + tableContent += DisplayTableByPriority("Priorité basse", 3); + tableContent += ''; + + tableContent += DisplayTableByPriority("Différé", 0); + + tableContent += ''; + + tableContent += DisplayTableRunningReport("Planifié"); + tableContent += '
    '; + + document.write(tableContent); +} + +/* Sub table for each scheduling report */ +function DisplayTableRunningReport(name) { + var tableContent = getSubTableHeaderScheduling(name); + + /* Browse each report */ + var reportCount = schedulingReportArray.length; + for (var i = 0; i < reportCount; i++) { + var currentReport = schedulingReportArray[i]; + /* Display columns of the current report */ + tableContent += ''; + tableContent += '' + currentReport['reportCode'] + ''; + tableContent += '' + currentReport['name'] + ''; + tableContent += ''; + } + tableContent += ''; + return tableContent; +} + +function getSubTableHeaderScheduling(aPriorityName) { + var content = '
    ' + + aPriorityName + '
    '; + content += ''; + return content; +} + +/* Sub table for each priority */ +function DisplayTableByPriority(aPriorityName, aPriority) { + var tableContent = getSubTableHeader(aPriorityName); + + // Browse each report + var reportCount = reportArray.length; + for (var i = 0; i < reportCount; i++) { + var currentReport = reportArray[i]; + if (aPriority == '0') { + // Special case of deferred + if (currentReport['state'] != 'WAIT') { + continue; + } + } else if (currentReport['priority'] != aPriority) { + // Check priority value compliance + continue; + } + // Display columns of the current report + tableContent += ''; + tableContent += ''; + tableContent += ''; + tableContent += ''; + } + tableContent += '
    RapportNom planification
    ' + currentReport['reportCode'] + '' + currentReport['login'] + '
    '; + return tableContent; +} + +function getSubTableHeader(aPriorityName) { + var content = '
    ' + + aPriorityName + '
    '; + content += ''; + return content; +} \ No newline at end of file diff --git a/kurt-web/src/main/webapp/js/running_reports.js b/kurt-web/src/main/webapp/js/running_reports.js new file mode 100644 index 0000000..1cb00ba --- /dev/null +++ b/kurt-web/src/main/webapp/js/running_reports.js @@ -0,0 +1,49 @@ +function DisplayTable() { + var tableContent = ''; + // Browse each report + var reportCount = reportArray.length; + for (var i = 0; i < reportCount; i++) { + var currentReport = reportArray[i]; + + // Prepare error column content + var currentError = currentReport['errorMessage']; + if (currentError != '') { + currentError = ''; + } + + // Prepare status column content + var currentStatus = currentReport['state']; + if (currentStatus != '') { + currentStatus = ''; + } + + // Report priority + var priority = "Inconnue"; + if (currentReport['priority'] === '1') { + priority = "Haute"; + } else if (currentReport['priority'] === '2') { + priority = "Moyenne"; + } else if (currentReport['priority'] === '3') { + priority = "Basse"; + } + + /* Display columns of the current report */ + tableContent += ''; + tableContent += ''; + tableContent += ''; + tableContent += ''; + tableContent += ''; + tableContent += ''; + tableContent += ''; + tableContent += ''; + tableContent += ''; + } + + document.write(tableContent); +} diff --git a/kurt-web/src/main/webapp/js/schedulingReport.js b/kurt-web/src/main/webapp/js/schedulingReport.js new file mode 100644 index 0000000..37176f4 --- /dev/null +++ b/kurt-web/src/main/webapp/js/schedulingReport.js @@ -0,0 +1,412 @@ +function DisplayTable() { + var tableContent = ''; + // Browse each report + var reportCount = reportArray.length; + + for (var i = 0; i < reportCount; i++) { + var currentReport = reportArray[i]; + + // Display columns of the current report + tableContent += '\n'; + tableContent += ' \n'; + tableContent += ' \n'; + tableContent += ' \n'; + tableContent += ' \n'; + tableContent += ' \n'; + tableContent += ' \n'; + // begin columns containing the buttons + // ->infos (magnifying glass) + tableContent += ' \n'; + + // ->update planification page + tableContent += ' \n'; + + // ->delete current planification + tableContent += ' \n'; + + tableContent += ''; + } + + document.write(tableContent); +} + +/* Redirect to page */ +function GoSchedulingPage(i, j) { + document.location.href = '/kurt-web/schedulingReader?page=' + i + "&reportCode=" + j; +} + +/* build select active or not active report */ +function displaySelectActivateDesactivateReport() { + if ('TOUS' === activeReportCode) { + document.getElementById('authorizedLabel').style.visibility = "hidden"; + document.getElementById('authorizedTd').style.visibility = "hidden"; + } else { + document.getElementById('authorizedLabel').style.visibility = "visible"; + document.getElementById('authorizedTd').style.visibility = "visible"; + var selectContentIsActiveReport = ''; + document.write(selectContentIsActiveReport); + } +} + +/* Redirect to page 1 */ +function getReport(i) { + document.location.href = '/kurt-web/schedulingReader?reportCode=' + i; +} + +/* get current value on select */ +function getSelectedValue(idElem) { + var e = document.getElementById(idElem); + var strUser = e.options[e.selectedIndex].value; + return strUser; +} + +/* persistence on select activate or enabled scheduling report */ +function saveAction() { + var curReportCode = "reportCode=" + activeReportCode; + var valueOfSelect = "reportAuthorized=" + getSelectedValue("selectEnableDisable"); + var data = curReportCode + "&" + valueOfSelect; + + // Detection du navigateur pour la creation de l'objet XMLHttpRequest + if (window.XMLHttpRequest) { + objPostRequest = new XMLHttpRequest(); + } else if (window.ActiveXObject) { + objPostRequest = new ActiveXObject("Microsoft.XMLHTTP"); + } + + // Envoi du formulaire en AJAX + objPostRequest.open('post', "/kurt-web/activateDeactivate", true); + objPostRequest.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); + objPostRequest.send(data); + objPostRequest.onreadystatechange = ServerResponseForSaveActionConfirmation; +} + +/* Popup after click button save to enabled or disabled report */ +function ServerResponseForSaveActionConfirmation() { + if (objPostRequest.readyState === 4) { + if (objPostRequest.status === 200) { + var queryResponse = JSON.parse(objPostRequest.responseText); + if (queryResponse.status === "success") { + parent.Dialog("Confirmation", queryResponse.success); + } else { + parent.Dialog("Erreur", queryResponse.error); + } + } + } +} + +/* */ +function refreshSchedulingPage(i) { + parent.hideDialog(); + top.frames['subFrame'].location.href = '/kurt-web/schedulingReader?reportCode=' + i; +} + +/* Hidden or show button new when user select value "TOUS" */ +function showHideButtonNewPlanification() { + var selectBox = document.getElementById("selectReportType"); + var selectedValue = selectBox.options[selectBox.selectedIndex].value; + getReport(selectedValue); +} + +function updateSchedulingReport(id, reportCode) { + return callSchedulingReport("update", id, reportCode); +} + +function newSchedulingReport() { + return callSchedulingReport("create", "", ""); +} + +function callSchedulingReport(status, id, reportCode) { + + var reportCodeActive = ""; + // reportCode = reportCode.replace("R", ""); + reportCodeActive = activeReportCode.replace("R", ""); + if (status === "create") { + var theReportCode = activeReportCode; + document.location.href = '/kurt-web/frames/scheduling_new.jsp?activeSchedulingList=' + reportCodeActive + + '&reportCode=' + theReportCode; + } else { + document.location.href = '/kurt-web/frames/scheduling_update.jsp?activeSchedulingList=' + reportCodeActive + + '&id=' + id + '&reportCode=' + reportCode; + } +} + +function getSubPeriod(name, id, isActive) { + // Detection du navigateur pour la creation de l'objet XMLHttpRequest + if (window.XMLHttpRequest) { + objPostRequest = new XMLHttpRequest(); + } else if (window.ActiveXObject) { + objPostRequest = new ActiveXObject("Microsoft.XMLHTTP"); + } + var concat = "&"; + var subPeriodData = 'subPeriod=' + encodeURIComponent(name); + var isUpdate = 'isUpdate=' + encodeURIComponent(isActive); + var idData = 'id=' + encodeURIComponent(id); + + // Envoi du formulaire en AJAX + objPostRequest.open('post', "/kurt-web/getScheduling", true); + objPostRequest.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); + objPostRequest.send(subPeriodData + concat + isUpdate + concat + idData); + objPostRequest.onreadystatechange = ServerResponseForGetSubPeriod; +} + +function createDiv(content) { + + var container = document.createElement('div'); + container.id = "div_temp"; + container.innerHTML = content; + + return container; +} + +// div_container_sub_period +function ServerResponseForGetSubPeriod() { + if (objPostRequest.readyState == 4) { + if (objPostRequest.status == 200) { + var queryResponse = JSON.parse(objPostRequest.responseText); + + var containerSubPeriod = document.getElementById("div_container_subPeriod"); + containerSubPeriod.innerHTML = ""; + + if (queryResponse.status == "success") { + containerSubPeriod.innerHTML = queryResponse.content; + initPicker('datepicker_planification', 'container_planification'); + } else { + containerSubPeriod.innerHTML = "Oh oh ......"; // FIXME + } + } else if (objPostRequest.status === 500) { + document.getElementById("div_container_subPeriod").innerHTML = "Erreur interne du serveur détectée. "; + + } else { + document.getElementById("div_container_subPeriod").innerHTML = "La connexion avec le site semble interrompue."; + + } + + } +} + +// Methode d'envoi via POST d'un formulaire +function deleteCommand(schedulingReportId) { + // active progress bar + showProgressBarOnDelete(); + // Detection du navigateur pour la creation de l'objet XMLHttpRequest + if (window.XMLHttpRequest) + objPostRequest = new XMLHttpRequest(); + else if (window.ActiveXObject) + objPostRequest = new ActiveXObject("Microsoft.XMLHTTP"); + var data = 'scheduling_report_id=' + encodeURIComponent(schedulingReportId); + // Envoi du formulaire en AJAX + objPostRequest.open('post', "/kurt-web/scheduling/delete", true); + objPostRequest.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); + objPostRequest.send(data); + objPostRequest.onreadystatechange = ServerResponseForDeleteCommand; +} + +/* Callback on delete */ +function ServerResponseForDeleteCommand() { + if (objPostRequest.readyState == 4) { + if (objPostRequest.status == 200) { + var queryResponse = JSON.parse(objPostRequest.responseText); + document.getElementById("div_message").innerHTML = ""; + if (queryResponse.status == "success") { + document.getElementById("div_message").innerHTML = queryResponse.success; + } else { + document.getElementById("div_message").innerHTML = queryResponse.failed; + } + // add button to close popup + document.getElementById("div_buttons").innerHTML = ""; + document.getElementById("div_buttons").innerHTML = addButtonClose(); + } else { + document.getElementById("div_message").innerHTML = "Erreur interne du serveur détectée. "; + document.getElementById("div_buttons").innerHTML = ""; + document.getElementById("div_buttons").innerHTML = addButtonClose(); + } + } +} + +/* Use on delete */ +function showProgressBarOnDelete() { + document.getElementById("div_message").innerHTML = progressBar(); + document.getElementById("div_buttons").innerHTML = ""; +} + +/* Build a progress bar */ +function progressBar() { + return "Traitement en cours..." + "
    " + + ""; +} + +/* build a close button */ +function addButtonClose() { + return ""; +} + +/* */ +function sendSchedulingReport(targetUrl, optionalParameters) { + /* call check of current report and call check of scheduling */ + + var isFormOK = checkForm(); + var isSchedulingOK = checkParamScheduling(); + if (isFormOK && isSchedulingOK) { + // PostForm(targetUrl,"reportSchedulingForm"); + /* Display loading bar and hide buttons */ + document.getElementById("loading").style.display = ''; + document.getElementById("div_buttons").style.display = 'none'; + postScheduling(targetUrl, "reportSchedulingForm", optionalParameters); + } + +} + +function postScheduling(url, form, optionalParameters) { + /* Lecure des donnees du formulaire */ + var data = getFormData(form); + data += optionalParameters; + /* Detection du navigateur pour la creation de l'objet XMLHttpRequest */ + if (window.XMLHttpRequest) { + objPostRequest = new XMLHttpRequest(); + } else if (window.ActiveXObject) { + objPostRequest = new ActiveXObject("Microsoft.XMLHTTP"); + } + + /* Envoi du formulaire en AJAX */ + objPostRequest.open('post', url, true); + objPostRequest.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); + // objPostRequest.setRequestHeader("Content-length", data.length); // Unsafe! + objPostRequest.onreadystatechange = serverResponseForPostScheduling; + objPostRequest.send(data); +} + +function serverResponseForPostScheduling() { + if (objPostRequest.readyState == 4) { + if (objPostRequest.status == 200) { + var queryResponse = JSON.parse(objPostRequest.responseText); + if (queryResponse.status == "success") { + parent.Dialog("Confirmation", queryResponse.success); + } else { + parent.Dialog("Erreur", queryResponse.error); + } + } else if (objPostRequest.status == 500) { + parent.Dialog("Erreur", "Erreur interne du serveur détectée."); + } else { + parent.Dialog("Erreur", "La connexion avec le site semble interrompue."); + } + // Display buttons and hide loading bar + document.getElementById("loading").style.display = 'none'; + document.getElementById("div_buttons").style.display = ''; + } +} + +/* check input button text of radio_all_month_day */ +function checkIsValidDay() { + return isValidDay("dayInMonthValue"); +} + +/* check input in field day in month */ +function isValidDay(inputText) { + var element = document.getElementById(inputText); + var isGood = true; + if (isNaN(element.value) || element.value == "" || element.value < 1 || element.value > 31) { + isGood = false; + } + return isGood; +} + +/* Check fields of planification */ +function checkParamScheduling() { + var maxCharacter = 40; + if (!checkMaxLenghtOnInputText("scheduling_name", maxCharacter)) { + parent.Dialog("Erreur", "Le champ Nom ne peut pas contenir plus de " + maxCharacter + " caractères."); + return false; + } + if (!checkInputAlphanumeric("scheduling_name")) { + parent.Dialog("Erreur", "Le champ Nom ne peut contenir que des caractères alphanumériques."); + return false; + } + /* Filed may not be empty */ + if (isEmptyFieldMaybeMandatory("scheduling_name", false)) { + document.getElementById("scheduling_name").focus(); + parent.Dialog("Erreur", "Saisir un nom pour la planification."); + return false; + } + if (!checkInputRadioDayOfMonth()) { + document.getElementById("scheduling_name").focus(); + parent + .Dialog("Erreur", + "Vous avez choisi une planification par mois, le champ ne doit pas etre vide ou comporter un jour entre 1 et 31."); + return false; + } + if (!checkInputRadioByDate()) { + document.getElementById("scheduling_name").focus(); + parent.Dialog("Erreur", "Vous avez choisi une planification par date, le champ ne doit pas etre vide."); + return false; + } + return true; +} + +/* Check by month */ +function checkInputRadioDayOfMonth() { + var returnValue = true; + if ((document.getElementById('div_period_monthly').checked) && (document.getElementById('dayInMonthValue').checked)) { // A + // day + // in + // month + // is + // selected + // --> field day in month may not be empty and between 1-31 day of month + returnValue = checkIsValidDay(); + } + return returnValue; +} + +/* Check by date */ +function checkInputRadioByDate() { + var returnValue = true; + // radio date + if (document.getElementById('div_period_date').checked) { + if (document.getElementById('datepicker_planification').value === "") { + returnValue = false; + } + } + return returnValue; +} + +/* Check max length on input text */ +function checkMaxLenghtOnInputText(idOfInput, max) { + var element = document.getElementById(idOfInput); + var returnValue = true; + if (element.value.length > max) { + returnValue = false; + } + return returnValue; +} + +/* Regex Authorized -> alaphanumeric[a-zA-Z0-9_], -, éèçà, whitespace and start min:0 to max:40 car */ +function checkInputAlphanumeric(idOfInput) { + var text = document.getElementById(idOfInput).value; + // var check = new RegExp("^([a-zA-Z0-9_-\\s]{0,40})$", "g"); + var check = /^([\w- éèçà]{0,40})$/; + return check.test(text); +} diff --git a/kurt-web/src/main/webapp/js/schedulingReportsCreaUpd.js b/kurt-web/src/main/webapp/js/schedulingReportsCreaUpd.js new file mode 100644 index 0000000..32fe7c9 --- /dev/null +++ b/kurt-web/src/main/webapp/js/schedulingReportsCreaUpd.js @@ -0,0 +1,42 @@ +/////////////----------SCRIPT NEW/UPDATE PLANIFICATION REPORT + +/* cleaning input text day in month */ +function cleaningFieldDayInMonth(isCleaning) { + if (isCleaning == "true") { + document.getElementById("dayInMonthValue").value = ""; + } +} + +/* use if when define period */ +function showSubPeriod(valueOfPeriod) { + showElements(valueOfPeriod); +} + +/* Active or not boc depend value */ +function showElements(myValue) { + + if (myValue === "daily") { + // on fait rien + document.getElementById("bloc_weekly").style.display = "none"; + document.getElementById("bloc_monthly").style.display = "none"; + document.getElementById("bloc_by_date").style.display = "none"; + } else if (myValue === "weekly") { + // active div bloc_weekly + document.getElementById("bloc_weekly").style.display = ""; + document.getElementById("bloc_monthly").style.display = "none"; + document.getElementById("bloc_by_date").style.display = "none"; + + } else if (myValue === "monthly") { + // active bloc_monthly + document.getElementById("bloc_monthly").style.display = ""; + document.getElementById("bloc_weekly").style.display = "none"; + document.getElementById("bloc_by_date").style.display = "none"; + + } else if (myValue === "date") { + // active bloc_by_date + document.getElementById("bloc_by_date").style.display = ""; + /* document.getElementById("bloc_by_date").style.visibility="visible"; */ + document.getElementById("bloc_weekly").style.display = "none"; + document.getElementById("bloc_monthly").style.display = "none"; + } +} diff --git a/kurt-web/src/main/webapp/js/statistics.js b/kurt-web/src/main/webapp/js/statistics.js new file mode 100644 index 0000000..3c8b2ce --- /dev/null +++ b/kurt-web/src/main/webapp/js/statistics.js @@ -0,0 +1,109 @@ +/* First table displaying statistics per report */ +function DisplayTablePerReport() { + var tableContent = ''; + // Browse each report + var reportCount = reportStatArray.length; + for (var i = 0; i < reportCount; i++) { // Display columns of the current report + var currentReport = reportStatArray[i]; + // Color first line for a new month + if (isColorLine(i)) { + tableContent += ''; + } else { + tableContent += ''; + } + + tableContent += ''; + tableContent += ''; + tableContent += ''; + tableContent += ''; + tableContent += ''; + tableContent += ''; + tableContent += ''; + tableContent += ''; + } + document.write(tableContent); +} + +// Every [nbReports] line, return true/ Warning, [nbReports] must exist as a global js variable +function isColorLine(i) { + if (i == 0) { + return false; + } else { + return i % nbReports === 0 + } +} + +/* Second table displaying statistics per user */ +function DisplayTablePerUser() { + var tableContent = ''; + // Browse each report + var reportUserCount = userStatArray.length; + for (var i = 0; i < reportUserCount; i++) { + var stat = userStatArray[i]; + tableContent += ''; + tableContent += ''; + tableContent += ''; + tableContent += ''; + tableContent += ''; + tableContent += ''; + tableContent += ''; + tableContent += ''; + tableContent += ''; + tableContent += ''; + tableContent += ''; + tableContent += ''; + tableContent += ''; + tableContent += ''; + tableContent += ''; + tableContent += ''; + tableContent += ''; + tableContent += ''; + tableContent += ''; + tableContent += ''; + tableContent += ''; + tableContent += ''; + tableContent += ''; + tableContent += ''; + tableContent += ''; + tableContent += ''; + tableContent += ''; + } + document.write(tableContent); +} + +function downloadTable(tableNum) { + var startPeriod = document.getElementById("startPeriod").value; + var endPeriod = document.getElementById("endPeriod").value; + var url = "/kurt-web/downloadStats" + tableNum + "?startPeriod=" + startPeriod + "&endPeriod=" + endPeriod; + window.open(url); +} + +/* Callback method after AJAX request */ +function ServerResponseForPostForm() { + if (objPostRequest.readyState === 4) { + if (objPostRequest.status === 200) { + parent.Dialog("Success", "Fichier généré"); + } else if (objPostRequest.status === 500) { + parent.Dialog("Erreur", "Erreur interne du serveur détectée."); + } else { + parent.Dialog("Erreur", "La connexion avec le site semble interrompue."); + } + } +} + +/* Extract the value of a GET parameter set in the URL */ +function parseURL(val, defaultVal) { + var result = defaultVal; + var urlParam = window.location.search; + if (urlParam != '') { + paramArray = urlParam.substr(1).split("&"); + for (var i = 0; i < paramArray.length; i++) { + var tmpArray = paramArray[i].split("="); + if ((tmpArray.length === 2) && (tmpArray[0] === val)) { + result = decodeURIComponent(tmpArray[1]); + break; + } + } + } + return result; +} \ No newline at end of file diff --git a/kurt-web/src/test/java/com/capgemini/reports/common/AbstractKurtServletTest.java b/kurt-web/src/test/java/com/capgemini/reports/common/AbstractKurtServletTest.java new file mode 100644 index 0000000..2c29652 --- /dev/null +++ b/kurt-web/src/test/java/com/capgemini/reports/common/AbstractKurtServletTest.java @@ -0,0 +1,178 @@ +package com.capgemini.reports.common; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.reports.exceptions.InvalidUserInputException; +import com.capgemini.reports.exceptions.UserInputErrorEnum; +import lombok.extern.slf4j.Slf4j; +import org.json.JSONObject; +import org.junit.Assert; +import org.junit.Test; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; + +import javax.jms.JMSException; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; + +/** JUnit test. **/ +@Slf4j +public class AbstractKurtServletTest { + + private static final String STATUS_TOKEN = "status"; + private static final String STATUS_SUCCESS = "success"; + private static final String STATUS_FAILED = "failed"; + + private static final String SUCCESS_TOKEN = "success"; + private static final String SUCCESS_MESSAGE = "Success message"; + + private static final String FAILURE_TOKEN = "error"; + private static final String FAILURE_MESSAGE = "Expected Generic Failure message"; + + private static final UserInputErrorEnum EXPECTED_BAD_SERVLET_ERROR = UserInputErrorEnum.INCORRECT_PRODUCT; + + /** JUnit test. **/ + @Test + public void testSuccessMessage() { + JSONObject json = ServletMessageHelper.successMessage(SUCCESS_MESSAGE); + Assert.assertEquals(STATUS_SUCCESS, json.get(STATUS_TOKEN)); + Assert.assertEquals(SUCCESS_MESSAGE, json.getString(SUCCESS_TOKEN)); + } + + /** JUnit test. **/ + @Test + public void testErrorMessage1() { + JSONObject json = ServletMessageHelper.errorMessage(FAILURE_MESSAGE); + Assert.assertEquals(STATUS_FAILED, json.get(STATUS_TOKEN)); + Assert.assertEquals(FAILURE_MESSAGE, json.getString(FAILURE_TOKEN)); + } + + /** JUnit test. **/ + @Test + public void testErrorMessage2() { + JSONObject json = ServletMessageHelper.errorMessage(new KurtException(FAILURE_MESSAGE)); + Assert.assertEquals(STATUS_FAILED, json.get(STATUS_TOKEN)); + Assert.assertEquals(FAILURE_MESSAGE, json.getString(FAILURE_TOKEN)); + } + + /** JUnit test. **/ + @Test + public void testErrorMessage3() { + UserInputErrorEnum expectedError = UserInputErrorEnum.PRODUCT_DOES_NOT_EXIST_NO_DATA_TO_PRINT; + JSONObject json = ServletMessageHelper.errorMessage(new InvalidUserInputException(expectedError)); + Assert.assertEquals(STATUS_FAILED, json.get(STATUS_TOKEN)); + Assert.assertEquals(expectedError.getMsgFr(), json.getString(FAILURE_TOKEN)); + } + + /** + * JUnit test. + * + * @throws ServletException should not happen + * @throws IOException should not happen + **/ + @Test + public void testDoPostSuccess() throws ServletException, IOException { + // Test the servlet + JSONObject responseJson = testSomeServlet(new SomeGoodServlet()); + + // Parse the contents + String resultStr = responseJson.getString(ServletMessageHelper.TOKEN_STATUS); + log.info("Json object received with status = \"" + resultStr + "\""); + Assert.assertEquals(ServletMessageHelper.STATUS_SUCCESS, resultStr); + Assert.assertEquals(SUCCESS_MESSAGE, responseJson.get(ServletMessageHelper.STATUS_SUCCESS)); + } + + /** + * JUnit test. + * + * @throws ServletException should not happen + * @throws IOException should not happen + **/ + @Test + public void testDoPostKurtFailure() throws ServletException, IOException { + // Test the servlet + JSONObject responseJson = testSomeServlet(new SomeBadServletWithBadJMScommunication()); + + // Parse the contents + String resultStr = responseJson.getString(ServletMessageHelper.TOKEN_STATUS); + log.info("Json object received with status = \"" + resultStr + "\""); + Assert.assertEquals(ServletMessageHelper.STATUS_FAILED, resultStr); + Assert.assertEquals(ServletMessageHelper.POSTING_ERROR_MESSAGE_FR, responseJson.get(ServletMessageHelper.TOKEN_ERROR)); + } + + /** + * JUnit test. + * + * @throws ServletException should not happen + * @throws IOException should not happen + **/ + @Test + public void testDoPostServletFailure() throws ServletException, IOException { + // Test the servlet + JSONObject responseJson = testSomeServlet(new SomeBadServletWithNiceExeption()); + + // Parse the contents + String resultStr = responseJson.getString(ServletMessageHelper.TOKEN_STATUS); + log.info("Json object received with status = \"" + resultStr + "\""); + Assert.assertEquals(ServletMessageHelper.STATUS_FAILED, resultStr); + Assert.assertEquals(EXPECTED_BAD_SERVLET_ERROR.getMsgFr(), responseJson.get(ServletMessageHelper.TOKEN_ERROR)); + } + + /** + * JUnit test. + * + * @param testerServlet should not happen + * @return JSON object should not happen + * @throws ServletException should not happen + * @throws IOException should not happen + **/ + public JSONObject testSomeServlet(final AbstractKurtServlet testerServlet) throws ServletException, IOException { + + // Setup request and responses + MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletResponse response = new MockHttpServletResponse(); + log.info("Request and Response ready"); + + // Create Servlet instance and test it + testerServlet.doPost(request, response); + log.info("doPost() Done"); + + // Obtain response content + String responseStr = response.getContentAsString(); + log.info("Raw response = \"" + responseStr + "\""); + + // Obtain response status + return new JSONObject(responseStr); + } + + /** Servlet sample for test purpose. **/ + public class SomeGoodServlet extends AbstractKurtServlet { + private static final long serialVersionUID = 8779144588360308332L; + + @Override + protected JSONObject perform(final HttpServletRequest request, final TcSession session) { + return ServletMessageHelper.successMessage(SUCCESS_MESSAGE); + } + } + + /** Servlet sample for test purpose. **/ + private class SomeBadServletWithBadJMScommunication extends AbstractKurtServlet { + private static final long serialVersionUID = 7423523975629997878L; + + @Override + protected JSONObject perform(final HttpServletRequest request, final TcSession session) throws JMSException { + throw new JMSException(FAILURE_MESSAGE); + } + } + + private class SomeBadServletWithNiceExeption extends AbstractKurtServlet { + private static final long serialVersionUID = 7423523975629997878L; + + @Override + protected JSONObject perform(final HttpServletRequest request, final TcSession session) throws InvalidUserInputException { + throw new InvalidUserInputException(UserInputErrorEnum.INCORRECT_PRODUCT); + } + } + +} diff --git a/kurt-web/src/test/java/com/capgemini/reports/common/AbstractSubmitServletTest.java b/kurt-web/src/test/java/com/capgemini/reports/common/AbstractSubmitServletTest.java new file mode 100644 index 0000000..0c1b680 --- /dev/null +++ b/kurt-web/src/test/java/com/capgemini/reports/common/AbstractSubmitServletTest.java @@ -0,0 +1,368 @@ +package com.capgemini.reports.common; + +import com.capgemini.framework.common.MailHelper; +import com.capgemini.framework.common.SettingsHelper; +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.exceptions.NoTeamcenterConnectionException; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.reports.ReportEnum; +import com.capgemini.reports.ReportLaunchTypeEnum; +import com.capgemini.reports.builder.ReportBuilder; +import com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum; +import com.capgemini.reports.database.manager.MngCriteriaVal.CriteriaValue; +import com.capgemini.reports.exceptions.InvalidInputException; +import com.capgemini.reports.exceptions.InvalidUserInputException; +import com.capgemini.reports.exceptions.UserInputErrorEnum; +import com.capgemini.reports.execution.AbstractExecutionReport; +import com.capgemini.reports.execution.IDataReportPreparator; +import com.capgemini.reports.execution.mapconstructor.AbstractStaticTemplateMapConstructor; +import com.capgemini.reports.execution.mapconstructor.IMapConstructor; +import com.capgemini.reports.execution.strategies.IExecutionStrategy; +import com.capgemini.reports.printing.PrintParameters; +import com.capgemini.reports.printing.Printer.PrintFormat; +import com.capgemini.reports.queuing.ReportPriority; +import com.capgemini.reports.reports.parameters.IChecker; +import com.teamcenter.schemas.soa._2006_03.exceptions.ServiceException; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import net.lingala.zip4j.exception.ZipException; +import org.json.JSONObject; +import org.junit.Assert; +import org.junit.Test; +import org.quartz.SchedulerException; +import org.springframework.mock.web.MockHttpServletRequest; + +import javax.jms.JMSException; +import javax.naming.NamingException; +import javax.servlet.http.HttpServletRequest; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.regex.Pattern; + +/** JUnit test. **/ +@Slf4j +public class AbstractSubmitServletTest { + + private static final String FAKE_REPORT = "FAKE_REPORT"; + private static final ReportPriority EXPECTED_REPORT_PRIORITY = ReportPriority.HIGH_PRIORITY; + private static final PolicyLocation XML_POLICY = PolicyLocation.make("test_policy", "/xml/policies/test_policy.xml"); + /** A non-space string of chars, followed by '@', followed by a non-space string of chars, followed by a dot ('.'), followed by a non-space string of chars. */ + private static final Pattern EMAIL_ADDRESS_REGEX = Pattern.compile("\\S+@\\S+\\.\\S+"); + + /** + * JUnit test. All tests must pass, the report should be submitted and an email sent to the user. + * + * @throws InvalidInputException Should not happen + * @throws JMSException Should not happen + * @throws ServiceException Should not happen + * @throws NamingException Should not happen + * @throws SchedulerException Should not happen + **/ + @Test + public void testPerformSuccess() throws InvalidInputException, JMSException, ServiceException, NamingException, SchedulerException, NoTeamcenterConnectionException { + // Create Servlet instance + log.info("Create Servlet instance"); + SomeGoodParameter quickCheck = new SomeGoodParameter(); + SomeGoodParameter longCheck = new SomeGoodParameter(); + SomeExecutionReport goodReport = new SomeExecutionReport(quickCheck, longCheck, new SomeDataPreparator(), new SomeMapConstructor()); + SomeSubmitServlet testerServlet = new SomeSubmitServlet(goodReport); + + // Execute servlet POST operation + log.info("Execute Good servlet POST operation"); + JSONObject json = testPerform(testerServlet); + + // Verify Report TcReleaseStatus : posted, start email sent, but not executed + log.info("Verify Report TcReleaseStatus : params checked, report posted, start email sent, but not executed"); + Assert.assertTrue(quickCheck.isChecked); + // TODO (Long Checks not yet activated) Assert.assertTrue(longCheck.isChecked); + Assert.assertNotNull(testerServlet.theReport); + Assert.assertFalse(testerServlet.theReport.isParametersCheckFailureEmailDone); + Assert.assertTrue(testerServlet.theReport.isStartEmailDone); + Assert.assertFalse(testerServlet.theReport.isPrepareDataDone()); + Assert.assertFalse(testerServlet.theReport.isEndEmailDone); + Assert.assertFalse(testerServlet.theReport.isErrorEmailDone); + Assert.assertEquals(EXPECTED_REPORT_PRIORITY, goodReport.getPriorityCode()); + + // Verify JSON (should be success) + log.info("Verify HttpServletResponse to the server (should be success)"); + log.info("raw JSON : " + json); + Assert.assertEquals(ServletMessageHelper.STATUS_SUCCESS, json.get(ServletMessageHelper.TOKEN_STATUS)); + log.info(json.get(ServletMessageHelper.STATUS_SUCCESS).toString()); + } + + /** + * JUnit test. Report check must fail. Report should not be submitted, an explanation should be sent to the user. + * + * @throws JMSException Should not happen + * @throws ServiceException Should not happen + * @throws NamingException Should not happen + * @throws SchedulerException Should not happen + **/ + @Test + public void testPerformServletEarlyFail() throws JMSException, ServiceException, NamingException, SchedulerException, NoTeamcenterConnectionException { + // Create Servlet instance + log.info("Create Servlet instance"); + SomeFailingParameter quickCheck = new SomeFailingParameter(); + SomeGoodParameter longCheck = new SomeGoodParameter(); + SomeExecutionReport badReport = new SomeExecutionReport(quickCheck, longCheck, new SomeDataPreparator(), new SomeMapConstructor()); + SomeSubmitServlet testerServlet = new SomeSubmitServlet(badReport); + + // Execute servlet POST operation + log.info("Execute Bad servlet POST operation"); + try { + testPerform(testerServlet); + } catch (InvalidInputException e) { + // Verify Report TcReleaseStatus : NOT posted, no eMail sent, report not executed + log.info("Verify Report TcReleaseStatus : NOT posted, no eMail sent, report not executed"); + Assert.assertNotNull(testerServlet.theReport); + Assert.assertFalse(testerServlet.theReport.isParametersCheckFailureEmailDone); + Assert.assertFalse(testerServlet.theReport.isStartEmailDone); + Assert.assertFalse(testerServlet.theReport.isPrepareDataDone()); + Assert.assertFalse(testerServlet.theReport.isEndEmailDone); + log.info("Test successful", e); + return; + } + log.info("Test failed!"); + Assert.fail(); + } + + /** + * JUnit test. Report check must fail. Report should not be submitted, an explanation should be sent to the user. + * + * @throws JMSException Should not happen + * @throws InvalidInputException Should not happen + **/ + @Test + public void testPerformServletLateFail() throws JMSException, InvalidInputException { + /* + // Create Servlet instance + log.info("Create Servlet instance"); + SomeGoodParameter quickCheck = new SomeGoodParameter(); + SomeFailingParameter longCheck = new SomeFailingParameter(); + SomeExecutionReport badReport = new SomeExecutionReport(quickCheck, longCheck); + SomeSubmitServlet testerServlet = new SomeSubmitServlet(badReport); + SomeMessagingServer messagingServer = new SomeMessagingServer(); + + // Execute servlet POST operation + log.info("Execute Good servlet POST operation"); + JSONObject json = testPerform(testerServlet, messagingServer); + + // Verify Report TcReleaseStatus : NOT posted, error eMail sent, report not executed + log.info("Verify Report TcReleaseStatus : NOT posted, Error eMail sent, report not executed"); + Assert.assertFalse(messagingServer.reportPosted); + Assert.assertNotNull(testerServlet.theReport); + Assert.assertTrue(quickCheck.isChecked); + Assert.assertTrue(testerServlet.theReport.isParametersCheckFailureEmailDone); + Assert.assertFalse(testerServlet.theReport.isStartEmailDone); + Assert.assertFalse(testerServlet.theReport.isPrepareDataDone); + Assert.assertFalse(testerServlet.theReport.isConstructDataMapsDone); + Assert.assertFalse(testerServlet.theReport.isEndEmailDone); + + // Verify HttpServletResponse (should be failed) + log.info("Verify HttpServletResponse to the server (should be failed, internal error)"); + Assert.assertEquals(AbstractSubmitServlet.SUCCESS, json.findAll(AbstractSubmitServlet.STATUS)); + Assert.assertEquals("BOM assemblage PU successfully posted in the queues", json.findAll(AbstractSubmitServlet.SUCCESS)); + log.info("Test successful");*/ + } + + private JSONObject testPerform(final AbstractSubmitServlet servlet) + throws InvalidInputException, JMSException, ServiceException, NamingException, SchedulerException, NoTeamcenterConnectionException { + // Setup request and responses + log.info("testPerform(): Setup request and responses"); + HttpServletRequest request = new MockHttpServletRequest(); + + // Execute servlet POST operation + log.info("Execute Good servlet POST operation"); + try (final TcSession session = new FakeTcSession()) { + // Return the servlet response for further checks + return servlet.perform(request, session); + } + } + + + @Test + public void getDefaultEmailDestinatorsTest() { + log.info("Input: '" + SettingsHelper.getDefaultDestinatorEmail()); + List defaults = MailHelper.DEFAULT_DESTINATORS; + Assert.assertFalse(defaults.isEmpty()); + for (String user : defaults) { + log.info("'" + user + "'"); + Assert.assertTrue(EMAIL_ADDRESS_REGEX.matcher(user).matches()); + } + } + + /** A placeholder implementation of SubmitServlet for testing. */ + @Getter + private class SomeSubmitServlet extends AbstractSubmitServlet { + private static final long serialVersionUID = 8030290777260376309L; + private final SomeExecutionReport theReport; + + public SomeSubmitServlet(final SomeExecutionReport report) { + this.theReport = report; + } + + @Override + public SomeExecutionReport prepareReport(final HttpServletRequest request) { + return theReport; + } + } + + @Getter + private class SomeDataPreparator implements IDataReportPreparator { + private static final long serialVersionUID = 4832031208271989060L; + private boolean done; + + @Override + public String print(TcSession session, SomeExecutionReport execution, IExecutionStrategy executionStrategy) throws KurtException, ZipException { + done = true; + return null; + } + } + + /** + * Fake {@link TcSession} that does nothing. + */ + private class FakeTcSession extends TcSession { + + public FakeTcSession() { + super(); + } + + @Override + public void close() { + // Do not logout! + } + + } + + @Getter + private class SomeMapConstructor extends AbstractStaticTemplateMapConstructor { + private static final long serialVersionUID = -6387054969518914371L; + private boolean done; + + @Override + public void constructDataMaps(TcSession session, final PrintParameters printParameters, final Void report) throws KurtException { + done = true; + } + + } + + /** A placeholder implementation of an ExecutionReport. */ + @Getter + private class SomeExecutionReport extends AbstractExecutionReport { + + private static final long serialVersionUID = 3104147701132381151L; + + private boolean isStartEmailDone; + private boolean isEndEmailDone; + private boolean isErrorEmailDone; + private boolean isParametersCheckFailureEmailDone; + + final List quickChecks; + final List longChecks; + + public SomeExecutionReport(final IChecker quickCheck, final IChecker longCheck, + final IDataReportPreparator prepaData, final IMapConstructor constructMap) { + super(EXPECTED_REPORT_PRIORITY.getPriorityValue(), "someRule", ReportLaunchTypeEnum.IMMEDIATE);// the highest priority code, launch type is immediate + quickChecks = new ArrayList<>(); + quickChecks.add(quickCheck); + longChecks = new ArrayList<>(); + longChecks.add(longCheck); + } + + public boolean isPrepareDataDone() { + return ((SomeDataPreparator) this.getDataPreparator()).isDone(); + } + + @Override + public ReportPriority getReportPriority() { + isStartEmailDone = true; + return EXPECTED_REPORT_PRIORITY; + } + + + @Override + public String getSpecifiedFileName() { + return FAKE_REPORT; + } + + @Override + public PrintFormat getPrintingFormat() { + return PrintFormat.XLSX; + } + + @Override + public List getQuickChecks() { + return quickChecks; + } + + @Override + public List getLongChecks() { + return longChecks; + } + + @Override + public ReportEnum getReportIdentifier() { + return ReportEnum.REPORT_R01; + } + + @Override + public PolicyLocation getPropertyPolicyForLongChecks() { + return XML_POLICY; + } + + @Override + public PolicyLocation getFullPolicy() { + return XML_POLICY; + } + + @Override + public String getTemplateLocation() { + return "somewhere"; + } + + @Override + public List getLaunchData() { + List crits = new ArrayList<>(); + crits.add(new CriteriaValue(ReportCriteriaEnum.PRODUCT, UUID.randomUUID().toString())); + return crits; // Random Data to avoid duplicates + } + + @Override + public IDataReportPreparator getDataPreparator() { + return new SomeDataPreparator(); + } + + @Override + public AbstractExecutionReport cloneTemplateToExecution() { + SomeFailingParameter quickCheck = new SomeFailingParameter(); + SomeGoodParameter longCheck = new SomeGoodParameter(); + return new SomeExecutionReport(quickCheck, longCheck, new SomeDataPreparator(), new SomeMapConstructor()); + } + + @Override + public Class getReportBuilderClass() { + return null; + } + + } + + private class SomeGoodParameter implements IChecker { + boolean isChecked; + + @Override + public void check(final TcSession session) throws InvalidUserInputException { + isChecked = true; + } + } + + private class SomeFailingParameter implements IChecker { + + @Override + public void check(final TcSession session) throws InvalidUserInputException { + throw new InvalidUserInputException(UserInputErrorEnum.INTERNAL_ERROR); + } + } +} diff --git a/kurt-web/src/test/java/com/capgemini/reports/common/scheduling/SchedulingServletTest.java b/kurt-web/src/test/java/com/capgemini/reports/common/scheduling/SchedulingServletTest.java new file mode 100644 index 0000000..f0e1a49 --- /dev/null +++ b/kurt-web/src/test/java/com/capgemini/reports/common/scheduling/SchedulingServletTest.java @@ -0,0 +1,87 @@ +package com.capgemini.reports.common.scheduling; + +import com.capgemini.framework.common.SettingsHelper; +import com.capgemini.reports.exceptions.InvalidInputException; +import com.capgemini.reports.exceptions.NotSupportedException; +import com.capgemini.reports.execution.AbstractExecutionReport; +import com.capgemini.reports.quartz.TriggerPreparator; +import lombok.extern.slf4j.Slf4j; +import org.junit.Assert; +import org.junit.Test; +import org.quartz.CronTrigger; +import org.quartz.JobKey; +import org.quartz.Trigger; +import org.quartz.TriggerKey; +import org.springframework.mock.web.MockHttpServletRequest; + + +@Slf4j +public class SchedulingServletTest { + + private final String LAUNCH_DATE_STR = SettingsHelper.getDelayedLaunchHour(); + + /** + * JUnit test. + * + * @throws NotSupportedException Should not happen + */ + @Test + public void testGetExecutionReportImpl() throws NotSupportedException { + // Get a mock HttpRequest to test the methods of the servlet + MockHttpServletRequest mockRequest = getMockHttpServletRequest(); + + SubmitServletScheduling servlet = new SubmitServletScheduling(); + AbstractExecutionReport reportTest = servlet.getExecutionReportImpl(mockRequest); + + // Check + Assert.assertNotNull(reportTest); + log.info(reportTest.toString()); + } + + /** + * JUnit test. + * + * @throws InvalidInputException Should not happen + */ + @Test + public void testGetSchedulingTrigger() throws InvalidInputException { + // Initialize the variables + Long uid = (long) 123456789; + int priority = 1; + + // Separate hours and minutes (format hour:minute) + String[] tableStrLaunchTime = LAUNCH_DATE_STR.split(":"); + int launchHour = Integer.parseInt(tableStrLaunchTime[0]); + int launchMinute = Integer.parseInt(tableStrLaunchTime[1]); + + // Get a mock HttpRequest to test the methods of the servlet + MockHttpServletRequest mockRequest = getMockHttpServletRequest(); + String schedulingName = mockRequest.getParameter("scheduling_name"); + + SubmitServletScheduling servlet = new SubmitServletScheduling(); + + Trigger triggerTest = TriggerPreparator.prepareScheduledTrigger(uid, priority, schedulingName, servlet.getSchedulingData(mockRequest)); + + // Check + Assert.assertNotNull(triggerTest); + CronTrigger cronTrigger = (CronTrigger) triggerTest; + log.info(cronTrigger.toString()); + JobKey jobKey = cronTrigger.getJobKey(); + TriggerKey triggerKey = cronTrigger.getKey(); + Assert.assertEquals("the name of the job is not the same as the expected value", "job_name_" + uid, jobKey.getName()); + Assert.assertEquals("the group of the job is not the same as the expected value", "scheduled", jobKey.getGroup()); + Assert.assertEquals("the name of the trigger is not the same as the expected value", "trigger_name_" + uid, triggerKey.getName()); + Assert.assertEquals("the group of the trigger is not the same as the expected value", "scheduled", triggerKey.getGroup()); + String schedulName = mockRequest.getParameter("scheduling_name"); + Assert.assertEquals("the name of the planification is not the same as the expected value", schedulName, cronTrigger.getDescription()); + Assert.assertEquals("the cron express which manage the planification is not the same as the expected value", "0 " + launchMinute + " " + launchHour + " ? * *", cronTrigger.getCronExpression()); + } + + private MockHttpServletRequest getMockHttpServletRequest() { + MockHttpServletRequest mockRequest = new MockHttpServletRequest(); + mockRequest.setParameter("report_code", "RTest"); + mockRequest.setParameter("scheduling_name", "myPlanif"); + mockRequest.setParameter("period", "daily"); + return mockRequest; + } +} diff --git a/kurt-web/src/test/java/com/capgemini/reports/formatting/MyReportsTest.java b/kurt-web/src/test/java/com/capgemini/reports/formatting/MyReportsTest.java new file mode 100644 index 0000000..d7c8a25 --- /dev/null +++ b/kurt-web/src/test/java/com/capgemini/reports/formatting/MyReportsTest.java @@ -0,0 +1,58 @@ +package com.capgemini.reports.formatting; + +import com.capgemini.framework.common.SettingsHelper; +import com.capgemini.framework.common.StringHelper; +import com.capgemini.reports.exceptions.InvalidInputException; +import junit.framework.Assert; +import org.junit.Test; + + +public class MyReportsTest { + + /** + * JUnit test. + * + * @throws InvalidInputException Should not happen + */ + @Test + public void obtainIntegerPageParamTestSuccess() throws InvalidInputException { + Assert.assertEquals(25, MyReports.obtainIntegerPageParam("25")); + } + + /** + * JUnit test. + * + * @throws InvalidInputException Should not happen + */ + @Test(expected = InvalidInputException.class) + public void obtainIntegerPageParamTestFailed() throws InvalidInputException { + Assert.assertEquals(1, MyReports.obtainIntegerPageParam("sgr " + "Pages: " + + " - " + + "", + MyReports.makePaging(1, 2)); + Assert.assertEquals( + "
     
    " + "Pages: " + + " - " + + " - " + + "", + MyReports.makePaging(2, 3)); + } +} diff --git a/kurt-web/src/test/java/com/capgemini/servlet/test/Report01Test.java b/kurt-web/src/test/java/com/capgemini/servlet/test/Report01Test.java new file mode 100644 index 0000000..7e864c3 --- /dev/null +++ b/kurt-web/src/test/java/com/capgemini/servlet/test/Report01Test.java @@ -0,0 +1,84 @@ +package com.capgemini.servlet.test; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.junit.After; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import junit.framework.Assert; + +/** JUnit test. **/ +public class Report01Test { + + /** JUnit setup. **/ + @BeforeClass + public static void setUpBeforeClass() { + // Nothing to do + } + + /** JUnit setup. **/ + @Before + public void setUp() { + // Nothing to do + } + + /** JUnit cleanup. **/ + @After + public void tearDown() { + // Nothing to do + } + + /** JUnit test. **/ + @Test + public void testURLGetsUnits() { + + String url = "http://localhost:8080/kurt-web/report_r01/obtain-data?action=getUnits&dataValues=p5bFrkT9hLofXA"; + + Pattern p = Pattern.compile("action=(.*)&dataValues=(.*)"); + Matcher m = p.matcher(url); + if (m.find()) { + + String action = m.group(1); + String datavalues = m.group(2); + + Assert.assertEquals("Check action ", "getUnits", action); + Assert.assertEquals("Check datavalues ", "p5bFrkT9hLofXA", datavalues); + } + } + + /** JUnit test. **/ + @Test + public void testURLGetGenerics() { + + String url = "http://localhost:8080/kurt-web/report_r01/obtain-data?action=getGenerics&dataValues=p5bFrkT9hLofXA&unit=20"; + + Pattern p = Pattern.compile("action=(.*)&dataValues=(.*)&unit=(.*)"); + Matcher m = p.matcher(url); + if (m.find()) { + + String action = m.group(1); + String datavalues = m.group(2); + String unit = m.group(3); + + Assert.assertEquals("Check action ", "getGenerics", action); + Assert.assertEquals("Check datavalues ", "p5bFrkT9hLofXA", datavalues); + Assert.assertEquals("Check unit ", "20", unit); + } + } + + /** JUnit test. **/ + @Test + public void testGetParams() { + + String urlUnit = "http://localhost:8080/kurt-web/report_r01/obtain-data?action=getUnits&dataValues=p5bFrkT9hLofXA"; + Assert.assertEquals("URL unit 1", "http://localhost:8080/kurt-web/report_r01/obtain-data?action=getUnits&dataValues=p5bFrkT9hLofXA", urlUnit); + + String urlGenerics = "http://localhost:8080/kurt-web/report_r01/obtain-data?action=getGenerics&dataValues=p5bFrkT9hLofXA&unit=20"; + Assert.assertEquals("URL unit 2", + "http://localhost:8080/kurt-web/report_r01/obtain-data?action=getGenerics&dataValues=p5bFrkT9hLofXA&unit=20", urlGenerics); + } + +} diff --git a/kurt-web/src/test/resources/htmlRef/my_reports_failed_ref.html b/kurt-web/src/test/resources/htmlRef/my_reports_failed_ref.html new file mode 100644 index 0000000..e7f61ff --- /dev/null +++ b/kurt-web/src/test/resources/htmlRef/my_reports_failed_ref.html @@ -0,0 +1,28 @@ + + + + Mes rapports - <%= theUserLogin %> + + + + + + +

    Mes rapports - <%= theUserLogin %> : <%= theUserReportCount %> rapport(s)

    + + + Rafraichir +

    + +
    +
    + [[ERROR_MESSAGE]] +

    + + +
    + + + diff --git a/kurt-web/src/test/resources/htmlRef/my_reports_success_ref.html b/kurt-web/src/test/resources/htmlRef/my_reports_success_ref.html new file mode 100644 index 0000000..b850b25 --- /dev/null +++ b/kurt-web/src/test/resources/htmlRef/my_reports_success_ref.html @@ -0,0 +1,46 @@ + + + + Mes rapports - <%= theUserLogin %> + + + + + + + + +

    Mes rapports - [[USER_LOGIN]] : [[USER_REPORT_COUNT]] rapport(s)

    + + + Rafraichir +

    + +
    +
    +
    RapportUtilisateur
    ' + currentReport['reportCode'] + '' + priority + '' + currentReport['login'] + '' + currentReport['requestDate'] + '' + currentReport['startGenerationDate'] + ' ' + + currentError + '' + currentStatus + '
    ' + reportArray[i]['report_code'] + '' + reportArray[i]['planif_name'] + '' + reportArray[i]['period'] + '' + reportArray[i]['date_maj'] + '' + reportArray[i]['user_responsable'] + '' + reportArray[i]['date_start'] + ''; + tableContent += ' \n'; + tableContent += ' '; + tableContent += ' \n'; + tableContent += ' '; + tableContent += ' \n'; + tableContent += '
    ' + currentReport['reportCode'] + '' + currentReport['executionCount'] + '' + currentReport['failedFuncCount'] + '' + currentReport['failedTechCount'] + '' + currentReport['minDuration'] + '' + currentReport['avgDuration'] + '' + currentReport['maxDuration'] + '
    ' + stat['name'] + '' + stat['R01'] + '' + stat['R03'] + '' + stat['R05'] + '' + stat['R06'] + '' + stat['R07'] + '' + stat['R10'] + '' + stat['R11'] + '' + stat['R13'] + '' + stat['R15'] + '' + stat['W15'] + '' + stat['R16'] + '' + stat['R17'] + '' + stat['R19'] + '' + stat['R20'] + '' + stat['R21'] + '' + stat['R22'] + '' + stat['W22'] + '' + stat['R23'] + '' + stat['R24'] + '' + stat['R25'] + '' + stat['R26'] + '' + stat['R27'] + '' + stat['R28'] + '' + stat['Global'] + '
    + + + + + + + + + +
    Code du rapportDate de demandeDate de lancementDate de finInfosStatut
    + + [[PAGING]] + +

    + + +
    + + + diff --git a/kurt-web/src/test/resources/log4j.properties b/kurt-web/src/test/resources/log4j.properties new file mode 100644 index 0000000..8f372cd --- /dev/null +++ b/kurt-web/src/test/resources/log4j.properties @@ -0,0 +1,13 @@ +log4j.logger.com.teamcenter.soa=WARN +log4j.logger.org.apache=WARN +log4j.logger.httpclient=WARN + +# Direct log messages to stdout +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.Target=System.out +log4j.appender.stdout.threshold=DEBUG +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %c{1}:%L - %m%n + +# Root logger option +log4j.rootLogger=DEBUG, stdout diff --git a/kurt-web/src/test/resources/logging.properties b/kurt-web/src/test/resources/logging.properties new file mode 100644 index 0000000..1983b8d --- /dev/null +++ b/kurt-web/src/test/resources/logging.properties @@ -0,0 +1,3 @@ +handlers=java.util.logging.ConsoleHandler +java.util.logging.ConsoleHandler.level=FINEST +com.capgemini.level=FINEST diff --git a/kurt-web/src/test/resources/simplelogger.properties b/kurt-web/src/test/resources/simplelogger.properties new file mode 100644 index 0000000..e69de29 diff --git a/kurt-web/src/test/resources/xml/policies/simple_policy.xml b/kurt-web/src/test/resources/xml/policies/simple_policy.xml new file mode 100644 index 0000000..2f3b98d --- /dev/null +++ b/kurt-web/src/test/resources/xml/policies/simple_policy.xml @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kurt-web/src/test/resources/xml/policies/test_policy.xml b/kurt-web/src/test/resources/xml/policies/test_policy.xml new file mode 100644 index 0000000..846457a --- /dev/null +++ b/kurt-web/src/test/resources/xml/policies/test_policy.xml @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..d1d8674 --- /dev/null +++ b/pom.xml @@ -0,0 +1,500 @@ + + + + 4.0.0 + com.capgemini.reports + kurt + pom + 1.32.9 + Kurt + Application de reporting + + + deployment-tool + core-ear + kurt-ejb + kurt-web + kurt-utility + jasper + teamcenter + distribution + + + + http://mrm.apps2.capgemini.com + ${capgemini.cip.project.id}-release-local + AD_DFP_PV_CDS + + + UTF-8 + + + 1.0.4.Final + + + 7.9.Final + + + 2.1.1 + + + 1.7 + 1.7 + + ${project.artifactId}_v${project.version} + distribution + https://coconet-svn-fr-01.capgemini.com/svn/repos/pv-reports + trunk + + + + scm:svn:https://coconet-svn-fr-01.capgemini.com/svn/repos/pv-reports/trunk/kurt + + scm:svn:https://coconet-svn-fr-01.capgemini.com/svn/repos/pv-reports/trunk/kurt + + + + jenkins + https://pvscnecma.pl.s2-eu.capgemini.com/jenkins + + + + + nexus + Internal Snapshot Releases + http://nexus3-core:8081/nexus3/repository/maven-snapshots/ + + + nexus + Internal Releases + http://nexus3-core:8081/nexus3/repository/maven-releases/ + + + + + + + org.jboss.spec + jboss-javaee-6.0 + 1.0.0.Final + pom + import + + + org.jboss.as + jboss-as-parent + 7.1.1.Final + pom + import + + + + org.testng + testng + 6.14.2 + test + + + + org.mockito + mockito-core + 2.12.0 + test + + + + org.assertj + assertj-core + 2.9.0 + test + + + + org.slf4j + slf4j-api + 1.7.7 + + + + org.projectlombok + lombok + 1.16.10 + + + + com.google.guava + guava + 20.0 + + + + org.json + json + 20140107 + + + + + + + + + development + + true + **/*Test.java + **/ExecutionR*Test.* + + + true + + + + + + validation + + **/ExecutionR*Test.* + + + + + + release + + + + org.apache.maven.plugins + maven-release-plugin + 2.5.3 + + https://coconet-svn-fr-01.capgemini.com/svn/repos/pv-reports/tags + svc-fr-plm + Passw0rd + + + + + + + com.maestrodev + collabnet-maven-plugin + 1.4 + + fr_south_t30_plateau_virtuel_sne + PV_SNECMA_interne + ${release.id} + ${project.description} + https://coconet2.capgemini.com + + + + install + install + + deploy-to-releases + + + + + + + + + + + sonar + + **/*Test.java + **/ExecutionR*Test.* + + + + + + org.codehaus.mojo + sonar-maven-plugin + 3.2 + + + + + + + + + + + + org.apache.maven.plugins + maven-deploy-plugin + 2.8.2 + + + org.apache.maven.plugins + maven-jar-plugin + 3.0.2 + + + org.apache.maven.plugins + maven-ejb-plugin + 3.0.1 + + + org.apache.maven.plugins + maven-war-plugin + 3.0.0 + + + org.apache.maven.plugins + maven-ear-plugin + 2.10.1 + + + org.apache.maven.plugins + maven-compiler-plugin + 3.5.1 + + ${maven.compiler.target} + ${maven.compiler.source} + ${project.build.sourceEncoding} + true + + + + org.apache.maven.plugins + maven-site-plugin + 3.5.1 + + + org.apache.maven.plugins + maven-resources-plugin + 3.0.1 + + + org.apache.maven.plugins + maven-dependency-plugin + 3.0.0 + + + org.apache.maven.plugins + maven-assembly-plugin + 3.0.0 + + + org.apache.maven.plugins + maven-surefire-plugin + 2.20.1 + + 1 + false + -Xmx1024m -XX:MaxPermSize=256m + + + ${maven.surefire.plugin.include.filter} + + + ${maven.surefire.plugin.exclude.filter} + + + + + org.apache.maven.plugins + maven-source-plugin + 3.0.1 + + + + org.codehaus.mojo + versions-maven-plugin + 2.3 + + + + + + org.jboss.as.plugins + jboss-as-maven-plugin + ${version.jboss.maven.plugin} + + + + org.jacoco + jacoco-maven-plugin + 0.7.7.201606060606 + + + + prepare-agent + + + + report + prepare-package + + report + + + + + + + org.projectlombok + lombok-maven-plugin + 1.16.10.0 + + + + + + + com.googlecode.maven-overview-plugin + maven-overview-plugin + 1.6 + + 1200 + 1200 + 1 + true + + + test + + + + com.capgemini.* + + + compile + provided + runtime + + + + + org.codehaus.mojo + versions-maven-plugin + + + org.apache.maven.plugins + maven-site-plugin + + + org.apache.maven.plugins + maven-dependency-plugin + + + analyze + + analyze-only + + + + + + org.apache.maven.plugins + maven-resources-plugin + + + false + + ${*} + + + pdf + + swf + + jpeg + + jpg + + png + + jrxml + + + + + + + default-resources + + + + filter-properties-files + process-resources + + copy-resources + + + + ISO-8859-1 + ${project.build.outputDirectory} + + + src/main/resources + true + + **/*.properties + + + + + + + + copy-other-resources + process-resources + + copy-resources + + + ${project.build.outputDirectory} + + + src/main/resources + true + + **/*.properties + + + + + + + + + org.apache.maven.plugins + maven-source-plugin + 3.0.1 + + + attach-sources + + jar-no-fork + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + org.jacoco + jacoco-maven-plugin + + + + + diff --git a/scripts/reports_installation_script.pl b/scripts/reports_installation_script.pl new file mode 100644 index 0000000..9988371 --- /dev/null +++ b/scripts/reports_installation_script.pl @@ -0,0 +1,96 @@ +#! /usr/bin/perl + +use strict; +use warnings; +use File::Copy qw/ cp /; # For cp and move command + +# Paths for FMS server +my $installFolderOnFMS = "/appl/plvt/install"; +my $tcdata = $ENV{'TC_DATA'}; +my $tcroot = $ENV{'TC_ROOT'}; + +if($#ARGV==-1) { + print("Error : Missing arguments\n"); + print("First argument accepted values are [fms|bas]\n"); +} else { + print("==== BEGIN ====\n"); + my $serveur = $ARGV[0]; + + if($serveur eq "fms") { + if(!($#ARGV==2)) { + print("Arguments and are mandatory [version number format X.XX.X]\n"); + } else { + my $newVersion = $ARGV[1]; + my $oldVersion = $ARGV[2]; + + print("Server : FMS | new version : $newVersion | old version: $oldVersion \n"); + + if(!(-d "$installFolderOnFMS/rapt$newVersion")) { + die("Process stopped : $installFolderOnFMS/rapt$newVersion does not exist"); + } else { + if(-e "$installFolderOnFMS/rapt$newVersion/snecma-reports-$newVersion.zip") { + + print("Step 1/2 : Unzip delivery package .. \n"); + + system("unzip $installFolderOnFMS/rapt$newVersion/snecma-reports-$newVersion.zip -d $installFolderOnFMS/rapt$newVersion"); + + print("Step 2/2 : Copy of the report_prefs.xml file from the previous installation (version $oldVersion).. \n"); + + if(-e "$installFolderOnFMS/rapt$oldVersion/Installation/teamcenter/data/report_prefs.xml") { + cp("$installFolderOnFMS/rapt$oldVersion/Installation/teamcenter/data/report_prefs.xml","$installFolderOnFMS/rapt$newVersion/Installation/teamcenter/data") or die "Copy failed: $!\n"; + chmod(0755,"$installFolderOnFMS/rapt$newVersion/Installation/teamcenter/data/report_prefs.xml") or die "Cannot chmod file: $!\n"; + } else { + die("Process stopped : The file report_prefs.xml does not exist in $installFolderOnFMS/rapt$oldVersion/Installation/teamcenter/data \n"); + } + } else { + die("Process stopped : snecma-reports-$newVersion.zip delivery package not found in $installFolderOnFMS/rapt$newVersion/"); + } + } + } + } elsif($serveur eq "bas") { + if (!($#ARGV==1)) { + print("Environment argument is mandatory. Accepted values [int|form|mco|ap|op]\n"); + } else { + my $environment = $ARGV[1]; + + if(("$environment" ne "ap") and ("$environment" ne "op") and ("$environment" ne "op") and ("$environment" ne "int") and ("$environment" ne "mco") and ("$environment" ne "form")) { + die("Environment argument accepted values are [int|form|mco|ap|op]\n"); + } + + print("Copy reports policies from FMS to all BAS | environment : $environment \n"); + if(defined($tcdata)) { + + chdir("$tcdata/soa/policies") or die("$tcdata/soa/policies does not exist"); + + if($environment eq "ap") { + system("scp R*pol*xml sp0plv02\@s04995h0:/appl/plvt/simu/tcdata_101/tcdbapdata/soa/policies"); + system("scp R*pol*xml sp0plv02\@s04996s0:/appl/plvt/simu/tcdata_101/tcdbapdata/soa/policies"); + } + if($environment eq "op") { + system("scp R*pol*xml sp0plv12\@s05196f0:/appl/plvt/oper/tcdata_101/tcdbodata/soa/policies"); + system("scp R*pol*xml sp0plv12\@s05197p0:/appl/plvt/oper/tcdata_101/tcdbodata/soa/policies"); + system("scp R*pol*xml sp0plv12\@s05198y0:/appl/plvt/oper/tcdata_101/tcdbodata/soa/policies"); + system("scp R*pol*xml sp0plv12\@s08702t0:/appl/plvt/oper/tcdata_101/tcdbodata/soa/policies"); + system("scp R*pol*xml sp0plv12\@s08914l0:/appl/plvt/oper/tcdata_101/tcdbodata/soa/policies"); + } + if($environment eq "int") { + system("scp R*pol*xml sp0plv42\@s04616m0:/appl/plvt/int/tcdata/tcdbint4data/soa/policies"); + system("scp R*pol*xml sp0plv42\@s07680f0:/appl/plvt/int/tcdata/tcdbint4data/soa/policies"); + system("scp R*pol*xml sp0plv42\@s07681p0:/appl/plvt/int/tcdata/tcdbint4data/soa/policies"); + } + if($environment eq "form") { + system("scp R*pol*xml sp0plv32\@s05804t0:/appl/plvt/form/tcdata_101/tcdbfodata/soa/policies"); + } + if($environment eq "mco") { + system("scp R*pol*xml sp0plv22\@s04648r0:/appl/plvt/mco/tcdata_101/tcdbm2data/soa/policies"); + } + } else { + print("Process stopped : Environment variables $tcdata is not defined \n"); + } + } + } else { + print("First argument accepted values are [fms|bas]\n"); + } + + print("==== END ====\n"); +} \ No newline at end of file diff --git a/standalone-pv-reports-auth.xml b/standalone-pv-reports-auth.xml new file mode 100644 index 0000000..934ebdb --- /dev/null +++ b/standalone-pv-reports-auth.xml @@ -0,0 +1,580 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + jdbc:oracle:thin:@10.24.192.36:1521:TC + oracle + + TAC + TAC + + + + jdbc:oracle:thin:@10.24.192.36:1521:TC + oracle + + TAC + TAC + + + + + oracle.jdbc.driver.OracleDriver + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + true + 102400 + 2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + jms.queue.DLQ + jms.queue.ExpiryQueue + 0 + 10485760 + BLOCK + 10 + + + + + + + + + + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + ${jboss.bind.address:127.0.0.1} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/standalone-pv-reports.xml b/standalone-pv-reports.xml new file mode 100644 index 0000000..9ace584 --- /dev/null +++ b/standalone-pv-reports.xml @@ -0,0 +1,584 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + jdbc:h2:mem:test;DB_CLOSE_DELAY=-1 + h2 + + sa + sa + + + + + org.h2.jdbcx.JdbcDataSource + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + true + 102400 + 2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + jms.queue.DLQ + jms.queue.ExpiryQueue + 0 + 10485760 + BLOCK + 10 + + + + + + + + + + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + ${jboss.bind.address:127.0.0.1} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/teamcenter/pom.xml b/teamcenter/pom.xml new file mode 100644 index 0000000..f64f0fb --- /dev/null +++ b/teamcenter/pom.xml @@ -0,0 +1,196 @@ + + + 4.0.0 + teamcenter + jar + teamcenter + + + com.capgemini.reports + kurt + 1.32.9 + + + + + + junit + junit + test + + + + org.projectlombok + lombok + + + + org.slf4j + slf4j-api + + + + org.slf4j + slf4j-log4j12 + 1.7.7 + + + + org.jboss.spec.javax.annotation + jboss-annotations-api_1.1_spec + + + + com.google.guava + guava + + + + + com.teamcenter + tcsoacommon + 10.1.7 + + + + com.teamcenter + tcsoaclient + 10.1.7 + + + + com.teamcenter + tcsoastrongmodel + 10.1.7 + + + + com.teamcenter + tcsoacorestrong + 10.1.7 + + + + com.teamcenter + tcsoacoreloose + 10.1.7 + + + + com.teamcenter + tcsoaquerystrong + 10.1.7 + + + + com.teamcenter + tcsoaquerytypes + 10.1.7 + + + + com.teamcenter + tcsoastrongmodelmodelcore + 10.1.7 + + + + com.teamcenter + tcsoacoretypes + 10.1.7 + + + + com.teamcenter + tcsoacadstrong + 10.1.7 + + + + com.teamcenter + tcsoacadtypes + 10.1.7 + + + + com.teamcenter + tcsoaworkflowstrong + 10.1.7 + + + + com.teamcenter + tcsoaworkflowtypes + 10.1.7 + + + + com.teamcenter + xml-apis + 10.1.6 + + + + com.teamcenter + resolver + 10.1.6 + + + + com.teamcenter + commons-codec + 10.1.6 + + + + com.teamcenter + fccclient + 10.1.7 + + + + com.teamcenter + fscclient + 10.1.7 + + + + com.teamcenter + commons-httpclient + 10.1.6 + + + + com.teamcenter + commons-httpclient-contrib + 10.1.7 + + + + com.teamcenter + icctstubs + 10.1.3 + + + + xerces + xercesImpl + 2.8.0 + + + + log4j + log4j + + + + + + + src/main/resources + true + + + + + diff --git a/teamcenter/src/main/java/com/capgemini/framework/common/BeanHelper.java b/teamcenter/src/main/java/com/capgemini/framework/common/BeanHelper.java new file mode 100644 index 0000000..d191a02 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/common/BeanHelper.java @@ -0,0 +1,79 @@ +package com.capgemini.framework.common; + +import lombok.extern.slf4j.Slf4j; + +import java.beans.BeanInfo; +import java.beans.IntrospectionException; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; +import java.lang.reflect.InvocationTargetException; +import java.sql.Timestamp; +import java.text.SimpleDateFormat; +import java.util.Map; +import java.util.TreeMap; + +/** + * JAVA bean attribute serializer. + **/ +@Slf4j +public final class BeanHelper { + + private static final String CLASS_ATT = "class"; + + private BeanHelper() { + // Makes this class static + } + + /** + * Map conversion for attributes of the current bean. + * + * @param aJavaBean Serialized JAVA bean + * @return Map with key as property name and value as a String conversion of the attribute value. + */ + public static Map toStringMap(final Object aJavaBean) { + Map theStrMap = new TreeMap<>(); + try { + fillStrMap(aJavaBean, theStrMap); + } catch (IntrospectionException | IllegalArgumentException | IllegalAccessException | InvocationTargetException e) { + log.error("Error occurred during instrospection, unable to analyse JAVA bean: " + aJavaBean.getClass().getName(), e); + } + return theStrMap; + } + + /** + * Sub-method of toStringMap() filling the map. + * + * @param aJavaBean Serialized JAVA bean + * @param aStrMap Map with key as property name and value as a String conversion of the attribute value. + */ + private static void fillStrMap(final Object aJavaBean, final Map aStrMap) + throws IntrospectionException, IllegalAccessException, InvocationTargetException { + + BeanInfo beanInfo = Introspector.getBeanInfo(aJavaBean.getClass()); + for (PropertyDescriptor propertyDesc : beanInfo.getPropertyDescriptors()) { + + /* Get the next property name and ignore the common attribute called "class" */ + String propertyName = propertyDesc.getName(); + if (CLASS_ATT.equals(propertyName)) { + continue; + } + + /* Try to access to the property through its getter */ + Object theAttValue = propertyDesc.getReadMethod().invoke(aJavaBean); + + /* Convert attribute value to string */ + String theAttributeStrValue = StringHelper.EMPTY; + if (theAttValue != null) { + + if (theAttValue instanceof Timestamp) { + theAttributeStrValue = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss").format(theAttValue); + } else { + theAttributeStrValue = theAttValue.toString(); + } + } + + /* Store attribute in map */ + aStrMap.put(propertyName, theAttributeStrValue); + } + } +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/common/LanguageHelper.java b/teamcenter/src/main/java/com/capgemini/framework/common/LanguageHelper.java new file mode 100644 index 0000000..ada175d --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/common/LanguageHelper.java @@ -0,0 +1,91 @@ +package com.capgemini.framework.common; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + + +/** Class which managed the language problematic of string values in reports. */ +public final class LanguageHelper { + + private static final int FIRST_GROUP = 1; + private static final int SECOND_GROUP = 2; + private static final int THIRD_GROUP = 3; + private static final int SIZE_2 = 2; + private static final int SIZE_4 = 4; + private static final String STR_SEPARATOR = "/"; + private static final String EMPTY_STRING = StringHelper.EMPTY; + private static final String REGEX_SEPARATOR = "\\s*\\/\\s*"; // A slash (/) character surrounded by any number of spaces (including none) + + private LanguageHelper() { + + } + + /** + * Extracts left side of a string of the form "French text / English text".
    + * Separator slash may have *any* number (0+) of white spaces around them.
    + * Warning : The form may be "French text 1 / French text 2 / English text 1 / English text 2". and in this case, the two left sides are extracted. + * + * @param string {@link String} - the string value to check + * @return the "French side" (if any "side" exists), an empty string otherwise + */ + public static String french(final String string) { + if (string == null || string.isEmpty()) { + return EMPTY_STRING; + } + String[] list = string.split(REGEX_SEPARATOR); + if (list.length > 0) { + String result; + if (list.length == SIZE_4) { + result = list[0].concat(STR_SEPARATOR).concat(list[1]); + } else { + result = list[0]; + } + return result; + } else { + return EMPTY_STRING; + } + } + + /** + * Extracts right side of a string of the form "French text / English text".
    + * Separator slash may have *any* number (0+) of white spaces around them.
    + * Warning : The form may be "French text 1 / French text 2 / English text 1 / English text 2". and in this case, the two right sides are extracted. + * + * @param string {@link String} - the string value to check + * @return the "English side" (if any "side" exists), an empty string otherwise + */ + public static String english(final String string) { + if (string == null || string.isEmpty()) { + return EMPTY_STRING; + } + String[] list = string.split(REGEX_SEPARATOR); + if (list.length > 0) { + String result; + if (list.length == SIZE_2) { + result = list[FIRST_GROUP]; + } else if (list.length == SIZE_4) { + result = list[SECOND_GROUP].concat(STR_SEPARATOR).concat(list[THIRD_GROUP]); + } else { + result = list[0]; + } + return result; + } else { + return EMPTY_STRING; + } + } + + /** + * Allow to findAll name of a type object without suffix "Revision". + * + * @param nameItemRevision the name + * @return name of type object. + */ + public static String getNameTypeWithoutRevision(String nameItemRevision) { + Pattern pattern = Pattern.compile("(.*)( Revision)"); + Matcher matcher = pattern.matcher(nameItemRevision); + if (matcher.find()) { + return matcher.group(1); + } + return ""; + } +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/common/ReflectionHelper.java b/teamcenter/src/main/java/com/capgemini/framework/common/ReflectionHelper.java new file mode 100644 index 0000000..a89127a --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/common/ReflectionHelper.java @@ -0,0 +1,93 @@ +package com.capgemini.framework.common; + +import lombok.extern.slf4j.Slf4j; + +import java.util.HashMap; +import java.util.Map; + +/** + * Utility class for reflection operations. + **/ +@Slf4j +public final class ReflectionHelper { + + /** + * Cache for getting class object using its name. + **/ + private static final Map> CACHED_CLASS_MAP = new HashMap<>(); + + /** + * Constructor. + **/ + private ReflectionHelper() { + // Constructor of helper classes must be private + } + + /** + * Dynamic instantiation of object using class name. + * + * @param aClassName Specific class name + * @return New object instance + */ + public static Object newFromClassForName(String aClassName) { + + Object theObj = null; + + Class theInvokedClass = getClassForName(aClassName); + if (theInvokedClass != null) { + theObj = newFromClass(theInvokedClass); + } + + return theObj; + } + + /** + * Dynamic instantiation of object using class. + * + * @param anInvokedClass Specific class + * @return New object instance + */ + private static Object newFromClass(Class anInvokedClass) { + + Object theObj = null; + if (anInvokedClass != null) { + // Try instantiation + try { + theObj = anInvokedClass.newInstance(); + } catch (InstantiationException e) { + log.error("Unable to create instance of: " + anInvokedClass.getName(), e); + } catch (IllegalAccessException e) { + log.error("Unable to access an instance of: " + anInvokedClass.getName(), e); + } + } + + return theObj; + } + + /** + * Dynamic creation of class using its name. + * + * @param aClassName Specific class name + * @return Searched class + */ + public static Class getClassForName(String aClassName) { + + // Try to retrieve the class from cache + Class theInvokedClass = CACHED_CLASS_MAP.get(aClassName); + + // Try class invocation when it has not been stored in cache yet + if (theInvokedClass == null) { + try { + // Run invocation + theInvokedClass = Class.forName(aClassName); + + // Save class in cache + CACHED_CLASS_MAP.put(aClassName, theInvokedClass); + } catch (ClassNotFoundException e) { + log.error("Unable to find class: " + aClassName, e); + } + } + + return theInvokedClass; + } +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/common/StringHelper.java b/teamcenter/src/main/java/com/capgemini/framework/common/StringHelper.java new file mode 100644 index 0000000..5376606 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/common/StringHelper.java @@ -0,0 +1,228 @@ +package com.capgemini.framework.common; + +import java.util.Collection; +import java.util.Map; +import java.util.Map.Entry; +import java.util.StringTokenizer; + +/** Utility class for common String operations. **/ +public final class StringHelper { + private static final int DOT_ZERO_LENGTH = 2; + + /** Empty constant. **/ + public static final String EMPTY = ""; + + /** Line feed char constant. **/ + public static final char LINE_FEED = 0x000A; + + /** Tabulation char constant. **/ + public static final String DASH = "-"; + + /** + * Regular expression used for filtering non alpha numerical characters (dot and underscore are authorized). + **/ + public static final String REGEXP_ALPHANUM = "[^a-zA-Z0-9_.]"; + + /** Constructor. **/ + private StringHelper() { + // Constructor of helper classes must be private + } + + /** + * Truncate a string to a specified length. + * + * @param aString String to truncate + * @param aLength Maximal length of string + * @return truncated string + */ + public static String truncate(final String aString, final int aLength) { + + String truncatedString = null; + + // Manage null value + if (aString != null) { + if (aString.length() > aLength) { + truncatedString = aString.substring(0, aLength); + } else { + truncatedString = aString; + } + } + + return truncatedString; + } + + + /** + * Merge array elements in a single String. + * + * @param aDelimiter : Delimiter between each element of the array + * @param aStringArray : Array of string values + * @return Merged String + */ + public static String implode(final String aDelimiter, final String... aStringArray) { + StringBuilder theBuilder = null; + // Browse array elements for concatenation + for (String currentString : aStringArray) { + if (theBuilder == null) { + theBuilder = new StringBuilder(); + } else { + // Add separator + theBuilder.append(aDelimiter); + } + // Add next element + theBuilder.append(currentString == null ? "null" : currentString); + } + // By default return an empty string + if (theBuilder == null) { + return EMPTY; + } + return theBuilder.toString(); + } + + /** + * Merge array elements in a single String. + * + * @param aDelimiter : Delimiter between each element of the array + * @param aStringArray : Array of string values + * @return Merged String + */ + public static String implodeList(final String aDelimiter, final Collection aStringArray) { + StringBuilder theBuilder = null; + + // Browse array elements for concatenation + for (Object obj : aStringArray) { + + if (theBuilder == null) { + theBuilder = new StringBuilder(); + } else { + // Add separator + theBuilder.append(aDelimiter); + } + // Add next element + theBuilder.append(obj == null ? "null" : obj.toString()); + } + + // By default return an empty string + if (theBuilder == null) { + return EMPTY; + } + + return theBuilder.toString(); + } + + /** + * String concatenation of multiple strings. + * + * @param aStringArray Array of value which must be concatenated + * @return Concatenated value in a String + */ + public static String concatToString(final String... aStringArray) { + return concat(aStringArray).toString(); + } + + /** + * String concatenation of multiple strings. + * + * @param aStringArray Array of value which must be concatenated + * @return Concatenated value in a StringBuilder + */ + public static StringBuilder concat(final String... aStringArray) { + StringBuilder theBuilder = new StringBuilder(); + for (String currentValue : aStringArray) { + theBuilder.append(currentValue); + } + return theBuilder; + } + + /** + * Fill value with 0 to format a string number Example: 1 converted to 4 digits => "0001". + * + * @param aValue integer value + * @param aDigitCount digit size + * @return Formated string with the expected digits count + */ + public static String fixedDigits(final double aValue, final int aDigitCount) { + + String theStringConvertion = String.valueOf(aValue); + if (theStringConvertion.endsWith(".0")) { + theStringConvertion = truncate(theStringConvertion, theStringConvertion.length() - DOT_ZERO_LENGTH); + } + StringBuilder theStringBuilder = new StringBuilder(theStringConvertion); + + /* Zero fill */ + int missing0 = aDigitCount - theStringBuilder.length(); + if (missing0 > 0) { + String insertion = truncate("0000000000000000", missing0); + theStringBuilder.insert(0, insertion); + } + + return theStringBuilder.toString(); + } + + /** + * Javascript code conversion for attributes of the current bean. + * + * @param aJsArrayName Name of the javascript array + * @param aJavaBean Serialized JAVA bean + * @return JS code. + */ + public static String toJs(final String aJsArrayName, final Object aJavaBean) { + + StringBuilder theJsCode = new StringBuilder(aJsArrayName).append(" = new Array();\n"); + Map theAttMap = BeanHelper.toStringMap(aJavaBean); + for (Entry currentEntry : theAttMap.entrySet()) { + + /* Avoid quotes or line feed in displayable content */ + String theJsValue = currentEntry.getValue(); + theJsValue = StringHelper.toHtml(theJsValue); + + /* Compute the JS code for current attribute */ + StringBuilder currentAtt = concat(aJsArrayName, "['", currentEntry.getKey(), "']='", theJsValue, "';\n"); + + /* Append to attribute list */ + theJsCode.append(currentAtt); + } + + return theJsCode.append(LINE_FEED).toString(); + } + + /** + * Replace String values with the HTML format. + * + * @param anHtmlCode String to convert + * @return HTML code with entities + */ + public static String toHtml(final String anHtmlCode) { + String filtered = anHtmlCode.replace("'", "'"); + filtered = filtered.replace("\"", ""e;"); + filtered = filtered.replace("\n", "
    "); + return filtered; + } + + /** + * If the input is null, returns "". Otherwise, return the input. + * @param input the input String + * @return a never-null String + */ + public static String replaceNullByEmpty(String input) { + return input == null ? EMPTY : input; + } + + /** + * Split a string to an array from a pattern delimiter in parameter, and not return delimiter as a token. + * + * @param delimiter a delimiter for the successive splits + * @param value a full sentence to splits + * @return string array + */ + public static String[] splitWithoutDelim(final String delimiter, final String value) { + StringTokenizer tokens = new StringTokenizer(value, delimiter, false); + String[] result = new String[tokens.countTokens()]; + int tokenCount = 0; + while (tokens.hasMoreTokens()) { + result[tokenCount] = tokens.nextToken(); + tokenCount++; + } + return result; + } +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/common/TeamcenterDateFormatter.java b/teamcenter/src/main/java/com/capgemini/framework/common/TeamcenterDateFormatter.java new file mode 100644 index 0000000..9055965 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/common/TeamcenterDateFormatter.java @@ -0,0 +1,161 @@ +package com.capgemini.framework.common; + +import lombok.extern.slf4j.Slf4j; + +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.Locale; +import java.util.TimeZone; + +/** This class formats Date for use with Teamcenter. */ +@Slf4j +public final class TeamcenterDateFormatter { + + /** Date Format of the form 'dd/MM/yyyy HH:mm:ss' which gives '2014/Apr/08 14:08:44' in US timezone. */ + public static final String DD_MM_YYYY_HH_MM_SS = "dd/MM/yyyy HH:mm:ss"; + /** Date Format of the form 'yyyy/MMM/dd' which gives '2014/Apr/08' in US timezone. */ + private static final String YYYY_MMM_DD = "yyyy/MMM/dd"; + /** Date Format of the form 'dd-MMMM-yyyy' which gives '08-April-2014' in US timezone. */ + private static final String DD_MMMM_YYYY = "dd MMMM yyyy"; + /** Date Format of the form 'dd-MMM-yyyy' which gives '08-Apr-2014' in US timezone. */ + private static final String DD_MMM_YYYY = "dd-MMM-yyyy"; + /** Date Format of the form 'dd-MM-yyyy' which gives '08-04-2014'. */ + public static final String DD_MM_YYYY = "dd-MM-yyyy"; + /** Date Format of the form 'dd-MM-yyyy HH:mm' which gives '08-07-2014 10:12'. */ + public static final String DD_MM_YYYY_HH_MM = DD_MM_YYYY + " HH:mm"; + /** Date Format of the form 'yyyyMMdd' which gives '20140408'. */ + public static final String YYYYMMDD = "yyyyMMdd"; + /** Date Format of the form 'YYYYMMDD_hhmmss' which gives '20140408_140844'. */ + public static final String YYYYMMDD_HHMMSS = "yyyyMMdd_HHmmss"; + + private static final Locale LOCAL_US = Locale.US; + private static final String TIME_ZONE_PARIS = "Europe/Paris"; + + private TeamcenterDateFormatter() { + // Private to make this class a Helper. + } + + /** + * Returns the current time with format "dd/MM/yyyy HH:mm:ss". + * + * @return a String + */ + public static String getCurrentTime() { + DateFormat dateFormat = new SimpleDateFormat(DD_MM_YYYY_HH_MM_SS); + Calendar cal = Calendar.getInstance(); + return dateFormat.format(cal.getTime()); // ex: "01/09/2014 16:00:22" + } + + /** + * Make an object Calendar for Teamcenter 10 with String parameter format : dd-MM-yyyy. + * + * @param aDate a string date to parseformat + * @return calendar + */ + public static Calendar makeTeamcenterCalendar(final String aDate) { + if (aDate == null || aDate.isEmpty()) { + return Calendar.getInstance(); + } else { + SimpleDateFormat curFormater = new SimpleDateFormat(DD_MM_YYYY); + try { + Date dateObj = curFormater.parse(aDate); + Calendar calendar = Calendar.getInstance(); + calendar.setTime(dateObj); + calendar.set(Calendar.HOUR, 23); + calendar.set(Calendar.MINUTE, 59); + calendar.set(Calendar.SECOND, 59); + return calendar; + } catch (ParseException e) { + log.error("WRONG format: " + aDate + ", expecting " + DD_MM_YYYY + " defaulting to current date", e); + return Calendar.getInstance(); + } + } + } + + /** + * Takes a {@link Calendar} and formats it to 'dd-MMM-yyyy' using {@link Locale#US} for use in the Saved Query of Teamcenter 10. + * + * @param inputDate (may be null, to represent 'NOW') + * @return a String showing the date in the new format + */ + public static synchronized String translateDateFormatForRequest(final Calendar inputDate) { + return new SimpleDateFormat(DD_MMM_YYYY, LOCAL_US).format(inputDate == null ? Calendar.getInstance().getTime() : inputDate.getTime()); + } + + /** + * Takes a date with format 'dd-MM-yyyy' and formats it to 'dd-MMM-yyyy' for Saved Query of Teamcenter 10. + * + * @param inputDate with this format: dd-MM-yyyy (may be null, to represent 'NOW') + * @return a String showing the date in the new format + */ + public static String translateDateFormatForRequest(final String inputDate) { + // format type + SimpleDateFormat dateFormatInput = new SimpleDateFormat(DD_MM_YYYY); + SimpleDateFormat dateFormatOutput = new SimpleDateFormat(DD_MMM_YYYY, LOCAL_US); + + if (inputDate == null || inputDate.isEmpty()) { + return dateFormatOutput.format(Calendar.getInstance().getTime()); + } else { + try { + Date dateInputParsed = dateFormatInput.parse(inputDate); + return dateFormatOutput.format(dateInputParsed); + } catch (ParseException e1) { + log.error("WRONG format : expecting " + DD_MMM_YYYY, e1); + return DD_MMM_YYYY; + } + } + } + + /** + * Format a date based on a pattern : yyyy/MMM/dd. + * + * @param calendar a Calendar to fromat + * @return date as a String + */ + public static String formatCalendarYearMonthDay(final Calendar calendar) { + SimpleDateFormat sdf = new SimpleDateFormat(YYYY_MMM_DD); + return sdf.format(calendar.getTime()); + } + + /** + * Format a date based on a pattern parameter. + * + * @param calendar a Calendar to format + * @param patternDate a format pattern + * @return date as a String + */ + public static String formatCalendarToPattern(final Calendar calendar, final String patternDate) { + try { + return new SimpleDateFormat(patternDate).format(calendar.getTime()); + } catch (IllegalArgumentException e) { + log.warn("Invalid Date Format received (\"" + patternDate + "\"), defaulting to dd_MM_yyyy", e); + return new SimpleDateFormat(DD_MM_YYYY).format(calendar.getTime()); + } + } + + /** + * Formats a date based on the following pattern : 'dd mmmm yyyy' , also using {@link TimeZone}: Europe (Paris) and french {@link Locale}. + * + * @param calendar a Calendar to format to french + * @return dateFormatFR + */ + public static String formatCalendarToFrench(final Calendar calendar) { + SimpleDateFormat sdf = new SimpleDateFormat(DD_MMMM_YYYY, Locale.FRENCH); + sdf.setTimeZone(getParisTimeZone()); + Calendar theCalendar = calendar == null ? Calendar.getInstance() : calendar; + return sdf.format(theCalendar.getTime()); + } + + /** + * Returns the Paris {@link TimeZone}. + * + * @return a {@link TimeZone} + */ + public static TimeZone getParisTimeZone() { + return TimeZone.getTimeZone(TeamcenterDateFormatter.TIME_ZONE_PARIS); + } + +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/common/security/AesEncoded.java b/teamcenter/src/main/java/com/capgemini/framework/common/security/AesEncoded.java new file mode 100644 index 0000000..cb59b9d --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/common/security/AesEncoded.java @@ -0,0 +1,39 @@ +package com.capgemini.framework.common.security; + +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import sun.misc.BASE64Decoder; + +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.spec.SecretKeySpec; +import java.io.IOException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; + +/** + * This program generates a AES key, retrieves its raw bytes, and then reinstantiates a AES key from the key bytes. The + * reinstantiated key is used to initialize a AES cipher for encryption and decryption. + */ +public class AesEncoded { + private final String encodedText; + + public AesEncoded(final String encodedText) { + this.encodedText = encodedText; + } + + /** + * Décodage d'une chaine de caractères suivant le cryptage défini. + */ + public String decode() throws KurtException { + try { + Cipher cipher = Cipher.getInstance("AES"); + cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec("pvsir123niabppq6".getBytes(), "AES")); + return new String(cipher.doFinal(new BASE64Decoder().decodeBuffer(encodedText))); + } + catch (NoSuchPaddingException | IOException | NoSuchAlgorithmException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) { + throw new KurtException("Error decoding the string " + encodedText, e); + } + } +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/ServiceDataHelper.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/ServiceDataHelper.java new file mode 100644 index 0000000..7bc882b --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/ServiceDataHelper.java @@ -0,0 +1,72 @@ +package com.capgemini.framework.teamcenter; + +import com.teamcenter.soa.client.model.ErrorStack; +import com.teamcenter.soa.client.model.ErrorValue; +import com.teamcenter.soa.client.model.ModelObject; +import com.teamcenter.soa.client.model.ServiceData; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ServiceDataHelper { + private static final Logger LOGGER = LoggerFactory.getLogger(ServiceDataHelper.class); + + private ServiceDataHelper() { + // utility + } + + /** + * Check if the service data has errors. + * + * @param serviceData + * ServiceData instance + * @return True when no error occurs, else return false + */ + public static boolean hasErrors(final ServiceData serviceData) { + return serviceData.sizeOfPartialErrors() > 0; + } + + /** + * Log potential errors throw from a service data. + * + * @param serviceData + * ServiceData instance + * @return True when no error occurs, else return false + */ + public static void displayErrors(final ServiceData serviceData) { + LOGGER.debug("Error count: {}", serviceData.sizeOfPartialErrors()); + for (int i = 0; i < serviceData.sizeOfPartialErrors(); i++) { + displayError(serviceData.getPartialError(i)); + } + } + + /** + * Display error stack from service data. + * + * @param errorStack Stack error from service + */ + private static void displayError(final ErrorStack errorStack) { + LOGGER.debug("Error stack from client: clientIndex = {}, clientId = {}", errorStack.getClientIndex(), + errorStack.getClientId()); + ModelObject associatedObject = errorStack.getAssociatedObject(); + StringBuilder theLogBuilder = new StringBuilder(); + if (associatedObject != null) { + theLogBuilder.append("object UID = [").append(associatedObject.getUid()).append("]"); + } else { + theLogBuilder.append("associatedObject = [null]"); + } + LOGGER.debug(" " + theLogBuilder.toString()); + + ErrorValue[] errorValues = errorStack.getErrorValues(); + if (errorValues == null) { + return; + } + for (ErrorValue currentErrorVal : errorValues) { + if (currentErrorVal != null) { + LOGGER.debug(" errVal :"); + LOGGER.debug(" code = {}", currentErrorVal.getCode()); + LOGGER.debug(" level = {}", currentErrorVal.getLevel()); + LOGGER.debug(" msg = {}", currentErrorVal.getMessage()); + } + } + } +} \ No newline at end of file diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/TeamcenterObjectProperties.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/TeamcenterObjectProperties.java new file mode 100644 index 0000000..0360a5b --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/TeamcenterObjectProperties.java @@ -0,0 +1,146 @@ +package com.capgemini.framework.teamcenter; + +import com.teamcenter.soa.client.model.strong.*; +import lombok.EqualsAndHashCode; +import lombok.extern.slf4j.Slf4j; + +/** + * Class regrouping all the properties for objects. + */ +@Slf4j +@EqualsAndHashCode +public class TeamcenterObjectProperties { + + /** + * Property for retrieving all the tasks associated to a Change. + */ + public static final String PROCESS_STAGE_LIST = "process_stage_list"; + /** + * Child tasks of an EPMTask. + */ + public static final String CHILD_TASKS = "child_tasks"; + /** + * List of target objects of an EPMTask. + */ + public static final String ROOT_TARGET_ATTACHMENTS = "root_target_attachments"; + /** + * List of all signoffs attached to an EPMTask. + */ + public static final String SIGNOFF_ATTACHMENTS = "signoff_attachments"; + /** + * Property for retrieving the {@link User} who last modified an object. + */ + public static final String LAST_MOD_USER = "last_mod_user"; + /** + * Property for retrieving the date at which an object was last modified. + */ + public static final String LAST_MOD_DATE = "last_mod_date"; + /** + * Property for retrieving the 'State' of an {@link EPMTask}. + */ + public static final String STATE = "state"; + /** + * Property for retrieving the valid signoffs of a task. + */ + public static final String VALID_SIGNOFFS = "valid_signoffs"; + /** + * End item of an Effectivity. Usually, a Product ID. + */ + public static final String END_ITEM = "end_item"; + /** + * Property for retrieving the main object associated to a TC {@link BOMLine}. + */ + public static final String BL_LINE_OBJECT = "bl_line_object"; + /** + * Property for retrieving the sequence_id of an Object. + */ + public static final String SEQUENCE_ID = "sequence_id"; + /** + * Property for retrieving the date released on a ReleaseStatus. + */ + public static final String DATE_RELEASED = "date_released"; + /** + * Property for retrieving the creationDate of an Object. + */ + public static final String CREATION_DATE = "creation_date"; + /** + * Property for retrieving the ID of an Item. + */ + public static final String ITEM_ID = "item_id"; + /** + * Property for retrieving the revision of an ItemRevision. + */ + public static final String ITEM_REVISION_ID = "item_revision_id"; + /** + * Property for retrieving the list of revision of an Item. + */ + public static final String REVISION_LIST = "revision_list"; + /** + * Property for retrieving the name of a ReleaseStatus. + */ + public static final String NAME = "name"; + /** + * Property for retrieving the name of a ModelObject. + */ + public static final String OBJECT_NAME = "object_name"; + /** + * Property for retrieving the Item of an ItemRevision. + */ + public static final String ITEMS_TAG = "items_tag"; + /** + * Property for retrieving the form of an Item or an ItemRevision. + */ + public static final String ITEM_MASTER_TAG = "item_master_tag"; + /** + * Property for retrieving the direct children of a RF Part Assemb Revision. + */ + public static final String ASSEMBLY_BOM = "AssemblyBom"; + /** + * Property for retrieving the direct children of a RF Part Revision. + */ + public static final String RF_PART_BOM = "RFPartBom"; + /** + * Property for retrieving the 'owning user'. + */ + public static final String OWNING_USER = "owning_user"; + /** + * Property for retrieving the 'user_name'. + */ + public static final String USER_NAME = "user_name"; + /** + * Property for retrieving the 'id'. + */ + public static final String USER_ID = "user_id"; + /** + * Property for retrieving the {@link Person} of a {@link User}. + */ + public static final String PERSON = "person"; + /** + * Property for Decision status on Signoff objects. + */ + public static final String DECISION = "decision"; + /** + * Property for 'Ligne Produit' on every Change Objects. + */ + public static final String PROP_LIGNE_PRODUIT = "pv4_ligne_produit"; + /** + * Property for retrieving the documents in the pseudofolder "Represented by". + */ + public static final String TC_IS_REPRESENTED_BY = "TC_Is_Represented_By"; + + + protected TeamcenterObjectProperties() { + // protected <-- because ObjectProperties will extend this class + } + + /** + * Get item id for an item. + * + * @param item the Item to search + * @return item id + */ + public static String getItemIdOrNull(final Item item) { + return item.get_item_id(); + } + +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/TeamcenterObjectTypes.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/TeamcenterObjectTypes.java new file mode 100644 index 0000000..a38956a --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/TeamcenterObjectTypes.java @@ -0,0 +1,83 @@ +package com.capgemini.framework.teamcenter; + +import com.teamcenter.soa.client.model.Type; + +import java.util.Arrays; +import java.util.regex.Pattern; + +/** Class regrouping all the used type of Teamcenter Revision objects. */ +public class TeamcenterObjectTypes { + + protected TeamcenterObjectTypes() { + // Move along, nothing to see + } + + // Some more frequent suffixes + protected static final String REVISION = " Revision"; + protected static final String MASTER = " Master"; + + /** The WokspaceObject type. */ + public static final String WORSKPACE_OBJECT = "WorkspaceObject"; + /** The Teamcenter type for a ReleaseStatus. */ + public static final String RELEASE_STATUS = "ReleaseStatus"; + /** The Teamcenter Item Revision. */ + public static final String ITEM_REVISION = "ItemRevision"; + /** The Teamcenter type for an EPMTask (workflow task). */ + public static final String EPM_TASK = "EPMTask"; + /** The Teamcenter type for an EPMPerformSignoffTask (workflow task). */ + public static final String EPM_PERFORM_SIGNOFF_TASK = "EPMPerformSignoffTask"; + /** The Teamcenter type for an EPMDoTask (workflow task). */ + public static final String EPM_DO_TASK = "EPMDoTask"; + /** The Teamcenter type for a Signoff (Action of a User on a task). */ + public static final String SIGNOFF = "Signoff"; + /** The Teamcenter type for a User. */ + public static final String USER = "User"; + /** The Teamcenter type for a Person. */ + public static final String PERSON = "Person"; + /** The Teamcenter type for a Change Item Revision. */ + public static final String CHANGE_ITEM_REVISION = "ChangeItemRevision"; + /** The Teamcenter type for a Change Request Revision. */ + public static final String CHANGE_REQUEST_REVISION = "ChangeRequestRevision"; + /** The Teamcenter type for a Change Notice Revision. */ + public static final String CHANGE_NOTICE_REVISION = "ChangeNoticeRevision"; + /** The Teamcenter type for a mockup. */ + public static final String MOCKUP = "Mockup"; + /** The Teamcenter type for a mockup revision. */ + public static final String MOCKUP_REVISION = MOCKUP + REVISION; + /** The Teamcenter type for a mockup revision. */ + public static final String MOCKUP_REVISION_MASTER = MOCKUP + REVISION + MASTER; + /** Link from Item to Dataset. */ + public static final String IMAN_SPECIFICATION = "IMAN_specification"; + /** Link from Part PV to Fiche Article. */ + public static final String IMAN_REQUIREMENT = "IMAN_requirement"; + /** Link from Part PV to Fiche Article. */ + public static final String IMAN_REFERENCE = "IMAN_reference"; + + /** + * Returns true if the provided object type String matches a provided item type. + * + * @param objectType the String describing the object type to be tested + * @param authorizedTypes a series of authorized String Types + * @return true if the object type matches any of the provided types, false otherwise + */ + public static boolean isA(final String objectType, final String... authorizedTypes) { + for (String type : authorizedTypes) { + if (Pattern.matches("^(" + type + ")$", objectType)) { + return true; + } + } + return false; + } + + /** + * Verify (recursively) if the candidate {@link Type} is a type (or super type of) the Tc target Class. + * + * @param targetClass the target class name + * @param candidate the candidate Tc {@link Type} + * @return true if any of the super types of the candidate matches the target class name + */ + public static boolean isRecursively(String targetClass, Type candidate) { + return Arrays.asList(candidate.getClassNameHierarchy()).contains(targetClass); + } + +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/authent/AuthentPropLoader.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/authent/AuthentPropLoader.java new file mode 100644 index 0000000..11f4b0f --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/authent/AuthentPropLoader.java @@ -0,0 +1,92 @@ +package com.capgemini.framework.teamcenter.authent; + +import lombok.extern.slf4j.Slf4j; + +import java.io.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; + +/** + * Utility class required for loading properties used by teamcenter session authentication. + **/ +@Slf4j +public final class AuthentPropLoader { + + private static final String KURT_PROP_FILENAME = "/reporting.properties"; + private static Properties tcProperties; + + /** + * Constructor. + **/ + private AuthentPropLoader() { + // Utility classes should not have a public constructor + } + + /** + * Retrieve the properties and load them if needed. + * + * @return Property content of file + **/ + private static synchronized Properties getPropLoader() { + // Check if the property file has been already loaded + if (tcProperties == null) { + tcProperties = new Properties(); + try (InputStream thePropStream = readPropertiesFile()) { + tcProperties.load(thePropStream); + } catch (IOException e) { + log.error("Unable to load properties file", e); + } + } + return tcProperties; + } + + // Try to access file in the configuration folder of JBOSS, else use by default the file provided in EAR + private static InputStream readPropertiesFile() { + String theJbossConfPath = System.getenv("JBOSS_HOME") + "/standalone/configuration" + KURT_PROP_FILENAME; + boolean isConfFile = new File(theJbossConfPath).exists(); + if (isConfFile) { + log.debug("JBOSS configuration file has been found in: " + theJbossConfPath); + try { + return new FileInputStream(theJbossConfPath); + } catch (FileNotFoundException e) { + log.error("Unable to load file: " + theJbossConfPath, e); + } + } + // default: JBoss file does not exist or not readable + log.warn("EAR file will be used, no configuration file found in: " + theJbossConfPath); + return AuthentPropLoader.class.getResourceAsStream(KURT_PROP_FILENAME); + } + + /** + * Getter for the property value corresponding to the property key. + * + * @param aPropKey Property key reference + * @return Property value + */ + public static String getString(final String aPropKey) { + return getPropLoader().getProperty(aPropKey); + } + + /** + * Returns an array of symbol-separated values. + * + * @param aPropKey the property name + * @param separator the separator symbol + * @return an array of Strings. Empty array if an empty string was found + */ + public static String[] getStringArray(final String aPropKey, String separator) { + String raw = System.getProperty(aPropKey); + if (raw == null || raw.isEmpty()) { + log.warn("No property array found in tc properties for key " + aPropKey); + return new String[0]; + } + List result = new ArrayList<>(); + for (String tmp : raw.split(separator)) { + if (!tmp.isEmpty()) { + result.add(tmp); + } + } + return result.toArray(new String[result.size()]); + } +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/authent/FscParameters.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/authent/FscParameters.java new file mode 100644 index 0000000..9c0263b --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/authent/FscParameters.java @@ -0,0 +1,20 @@ +package com.capgemini.framework.teamcenter.authent; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** Simple holder class for all data regarding connection to FSC service. */ +@Getter +@AllArgsConstructor +public class FscParameters { + + /** Connection to FSC. */ + private final String clientIPAddress; + /** FSC assigned URL. */ + private final String[] assignedFscURIs; + /** FSC bootstrap URL. */ + private final String[] bootstrapFscURIs; + /** Local cache directory. */ + private final String cacheDir; + +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/authent/KurtModelEventListener.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/authent/KurtModelEventListener.java new file mode 100644 index 0000000..2ab0edf --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/authent/KurtModelEventListener.java @@ -0,0 +1,57 @@ +package com.capgemini.framework.teamcenter.authent; + +import com.teamcenter.soa.client.model.ModelEventListener; +import com.teamcenter.soa.client.model.ModelObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Arrays; + +/** + * Events logger: object creation, modification and suppression trigger a call to this object's corresponding method. + */ +public class KurtModelEventListener extends ModelEventListener { + private static final Logger LOGGER = LoggerFactory.getLogger(KurtModelEventListener.class); + + @Override + public void localObjectCreate(ModelObject[] createdObjs) { + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("Local objects created: {}", Arrays.toString(createdObjs)); + } + } + + @Override + public void localObjectChange(ModelObject[] changedObjs) { + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("Local objects modified: {}", Arrays.toString(changedObjs)); + } + } + + @Override + public void localObjectDelete(String[] uids) { + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("Local objects deleted: {}", Arrays.toString(uids)); + } + } + + @Override + public void sharedObjectCreate(ModelObject[] createdObjs) { + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("Shared objects created: {}", Arrays.toString(createdObjs)); + } + } + + @Override + public void sharedObjectChange(ModelObject[] changedObjs) { + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("Shared objects modified: {}", Arrays.toString(changedObjs)); + } + } + + @Override + public void sharedObjectDelete(String[] uids) { + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("Shared objects deleted: {}", Arrays.toString(uids)); + } + } +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/authent/TcCredentialManager.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/authent/TcCredentialManager.java new file mode 100644 index 0000000..9c9767d --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/authent/TcCredentialManager.java @@ -0,0 +1,77 @@ +package com.capgemini.framework.teamcenter.authent; + +import com.teamcenter.schemas.soa._2006_03.exceptions.InvalidCredentialsException; +import com.teamcenter.schemas.soa._2006_03.exceptions.InvalidUserException; +import com.teamcenter.services.strong.core.SessionService; +import com.teamcenter.soa.client.CredentialManager; +import com.teamcenter.soa.client.model.strong.GroupMember; + +/** + * The CredentialManager is used by the Teamcenter Services framework to findAll the user's credentials when challenged by the server. This can occur after a period of inactivity and the server has timed-out the user's session, at which time the client application will need to re-authenticate. The + * framework will call one of the getCredentials methods (depending on circumstances) and will send the SessionService.login service request. Upon successful completion of the login service request. The last service request (one that caused the challenge) will be resent. + *

    + * The framework will also call the setUserPassword setGroupRole methods when ever these credentials change, thus allowing this implementation of the CredentialManager to cache these values so prompting of the user is not required for re-authentication. + */ +public class TcCredentialManager implements CredentialManager { + + private String name; + private String password; + private String discriminator; + private String group = ""; + private String role = ""; + + // always connect same user to same instance of server + + /** + * Return the type of credentials this implementation provides, standard (user/password) or Single-Sign-On. In this case Standard credentials are returned. + * + * @see com.teamcenter.soa.client.CredentialManager#getCredentialType() + */ + @Override + public int getCredentialType() { + return CredentialManager.CLIENT_CREDENTIAL_TYPE_STD; + } + + /** + * Prompts the user for credentials. This method will only be called by the framework when a login attempt has failed. + * + * @see com.teamcenter.soa.client.CredentialManager#getCredentials(com.teamcenter.schemas.soa._2006_03.exceptions.InvalidCredentialsException) + */ + @Override + public String[] getCredentials(final InvalidCredentialsException anException) { + return new String[]{name, password, group, role, discriminator}; + } + + /** + * Return the cached credentials. This method will be called when a service request is sent without a valid session ( session has expired on the server). + * + * @see com.teamcenter.soa.client.CredentialManager#getCredentials(com.teamcenter.schemas.soa._2006_03.exceptions.InvalidUserException) + */ + @Override + public String[] getCredentials(final InvalidUserException anException) { + return new String[]{name, password, group, role, discriminator}; + } + + /** + * Cache the group and role. This is called after the {@link SessionService#setSessionGroupMember(GroupMember)} service operation is called. + * + * @see com.teamcenter.soa.client.CredentialManager#setGroupRole(java.lang.String, java.lang.String) + */ + @Override + public void setGroupRole(final String group, final String role) { + this.group = group; + this.role = role; + } + + /** + * Cache the User and Password This is called after the SessionService.login service operation is called. + * + * @see com.teamcenter.soa.client.CredentialManager#setUserPassword(java.lang.String, java.lang.String, java.lang.String) + */ + @Override + public void setUserPassword(final String user, final String password, final String discriminator) { + this.name = user; + this.password = password; + this.discriminator = discriminator; + } +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/authent/TcExceptionHandler.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/authent/TcExceptionHandler.java new file mode 100644 index 0000000..b71de44 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/authent/TcExceptionHandler.java @@ -0,0 +1,108 @@ +package com.capgemini.framework.teamcenter.authent; + +import com.capgemini.framework.teamcenter.exceptions.runtime.ConnectionLostException; +import com.teamcenter.schemas.soa._2006_03.exceptions.ConnectionException; +import com.teamcenter.schemas.soa._2006_03.exceptions.InternalServerException; +import com.teamcenter.schemas.soa._2006_03.exceptions.ProtocolException; +import com.teamcenter.soa.client.ExceptionHandler; +import com.teamcenter.soa.exceptions.CanceledOperationException; +import lombok.extern.slf4j.Slf4j; + +/** Implementation of the ExceptionHandler for Teamcenter requests. **/ +@Slf4j +public class TcExceptionHandler implements ExceptionHandler { + + /** If delay between two Exceptions is higher than this, then the two exceptions are non-related, so we can restart the countdown, ms. */ + private static final long MAX_INTERVAL_BETWEEN_BREAKUPS = 60 * 60 * 1000; // 60 minutes + /** Number maximum of consecutive retries before fatal exception is thrown. */ + private static final int MAX_COUNTDOWN = 10; + /** Wait time between consecutive retries, ms. */ + private static final int WAIT_BETWEEN_RETRIES_MS = 10000; // 10s + + long firstErrorTimeMillis; + int countdown; + + /** + * Creates an Exception Handler.
    + * The typical behaviour of this handler when subject to an {@link InternalServerException} is the following: + *

      + *
    • If the exception is a {@link ProtocolException}, a RuntimeException is thrown to interrupt report generation, as these ProtocolException are usually not recoverable from.
    • + *
    • If the exception is a {@link ConnectionException}, then the following happens: + *
        + *
      1. The connection is retried after a delay of
      2. + *
      3. + *
      + *
    • + *
    • Otherwise the exception is an unknown InternalServerException, a RuntimeException (actually a {@link ConnectionLostException}) is thrown
    • + *
    + */ + public TcExceptionHandler() { + firstErrorTimeMillis = System.currentTimeMillis(); + countdown = 0; + } + + /** + * Takes care of {@link InternalServerException}s. + * + * @see com.teamcenter.soa.client.ExceptionHandler#handleException(com.teamcenter.schemas.soa._2006_03.exceptions.InternalServerException) + */ + @Override + public void handleException(final InternalServerException anException) { + if (anException instanceof ProtocolException) { + // ProtocolException are typically due to programming errors (content of HTTP request is incorrect). These generally cannot be recovered from. + throw new ConnectionLostException("Internal Teamcenter ProtocolException encountered, not recoverable", anException); + } + else if (anException instanceof ConnectionException) { + handleTemporaryConnectionException((ConnectionException) anException); + } + else { + throw new ConnectionLostException("InternalServerException encountered, not recoverable", anException); + } + } + + private void handleTemporaryConnectionException(final ConnectionException anException) { + // ConnectionException are typically due to a network error (server down .etc) and can be recovered from (the last request can be sent again, after the problem is corrected). + long time = System.currentTimeMillis(); + if (time > MAX_INTERVAL_BETWEEN_BREAKUPS + firstErrorTimeMillis) { + // This is the first Exception of a new series of errors + countdown = 0; + firstErrorTimeMillis = time; + log.error("The teamcenter server returned an protocol error: " + anException.getMessage(), anException); + } + else { + // This is the continuation of an on-going series of error, so we increment the countdown + countdown++; + } + if (countdown > MAX_COUNTDOWN) { + // The maximum number of consecutive errors has been reached, the connection is definitely lost, let's findAll out of here! + throw new ConnectionLostException("Maximum number of retries reached during connection loss", anException); + } + else { + // To let the TC servers time to recover, let's wait a bit + try { + String msg = "A series of " + countdown + + " errors from the Teamcenter servers has been detected. A retry will be attempted within " + + WAIT_BETWEEN_RETRIES_MS + "ms. Last exception encountered: " + anException.getMessage(); + log.error(msg, anException); + Thread.sleep(WAIT_BETWEEN_RETRIES_MS); + } + catch (InterruptedException e) { + log.info("Exception handler was interrupted during sleep, while awaiting to recover from a previous connection exception (" + + anException.getMessage() + ")", e); // Oh, the irony! + } + } + // Continuing normally will eventually lead to re-trying to perform the operation that did not succeed because of the InternalServerException + } + + /** + * Takes care of {@link CanceledOperationException}s. + * + * @see com.teamcenter.soa.client.ExceptionHandler#handleException(com.teamcenter.soa.exceptions.CanceledOperationException) + */ + @Override + public void handleException(final CanceledOperationException aCanceledOpException) { + log.error("Teamcenter server returned a CanceledOperationException:\nIt could be caused by invalid credential during login operation", + aCanceledOpException); + } + +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/authent/TcSession.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/authent/TcSession.java new file mode 100644 index 0000000..0d8b38f --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/authent/TcSession.java @@ -0,0 +1,716 @@ +package com.capgemini.framework.teamcenter.authent; + +import com.capgemini.framework.common.security.AesEncoded; +import com.capgemini.framework.teamcenter.ServiceDataHelper; +import com.capgemini.framework.teamcenter.exceptions.ConnectionMisconguredException; +import com.capgemini.framework.teamcenter.exceptions.FailedRelationshipActionException; +import com.capgemini.framework.teamcenter.exceptions.InvalidConfigurationException; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.exceptions.MalformedDataSetException; +import com.capgemini.framework.teamcenter.exceptions.NoSuchRevisionRuleException; +import com.capgemini.framework.teamcenter.exceptions.NoTeamcenterConnectionException; +import com.capgemini.framework.teamcenter.exceptions.runtime.ConnectionLostException; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcRevisionRule; +import com.capgemini.framework.teamcenter.object.runtime.TcBomWindow; +import com.capgemini.framework.teamcenter.object.runtime.TcBomWindowConfiguration; +import com.capgemini.framework.teamcenter.object.runtime.TcBomWindowFactory; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.teamcenter.schemas.soa._2006_03.exceptions.InvalidCredentialsException; +import com.teamcenter.schemas.soa._2006_03.exceptions.ServiceException; +import com.teamcenter.services.loose.core._2006_03.FileManagement.DatasetFileInfo; +import com.teamcenter.services.loose.core._2006_03.FileManagement.GetDatasetWriteTicketsInputData; +import com.teamcenter.services.strong.cad.StructureManagementService; +import com.teamcenter.services.strong.cad._2007_01.StructureManagement.GetRevisionRulesResponse; +import com.teamcenter.services.strong.cad._2007_01.StructureManagement.RevisionRuleInfo; +import com.teamcenter.services.strong.core.DataManagementService; +import com.teamcenter.services.strong.core.SessionService; +import com.teamcenter.services.strong.core._2006_03.DataManagement.CreateRelationsResponse; +import com.teamcenter.services.strong.core._2006_03.DataManagement.Relationship; +import com.teamcenter.services.strong.core._2007_01.DataManagement.WhereReferencedInfo; +import com.teamcenter.services.strong.core._2007_01.DataManagement.WhereReferencedOutput; +import com.teamcenter.services.strong.core._2007_01.DataManagement.WhereReferencedResponse; +import com.teamcenter.services.strong.core._2007_12.Session.StateNameValue; +import com.teamcenter.services.strong.core._2010_04.DataManagement.CreateDatasetsResponse; +import com.teamcenter.services.strong.core._2010_04.DataManagement.DatasetInfo; +import com.teamcenter.services.strong.core._2010_09.DataManagement.NameValueStruct1; +import com.teamcenter.services.strong.core._2010_09.DataManagement.PropInfo; +import com.teamcenter.services.strong.core._2010_09.DataManagement.SetPropertyResponse; +import com.teamcenter.services.strong.core._2011_06.Session.Credentials; +import com.teamcenter.services.strong.core._2011_06.Session.LoginResponse; +import com.teamcenter.services.strong.core._2012_02.DataManagement.WhereUsedConfigParameters; +import com.teamcenter.services.strong.core._2012_02.DataManagement.WhereUsedInputData; +import com.teamcenter.services.strong.core._2012_02.DataManagement.WhereUsedParentInfo; +import com.teamcenter.services.strong.core._2012_02.DataManagement.WhereUsedResponse; +import com.teamcenter.services.strong.query.FinderService; +import com.teamcenter.services.strong.query.SavedQueryService; +import com.teamcenter.services.strong.workflow.WorkflowService; +import com.teamcenter.soa.SoaConstants; +import com.teamcenter.soa.client.Connection; +import com.teamcenter.soa.client.FileManagementUtility; +import com.teamcenter.soa.client.model.ErrorStack; +import com.teamcenter.soa.client.model.ModelObject; +import com.teamcenter.soa.client.model.ServiceData; +import com.teamcenter.soa.client.model.strong.ImanRelation; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import com.teamcenter.soa.client.model.strong.RevisionRule; +import com.teamcenter.soa.client.model.strong.User; +import com.teamcenter.soa.client.model.strong.WorkspaceObject; +import com.teamcenter.soaictstubs.ICCTRevisionRule; +import com.teamcenter.soaictstubs.ICCTSession; +import com.teamcenter.soaictstubs.StringHolder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.Closeable; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + + +/** + * Teamcenter connection management. + **/ +public class TcSession implements Closeable { + /** + * Default user login. + **/ + private static final String USERNAME = System.getProperty("teamcenter.session.login"); // Prefix is required + private static final Logger LOGGER = LoggerFactory.getLogger(TcSession.class); + /** + * Teamcenter server URL. + **/ + private static final String URL = System.getProperty("teamcenter.url"); + private static final String ERROR_MSG_UNABLE_TO_OBTAIN_SESSION_INFO_TC_SERVER_ID = "Unable to obtain usual session info: TcServerID"; + private static final String TC_SERVER_ID = "TcServerID"; + private static final int TIMEOUT_SEC = 120; + private static final String ERROR_MSG_LOGIN_TIMEOUT = "Timed out during login to Tc Servers after " + TIMEOUT_SEC + "sec"; + /** + * Default user password. + **/ + private static final String PASSWORD = System.getProperty("teamcenter.session.password"); // Prefix is required + + private static final String FSC_CLIENT_IP = System.getProperty("fsc.clientip"); // Prefix is required + private static final String FSC_CACHE_DIR = System.getProperty("fsc.cachedir"); // Prefix is required + private static final String[] FSC_ASSIGNED_URI = AuthentPropLoader.getStringArray("fsc.assignedURI", ","); // Prefix is required + private static final String[] FSC_BOOTSTRAP_URI = AuthentPropLoader.getStringArray("fsc.bootstrapURI", ","); // Prefix is required + private static final FscParameters DEFAULT_FSC_PARAMS = new FscParameters(FSC_CLIENT_IP, FSC_ASSIGNED_URI, FSC_BOOTSTRAP_URI, FSC_CACHE_DIR); + private final FscParameters fscParams; + /** + * Single instance of the Connection object that is shared throughout the application.
    + * This Connection object is needed whenever a Service stub is instantiated. + */ + private Connection connection; + + /** + * Connection status. Helps prevent double-logout, double login, or logout without prior login. + */ + private LoginResponse loggedIn; + /** + * Common service for structure resolutions. Lazily initialized, use getter method. + **/ + private StructureManagementService structureManagementService; + /** + * Common service for finding records in Teamcenter. Lazily initialized, use getter method. + **/ + private FinderService finderService; + /** + * Saved Query Service. Lazily initialized, use getter method. + */ + private SavedQueryService savedQueryService; + /** + * file Management Utility. Lazily initialized, use getter method. + */ + private FileManagementUtility fileManagementUtility; + /** + * Worfklow service. Lazily initialized, use getter method. + */ + private WorkflowService workflowService; + private String discriminator; + + /** + * Default constructor using settings from properties. + **/ + public TcSession() { + this(URL, DEFAULT_FSC_PARAMS); + } + + /** + * Create an instance of the Session with a connection to the specified server. + *

    + * Add implementations of the ExceptionHandler, PartialErrorListener, ChangeListener, and DeleteListeners. + * + * @param aConnectionUrl Address of the host to connect to, http://serverName:port/tc + * @param fscParameters the FSC connection parameters + */ + public TcSession(final String aConnectionUrl, final FscParameters fscParameters) { + this.fscParams = fscParameters; + initHostConnection(aConnectionUrl); + } + + /** + * Connection status. + * + * @return true if the connection is logged in. + */ + private boolean isLoggedIn() { + return loggedIn != null; + } + + /** + * Create an instance of the CredentialManager.
    + * This is used by the SOA Framework to findAll the user's credentials when challenged by the server
    + * (session timeout on the web tier). + **/ + private void initHostConnection(final String aConnectionUrl) { + TcCredentialManager credentialManager = new TcCredentialManager(); + LOGGER.debug("Initialize connection to URL: {}", aConnectionUrl); + String connectionUrl; + String protocol; + String envNameTccs = null; + if (aConnectionUrl.startsWith("http")) { + protocol = SoaConstants.HTTP; + connectionUrl = aConnectionUrl; + } else if (aConnectionUrl.startsWith("tccs")) { + protocol = SoaConstants.TCCS; + connectionUrl = aConnectionUrl.trim(); + int envNameStart = connectionUrl.indexOf('/') + 2; + envNameTccs = connectionUrl.substring(envNameStart, connectionUrl.length()); + connectionUrl = ""; + } else { + protocol = SoaConstants.IIOP; + connectionUrl = aConnectionUrl; + } + + // Create the Connection object, no contact is made with the server until a service request is made + connection = new Connection(connectionUrl, credentialManager, SoaConstants.REST, protocol); + + if (protocol.equals(SoaConstants.TCCS)) { + connection.setOption(Connection.TCCS_ENV_NAME, envNameTccs); + } + + connection.getModelManager().addModelEventListener(new KurtModelEventListener()); + + // Add an ExceptionHandler to the Connection, this will handle any InternalServerException, communication errors, XML marshaling errors + connection.setExceptionHandler(new TcExceptionHandler()); + } + + /** + * Login to the Teamcenter Server. This method is guaranteed to terminate. + * + * @return a {@link LoginResponse} object + * @throws NoTeamcenterConnectionException if unable to setup the connection (Tc might not be responding) + */ + public LoginResponse login() throws NoTeamcenterConnectionException { + if (loggedIn != null) { + return loggedIn; + } + // Timeout the logout in async thread + ExecutorService executor = Executors.newSingleThreadExecutor(); + Future future = executor.submit(new LoginTask()); // Start performing the logout... + try { + loggedIn = future.get(TIMEOUT_SEC, TimeUnit.SECONDS); // Check if successful, do not wait more than this + emptyPolicy(); + enableBypass(); + LOGGER.info("TcSession logged in {}/{}", USERNAME, discriminator); + } catch (TimeoutException e) { + // More than xxx seconds for a login? the Tc servers must be hanging, findAll out + future.cancel(true); + throw new NoTeamcenterConnectionException(ERROR_MSG_LOGIN_TIMEOUT, e); + } catch (InterruptedException e) { + throw new NoTeamcenterConnectionException("Login interrupted", e); + } catch (Exception e) { + Throwable rootCause = e.getCause(); + if (rootCause instanceof InvalidCredentialsException) { + NoTeamcenterConnectionException noTeamcenterConnectionException = + new NoTeamcenterConnectionException("Failed connection to Tc services", rootCause); + noTeamcenterConnectionException.addSuppressed(e); + throw noTeamcenterConnectionException; + } else if (rootCause instanceof ConnectionLostException) { // Connections as made, but no session were available + throw (ConnectionLostException) rootCause; + } else if (rootCause instanceof ServiceException) { + throw new NoTeamcenterConnectionException("Service Exception encountered during login", rootCause); + } else { + throw new NoTeamcenterConnectionException("Connection to Teamcenter failed", e); + } + } + executor.shutdown(); + return loggedIn; + } + + /** + * Terminate the session with the Teamcenter Server gracefully. + */ + @Override + public void close() { + if (isLoggedIn()) { + // Terminate an optional FileManagementUtility separately + if (fileManagementUtility != null) { + fileManagementUtility.term(); + } + + // Timeout the logout in async thread + ExecutorService executor = Executors.newSingleThreadExecutor(); + Future future = executor.submit(new LogoutTask()); // Start performing the logout... + try { + LOGGER.debug(future.get(TIMEOUT_SEC, TimeUnit.SECONDS)); // Check if successful, do not wait more than that + LOGGER.info("TcSession logged out {}/{}", USERNAME, discriminator); + } catch (TimeoutException e) { + // More than xxx seconds for a logout? the Tc servers must be hanging, findAll out + future.cancel(true); + LOGGER.info("Timed out during logout of Tc Servers", e); + } catch (InterruptedException e) { + LOGGER.info("Logout interrupted", e); + } catch (ExecutionException e) { + Throwable rootCause = e.getCause(); + if (rootCause instanceof ConnectionLostException) { + // This is ok, we can't LOGGER out because lost connection in the first place + LOGGER.trace("Unable to logout of Tc session", e); + } else { + LOGGER.info("Unable to logout of Tc session", e); + } + } + executor.shutdown(); + loggedIn = null; + } else { + LOGGER.warn("Trying to logout of the session, but the session is not logged in"); + } + } + + public void setObjectPropPolicy(final PolicyLocation policy) throws InvalidConfigurationException { + boolean success = setPolicy(policy.getIdentifier()); + LOGGER.info(success ? "Policy \"{}\" file is now the active policy" : "Policy \"{}\" file could not be loaded ({})", policy.getIdentifier()); + } + + public void emptyPolicy() throws InvalidConfigurationException { + setPolicy("Empty"); + } + + /** + * Changes the policy on the server, for this session. + */ + private boolean setPolicy(String identifier) throws InvalidConfigurationException { + try { + return SessionService.getService(connection).setObjectPropertyPolicy(identifier); + } catch (ServiceException e) { + throw new InvalidConfigurationException("Teamcenter could not load Object Property Policy file \"" + identifier + "\"", e); + } + } + + /** + * Enable bypass for dba user. + */ + private void enableBypass() { + StateNameValue property = new StateNameValue(); + property.name = "bypassFlag"; + property.value = Boolean.TRUE.toString(); + SessionService sessionService = SessionService.getService(connection); + ServiceData response = sessionService.setUserSessionState(new StateNameValue[]{property}); + if (ServiceDataHelper.hasErrors(response)) { + ServiceDataHelper.displayErrors(response); + } + } + + /** + * Getter for structureManagementService. + * + * @return Service instance for structure management + **/ + public StructureManagementService getStructureManagementService() { + if (structureManagementService == null) { + structureManagementService = StructureManagementService.getService(connection); + } + return structureManagementService; + } + + /** + * Getter for finderService. + * + * @return Service instance for finder + **/ + public FinderService getFinderService() { + if (finderService == null) { + finderService = FinderService.getService(connection); + } + return finderService; + } + + /** + * Returns a {@link SavedQueryService} to perform searches using Saved Queries. + * + * @return a SavedQueryService + */ + public SavedQueryService getSavedQueryService() { + if (savedQueryService == null) { + savedQueryService = SavedQueryService.getService(connection); + } + return savedQueryService; + } + + /** + * Returns a new instance of {@link WorkflowService}. + * + * @return a new instance of the service + */ + public WorkflowService getWorkflowService() { + if (workflowService == null) { + workflowService = WorkflowService.getService(connection); + } + return workflowService; + } + + /** + * Returns a {@link FileManagementUtility} instance. + *

    + * There is no need to {@link FileManagementUtility#term() term()} this instance after usage.
    + * Cleanup will be performed by this {@link TcSession} upon being {@link TcSession#close() closed}.
    + * This instance is created on-demand, and cached for later use, as the object is rather heavy (server-side). + * + * @return a {@link FileManagementUtility} instance + * @throws ConnectionMisconguredException if FSC parameters are incorrect + */ + public FileManagementUtility getFileManagementUtility() throws ConnectionMisconguredException { + if (fileManagementUtility == null) { + String clientIPAddress = fscParams.getClientIPAddress(); + String[] assignedFscURIs = fscParams.getAssignedFscURIs(); + String[] bootstrapFscURIs = fscParams.getBootstrapFscURIs(); + String cacheDir = fscParams.getCacheDir(); + try { + fileManagementUtility = new FileManagementUtility(connection, clientIPAddress, assignedFscURIs, bootstrapFscURIs, cacheDir); + } catch (FileNotFoundException e) { + throw new ConnectionMisconguredException("Failed to start FileManagementUtility, FSC parameters might not be set properly", e); + } + } + return fileManagementUtility; + } + + public TcBomWindow createBomWindow(final TcBomWindowConfiguration bomWindowConfiguration) throws KurtException { + return new TcBomWindowFactory(this, bomWindowConfiguration).create(); + } + + public TcRevisionRule findRevRule(final String revRuleNameToFind) throws KurtException { + try { + GetRevisionRulesResponse revisionRulesResponse = getStructureManagementService().getRevisionRules(); + if (ServiceDataHelper.hasErrors(revisionRulesResponse.serviceData)) { + ServiceDataHelper.displayErrors(revisionRulesResponse.serviceData); + throw new NoSuchRevisionRuleException("Error while loading revision rules."); + } + for (RevisionRuleInfo revisionRuleInfo: revisionRulesResponse.output) { + RevisionRule revRule = revisionRuleInfo.revRule; + loadProperties(revRule, "object_name"); + String revRuleName = revRule.get_object_name(); + if (revRuleNameToFind.equals(revRuleName)) { + LOGGER.debug("Revision rule {} found.", revRuleName); + return new TcRevisionRule(this, revRule); + } + } + } catch (ServiceException e) { + throw new NoSuchRevisionRuleException("Teamcenter could not load the revision rules.", e); + } + throw new NoSuchRevisionRuleException("Unable to find the Revision Rule: " + revRuleNameToFind); + } + + public List findR26RevRule(String reportRevRule) throws NoSuchRevisionRuleException { + List revisionRules = new ArrayList<>(); + try { + GetRevisionRulesResponse revisionRulesResponse = getStructureManagementService().getRevisionRules(); + if (ServiceDataHelper.hasErrors(revisionRulesResponse.serviceData)) { + ServiceDataHelper.displayErrors(revisionRulesResponse.serviceData); + throw new NoSuchRevisionRuleException("Error while loading revision rules."); + } + for (RevisionRuleInfo revisionRuleInfo: revisionRulesResponse.output) { + RevisionRule revRule = revisionRuleInfo.revRule; + loadProperties(revRule, "object_name"); + String revRuleName = revRule.get_object_name(); + if (revRuleName.startsWith(reportRevRule + "-")) { + LOGGER.debug("Revision rule {} found.", revRuleName); + revisionRules.add(revRule); + } + } + } catch (ServiceException e) { + throw new NoSuchRevisionRuleException("Teamcenter could not load the revision rules.", e); + } + return revisionRules; + } + + public void loadProperties(ModelObject modelObjects, String... properties) { + loadProperties(new ModelObject[]{modelObjects}, properties); + } + + public void loadProperties(ModelObject[] modelObjects, String... properties) { + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("Loading {} properties on objects {}", properties.length == 0 ? "all" : Arrays.toString(properties), Arrays.toString(modelObjects)); + } + ServiceData serviceData = DataManagementService.getService(connection).getProperties(modelObjects, properties); + if (ServiceDataHelper.hasErrors(serviceData)) { + ServiceDataHelper.displayErrors(serviceData); + } + } + + public void setProperties(ModelObject modelObject, Map map) { + PropInfo propInfo = new PropInfo(); + propInfo.object = modelObject; + propInfo.vecNameVal = new NameValueStruct1[map.size()]; + + int i = 0; + for (Map.Entry entry : map.entrySet()) { + NameValueStruct1 nameValueStruct1 = new NameValueStruct1(); + nameValueStruct1.name = entry.getKey(); + + Object propertyValue = entry.getValue(); + if (propertyValue != null) { + if (propertyValue.getClass().equals(String.class)) { + nameValueStruct1.values = new String[1]; + nameValueStruct1.values[0] = (String) propertyValue; + + propInfo.vecNameVal[i] = nameValueStruct1; + i++; + } else if (propertyValue.getClass().equals(String[].class)) { + nameValueStruct1.values = (String[]) propertyValue; + + propInfo.vecNameVal[i] = nameValueStruct1; + i++; + } + } + } + + SetPropertyResponse setPropertyResponse = DataManagementService.getService(connection).setProperties(new PropInfo[]{propInfo}, new String[]{}); + if (ServiceDataHelper.hasErrors(setPropertyResponse.data)) { + ServiceDataHelper.displayErrors(setPropertyResponse.data); + } + } + + public List loadObjects(String... uids) { + List objectLoaded = new ArrayList<>(); + ServiceData serviceData = DataManagementService.getService(connection).loadObjects(uids); + if (ServiceDataHelper.hasErrors(serviceData)) { + ServiceDataHelper.displayErrors(serviceData); + } + for (int objectIndex = 0; objectIndex < serviceData.sizeOfPlainObjects(); objectIndex++) { + T object = (T) serviceData.getPlainObject(objectIndex); + objectLoaded.add(object); + } + return objectLoaded; + } + + public List whereReferenced(final WorkspaceObject workspaceObject, final int level, final Map> relationAndTypesFilter) throws KurtException { + WhereReferencedResponse whereReferencedResponse = DataManagementService.getService(connection).whereReferenced(new WorkspaceObject[]{workspaceObject}, level); + if (ServiceDataHelper.hasErrors(whereReferencedResponse.serviceData)) { + ServiceDataHelper.displayErrors(whereReferencedResponse.serviceData); + throw new KurtException("Some errors were encountered while performing 'referencedBy' request"); + } + List referencedObjects = new ArrayList<>(); + WhereReferencedOutput[] response = whereReferencedResponse.output; + for (WhereReferencedOutput whereReferencedOutput: response) { + LOGGER.debug("InputObject client : {}", whereReferencedOutput.inputObject); + for (WhereReferencedInfo outputInfo: whereReferencedOutput.info) { + String objectType = workspaceObject.getTypeObject().getName(); + LOGGER.debug("object candidate {} relation {}", objectType, outputInfo.relation); + List listRelationTypes = relationAndTypesFilter.get(objectType); + if (listRelationTypes != null && listRelationTypes.contains(outputInfo.relation)) { + referencedObjects.add((ItemRevision) outputInfo.referencer); + } + } + } + return referencedObjects; + } + + public GetDatasetWriteTicketsInputData createDatasets(final DatasetInfo[] datasetProperties, final DatasetFileInfo[] currFiles) throws MalformedDataSetException { + // Perform dataset request using properties + CreateDatasetsResponse resp = DataManagementService.getService(connection).createDatasets(datasetProperties); + if (ServiceDataHelper.hasErrors(resp.servData)) { + ServiceDataHelper.displayErrors(resp.servData); + throw new MalformedDataSetException("Unable to perform the request, dataset creation failed"); + } + + // dataset accepted, now fill the response with dataset data + GetDatasetWriteTicketsInputData dataSetInfoAndData = new GetDatasetWriteTicketsInputData(); + dataSetInfoAndData.dataset = resp.datasetOutput[0].dataset; + dataSetInfoAndData.createNewVersion = false; + dataSetInfoAndData.datasetFileInfos = currFiles; + return dataSetInfoAndData; + } + + public ImanRelation createRelation(final ModelObject primary, final ModelObject secondary, final String relationType) throws FailedRelationshipActionException { + Relationship relation = new Relationship(); + relation.clientId = "KURT-reports"; + relation.primaryObject = primary; + relation.secondaryObject = secondary; + relation.relationType = relationType; + CreateRelationsResponse relationCreationResult = DataManagementService.getService(connection).createRelations(new Relationship[]{relation}); + if (ServiceDataHelper.hasErrors(relationCreationResult.serviceData)) { + ServiceDataHelper.displayErrors(relationCreationResult.serviceData); + } + if (relationCreationResult.output.length == 0) { + throw new FailedRelationshipActionException("The requested relationship could not be created."); + } + return relationCreationResult.output[0].relation; + } + + public void deleteRelations(final ModelObject primary, final ModelObject secondary, final String relationType) throws FailedRelationshipActionException { + Relationship relation = new Relationship(); + relation.clientId = "KURT-reports"; + relation.primaryObject = primary; + relation.secondaryObject = secondary; + relation.relationType = relationType; + ServiceData relationDeletionResult = DataManagementService.getService(connection).deleteRelations(new Relationship[]{relation}); + if (ServiceDataHelper.hasErrors(relationDeletionResult)) { + ServiceDataHelper.displayErrors(relationDeletionResult); + } + if (relationDeletionResult.sizeOfDeletedObjects() == 0) { + throw new FailedRelationshipActionException("The requested relationship could not be destroyed."); + } + } + + public void deleteObjects(final ModelObject... modelObjects) { + ServiceData serviceData = DataManagementService.getService(connection).deleteObjects(modelObjects); + if (ServiceDataHelper.hasErrors(serviceData)) { + ServiceDataHelper.displayErrors(serviceData); + } + } + + + public List whereUsed(final ItemRevision inputObject, final String typeWanted) throws KurtException { + + WhereUsedConfigParameters configParameters = new WhereUsedConfigParameters(); + configParameters.stringMap.put("Type", typeWanted); + configParameters.intMap.put("numLevels", BigInteger.valueOf(1)); + + WhereUsedInputData inputData = new WhereUsedInputData(); + inputData.inputObject = inputObject; + inputData.inputParams = configParameters; + + WhereUsedResponse allResponses = DataManagementService.getService(connection).whereUsed(new WhereUsedInputData[]{inputData}, configParameters); + + List results = new ArrayList<>(); + + if (ServiceDataHelper.hasErrors(allResponses.serviceData)) { + ServiceDataHelper.displayErrors(allResponses.serviceData); + throw new KurtException("Error while retrieving whereUsed on " + inputObject.get_item_id() ); + } + + + + for (WhereUsedParentInfo info: allResponses.output[0].info) { + + if (info.level == 1) { + ItemRevision result = (ItemRevision) info.parentObject; + if (typeWanted.equals(result.getTypeObject().getName())) { + + results.add(result); + } + } + } + + return results; + } + + + + public List whereUsed(final WorkspaceObject inputObject, final int level, final RevisionRule revisionRule) { + WhereUsedConfigParameters configParameters = new WhereUsedConfigParameters(); + configParameters.intMap.put("numLevels", BigInteger.valueOf(level)); + if (revisionRule != null) { + configParameters.tagMap.put("revision_rule", revisionRule); + } + + WhereUsedInputData inputData = new WhereUsedInputData(); + inputData.inputObject = inputObject; + inputData.inputParams = configParameters; + + WhereUsedResponse allResponses = DataManagementService.getService(connection).whereUsed(new WhereUsedInputData[]{inputData}, configParameters); + List results = new ArrayList<>(); + for (WhereUsedParentInfo info: allResponses.output[0].info) { + ItemRevision itemRevision = (ItemRevision) info.parentObject; + + loadProperties(itemRevision, "active_seq"); + int activeSeq = itemRevision.get_active_seq(); + + // only add item last sequence (means the active sequence) + if (activeSeq != 0) { + results.add((ItemRevision) info.parentObject); + } + } + return results; + } + + /** + * Login task. This {@link Callable} can be executed concurrently to perform login. Outcome is the {@link User} logged in. + */ + private final class LoginTask implements Callable { + @Override + public LoginResponse call() throws IOException, KurtException { + try { + SessionService sessionService = SessionService.getService(connection); + Credentials crd = new Credentials(); + crd.user = USERNAME; + crd.password = new AesEncoded(PASSWORD).decode(); + discriminator = UUID.randomUUID().toString(); + crd.descrimator = discriminator; + crd.locale = "FR"; + LoginResponse loginResponse = sessionService.login(crd); + for (Object obj: loginResponse.serverInfo.entrySet()) { + @SuppressWarnings("unchecked") + Map.Entry entry = (Map.Entry) obj; + LOGGER.info(entry.getKey() + " : " + entry.getValue()); + } + return loginResponse; + } finally { + if (Thread.interrupted()) { // The Future got cancelled (probably because of Timeout)... + close(); // ...so we make sure to close() the session (the caller has given up and won't do it) + } + } + } + } + + /** + * Logout task. This {@link Callable} can be executed concurrently to perform logout. Outcome is the {@link User} logged out. + */ + private final class LogoutTask implements Callable { + @Override + public String call() throws ServiceException { + SessionService sessionService = SessionService.getService(connection); + if (LOGGER.isDebugEnabled()) { + try { + LOGGER.debug("[LOGOUT] Showing TCInfo content for session {} : {}", discriminator, sessionService.getTCSessionInfo().extraInfo.get(TC_SERVER_ID).toString()); + } catch (ServiceException e) { + LOGGER.warn(ERROR_MSG_UNABLE_TO_OBTAIN_SESSION_INFO_TC_SERVER_ID, e); + } + } + sessionService.logout(); + return "Logout successful"; + } + } + + + /** + * Clone revision rule: a new Revision Rule is created with the name defined in parameter. + */ + public void cloneRevisionRule(RevisionRule revRuleToCopy, String name) throws Exception { + ICCTSession icctSession = new ICCTSession(connection); + int markpoint = icctSession.placeMarkpoint(new String[0]); + try { + ICCTRevisionRule icctRevisionRule = new ICCTRevisionRule(connection, revRuleToCopy.getTypeObject().getName(), revRuleToCopy.getTypeObject().getUid()); + StringHolder newRevRule = new StringHolder(); + StringHolder revisionRuleType = new StringHolder(); + icctRevisionRule.create(name, name, newRevRule, revisionRuleType); + icctRevisionRule.cloneInstance(revRuleToCopy.getUid(), newRevRule.value); + icctRevisionRule.save(newRevRule.value); + icctSession.forgetMarkpoint(markpoint); + } + catch (Exception e) { + icctSession.rollToMarkpoint(markpoint); + } + } +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/exceptions/ConnectionMisconguredException.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/exceptions/ConnectionMisconguredException.java new file mode 100644 index 0000000..957030a --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/exceptions/ConnectionMisconguredException.java @@ -0,0 +1,24 @@ +package com.capgemini.framework.teamcenter.exceptions; + +/** Exception thrown if the Connection to Teamcenter or to the FSC is not configured properly. */ +public class ConnectionMisconguredException extends KurtException { + private static final long serialVersionUID = -8984259943413332487L; + + /** + * Usual constructor. + * @param aMessage a message + */ + public ConnectionMisconguredException(String aMessage) { + super(aMessage); + } + + /** + * Usual constructor with root cause. + * @param aMessage a message + * @param rootCause the root exception + */ + public ConnectionMisconguredException(String aMessage, Throwable rootCause) { + super(aMessage, rootCause); + } + +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/exceptions/EmptyNomenclatureException.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/exceptions/EmptyNomenclatureException.java new file mode 100644 index 0000000..70d9d59 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/exceptions/EmptyNomenclatureException.java @@ -0,0 +1,35 @@ +package com.capgemini.framework.teamcenter.exceptions; + +/** Error occurring if the resolution structure doesn't work. */ +public class EmptyNomenclatureException extends KurtException { + + private static final long serialVersionUID = -3412885624655787481L; + + /** + * Constructor. + * + * @param aMessage String - the message + */ + public EmptyNomenclatureException(final String aMessage) { + super(aMessage); + } + + /** + * Constructor. + * + * @param aMessage String - the message + * @param anException {@link Throwable} - the exception + */ + public EmptyNomenclatureException(final String aMessage, final Throwable anException) { + super(aMessage, anException); + } + + /** + * Constructor. + * + * @param anException {@link Throwable} - the exception + */ + public EmptyNomenclatureException(final Throwable anException) { + super(anException.getMessage(), anException); + } +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/exceptions/FailedRelationshipActionException.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/exceptions/FailedRelationshipActionException.java new file mode 100644 index 0000000..b48b5d5 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/exceptions/FailedRelationshipActionException.java @@ -0,0 +1,29 @@ +package com.capgemini.framework.teamcenter.exceptions; + +import com.teamcenter.services.strong.core._2006_03.DataManagement.Relationship; + +/** This exception is thrown when unable to perform an operation on {@link Relationship} between objects. */ +public class FailedRelationshipActionException extends KurtException { + + private static final long serialVersionUID = 4835457230745841725L; + + /** + * Simple constructor. For an original exception. + * + * @param msg the tech error message + */ + public FailedRelationshipActionException(final String msg) { + super(msg); + } + + /** + * Simple constructor. For an derived exception. + * + * @param msg the tech error message + * @param exc original exception + */ + public FailedRelationshipActionException(final String msg, final Throwable exc) { + super(msg, exc); + } + +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/exceptions/InvalidConfigurationException.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/exceptions/InvalidConfigurationException.java new file mode 100644 index 0000000..a8f82cd --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/exceptions/InvalidConfigurationException.java @@ -0,0 +1,29 @@ +package com.capgemini.framework.teamcenter.exceptions; + +/** + * {@link Exception} thrown when the configuration is invalid.
    + * It may be missing data or, or maybe the Generic does not exist under the specified Product etc. + */ +public class InvalidConfigurationException extends KurtException { + + private static final long serialVersionUID = 1271823633534992733L; + + /** + * Simple constructor. For an original exception. + * + * @param msg the tech error message + */ + public InvalidConfigurationException(final String msg) { + super(msg); + } + + /** + * Simple constructor. For an derived exception. + * + * @param msg the tech error message + * @param exc original exception + */ + public InvalidConfigurationException(final String msg, final Throwable exc) { + super(msg, exc); + } +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/exceptions/KurtException.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/exceptions/KurtException.java new file mode 100644 index 0000000..a3f26d1 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/exceptions/KurtException.java @@ -0,0 +1,40 @@ +package com.capgemini.framework.teamcenter.exceptions; + +/** + * Generic Exception to be able to catch all the KURT-Generated exceptions in a single catch. + * + */ +public class KurtException extends Exception { + + /** Serialization UID. **/ + private static final long serialVersionUID = -7235562571986874642L; + + /** + * Simple Constructor. Takes an input error message as parameter. + * + * @param aMessage Error message + */ + public KurtException(final String aMessage) { + super(aMessage); + } + + /** + * Constructor. + * + * @param aMessage Error message + * @param anException Original exception + */ + public KurtException(final String aMessage, final Throwable anException) { + super(aMessage, anException); + } + + /** + * Returns the message to be sent to the user. + * + * @return the message + */ + public String getErrorMessageForUser() { + return "Une erreur interne s’est produite."; + } + +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/exceptions/MalformedDataSetException.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/exceptions/MalformedDataSetException.java new file mode 100644 index 0000000..9ee2036 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/exceptions/MalformedDataSetException.java @@ -0,0 +1,27 @@ +package com.capgemini.framework.teamcenter.exceptions; + +/** Exception encountered when a DataSet could not be created because of incoorect inputs. */ +public class MalformedDataSetException extends KurtException { + + private static final long serialVersionUID = 1852176831050983022L; + + /** + * Simple constructor. For an original exception. + * + * @param msg the tech error message + */ + public MalformedDataSetException(final String msg) { + super(msg); + } + + /** + * Simple constructor. For an derived exception. + * + * @param msg the tech error message + * @param exc original exception + */ + public MalformedDataSetException(final String msg, final Throwable exc) { + super(msg, exc); + } + +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/exceptions/NoSuchBomViewException.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/exceptions/NoSuchBomViewException.java new file mode 100644 index 0000000..d58f9d8 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/exceptions/NoSuchBomViewException.java @@ -0,0 +1,28 @@ +package com.capgemini.framework.teamcenter.exceptions; + +import com.teamcenter.soa.client.model.strong.BOMView; + +/** Exception thrown whan the Request {@link BOMView} does not exist on an object. */ +public class NoSuchBomViewException extends KurtException { + + private static final long serialVersionUID = -7773553173685231832L; + + /** + * Exception thrown when the Request {@link BOMView} does not exist on an object. + * + * @param msg the reason + */ + public NoSuchBomViewException(final String msg) { + super(msg); + } + + /** + * Simple constructor. For an derived exception. + * + * @param msg the reason + * @param exc original exception + */ + public NoSuchBomViewException(final String msg, final Throwable exc) { + super(msg, exc); + } +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/exceptions/NoSuchRevisionRuleException.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/exceptions/NoSuchRevisionRuleException.java new file mode 100644 index 0000000..bdd2702 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/exceptions/NoSuchRevisionRuleException.java @@ -0,0 +1,29 @@ +package com.capgemini.framework.teamcenter.exceptions; + +import com.teamcenter.soa.client.model.strong.RevisionRule; + +/** {@link Exception} thrown when the requested {@link RevisionRule} does not seem to exist on the TC servers. */ +public class NoSuchRevisionRuleException extends KurtException { + + private static final long serialVersionUID = -1497854843179454406L; + + /** + * Simple constructor. For an Original exception. + * + * @param msg the tech error message + */ + public NoSuchRevisionRuleException(final String msg) { + super(msg); + } + + /** + * Simple constructor. For a derived exception. + * + * @param msg the tech error message + * @param exc original exception + */ + public NoSuchRevisionRuleException(final String msg, final Throwable exc) { + super(msg, exc); + } + +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/exceptions/NoTeamcenterConnectionException.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/exceptions/NoTeamcenterConnectionException.java new file mode 100644 index 0000000..ea305f7 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/exceptions/NoTeamcenterConnectionException.java @@ -0,0 +1,27 @@ +package com.capgemini.framework.teamcenter.exceptions; + +/** Thrown when no connection could be obtained to a Tc server. */ +public class NoTeamcenterConnectionException extends KurtException { + + private static final long serialVersionUID = 7317052053857458609L; + + /** + * Simple constructor. For an Original exception. + * + * @param aMessage the tech error message + */ + public NoTeamcenterConnectionException(String aMessage) { + super(aMessage); + } + + /** + * Simple constructor. For a derived exception. + * + * @param aMessage the tech error message + * @param anException original exception + */ + public NoTeamcenterConnectionException(String aMessage, Throwable anException) { + super(aMessage, anException); + } + +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/exceptions/QueryDoesNotExist.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/exceptions/QueryDoesNotExist.java new file mode 100644 index 0000000..02f9d9a --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/exceptions/QueryDoesNotExist.java @@ -0,0 +1,27 @@ +package com.capgemini.framework.teamcenter.exceptions; + +/** Exception to be used when the requested SavedQuery does not exist. */ +public class QueryDoesNotExist extends KurtException { + + private static final long serialVersionUID = 5026463541399654426L; + + /** + * Usual constructor for a newly found exception. + * + * @param msg error message + */ + public QueryDoesNotExist(final String msg) { + super(msg); + } + + /** + * Usual constructor to explain an incoming exception. + * + * @param msg error message + * @param exc original exception + */ + public QueryDoesNotExist(final String msg, final Throwable exc) { + super(msg, exc); + } + +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/exceptions/UnableToCreateStatusException.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/exceptions/UnableToCreateStatusException.java new file mode 100644 index 0000000..771525c --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/exceptions/UnableToCreateStatusException.java @@ -0,0 +1,28 @@ +package com.capgemini.framework.teamcenter.exceptions; + +/** Exception encountered when unable to create a Status on an Object. */ +public class UnableToCreateStatusException extends KurtException { + + private static final long serialVersionUID = 5026463541399654426L; + + /** + * Usual constructor for a newly found exception. + * + * @param msg error message + */ + public UnableToCreateStatusException(final String msg) { + super(msg); + } + + /** + * Usual constructor to explain an incoming exception. + * + * @param msg error message + * @param exc original exception + */ + public UnableToCreateStatusException(final String msg, final Throwable exc) { + super(msg, exc); + } + + +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/exceptions/runtime/ConnectionLostException.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/exceptions/runtime/ConnectionLostException.java new file mode 100644 index 0000000..fa2e125 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/exceptions/runtime/ConnectionLostException.java @@ -0,0 +1,19 @@ +package com.capgemini.framework.teamcenter.exceptions.runtime; + +import com.teamcenter.schemas.soa._2006_03.exceptions.InternalServerException; + +/** {@link RuntimeException} thrown when connection is suddenly lost. */ +public class ConnectionLostException extends KurtRuntimeException { + + private static final long serialVersionUID = -7645238831152306945L; + + /** + * Builds an {@link ConnectionLostException} that has a custom error message, and originates from a Tc {@link InternalServerException}. + * @param message custom error message + * @param anException original Tc exception + */ + public ConnectionLostException(final String message, final InternalServerException anException) { + super(message, anException); + } + +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/exceptions/runtime/KurtRuntimeException.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/exceptions/runtime/KurtRuntimeException.java new file mode 100644 index 0000000..7988f8d --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/exceptions/runtime/KurtRuntimeException.java @@ -0,0 +1,26 @@ +package com.capgemini.framework.teamcenter.exceptions.runtime; + +/** + * Super type of any {@link RuntimeException} thrown by the KURT application. + */ +public class KurtRuntimeException extends RuntimeException { + private static final long serialVersionUID = 6157368198636151053L; + + public KurtRuntimeException() { + } + + public KurtRuntimeException(String message) { + super(message); + } + + /** + * Builds an {@link KurtRuntimeException} that has a custom error message, and originates from an original exception. + * + * @param message custom error message + * @param anException original exception + */ + public KurtRuntimeException(final String message, final Throwable anException) { + super(message, anException); + } + +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/files/DatasetPreparator.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/files/DatasetPreparator.java new file mode 100644 index 0000000..047c590 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/files/DatasetPreparator.java @@ -0,0 +1,154 @@ +package com.capgemini.framework.teamcenter.files; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.MalformedDataSetException; +import com.capgemini.framework.teamcenter.files.FileManagement.FileType; +import com.google.common.base.Optional; +import com.teamcenter.services.loose.core._2006_03.FileManagement.DatasetFileInfo; +import com.teamcenter.services.loose.core._2006_03.FileManagement.GetDatasetWriteTicketsInputData; +import com.teamcenter.services.strong.core._2010_04.DataManagement.DatasetInfo; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.io.File; +import java.util.Comparator; +import java.util.Set; +import java.util.TreeSet; + +/** + * This class compiles and prepare the necessary data for creating a dataset, then is able to create it on the TC servers.
    + * The dataset may contain several files. + */ +@Getter(value = AccessLevel.PROTECTED) +public class DatasetPreparator { + + /** + * constant for debugging and retrieving the origin of a dataset. + */ + private static final String CLIENT_ID = "KurtReport_FromWorkflow"; + + /** + * We apparently cannot upload two files with the same name to the same Dataset because this creates a relation name conflict.
    + * So this comparator ensures there are no two files with the same filenames. + */ + private static final Comparator fileNameComparator = new Comparator() { + @Override + public int compare(final DataBundle obj1, final DataBundle obj2) { + return obj1.getDatasetInfo().fileName.compareTo(obj2.getDatasetInfo().fileName); + } + }; + + private final String datasetName; + private final String datasetDescription; + private final Set filesInDataSet = new TreeSet<>(fileNameComparator); + private final TcSession session; + private Optional datasetTicket = Optional.absent(); + + /** + * Constructs a {@link DatasetPreparator}, defines its name and description. + */ + public DatasetPreparator(final TcSession session, final String datasetName, final String datasetDescription) throws MalformedDataSetException { + this.session = session; + if (datasetName == null || datasetName.isEmpty()) { + throw new MalformedDataSetException("Insufficient parameters for dataset creation"); + } + this.datasetName = datasetName; + this.datasetDescription = datasetDescription == null ? "" : datasetDescription; + } + + /** + * Returns true if a dataset ticket has been created. + * + * @return true if a dataset ticket has been created. + */ + public boolean isCreated() { + return datasetTicket.isPresent(); + } + + /** + * Obtain the Dataset ticket (a {@link GetDatasetWriteTicketsInputData} object).
    + * This method only works if {@link DatasetPreparator#isCreated()} is true. + */ + public GetDatasetWriteTicketsInputData getCreatedDataset() { + return datasetTicket.get(); + } + + /** + * Add a file to the dataset. + *

    + * Be careful, no two files may have the same name:
    + * If a file already exists with the same name, the new file will NOT be added, and the method will return false (just like in {@link Set} definition). + * + * @param file the File to be added (please ensure the file does exist) + * @param type the {@link FileType} of the file + * @return true if the operation is successful, false if not (maybe a file with same name already exists?) + * @throws MalformedDataSetException when the provided File is null, does not exist, or name is null, empty, or no type is specified + */ + public boolean addFile(final File file, final FileType type) throws MalformedDataSetException { + // Pre conditions + if (file == null || !file.exists()) { + throw new MalformedDataSetException("File for dataset does not exist"); + } + + // Prepare file info + DatasetFileInfo fileInfo = new DatasetFileInfo(); + fileInfo.clientId = CLIENT_ID; + fileInfo.fileName = file.getAbsolutePath(); + fileInfo.namedReferencedName = type.getNamedReferenceName(); + fileInfo.isText = type.isText(); + fileInfo.allowReplace = false; + + + // Prepare dataset request properties + DatasetInfo properties = new DatasetInfo(); + properties.clientId = CLIENT_ID; + properties.type = type.getType(); + properties.name = datasetName; + properties.description = datasetDescription; + + // Store this demand + return filesInDataSet.add(new DataBundle(fileInfo, properties)); + } + + /** + * Creates the dataset on the TC servers. + */ + public GetDatasetWriteTicketsInputData prepare() throws MalformedDataSetException { + if (filesInDataSet.isEmpty()) { + throw new MalformedDataSetException("Insufficient parameters for dataset creation"); + } + if (isCreated()) { + throw new MalformedDataSetException("This Dataset has already been created, cannot ask to create it twice"); + } + + DatasetInfo[] currProps = new DatasetInfo[filesInDataSet.size()]; + DatasetFileInfo[] currFiles = new DatasetFileInfo[filesInDataSet.size()]; + int num = 0; + for (DataBundle bundle : filesInDataSet) { + currProps[num] = bundle.getDatasetProperties(); + currFiles[num] = bundle.getDatasetInfo(); + num++; + } + + GetDatasetWriteTicketsInputData dataSetInfoAndData = session.createDatasets(currProps, currFiles); + datasetTicket = Optional.of(dataSetInfoAndData); + return dataSetInfoAndData; + } + + /** + * Tells if this dataset does not have any files into it. + * + * @return true if no files are specified + */ + public boolean isEmpty() { + return filesInDataSet.isEmpty(); + } + + @AllArgsConstructor + @Getter + private static class DataBundle { + private final DatasetFileInfo datasetInfo; + private final DatasetInfo datasetProperties; + } +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/files/FileManagement.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/files/FileManagement.java new file mode 100644 index 0000000..7307423 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/files/FileManagement.java @@ -0,0 +1,117 @@ +package com.capgemini.framework.teamcenter.files; + +import com.capgemini.framework.teamcenter.ServiceDataHelper; +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.ConnectionMisconguredException; +import com.capgemini.framework.teamcenter.exceptions.MalformedDataSetException; +import com.teamcenter.services.loose.core._2006_03.FileManagement.GetDatasetWriteTicketsInputData; +import com.teamcenter.soa.client.model.ServiceData; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +/** + * Use this class to transfer files into datasets. + */ +@Getter(value = AccessLevel.PROTECTED) +public class FileManagement { + + private final TcSession session; + private final List dataSets = new ArrayList<>(); + + public FileManagement(final TcSession session) { + this.session = session; + } + + /** + * Creates a Dataset with a single file in it. + * + * @param session a logged-in {@link TcSession} + * @param datasetName the name of the dataset + * @param dataSetDescription a description for the dataset (optional: null or empty allowed)) + * @param file a valid {@link File} pointing to the file on local file system to upload on the Tc servers + * @param type the {@link FileType} of file + * @return a {@link GetDatasetWriteTicketsInputData} containing data on the dataset that has been created. + * @throws MalformedDataSetException if anything goes wrong: missing file, conflicting names, wrong types etc. + */ + public static GetDatasetWriteTicketsInputData addSingleDataSet(final TcSession session, final String datasetName, + final String dataSetDescription, final File file, final FileType type) throws MalformedDataSetException, ConnectionMisconguredException { + FileManagement fileManagement; + fileManagement = new FileManagement(session); + fileManagement.addDataSetWithSingleFile(datasetName, dataSetDescription, file, type); + fileManagement.upload(); + return fileManagement.dataSets.get(0); // Only one element + } + + /** + * Adds a dataset definition to the list of datasets to create, with a single file in it. + * + * @param datasetName the name of the dataset + * @param dataSetDescription a description for the dataset (optional: null or empty allowed)) + * @param file a valid {@link File} pointing to the file on local file system to upload on the Tc servers + * @param type the {@link FileType} of file + * @throws MalformedDataSetException if anything goes wrong: missing file, conflicting names, wrong types etc. + */ + public void addDataSetWithSingleFile(final String datasetName, final String dataSetDescription, final File file, final FileType type) + throws MalformedDataSetException { + DatasetPreparator dataset = new DatasetPreparator(session, datasetName, dataSetDescription); + dataset.addFile(file, type); + addDataSet(dataset); + } + + /** + * Adds a custom {@link DatasetPreparator} instance to the batch of datasets to be uploaded.
    + */ + public void addDataSet(final DatasetPreparator dataset) throws MalformedDataSetException { + if (!dataset.isCreated()) { + dataset.prepare(); + } + dataSets.add(dataset.getCreatedDataset()); + } + + /** + * Uploads the files to each registered dataset in Tc. + * + * @throws MalformedDataSetException if anything goes wrong (the files were not uploaded + */ + public void upload() throws MalformedDataSetException, ConnectionMisconguredException { + if (dataSets.isEmpty()) { + throw new MalformedDataSetException("No dataset was provided, unable to create the datasets."); + } + GetDatasetWriteTicketsInputData[] datasetTickets = dataSets.toArray(new GetDatasetWriteTicketsInputData[dataSets.size()]); + ServiceData response = session.getFileManagementUtility().putFiles(datasetTickets); + if (ServiceDataHelper.hasErrors(response)) { + ServiceDataHelper.displayErrors(response); + throw new MalformedDataSetException("Unable to perform fully the request, file upload may have failed"); + } + } + + /** + * Enums of each file type supported as a Teamcenter dataset file. + */ + @Getter + @AllArgsConstructor + public enum FileType { + /** + * Generic Text document. + */ + TEXT_FILE("Text", "Text", true), + /** + * 'Fiche Article' PDF document on Parts. + */ + FICHE_ARTICLE("Fiche Article", "PDF_Reference", false), + /** + * Generic PDF document. + */ + PDF("PDF", "PDF_Reference", false); + + private final String type; + private final String namedReferenceName; + private final boolean text; + } + +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/SnecmaObjectProperties.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/SnecmaObjectProperties.java new file mode 100644 index 0000000..269d615 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/SnecmaObjectProperties.java @@ -0,0 +1,221 @@ +package com.capgemini.framework.teamcenter.object; + +import com.capgemini.framework.teamcenter.TeamcenterObjectProperties; +import lombok.EqualsAndHashCode; + +/** Class regrouping all the properties for objects. */ +@EqualsAndHashCode(callSuper = true) +public final class SnecmaObjectProperties extends TeamcenterObjectProperties { + + /** Property for retrieving the Tc type of an object. */ + public static final String OBJECT_TYPE = "object_type"; + /** Property for retrieving the documents in the pseudofolder "Documents de definition". */ + public static final String PV_DEFINITION_DOCS = "_PV_definition_docs"; + /** Property for retrieving the documents in the pseudofolder "Documents de reference". */ + public static final String PV_REFERENCE_DOCS = "_PV_reference_docs"; + /** Property for retrieving the ChangeRequests in the pseudofolder CR. */ + public static final String PV4_RUNTIME_CR_RELATED = "pv4_runtime_cr_related"; + /** Property for retrieving the ChangeRequests in the pseudofolder CN. */ + public static final String PV4_RUNTIME_CN_RELATED = "pv4_runtime_cn_related"; + /** Property for retrieving the list of ReleaseStatus. */ + public static final String RELEASE_STATUS_LIST = "release_status_list"; + /** Property for retrieving the due date on a EPMTask. */ + public static final String DUE_DATE = "due_date"; + /** Property for retrieving the list of changes for a Unit via the pseudofolder "liste des modifications". */ + public static final String PV_CHANGE_LIST = "_PV_change_list"; + /** Property for retrieving the list of Units for a Product via the pseudofolder "Unit". */ + public static final String PV_UNIT = "_PV_unit"; + /** Property for retrieving the domain of a Product Revision. */ + public static final String PV_DOMAINE = "pv_domaine"; + /** Property for retrieving the ligne produit. */ + public static final String PV_LIGNE_PRODUIT = "pv_ligne_produit"; + /** Property for retrieving Oui/Yes if the Unit is exceptionnel. Else Non/No. */ + public static final String PV_UNIT_EXCEPTIONNEL = "pv_unit_exceptionnel"; + /** Property for retrieving the deliverables. */ + public static final String PV_DELIVERABLES = "_PV_deliverables"; + /** Property for retrieving the generic for a Unit via the pseudofolder "generique". */ + public static final String PV_GENERIC = "_PV_generic"; + /** Property for retrieving the ChangeNotice implementing a ChangeRequest, or the ChangeRequest implementing a ProblemReport. */ + public static final String CM_IMPLEMENTED_BY = "CMImplementedBy"; + /** Pseudo-folder where the Change object links to the Parts that are solution of the change. */ + public static final String CM_HAS_SOLUTION_ITEM = "CMHasSolutionItem"; + /** Property for retrieving the ChangeRequest of an Object. */ + public static final String CM_IMPLEMENTS = "CMImplements"; + /** Property for retrieving the 'external approbation'. */ + public static final String PV_EXTERNAL_APPROBATION = "_PV_external_approbation"; + /** Property for retrieving the 'numero d'approbation SO' (services officiels). */ + public static final String PV_NUMERO_APPROBATION = "pv_numero_approbation_so"; + /** Property for retrieving the type of a modification. */ + public static final String PV4_TYPE_MODIFICATION = "pv4_type_modification"; + /** Property for retrieving the list of generic with interruption for a ChangeItem. */ + public static final String PV_IMP_GENERICS_WITH_INTER = "_PV_imp_generics_with_inter"; + /** Property for retrieving the list of generic without interruption for a ChangeItem. */ + public static final String PV_IMP_GENERICS_WITHOUT_INTER = "_PV_imp_generics_without_inter"; + /** Property for retrieving the 'indice plan'. */ + public static final String PV_INDICE_PLAN = "pv_indice_plan"; + /** Property for retrieving the 'indice cartouche'. */ + public static final String PV_INDICE_CARTOUCHE = "pv_indice_cartouche"; + /** Property for retrieving the 'id origine'. */ + public static final String PV_ID_ORIGINE = "pv_id_origine"; + /** Property for retrieving the security message. */ + public static final String PV_SENSIBILITE_SECURITE = "pv_sensibilite_securite"; + /** Property for retrieving the 'niveau de sensibilite'. */ + public static final String NIVEAU_SENSIBILITE = "ip_classification"; + /** Property for retrieving the 'indice' of a document. */ + public static final String PV_INDICE_DOCUMENT = "pv_indice_document"; + /** Property for retrieving the 'type DocTechnic 1'. */ + public static final String PV_TYPE_DOC_TECHNIC_1 = "pv_type_doc_technic_1"; + /** Property for retrieving the 'type DocTechnic 2'. */ + public static final String PV_TYPE_DOC_TECHNIC_2 = "pv_type_doc_technic_2"; + /** Property for retrieving the mass (double). */ + public static final String PV_MASSE_INDICATIVE = "pv_masse_indicative"; + /** Property for retrieving the mass unit. */ + public static final String PV_UNITE_MASSE = "pv_unite_masse"; + /** Property for retrieving the 'Date de péremption'. */ + public static final String PV4_EXPIRATION_DATE = "pv4_Expiration_date"; + /** Property for retrieving the 'suivi duree de vie'. */ + public static final String PV_SUIVI_DUREE_VIE = "pv_suivi_duree_vie"; + /** Property for retrieving the 'duree de vie'. */ + public static final String PV_DUREE_VIE = "pv_duree_vie"; + /** Property for retrieving the 'unite duree de vie'. */ + public static final String PV_UNITE_DUREE_VIE = "pv_unite_duree_vie"; + /** DMD value of type docNorm */ + public static final String DMD_VALUE_OF_TYPE_DOCNORM = "DMD-Document Matériaux Définition"; + /** DMF value of type docNorm */ + public static final String DMF_VALUE_OF_TYPE_DOCNORM = "DMF général-Document Matériaux Fabrication"; + /** Property for retrieving the 'suivi utilisation'. */ + public static final String PV_SUIVI_UTILISATION = "pv_suivi_utilisation"; + /** Property for retrieving the effectivity. */ + public static final String PV4_TYPE_EFFECTIVITY = "pv4_type_effectivite"; + /** + * Property for retrieving the 'suivi utilisation'. + */ + public static final String PV_SUIVI_DEVELOPPEMENT = "pv_suivi_developpement"; + /** Property for retrieving the 'suivi montage'. */ + public static final String PV_SUIVI_MONTAGE = "pv_suivi_montage"; + /** + * Property for retrieving the 'transfert lien logitique'. + */ + public static final String PV_TRANSFERT_LIEN_LOGISTI = "pv_transfert_lien_logisti"; + /** + * Property for retrieving the 'transfert lien montage'. + */ + public static final String PV_TRANSFERT_LIEN_MONTAGE = "pv_transfert_lien_montage"; + /** Property for retrieving the 'classement'. */ + public static final String PV_CLASSEMENT = "pv_classement"; + /** Property for retrieving the 'classement matiere'. */ + public static final String PV_CLASSEMENT_MATIERE = "pv_classement_matiere"; + /** Property for retrieving the 'responsable conception' user id. */ + public static final String PV_RESPONSABLE_CONCEPTION = "pv_responsable_conception"; + /** Property for retrieving the 'fournisseurs' (Array of String). */ + public static final String PV_FOURNISSEURS = "pv4_pv_fournisseurs"; + /** Property for retrieving the responsable repere of a Form. */ + public static final String PV_RESPONSABLE_REPERE = "pv_responsable_repere"; + /** Property for retrieving the reference transposee snecma of a Form. */ + public static final String PV_REF_TRANSPO_SNECMA = "pv_ref_transpo_snecma"; + /** Property for retrieving the designationEN of a Form. */ + public static final String PV_REF_COMPLETE_CONCEPTEUR = "pv_ref_complete_concepteur"; + /** Property for retrieving the designationEN of a Form. */ + public static final String PV_DESIGNATION_EN = "pv_designation_en"; + /** Property for retrieving the document controle of a Part. */ + public static final String PV_DOCUMENT_CONTROLE = "pv_document_controle"; + /** Property for retrieving the obturation of a Part. */ + public static final String PV_OBTURATION = "pv_obturation"; + /** Property for retrieving the ref associated. */ + public static final String PV_REF_ASSOCIEE = "pv_ref_associee"; + /** Property for retrieving the coherence control. */ + public static final String PV_COHERENCE_CONTROL = "pv_controle_coherence"; + /** Property for retrieving the equivalent sns sin of a RF. */ + public static final String PV_EQUIVALENT_SNS_SIN = "pv_equivalent_sns_sin"; + /** + * Property for retrieving the equivalent maquette int ext of a RF Admin / RF Admin A. + */ + public static final String PV_MAQ_INT_EXT = "pv_maq_int_ext"; + /** Property for retrieving the type produit of a Part PV. */ + public static final String PV_TYPE_PRODUIT = "pv_type_produit"; + /** Property for retrieving the frontiere cooperant of a RF Admin Revision. */ + public static final String PV_FRONTIERE_COOPERANT = "pv_frontiere_cooperant"; + /** Property for retrieving the frontiere avion of a RF Admin Revision. */ + public static final String PV_FRONTIERE_AVION = "pv_frontiere_avion"; + /** Property for retrieving the 'origine demande'. */ + public static final String PV_ORIGINE_DEMANDE = "pv4_origine_demande"; + /** Property for retrieving the status of a User. */ + public static final String STATUS = "status"; + /** Property for retrieving the parts which are alternatives to an Alt Part. */ + public static final String PV_ALTERNATIVE = "_PV_alternative"; + /** Property for retrieving the 'Clause de propriete'. */ + public static final String PV_CLAUSE_PROPRIETE = "pv_clause_propriete"; + /** + * Property for retrieving the Effectivities of an effectivity TcReleaseStatus. + */ + public static final String EFFECTIVITIES = "effectivities"; + + // Internal Object types + /** Property for retrieving the type alternative 1 of an Alternate Revision Master. */ + public static final String PV_TYPE_ALTERNATIVE_1 = "pv_type_alternative_1"; + /** Property for retrieving the type alternative 2 of an Alternate Revision Master. */ + public static final String PV_TYPE_ALTERNATIVE_2 = "pv_type_alternative_2"; + /** Property for retrieving the type det 1 of a DET Revision Master. */ + public static final String PV_TYPE_DET_1 = "pv_type_det_1"; + /** Property for retrieving the type det 2 of a DET Revision Master. */ + public static final String PV_TYPE_DET_2 = "pv_type_det_2"; + /** Property for retrieving the type part montage 1 of a Part Assemb Revision Master. */ + public static final String PV_TYPE_PART_MONTAGE_1 = "pv_type_part_montage_1"; + /** Property for retrieving the type part montage 2 of a Part Assemb Revision Master. */ + public static final String PV_TYPE_PART_MONTAGE_2 = "pv_type_part_montage_2"; + /** Property for retrieving the type part non aero of a Part No Aero Revision Master. */ + public static final String PV_TYPE_PART_NON_AERO = "pv_type_part_non_aero"; + /** Property for retrieving the type part aero 3 of a Part Aero Revision Master. */ + public static final String PV_TYPE_PART_AERO_3 = "pv_type_part_aero_3"; + /** Property for retrieving the type part aero 2 of a Part Aero Revision Master. */ + public static final String PV_TYPE_PART_AERO_2 = "pv_type_part_aero_2"; + /** Property for retrieving the type part aero 1 of a Part Aero Revision Master. */ + public static final String PV_TYPE_PART_AERO_1 = "pv_type_part_aero_1"; + /** Property for retrieving the type standard of a Standard Revision Master. */ + public static final String PV_TYPE_STANDARD = "pv_type_standard"; + /** Property for retrieving the type of a DocNorm. */ + public static final String PV_TYPE_DOC_NORM = "pv_type_doc_norm"; + + // TcReleaseStatus names + /** TcReleaseStatus name 'Def Approved'. */ + public static final String DEF_APPROVED = "Def Approved"; + + // Geometry properties + /** Property for retrieving the 'geometrie piece rigide'. */ + public static final String PV_GEOMETRIE_PIECE_RIGIDE = "pv_geo_piece_rigide"; + /** Property for retrieving the 'geometrie simplifiee'. */ + public static final String PV_GEOMETRIE_SIMPLIFIEE = "pv_geo_piece_simplifiee"; + /** Property for retrieving the 'enveloppe cinematique'. */ + public static final String PV_ENVELOPPE_CINEMATIQUE = "pv_enveloppe_cinematique"; + /** Property for retrieving the 'enveloppe maintenance'. */ + public static final String PV_ENVELOPPE_MAINTENANCE = "pv_enveloppe_maintenance"; + /** Property for retrieving the 'enveloppe montage'. */ + public static final String PV_ENVELOPPE_MONTAGE = "pv_enveloppe_montage"; + /** Property for retrieving the 'trace axiale'. */ + public static final String PV_TRACE_AXIALE = "pv_trace_axiale"; + /** Property for retrieving the 'interface RF Admn'. */ + public static final String PV_INTERFACE_RF_ADMIN = "pv_interface"; + public static final String PV_PROJET_MOTEUR = "pv_projet_moteur"; + public static final String PV_MAQ_ECHANGEABLE = "pv_maq_echangeable"; + public static final String PV_WORKPACKAGE = "pv_workpackage"; + + // TcEffectivity properties + /** Property for retrieving the date_range_text of a date TcEffectivity. */ + public static final String DATE_TEXT_RANGE = "date_range_text"; + /** Property for retrieving the unit_range_text of a Unit. */ + public static final String UNIT_RANGE_TEXT = "unit_range_text"; + + // documentation pseudo-folder (Specific Snecma) + /** Property for retrieving the REACH documents of a Part. */ + public static final String FOLDER_PV_REACH_DOCS = "_PV_reach_docs"; + /** Property for retrieving the ITAR documents of a Part. */ + public static final String FOLDER_PV_ITAR_DOCS = "_PV_itar_docs"; + /** Property for retrieving the definition documents of a Part. */ + public static final String FOLDER_PV_DEFINITION_DOCS = "_PV_definition_docs"; + + // Spare Parts form properties + /** Property for retrieving the 'mot cle EN' */ + public static final String PV_MOT_CLEF_EN = "pv_mot_clef_en"; + /** Property for retrieving the 'mot cle FR' */ + public static final String PV_MOT_CLEF_FR = "pv_mot_clef_fr"; +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/TcBusinessObject.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/TcBusinessObject.java new file mode 100644 index 0000000..33de617 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/TcBusinessObject.java @@ -0,0 +1,4 @@ +package com.capgemini.framework.teamcenter.object; + +public interface TcBusinessObject extends TcModelObject { +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/TcModelObject.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/TcModelObject.java new file mode 100644 index 0000000..6e9860c --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/TcModelObject.java @@ -0,0 +1,6 @@ +package com.capgemini.framework.teamcenter.object; + +public interface TcModelObject { + + +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/TcPomObject.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/TcPomObject.java new file mode 100644 index 0000000..6ec23ae --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/TcPomObject.java @@ -0,0 +1,6 @@ +package com.capgemini.framework.teamcenter.object.pom; + +import com.capgemini.framework.teamcenter.object.TcBusinessObject; + +public interface TcPomObject extends TcBusinessObject { +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/status/StatusEnum.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/status/StatusEnum.java new file mode 100644 index 0000000..0d91940 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/status/StatusEnum.java @@ -0,0 +1,273 @@ +package com.capgemini.framework.teamcenter.object.pom.status; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import com.teamcenter.soa.client.model.strong.ReleaseStatus; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * Enumeration of status. Use {@link StatusEnum#toString()} for the user-friendly name, and {@link StatusEnum#getIdentifier()} for the actual Tc code name. + */ +@Slf4j +@Getter +@AllArgsConstructor +public enum StatusEnum { + AD_CANCELLED("AD Cancelled"), + AD("AD"), + J0("J0"), + J1("J1"), + J2("J2"), + J3A("J3A"), + J3B("J3B"), + STUDY_CLOSED("Study closed"), + STUDY_FINISHED("PV4_STU_FINISHED"), + STUDY_FINISHED_A("PV4_STU_FINISHED_A"), + PRELIM_DEF_READY("Prelim Def Ready"), + DEF_READY("Def Ready"), + PRELIM_DEF_APPROVED("Prelim Def Approved"), + DEF_APPROVED("Def Approved"), + DEF_FINISHED("PV4_DEF_FINISHED"), + PUBLISHED("Published"), + FROZEN_IN_PROCESS("Frozen in process"), + FROZEN("Frozen"), + CREATED("Created"), + PRELIM_CREATED("Prelim Created"), + OPENING_IN_PROCESS("Opening in process"), + OPEN("Open"), + CANCELLED("Cancelled"), + FINISHED("Finished"), + PB_REPORT_APPROVED("Pb Report Approved"), + SB_DISTRIBUTED("SB distributed"), + + INTERFACE_TODO("Interface TODO"), + DMU_KO_PART_R("DMU KO PART R"), + DMU_KO_PART_S("DMU KO PART S"), + DMU_KO_PART_P("DMU KO PART P"), + DMU_KO_PART_K("DMU KO PART K"), + DMU_KO_PART_M("DMU KO PART M"), + DMU_KO_PART_I("DMU KO PART I"), + DMU_KO_PART_C("DMU KO PART C"), + DMU_OK("DMU OK"), + DMU_READY("DMU Ready"), + + EFFECTIVITY(SnecmaObjectTypes.EFFECTIVITY), + SET_EFFECTIVITY("Set_Effectivity"), + OLD_EFFECTIVITY("Old effectivity"), + UNKNOWN_STATUS("Unknown"); + + /** + * Filter that keeps only DMU statuses. + */ + public static final AbstractStatusFilter ONLY_DMU = + new StatusInclusionFilter(DMU_KO_PART_C, DMU_KO_PART_I, DMU_KO_PART_K, DMU_KO_PART_M, DMU_KO_PART_P, DMU_KO_PART_R, DMU_KO_PART_S); + /** + * Filter that keeps only TcEffectivity statuses. + */ + public static final AbstractStatusFilter ONLY_EFFECTIVITIES = new StatusInclusionFilter(EFFECTIVITY, SET_EFFECTIVITY, OLD_EFFECTIVITY); + /** + * Filter that keeps Change Maturity statuses. + */ + public static final AbstractStatusFilter CHANGE_MATURITY = new StatusInclusionFilter(AD, AD_CANCELLED, CANCELLED, CREATED, DEF_APPROVED, + DEF_READY, DEF_FINISHED, FINISHED, J0, J1, J2, J3A, J3B, PB_REPORT_APPROVED, PRELIM_CREATED, PRELIM_DEF_APPROVED, PRELIM_DEF_READY, + SB_DISTRIBUTED, STUDY_CLOSED, STUDY_FINISHED, STUDY_FINISHED_A); + /** + * Filter that keeps Unit Maturity statuses. + */ + public static final AbstractStatusFilter UNIT_MATURITY = + new StatusInclusionFilter(OPENING_IN_PROCESS, OPEN, J3A, J3B, FROZEN_IN_PROCESS, FROZEN, CANCELLED); + private final String identifier; + + /** + * Give the appropriate {@link StatusEnum} associate to the string value.
    + * Else return null. + * + * @param value String - the string value + * @return the appropriate {@link StatusEnum}. Return {@link StatusEnum#UNKNOWN_STATUS} if the string value doesn't exist. + */ + public static StatusEnum getStatusEnum(final String value) { + for (StatusEnum status : StatusEnum.values()) { + if (status.identifier.equals(value)) { + return status; + } + } + log.warn("Unsupported status found. The string {} is not valid.", value); + return UNKNOWN_STATUS; + } + + /** + * Creates a {@link AbstractStatusFilter} object which will only allow the provided StatusEnum. + * + * @param authorized the authorized {@link StatusEnum}s. + * @return the {@link AbstractStatusFilter} + */ + public static AbstractStatusFilter allow(final StatusEnum... authorized) { + return new StatusInclusionFilter(authorized); + } + + /** + * Creates a {@link AbstractStatusFilter} object which will only not allow the provided StatusEnum. + * + * @param forbidden the forbidden {@link StatusEnum}s. + * @return the {@link AbstractStatusFilter} + */ + public static AbstractStatusFilter forbid(final StatusEnum... forbidden) { + return new StatusExclusionFilter(forbidden); + } + + /** + * Definition of a filter that may allow or not a StatusEnum based on its (String) name, or on its StatusEnum instance. + */ + public abstract static class AbstractStatusFilter { + + /** + * Returns true if the provided status should be excluded. + * + * @param status the status to evaluate + * @return true if it should be excluded, false otherwise + */ + public abstract boolean isExcluded(final StatusEnum status); + + /** + * Returns true if the provided status should be included. + * + * @param status the status to evaluate + * @return true if it should be included, false otherwise + */ + public abstract boolean isIncluded(final StatusEnum status); + + /** + * Returns true if the provided status name should be excluded. + * + * @param status the status to evaluate + * @return true if it should be excluded, false otherwise. + */ + public boolean isExcluded(final TcReleaseStatus status) { + StatusEnum statusEnum = status.getStatusEnum(); + return isExcluded(statusEnum); + } + + /** + * Returns true if the provided status name should be included. + * + * @param status the status to evaluate + * @return true if it should be included, false otherwise. + */ + public boolean isIncluded(final TcReleaseStatus status) { + StatusEnum statusEnum = status.getStatusEnum(); + return isIncluded(statusEnum); + } + + /** + * Returns true if the provided status name should be excluded. + * + * @param status the name of the status to evaluate + * @return true if it should be excluded, false otherwise. + */ + public boolean isExcluded(final String status) { + StatusEnum statusEnum = getStatusEnum(status); + return isExcluded(statusEnum); + } + + /** + * Returns true if the provided status name should be included. + * + * @param status the name of the status to evaluate + * @return true if it should be included, false otherwise. + */ + public boolean isIncluded(final String status) { + StatusEnum statusEnum = getStatusEnum(status); + return isIncluded(statusEnum); + } + + /** + * Returns true if the provided {@link ReleaseStatus} name should be excluded. + * + * @param status the status to evaluate + * @return true if it should be excluded, false otherwise. + */ + public boolean isExcluded(final ReleaseStatus status) { + StatusEnum statusEnum = getStatusEnum(status.get_name()); + return isExcluded(statusEnum); + } + + /** + * Returns true if the provided {@link ReleaseStatus} name should be included. + * + * @param status the status to evaluate + * @return true if it should be included, false otherwise. + */ + public boolean isIncluded(final ReleaseStatus status) { + StatusEnum statusEnum = getStatusEnum(status.get_name()); + return isIncluded(statusEnum); + } + + /** + * Filter the statuses of the provided {@link ItemRevision}. + * + * @param curItemRevision the item carrying some statuses. + * @return a {@link List} of {@link ReleaseStatus} that comply with this filter. + */ + public List filterStatusOf(final TcSession session, final ItemRevision curItemRevision) { + List selected = new ArrayList<>(); + session.loadProperties(curItemRevision, "release_status_list"); + ReleaseStatus[] releaseStatuses = curItemRevision.get_release_status_list(); + session.loadProperties(releaseStatuses); + for (ReleaseStatus status : releaseStatuses) { + String statusName = status.get_name(); + if (isIncluded(statusName)) { + selected.add(status); + } + } + return selected; + } + } + + static class StatusInclusionFilter extends AbstractStatusFilter { + + private final StatusEnum[] authorized; + + protected StatusInclusionFilter(final StatusEnum... authorized) { + super(); + this.authorized = authorized; + Arrays.sort(authorized); + } + + @Override + public boolean isExcluded(final StatusEnum status) { + return !isIncluded(status); + } + + @Override + public boolean isIncluded(final StatusEnum status) { + return Arrays.binarySearch(authorized, status) >= 0; + } + } + + private static class StatusExclusionFilter extends AbstractStatusFilter { + + private final StatusEnum[] forbidden; + + protected StatusExclusionFilter(final StatusEnum... forbidden) { + super(); + this.forbidden = forbidden; + Arrays.sort(forbidden); + } + + @Override + public boolean isExcluded(final StatusEnum type) { + return Arrays.binarySearch(forbidden, type) >= 0; + } + + @Override + public boolean isIncluded(final StatusEnum type) { + return !isExcluded(type); + } + } +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/status/TcEffectivity.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/status/TcEffectivity.java new file mode 100644 index 0000000..6fb3d6a --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/status/TcEffectivity.java @@ -0,0 +1,62 @@ +package com.capgemini.framework.teamcenter.object.pom.status; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.teamcenter.soa.client.model.strong.Effectivity; +import com.teamcenter.soa.client.model.strong.Item; + +import java.io.Serializable; + +/** + * Represents a Unit effectivity. + */ +public final class TcEffectivity implements Serializable { + private static final long serialVersionUID = -181276898335854241L; + private final Effectivity effectivity; + private final TcSession session; + + public TcEffectivity(TcSession session, final Effectivity effectivity) { + this.session = session; + this.effectivity = effectivity; + } + + public String endItemId() { + session.loadProperties(effectivity, "end_item"); + Item endItem = effectivity.get_end_item(); + if (endItem != null) { + session.loadProperties(endItem, "item_id"); + return endItem.get_item_id(); + } else { + return ""; + } + } + + public Item endItem() { + session.loadProperties(effectivity, "end_item"); + return effectivity.get_end_item(); + } + + public int[] unitNumbers() { + session.loadProperties(effectivity, "effectivity_units"); + return effectivity.get_effectivity_units(); + } + + public String unitRange() { + session.loadProperties(effectivity, "unit_range_text"); + return effectivity.get_unit_range_text(); + } + + public String dateRange() { + session.loadProperties(effectivity, "date_range_text"); + return effectivity.get_date_range_text(); + } + + public int unitOpenEndedStatus() { + session.loadProperties(effectivity, "unit_open_ended_status"); + return effectivity.get_unit_open_ended_status(); + } + + @Override + public String toString() { + return "TcEffectivity " + endItemId() + "[" + ((unitRange() == null || unitRange().isEmpty()) ? dateRange() : unitRange()) + "]"; + } +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/status/TcReleaseStatus.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/status/TcReleaseStatus.java new file mode 100644 index 0000000..caf3971 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/status/TcReleaseStatus.java @@ -0,0 +1,202 @@ +package com.capgemini.framework.teamcenter.object.pom.status; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.teamcenter.soa.client.model.ModelObject; +import com.teamcenter.soa.client.model.strong.Effectivity; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import com.teamcenter.soa.client.model.strong.ReleaseStatus; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Comparator; +import java.util.List; + +import static com.capgemini.framework.teamcenter.TeamcenterObjectProperties.NAME; + +/** + * Represents a Release TcReleaseStatus.
    + * A Release TcReleaseStatus may represent either of the following : + *

      + *
    • An effectivity
      + * In this case the ReleaseStatus is named "TcEffectivity" and owns a {@link List} of {@link TcEffectivity Effectivities}
    • + *
    • A Maturity (J3A, J3B etc.)
    • + *
    • Any other TcReleaseStatus ('Interface Todo', etc.)
    • + *
    + */ +public class TcReleaseStatus { + private static final Logger LOGGER = LoggerFactory.getLogger(TcReleaseStatus.class); + + private final ReleaseStatus releaseStatus; + private TcSession session; + + public TcReleaseStatus(final TcSession session, final ReleaseStatus status) { + this.session = session; + this.releaseStatus = status; + } + + /** + * Filters a {@code List} of {@link TcReleaseStatus} according to a list of eligible statuses. + * + * @param releaseStatusList List<{@link TcReleaseStatus}> - all the releaseStatus of an object + * @param eligible ({@link StatusEnum}) - Enumeration of eligible statuses + * @return the list of the appropriate releaseStatus + */ + public static List filter(final List releaseStatusList, final StatusEnum... eligible) { + List listOfChosenRS = new ArrayList<>(); + for (TcReleaseStatus status : releaseStatusList) { + if (status != null) { + for (StatusEnum wantedStatus : eligible) { + if (wantedStatus == status.getStatusEnum()) { + listOfChosenRS.add(status); + } + } + } + } + return listOfChosenRS; + } + + /** + * Obtains the list of {@link ReleaseStatus} and filter them according to a list of eligible statuses. + * + * @param itemRevision {@link ItemRevision} + * @param eligibleStatus Enumeration of wanted releaseStatus ({@link StatusEnum}). + * @return List + */ + public static List getChosenStatus(final TcSession session, final ItemRevision itemRevision, final StatusEnum... eligibleStatus) { + List listOfChosenRS = new ArrayList<>(); + session.loadProperties(itemRevision, "release_status_list"); + ReleaseStatus[] releaseStatuses = itemRevision.get_release_status_list(); + session.loadProperties(releaseStatuses); + for (ReleaseStatus status : releaseStatuses) { + if (status != null) { + for (StatusEnum wantedStatus : eligibleStatus) { + if (wantedStatus.getIdentifier().equals(status.get_name())) { + listOfChosenRS.add(status); + } + } + } + } + return listOfChosenRS; + } + + /** + * Get the list of {@link ReleaseStatus} and filter the {@link ReleaseStatus} in function of the forbidden releaseStatus. + * + * @param itemRevision {@link ItemRevision} + * @param forbiddenStatus Enumeration of forbidden releaseStatus({@link StatusEnum}) + * @return List + */ + public static List getAllStatusExceptSome(final TcSession session, final ItemRevision itemRevision, final StatusEnum... forbiddenStatus) { + List listOfChosenRS = new ArrayList<>(); + session.loadProperties(itemRevision, "release_status_list"); + ReleaseStatus[] releaseStatuses = itemRevision.get_release_status_list(); + session.loadProperties(releaseStatuses); + for (ReleaseStatus status : releaseStatuses) { + if (status != null) { + boolean isSelected = true; + for (StatusEnum wantedStatus : forbiddenStatus) { + if (wantedStatus.getIdentifier().equals(status.get_name())) { + isSelected = false; + } + } + if (isSelected) { + listOfChosenRS.add(status); + } + } + } + return listOfChosenRS; + } + + public StatusEnum getStatusEnum() { + session.loadProperties(releaseStatus, "name"); + return StatusEnum.getStatusEnum(releaseStatus.get_name()); + } + + public Calendar dateReleased() { + session.loadProperties(releaseStatus, "date_released"); + return releaseStatus.get_date_released(); + } + + public String getDisplayableName() { + return releaseStatus.getPropertyObject(NAME).getDisplayableValue(); + } + + public TcEffectivity getEffectivity() { + if (isEffectivity()) { + session.loadProperties(releaseStatus, "effectivities"); + ModelObject[] effectivities = releaseStatus.get_effectivities(); + session.loadProperties(effectivities); + if (effectivities == null || effectivities.length == 0) { + LOGGER.debug("ReleaseStatus named '{}' does not contain Effectivities", getDisplayableName()); + } + else { + ModelObject objectEffectivity = effectivities[0]; // There should only be one effectivity, we ignore the rest of the list's content + // Cast of the ModelObject to the TcEffectivity of Teamcenter, do not confuse with the TcEffectivity of this application + return new TcEffectivity(session, (Effectivity) objectEffectivity); + } + } + return null; + } + + public List getEffectivities() { + List tcEffectivities = new ArrayList<>(); + if (isEffectivity()) { + session.loadProperties(releaseStatus, "effectivities"); + ModelObject[] effectivities = releaseStatus.get_effectivities(); + session.loadProperties(effectivities); + for (ModelObject effectivity : effectivities) { + tcEffectivities.add(new TcEffectivity(session, (Effectivity) effectivity)); + } + } + return tcEffectivities; + } + + public boolean isEffectivity() { + StatusEnum statusName = getStatusEnum(); + return StatusEnum.ONLY_EFFECTIVITIES.isIncluded(statusName) || StatusEnum.ONLY_DMU.isIncluded(statusName); + } + + /** + * Returns true if this ReleaseStatus controls a Change's maturity. + * + * @return true if the releaseStatus represents a Maturity + */ + public boolean isChangeMaturity() { + return StatusEnum.CHANGE_MATURITY.isIncluded(getStatusEnum()); + } + + public boolean isOneOf(StatusEnum... statuses) { + StatusEnum statusEnum = getStatusEnum(); + for (StatusEnum status : statuses) { + if (statusEnum.equals(status)) { + return true; + } + } + return false; +} + + @Override + public String toString() { + TcEffectivity effectivity = getEffectivity(); + if (effectivity == null) { + return "TcReleaseStatus with NAME= " + getStatusEnum(); + } + else { + return "TcReleaseStatus with NAME= " + getStatusEnum() + " RANGE= " + effectivity.unitRange(); + } + } + + public enum Order implements Comparator { + BY_RELEASE_DATE() { + @Override + public int compare(final TcReleaseStatus releaseStatus1, final TcReleaseStatus releaseStatus2) { + return releaseStatus1.dateReleased().compareTo(releaseStatus2.dateReleased()); + } + }; + + @Override + public abstract int compare(final TcReleaseStatus releaseStatus1, final TcReleaseStatus releaseStatus2); + } +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/TcItem.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/TcItem.java new file mode 100644 index 0000000..978d83f --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/TcItem.java @@ -0,0 +1,5 @@ +package com.capgemini.framework.teamcenter.object.pom.workspace; + +public interface TcItem extends TcWorkspaceObject { + +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/TcItemRevision.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/TcItemRevision.java new file mode 100644 index 0000000..c28913c --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/TcItemRevision.java @@ -0,0 +1,4 @@ +package com.capgemini.framework.teamcenter.object.pom.workspace; + +public interface TcItemRevision extends TcWorkspaceObject { +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/TcWorkspaceObject.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/TcWorkspaceObject.java new file mode 100644 index 0000000..79cbd8d --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/TcWorkspaceObject.java @@ -0,0 +1,6 @@ +package com.capgemini.framework.teamcenter.object.pom.workspace; + +import com.capgemini.framework.teamcenter.object.pom.TcPomObject; + +public interface TcWorkspaceObject extends TcPomObject { +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/TcBomObject.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/TcBomObject.java new file mode 100644 index 0000000..c6587a0 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/TcBomObject.java @@ -0,0 +1,8 @@ +package com.capgemini.framework.teamcenter.object.pom.workspace.bom; + +import com.capgemini.framework.teamcenter.object.pom.workspace.TcWorkspaceObject; +import com.teamcenter.services.strong.cad._2013_05.StructureManagement.CreateWindowsInfo2; + +public interface TcBomObject extends TcWorkspaceObject { + void addInfo(final CreateWindowsInfo2 createWindowsInfo2); +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/TcBomObjectFactory.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/TcBomObjectFactory.java new file mode 100644 index 0000000..85a0d86 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/TcBomObjectFactory.java @@ -0,0 +1,105 @@ +package com.capgemini.framework.teamcenter.object.pom.workspace.bom; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.generic.*; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.part.*; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.product.TcProduct; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.product.TcProductRevision; +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.teamcenter.soa.client.model.strong.Item; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import com.teamcenter.soa.client.model.strong.WorkspaceObject; + +public class TcBomObjectFactory { + private final WorkspaceObject modelObject; + private final TcSession session; + + public TcBomObjectFactory(final TcSession session, final WorkspaceObject modelObject) { + this.session = session; + this.modelObject = modelObject; + } + + + public TcBomObject create() throws KurtException { + TcBomObject tcBomObject; + switch (modelObject.getTypeObject().getName()) { + case SnecmaObjectTypes.PRODUCT: + tcBomObject = new TcProduct(session, (Item) modelObject); + break; + case SnecmaObjectTypes.GENERIC: + tcBomObject = new TcGeneric((Item) modelObject); + break; + case SnecmaObjectTypes.RF_GENERIC: + tcBomObject = new TcRFGeneric((Item) modelObject); + break; + case SnecmaObjectTypes.GENERIC_ASSEMB: + tcBomObject = new TcGenericAssemb((Item) modelObject); + break; + case SnecmaObjectTypes.GENERIC_REVISION: + tcBomObject = new TcGenericRevision((ItemRevision) modelObject); + break; + case SnecmaObjectTypes.GENERIC_ASSEMB_REVISION: + tcBomObject = new TcGenericAssembRevision((ItemRevision) modelObject); + break; + /*case SnecmaObjectTypes.SUPERMODEL_REVISION: + tcBomObject = new TcSuper + */ + case SnecmaObjectTypes.RF_GENERIC_REVISION: + tcBomObject = new TcRFGenericRevision((ItemRevision) modelObject); + break; + case SnecmaObjectTypes.PART_AERO_REVISION: + tcBomObject = new TcPartAeroRevision((ItemRevision) modelObject); + break; + case SnecmaObjectTypes.PART_NO_AERO_REVISION: + tcBomObject = new TcPartNoAeroRevision((ItemRevision) modelObject); + break; + case SnecmaObjectTypes.PART_MAT_REVISION: + tcBomObject = new TcPartMatRevision((ItemRevision) modelObject); + break; + case SnecmaObjectTypes.STANDARD_REVISION: + tcBomObject = new TcStandardRevision((ItemRevision) modelObject); + break; + case SnecmaObjectTypes.DET_REVISION: + tcBomObject = new TcDetRevision((ItemRevision) modelObject); + break; + case SnecmaObjectTypes.ALTERNATE_REVISION: + tcBomObject = new TcAlternateRevision((ItemRevision) modelObject); + break; + case SnecmaObjectTypes.PART_ASSEMB_REVISION: + tcBomObject = new TcPartAssembRevision((ItemRevision) modelObject); + break; + case SnecmaObjectTypes.RF_PART_REVISION: + tcBomObject = new TcRFPartRevision((ItemRevision) modelObject); + break; + case SnecmaObjectTypes.ALTERNATE: + tcBomObject = new TcAlternate((Item) modelObject); + break; + case SnecmaObjectTypes.DET: + tcBomObject = new TcDet((Item) modelObject); + break; + case SnecmaObjectTypes.PART_AERO: + tcBomObject = new TcPartAero((Item) modelObject); + break; + case SnecmaObjectTypes.PART_ASSEMB: + tcBomObject = new TcPartAssemb((Item) modelObject); + break; + case SnecmaObjectTypes.PART_MAT: + tcBomObject = new TcPartMat((Item) modelObject); + break; + case SnecmaObjectTypes.PART_NO_AERO: + tcBomObject = new TcPartNoAero((Item) modelObject); + break; + case SnecmaObjectTypes.STANDARD: + tcBomObject = new TcStandard((Item) modelObject); + break; + case SnecmaObjectTypes.PRODUCT_REVISION: + tcBomObject = new TcProductRevision(session, (ItemRevision) modelObject); + break; + default: + throw new KurtException("Invalid Teamcenter type for: (" + modelObject.getTypeObject().getName() + ")" + modelObject.getUid()); + } + + return tcBomObject; + } +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/TcRFPartRevision.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/TcRFPartRevision.java new file mode 100644 index 0000000..9ef4806 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/TcRFPartRevision.java @@ -0,0 +1,17 @@ +package com.capgemini.framework.teamcenter.object.pom.workspace.bom; + +import com.teamcenter.services.strong.cad._2013_05.StructureManagement; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +public class TcRFPartRevision implements TcBomObject { + private final ItemRevision itemRevision; + + public TcRFPartRevision(final ItemRevision itemRevision) { + this.itemRevision = itemRevision; + } + + @Override + public void addInfo(StructureManagement.CreateWindowsInfo2 createWindowsInfo2) { + createWindowsInfo2.itemRev = itemRevision; + } +} \ No newline at end of file diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/TcRevisionRule.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/TcRevisionRule.java new file mode 100644 index 0000000..a5866ea --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/TcRevisionRule.java @@ -0,0 +1,29 @@ +package com.capgemini.framework.teamcenter.object.pom.workspace.bom; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.object.pom.workspace.TcWorkspaceObject; +import com.teamcenter.services.strong.cad._2007_01.StructureManagement.RevisionRuleConfigInfo; +import com.teamcenter.soa.client.model.ModelObject; +import com.teamcenter.soa.client.model.strong.RevisionRule; + +import java.util.Map; + +public class TcRevisionRule implements TcWorkspaceObject { + private TcSession session; + private final RevisionRule revisionRule; + + public TcRevisionRule(final TcSession session, final RevisionRule revisionRule) { + this.session = session; + this.revisionRule = revisionRule; + } + + + public void addInfo(final RevisionRuleConfigInfo revRuleConfigInfo) { + revRuleConfigInfo.revRule = revisionRule; + } + + public void setProperties(Map map) { + session.setProperties(revisionRule, map); + } + +} \ No newline at end of file diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/TcRevisionRuleProperties.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/TcRevisionRuleProperties.java new file mode 100644 index 0000000..0fffd6f --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/TcRevisionRuleProperties.java @@ -0,0 +1,43 @@ +package com.capgemini.framework.teamcenter.object.pom.workspace.bom; + +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.product.TcProduct; +import com.teamcenter.services.strong.cad._2007_01.StructureManagement.RevisionRuleConfigInfo; +import com.teamcenter.services.strong.cad._2007_01.StructureManagement.RevisionRuleEntryProps; + +import java.util.Calendar; + +public class TcRevisionRuleProperties { + private final TcProduct product; + private final int unit; + private final Calendar effectivityDate; + + public TcRevisionRuleProperties(final TcProduct product, final int unit) { + this(product, unit, null); + } + + public TcRevisionRuleProperties(final Calendar effectivityDate) { + this(null, 0, effectivityDate); + } + + public TcRevisionRuleProperties(final TcProduct product, final int unit, final Calendar effectivityDate) { + this.product = product; + this.unit = unit; + this.effectivityDate = effectivityDate; + } + + public void addInfo(final RevisionRuleConfigInfo revisionRuleConfigInfo) { + RevisionRuleEntryProps props = new RevisionRuleEntryProps(); + // Date used by configuration, else the current date is used for configuration + if (effectivityDate != null) { + props.date = effectivityDate; + } else { + props.today = true; + } + + if (product != null) { + product.addInfo(props); + } + props.unitNo = unit; + revisionRuleConfigInfo.props = props; + } +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/generic/TcGeneric.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/generic/TcGeneric.java new file mode 100644 index 0000000..c8d3d87 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/generic/TcGeneric.java @@ -0,0 +1,21 @@ +package com.capgemini.framework.teamcenter.object.pom.workspace.bom.generic; + +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcBomObject; +import com.teamcenter.soa.client.model.strong.Item; +import lombok.Getter; + +import static com.teamcenter.services.strong.cad._2013_05.StructureManagement.CreateWindowsInfo2; + +@Getter +public class TcGeneric implements TcGenericPv, TcBomObject { + private final Item item; + + public TcGeneric(final Item item) { + this.item = item; + } + + @Override + public void addInfo(final CreateWindowsInfo2 createWindowsInfo2) { + createWindowsInfo2.item = item; + } +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/generic/TcGenericAssemb.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/generic/TcGenericAssemb.java new file mode 100644 index 0000000..c129a3c --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/generic/TcGenericAssemb.java @@ -0,0 +1,19 @@ +package com.capgemini.framework.teamcenter.object.pom.workspace.bom.generic; + +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcBomObject; +import com.teamcenter.soa.client.model.strong.Item; + +import static com.teamcenter.services.strong.cad._2013_05.StructureManagement.CreateWindowsInfo2; + +public class TcGenericAssemb implements TcGenericPv, TcBomObject { + private final Item item; + + public TcGenericAssemb(final Item item) { + this.item = item; + } + + @Override + public void addInfo(final CreateWindowsInfo2 createWindowsInfo2) { + createWindowsInfo2.item = item; + } +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/generic/TcGenericAssembRevision.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/generic/TcGenericAssembRevision.java new file mode 100644 index 0000000..6ec658a --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/generic/TcGenericAssembRevision.java @@ -0,0 +1,18 @@ +package com.capgemini.framework.teamcenter.object.pom.workspace.bom.generic; + +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcBomObject; +import com.teamcenter.services.strong.cad._2013_05.StructureManagement; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +public class TcGenericAssembRevision implements TcGenericPv, TcBomObject { + private final ItemRevision itemRevision; + + public TcGenericAssembRevision(final ItemRevision itemRevision) { + this.itemRevision = itemRevision; + } + + @Override + public void addInfo(StructureManagement.CreateWindowsInfo2 createWindowsInfo2) { + createWindowsInfo2.itemRev = itemRevision; + } +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/generic/TcGenericPv.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/generic/TcGenericPv.java new file mode 100644 index 0000000..dfb52e6 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/generic/TcGenericPv.java @@ -0,0 +1,6 @@ +package com.capgemini.framework.teamcenter.object.pom.workspace.bom.generic; + +import com.capgemini.framework.teamcenter.object.pom.workspace.TcItem; + +public interface TcGenericPv extends TcItem { +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/generic/TcGenericPvRevision.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/generic/TcGenericPvRevision.java new file mode 100644 index 0000000..b51d9a9 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/generic/TcGenericPvRevision.java @@ -0,0 +1,6 @@ +package com.capgemini.framework.teamcenter.object.pom.workspace.bom.generic; + +import com.capgemini.framework.teamcenter.object.pom.workspace.TcItemRevision; + +public interface TcGenericPvRevision extends TcItemRevision { +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/generic/TcGenericRevision.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/generic/TcGenericRevision.java new file mode 100644 index 0000000..798bc4a --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/generic/TcGenericRevision.java @@ -0,0 +1,18 @@ +package com.capgemini.framework.teamcenter.object.pom.workspace.bom.generic; + +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcBomObject; +import com.teamcenter.services.strong.cad._2013_05.StructureManagement; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +public class TcGenericRevision implements TcGenericPv, TcBomObject { + private final ItemRevision itemRevision; + + public TcGenericRevision(final ItemRevision itemRevision) { + this.itemRevision = itemRevision; + } + + @Override + public void addInfo(StructureManagement.CreateWindowsInfo2 createWindowsInfo2) { + createWindowsInfo2.itemRev = itemRevision; + } +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/generic/TcRFGeneric.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/generic/TcRFGeneric.java new file mode 100644 index 0000000..2790867 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/generic/TcRFGeneric.java @@ -0,0 +1,18 @@ +package com.capgemini.framework.teamcenter.object.pom.workspace.bom.generic; + +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcBomObject; +import com.teamcenter.services.strong.cad._2013_05.StructureManagement; +import com.teamcenter.soa.client.model.strong.Item; + +public class TcRFGeneric implements TcGenericPv, TcBomObject { + private final Item item; + + public TcRFGeneric(final Item item) { + this.item = item; + } + + @Override + public void addInfo(StructureManagement.CreateWindowsInfo2 createWindowsInfo2) { + createWindowsInfo2.item = item; + } +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/generic/TcRFGenericRevision.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/generic/TcRFGenericRevision.java new file mode 100644 index 0000000..a3d27c9 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/generic/TcRFGenericRevision.java @@ -0,0 +1,16 @@ +package com.capgemini.framework.teamcenter.object.pom.workspace.bom.generic; + +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcBomObject; +import com.teamcenter.services.strong.cad._2013_05.StructureManagement; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +public class TcRFGenericRevision implements TcGenericPv, TcBomObject { + private final ItemRevision itemRevision; + + public TcRFGenericRevision(final ItemRevision itemRevision) { + this.itemRevision = itemRevision; + } + + @Override + public void addInfo(StructureManagement.CreateWindowsInfo2 createWindowsInfo2) { createWindowsInfo2.itemRev = itemRevision; } +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/part/TcAlternate.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/part/TcAlternate.java new file mode 100644 index 0000000..16f67c3 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/part/TcAlternate.java @@ -0,0 +1,20 @@ +package com.capgemini.framework.teamcenter.object.pom.workspace.bom.part; + +import com.capgemini.framework.teamcenter.object.pom.workspace.TcItem; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcBomObject; +import com.teamcenter.services.strong.cad._2013_05.StructureManagement; +import com.teamcenter.soa.client.model.strong.Item; + +public class TcAlternate implements TcItem, TcBomObject { + private final Item item; + + public TcAlternate(final Item item) { + this.item = item; + } + + @Override + public void addInfo(final StructureManagement.CreateWindowsInfo2 createWindowsInfo2) { + createWindowsInfo2.item = item; + } +} + diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/part/TcAlternateRevision.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/part/TcAlternateRevision.java new file mode 100644 index 0000000..7d855a6 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/part/TcAlternateRevision.java @@ -0,0 +1,18 @@ +package com.capgemini.framework.teamcenter.object.pom.workspace.bom.part; + +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcBomObject; +import com.teamcenter.services.strong.cad._2013_05.StructureManagement; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +public class TcAlternateRevision implements TcBomObject { + private final ItemRevision itemRevision; + + public TcAlternateRevision(final ItemRevision itemRevision) { + this.itemRevision = itemRevision; + } + + @Override + public void addInfo(StructureManagement.CreateWindowsInfo2 createWindowsInfo2) { + createWindowsInfo2.itemRev = itemRevision; + } +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/part/TcDet.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/part/TcDet.java new file mode 100644 index 0000000..8697bb5 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/part/TcDet.java @@ -0,0 +1,20 @@ +package com.capgemini.framework.teamcenter.object.pom.workspace.bom.part; + +import com.capgemini.framework.teamcenter.object.pom.workspace.TcItem; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcBomObject; +import com.teamcenter.services.strong.cad._2013_05.StructureManagement; +import com.teamcenter.soa.client.model.strong.Item; + +public class TcDet implements TcItem, TcBomObject { + private final Item item; + + public TcDet(final Item item) { + this.item = item; + } + + @Override + public void addInfo(final StructureManagement.CreateWindowsInfo2 createWindowsInfo2) { + createWindowsInfo2.item = item; + } +} + diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/part/TcDetRevision.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/part/TcDetRevision.java new file mode 100644 index 0000000..0798f62 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/part/TcDetRevision.java @@ -0,0 +1,18 @@ +package com.capgemini.framework.teamcenter.object.pom.workspace.bom.part; + +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcBomObject; +import com.teamcenter.services.strong.cad._2013_05.StructureManagement; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +public class TcDetRevision implements TcBomObject { + private final ItemRevision itemRevision; + + public TcDetRevision(final ItemRevision itemRevision) { + this.itemRevision = itemRevision; + } + + @Override + public void addInfo(StructureManagement.CreateWindowsInfo2 createWindowsInfo2) { + createWindowsInfo2.itemRev = itemRevision; + } +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/part/TcPartAero.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/part/TcPartAero.java new file mode 100644 index 0000000..593dc39 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/part/TcPartAero.java @@ -0,0 +1,19 @@ +package com.capgemini.framework.teamcenter.object.pom.workspace.bom.part; + +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcBomObject; +import com.teamcenter.services.strong.cad._2013_05.StructureManagement; +import com.teamcenter.soa.client.model.strong.Item; + +public class TcPartAero implements TcBomObject { + private final Item item; + + public TcPartAero(final Item item) { + this.item = item; + } + + @Override + public void addInfo(final StructureManagement.CreateWindowsInfo2 createWindowsInfo2) { + createWindowsInfo2.item = item; + } +} + diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/part/TcPartAeroRevision.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/part/TcPartAeroRevision.java new file mode 100644 index 0000000..851cfb3 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/part/TcPartAeroRevision.java @@ -0,0 +1,18 @@ +package com.capgemini.framework.teamcenter.object.pom.workspace.bom.part; + +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcBomObject; +import com.teamcenter.services.strong.cad._2013_05.StructureManagement; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +public class TcPartAeroRevision implements TcBomObject { + private final ItemRevision itemRevision; + + public TcPartAeroRevision(final ItemRevision itemRevision) { + this.itemRevision = itemRevision; + } + + @Override + public void addInfo(StructureManagement.CreateWindowsInfo2 createWindowsInfo2) { + createWindowsInfo2.itemRev = itemRevision; + } +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/part/TcPartAssemb.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/part/TcPartAssemb.java new file mode 100644 index 0000000..828a3d7 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/part/TcPartAssemb.java @@ -0,0 +1,18 @@ +package com.capgemini.framework.teamcenter.object.pom.workspace.bom.part; + +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcBomObject; +import com.teamcenter.services.strong.cad._2013_05.StructureManagement; +import com.teamcenter.soa.client.model.strong.Item; + +public class TcPartAssemb implements TcBomObject { + private final Item item; + + public TcPartAssemb(final Item item) { + this.item = item; + } + + @Override + public void addInfo(final StructureManagement.CreateWindowsInfo2 createWindowsInfo2) { + createWindowsInfo2.item = item; + } +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/part/TcPartAssembRevision.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/part/TcPartAssembRevision.java new file mode 100644 index 0000000..a34e6dd --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/part/TcPartAssembRevision.java @@ -0,0 +1,18 @@ +package com.capgemini.framework.teamcenter.object.pom.workspace.bom.part; + +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcBomObject; +import com.teamcenter.services.strong.cad._2013_05.StructureManagement; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +public class TcPartAssembRevision implements TcBomObject { + private final ItemRevision itemRevision; + + public TcPartAssembRevision(final ItemRevision itemRevision) { + this.itemRevision = itemRevision; + } + + @Override + public void addInfo(StructureManagement.CreateWindowsInfo2 createWindowsInfo2) { + createWindowsInfo2.itemRev = itemRevision; + } +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/part/TcPartMat.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/part/TcPartMat.java new file mode 100644 index 0000000..2f4a4d8 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/part/TcPartMat.java @@ -0,0 +1,18 @@ +package com.capgemini.framework.teamcenter.object.pom.workspace.bom.part; + +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcBomObject; +import com.teamcenter.services.strong.cad._2013_05.StructureManagement; +import com.teamcenter.soa.client.model.strong.Item; + +public class TcPartMat implements TcBomObject { + private final Item item; + + public TcPartMat(final Item item) { + this.item = item; + } + + @Override + public void addInfo(final StructureManagement.CreateWindowsInfo2 createWindowsInfo2) { + createWindowsInfo2.item = item; + } +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/part/TcPartMatRevision.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/part/TcPartMatRevision.java new file mode 100644 index 0000000..78349f4 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/part/TcPartMatRevision.java @@ -0,0 +1,18 @@ +package com.capgemini.framework.teamcenter.object.pom.workspace.bom.part; + +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcBomObject; +import com.teamcenter.services.strong.cad._2013_05.StructureManagement; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +public class TcPartMatRevision implements TcBomObject { + private final ItemRevision itemRevision; + + public TcPartMatRevision(final ItemRevision itemRevision) { + this.itemRevision = itemRevision; + } + + @Override + public void addInfo(StructureManagement.CreateWindowsInfo2 createWindowsInfo2) { + createWindowsInfo2.itemRev = itemRevision; + } +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/part/TcPartNoAero.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/part/TcPartNoAero.java new file mode 100644 index 0000000..a7512a9 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/part/TcPartNoAero.java @@ -0,0 +1,18 @@ +package com.capgemini.framework.teamcenter.object.pom.workspace.bom.part; + +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcBomObject; +import com.teamcenter.services.strong.cad._2013_05.StructureManagement; +import com.teamcenter.soa.client.model.strong.Item; + +public class TcPartNoAero implements TcBomObject { + private final Item item; + + public TcPartNoAero(final Item item) { + this.item = item; + } + + @Override + public void addInfo(final StructureManagement.CreateWindowsInfo2 createWindowsInfo2) { + createWindowsInfo2.item = item; + } +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/part/TcPartNoAeroRevision.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/part/TcPartNoAeroRevision.java new file mode 100644 index 0000000..567d143 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/part/TcPartNoAeroRevision.java @@ -0,0 +1,18 @@ +package com.capgemini.framework.teamcenter.object.pom.workspace.bom.part; + +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcBomObject; +import com.teamcenter.services.strong.cad._2013_05.StructureManagement; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +public class TcPartNoAeroRevision implements TcBomObject { + private final ItemRevision itemRevision; + + public TcPartNoAeroRevision(final ItemRevision itemRevision) { + this.itemRevision = itemRevision; + } + + @Override + public void addInfo(StructureManagement.CreateWindowsInfo2 createWindowsInfo2) { + createWindowsInfo2.itemRev = itemRevision; + } +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/part/TcStandard.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/part/TcStandard.java new file mode 100644 index 0000000..7770c99 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/part/TcStandard.java @@ -0,0 +1,18 @@ +package com.capgemini.framework.teamcenter.object.pom.workspace.bom.part; + +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcBomObject; +import com.teamcenter.services.strong.cad._2013_05.StructureManagement; +import com.teamcenter.soa.client.model.strong.Item; + +public class TcStandard implements TcBomObject { + private final Item item; + + public TcStandard(final Item item) { + this.item = item; + } + + @Override + public void addInfo(final StructureManagement.CreateWindowsInfo2 createWindowsInfo2) { + createWindowsInfo2.item = item; + } +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/part/TcStandardRevision.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/part/TcStandardRevision.java new file mode 100644 index 0000000..f929a63 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/part/TcStandardRevision.java @@ -0,0 +1,18 @@ +package com.capgemini.framework.teamcenter.object.pom.workspace.bom.part; + +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcBomObject; +import com.teamcenter.services.strong.cad._2013_05.StructureManagement; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +public class TcStandardRevision implements TcBomObject { + private final ItemRevision itemRevision; + + public TcStandardRevision(final ItemRevision itemRevision) { + this.itemRevision = itemRevision; + } + + @Override + public void addInfo(StructureManagement.CreateWindowsInfo2 createWindowsInfo2) { + createWindowsInfo2.itemRev = itemRevision; + } +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/product/TcProduct.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/product/TcProduct.java new file mode 100644 index 0000000..927942d --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/product/TcProduct.java @@ -0,0 +1,43 @@ +package com.capgemini.framework.teamcenter.object.pom.workspace.bom.product; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.object.pom.workspace.TcItem; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcBomObject; +import com.teamcenter.services.strong.cad._2007_01.StructureManagement.RevisionRuleEntryProps; +import com.teamcenter.services.strong.cad._2013_05.StructureManagement.CreateWindowsInfo2; +import com.teamcenter.soa.client.model.ModelObject; +import com.teamcenter.soa.client.model.strong.Item; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +import java.util.ArrayList; +import java.util.List; + +public class TcProduct implements TcItem, TcBomObject { + private final TcSession session; + private final Item item; + + public TcProduct(final TcSession session, final Item item) { + this.session = session; + this.item = item; + } + + @Override + public void addInfo(final CreateWindowsInfo2 createWindowsInfo2) { + createWindowsInfo2.item = item; + } + + public void addInfo(final RevisionRuleEntryProps revisionRulesProps) { + revisionRulesProps.endItem = item; + } + + public List revisions() { + List revisions = new ArrayList<>(); + session.loadProperties(item, "revision_list"); + ModelObject[] revisionObjects = item.get_revision_list(); + session.loadProperties(revisionObjects); + for (ModelObject revision : revisionObjects) { + revisions.add(new TcProductRevision(session, (ItemRevision) revision)); + } + return revisions; + } +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/product/TcProductRevision.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/product/TcProductRevision.java new file mode 100644 index 0000000..1c3ae96 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/product/TcProductRevision.java @@ -0,0 +1,219 @@ +package com.capgemini.framework.teamcenter.object.pom.workspace.bom.product; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.object.pom.status.StatusEnum; +import com.capgemini.framework.teamcenter.object.pom.workspace.TcItemRevision; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcBomObject; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.unit.TcUnitRevision; +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.capgemini.reports.reports.parameters.ProductUnit; +import com.google.common.base.Optional; +import com.google.common.collect.ArrayListMultimap; +import com.teamcenter.services.strong.cad._2013_05.StructureManagement.CreateWindowsInfo2; +import com.teamcenter.soa.client.model.ModelObject; +import com.teamcenter.soa.client.model.strong.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import static com.capgemini.framework.teamcenter.object.SnecmaObjectProperties.*; +import static com.capgemini.framework.teamcenter.object.pom.status.StatusEnum.*; + +public class TcProductRevision implements TcItemRevision, TcBomObject { + private final TcSession session; + private final ItemRevision itemRevision; + private static final Logger LOGGER = LoggerFactory.getLogger(TcProductRevision.class); + + public TcProductRevision(final TcSession session, final ItemRevision itemRevision) { + this.session = session; + this.itemRevision = itemRevision; + } + + @Override + public void addInfo(final CreateWindowsInfo2 createWindowsInfo2) { + createWindowsInfo2.itemRev = itemRevision; + } + + /** + * Method specific to r23. + * Returns a list of TcUnitRevision corresponding to R23 criteria + * */ + public List r23UnitRevisions(boolean isWithFrozenUnit, ProductUnit productUnitForUnit, ProductUnit productUnitFromUnit, String nbDaysSinceFrozenStr) throws KurtException { + List r23UnitRevisions = new ArrayList<>(); + LOGGER.debug("== r23UnitRevisions method -> START"); + List filteredUnitRevision = filterOnlyMostRecentReleasedUnitRevisions(); + if(!productUnitForUnit.getUnitStr().isEmpty()) { // Case : We search a specific unit + productUnitForUnit.parseUserUnit(); + int unitNumber = productUnitForUnit.getUnit(); + LOGGER.debug("We search only the unit : [{}]", unitNumber); + for (TcUnitRevision unitRevision : filteredUnitRevision) { + if(unitRevision.unitNumber() == unitNumber) { + r23UnitRevisions.add(unitRevision); + } + } + } else { // Case : we first get all units + Collections.sort(filteredUnitRevision, TcUnitRevision.Order.BY_UNIT_NUMBER); + List finalUnitRevisionList = new ArrayList<>(); + if(!productUnitFromUnit.getUnitStr().isEmpty()) { // Case : We take units "from a given one" + productUnitFromUnit.parseUserUnit(); + int unit = productUnitFromUnit.getUnit(); + LOGGER.debug("We search units from unit : [{}]", unit); + for (TcUnitRevision unitRevision : filteredUnitRevision) { + if(unitRevision.unitNumber() >= unit) { + finalUnitRevisionList.add(unitRevision); + } + } + } else { + finalUnitRevisionList = filteredUnitRevision; + } + for (TcUnitRevision unitRevision : finalUnitRevisionList) { + if (unitRevision.isValidUnitToR23(isWithFrozenUnit, nbDaysSinceFrozenStr)) { + r23UnitRevisions.add(unitRevision); + } + } + } + StringBuilder stringBuilder = new StringBuilder(); + for(TcUnitRevision unitRevision : r23UnitRevisions) { + if(stringBuilder.length() > 0) { + stringBuilder.append(";"); + } + stringBuilder.append(unitRevision.unitNumber()); + } + LOGGER.info("List of unit selected : [{}]", stringBuilder); + LOGGER.debug("== r23UnitRevisions method -> END"); + return r23UnitRevisions; + } + + /** + * Return a list of TcUnitRevision containing the revision with the most recent release date of each unit of the the Product + * */ + private List filterOnlyMostRecentReleasedUnitRevisions() throws KurtException { + List filteredUnitRevisions = new ArrayList<>(); + ArrayListMultimap unitMap = ArrayListMultimap.create(); + for (TcUnitRevision unitRevision : unitRevisions()) { + unitMap.put(unitRevision.unitNumber(), unitRevision); + } + for (Integer unitNum : unitMap.keySet()) { + List tcUnitRevisions = unitMap.get(unitNum); + Collections.sort(tcUnitRevisions, TcUnitRevision.Order.BY_RELEASE_DATE); + filteredUnitRevisions.add(tcUnitRevisions.get(tcUnitRevisions.size() - 1)); + } + return filteredUnitRevisions; + } + + private TcUnitRevision refUnitRevision(List filteredUnitRevision) { + for (int i = 0; i < filteredUnitRevision.size(); i++) { + TcUnitRevision unitRevision = filteredUnitRevision.get(i); + if (unitRevision.hasStatus(OPEN) && !unitRevision.isExceptionnel()) { + for (int j = i - 1; j >= 0; j--) { + TcUnitRevision searchedUnitRevision = filteredUnitRevision.get(j); + if (searchedUnitRevision.hasStatus(J3A, J3B, FROZEN) && !searchedUnitRevision.isExceptionnel()) { + return searchedUnitRevision; + } + } + } + } + return null; + } + + public List unitRevisionsWithStatus(final StatusEnum... statuses) { + List unitRevisions = new ArrayList<>(); + for (TcUnitRevision unitRevision : unitRevisions()) { + if (unitRevision.hasStatus(statuses)) { + unitRevisions.add(unitRevision); + } + } + return unitRevisions; + } + + public Optional unitRevision(int unitNumber) throws KurtException { + for (TcUnitRevision unitRevision : unitRevisions()) { + if (unitRevision.unitNumber() == unitNumber) { + return Optional.of(unitRevision); + } + } + return Optional.absent(); + } + + /** + * Method to retrieve the latest open status unit revision + * @param unitNumber Unit number of the unit to retrieve + * @return the Unit Revision as an Optional. + * @throws KurtException + */ + public Optional openUnitRevision(int unitNumber) throws KurtException { + for (TcUnitRevision unitRevision : unitRevisions()) { + if (unitRevision.unitNumber() == unitNumber && unitRevision.hasStatus(OPEN)) { + return Optional.of(unitRevision); + } + } + return Optional.absent(); + } + + /** + * Method that returns the latest uncancelled unit revision for a given unit number + * @param unitNumber Unit number of the unit to retrieve + * @return the Unit Revision as an Optional. + * @throws KurtException + */ + public Optional notCancelledRevision(int unitNumber) throws KurtException { + for (TcUnitRevision unitRevision : unitRevisions()) { + if (unitRevision.unitNumber() == unitNumber && !unitRevision.hasStatus(CANCELLED)) { + return Optional.of(unitRevision); + } + } + return Optional.absent(); + } + + public String ligneProduit() { + Form masterForm = masterForm(); + session.loadProperties(masterForm, PV_LIGNE_PRODUIT); + return masterForm.getPropertyObject(PV_LIGNE_PRODUIT).getStringValue(); + } + + private List unitRevisions() { + List unitRevisions = new ArrayList<>(); + session.loadProperties(itemRevision, PV_UNIT); + ModelObject[] listOfUnitsBelowProduct = itemRevision.getPropertyObject(PV_UNIT).getModelObjectArrayValue(); + session.loadProperties(listOfUnitsBelowProduct); + for (ModelObject unitRevision : listOfUnitsBelowProduct) { + if (SnecmaObjectTypes.UNIT_REVISION.equals(unitRevision.getTypeObject().getName())) { + unitRevisions.add(new TcUnitRevision(session, (ItemRevision) unitRevision)); + } + } + return unitRevisions; + } + + public String productType() { + Form masterForm = masterForm(); + session.loadProperties(masterForm, PV_TYPE_PRODUIT); + return masterForm().getPropertyObject(PV_TYPE_PRODUIT).getStringValue(); + } + + private Form masterForm() { + session.loadProperties(itemRevision, "item_master_tag"); + return itemRevision.get_item_master_tag(); + } + + public PSBOMView bomViewRev(){ + PSBOMView modelBom = null; + session.loadProperties(itemRevision ,"structure_revisions"); + for (ModelObject psBomViewRev : itemRevision.get_structure_revisions() ) { + session.loadProperties(psBomViewRev, "bom_view"); + PSBOMView bomView = ((PSBOMViewRevision) psBomViewRev).get_bom_view(); + session.loadProperties(bomView, "view_type"); + PSViewType viewType = bomView.get_view_type(); + session.loadProperties(viewType,"name"); + String bvrTypeName = viewType.get_name(); + if ("ModelListBom".equals(bvrTypeName)) { + modelBom = bomView; + break; + } + } + return modelBom; + } +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/unit/TcUnitRevision.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/unit/TcUnitRevision.java new file mode 100644 index 0000000..ea8a148 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/pom/workspace/bom/unit/TcUnitRevision.java @@ -0,0 +1,177 @@ +package com.capgemini.framework.teamcenter.object.pom.workspace.bom.unit; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.object.pom.status.StatusEnum; +import com.capgemini.framework.teamcenter.object.pom.status.TcEffectivity; +import com.capgemini.framework.teamcenter.object.pom.status.TcReleaseStatus; +import com.capgemini.framework.teamcenter.object.pom.workspace.TcItemRevision; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.generic.TcGeneric; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.generic.TcGenericAssemb; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.generic.TcGenericPv; +import com.teamcenter.soa.client.model.ModelObject; +import com.teamcenter.soa.client.model.strong.Form; +import com.teamcenter.soa.client.model.strong.Item; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import com.teamcenter.soa.client.model.strong.ReleaseStatus; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Comparator; +import java.util.List; + +import static com.capgemini.framework.teamcenter.object.SnecmaObjectProperties.PV_GENERIC; +import static com.capgemini.framework.teamcenter.object.pom.status.StatusEnum.*; +import static com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes.GENERIC; +import static com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes.GENERIC_ASSEMB; + +public class TcUnitRevision implements TcItemRevision { + private final TcSession session; + private final ItemRevision itemRevision; + private static final Logger LOGGER = LoggerFactory.getLogger(TcUnitRevision.class); + + public TcUnitRevision(TcSession session, final ItemRevision itemRevision) { + this.session = session; + this.itemRevision = itemRevision; + } + + public boolean hasStatus(final StatusEnum... statuses) { + for (TcReleaseStatus releaseStatus : releaseStatuses()) { + if (releaseStatus.isOneOf(statuses)) { + return true; + } + } + return false; + } + + public int unitNumber() throws KurtException { + for (TcReleaseStatus releaseStatus : releaseStatuses()) { + if (releaseStatus.isEffectivity()) { + TcEffectivity tcEffectivity = releaseStatus.getEffectivity(); + if (tcEffectivity != null) { + return tcEffectivity.unitNumbers()[0]; + } + } + } + throw new KurtException("Aucune effectivité portant un numéro de unit trouvé sur le Unit " + itemRevision.getUid()); + } + + public Calendar dateReleased() { + session.loadProperties(itemRevision, "date_released"); + return itemRevision.get_date_released(); + } + + public boolean isExceptionnel() { + Form formRev = getMasterFormRev(); + session.loadProperties(formRev, "pv_unit_exceptionnel"); + return "Oui / Yes".equalsIgnoreCase(formRev.getPropertyObject("pv_unit_exceptionnel").getStringValue()); + } + + + public List genericPvs() { + List generics = new ArrayList<>(); + session.loadProperties(itemRevision, PV_GENERIC); + ModelObject[] genericObjs = itemRevision.getPropertyObject(PV_GENERIC).getModelObjectArrayValue(); + session.loadProperties(genericObjs); + for (ModelObject generic : genericObjs) { + String typeName = generic.getTypeObject().getName(); + if (GENERIC.equals(typeName)) { + generics.add(new TcGeneric((Item) generic)); + } + else if (GENERIC_ASSEMB.equals(typeName)) { + generics.add(new TcGenericAssemb((Item) generic)); + } + } + return generics; + } + + private List releaseStatuses() { + List releaseStatuses = new ArrayList<>(); + session.loadProperties(itemRevision, "release_status_list"); + ReleaseStatus[] statuses = itemRevision.get_release_status_list(); + session.loadProperties(statuses); + for (ReleaseStatus releaseStatus : statuses) { + releaseStatuses.add(new TcReleaseStatus(session, releaseStatus)); + } + return releaseStatuses; + } + + private TcReleaseStatus frozenStatus() { + for (TcReleaseStatus releaseStatus : releaseStatuses()) { + if (releaseStatus.isOneOf(StatusEnum.FROZEN)) { + return releaseStatus; + } + } + return null; + } + + private Form getMasterFormRev() { + session.loadProperties(itemRevision, "item_master_tag"); + return itemRevision.get_item_master_tag(); + } + + public boolean isValidUnitToR23(boolean withFrozenUnits, String nbDaysSinceFrozenStr) { + int unit = 0; + String rev = this.getUnitRev(); + try { + unit = this.unitNumber(); + } catch (KurtException e) { + LOGGER.debug("Error message when trying access unitNumber of TcUnitRevision : [{}]", e.getMessage()); + } + LOGGER.debug("Check validity of unit [{}] rev [{}] for R23, withFrozenUnit = [{}], nbDaysSinceFrozen = [{}]", + unit, rev, withFrozenUnits, nbDaysSinceFrozenStr); + if(withFrozenUnits) { + if(!nbDaysSinceFrozenStr.isEmpty()) { + int nbJour = Integer.parseInt(nbDaysSinceFrozenStr); + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); + Calendar c = Calendar.getInstance(); // Get current date + c.add(Calendar.DAY_OF_MONTH, -nbJour); + LOGGER.debug("Date after soustraction of {} day(s) : {}", nbJour, sdf.format(c.getTime())); + LOGGER.debug("Unit [{}] has status OPEN OR (date release after [{}] AND a status FROZEN, FROZEN_IN_PROCESS, J3A or J3B) ? : [{}]", unit, sdf.format(c.getTime()), hasStatus(J3A, J3B, FROZEN, FROZEN_IN_PROCESS)); + return hasStatus(OPEN) || (dateReleased().after(c) && hasStatus(J3A, J3B, FROZEN, FROZEN_IN_PROCESS)); + } + LOGGER.debug("Unit [{}] has status OPEN or FROZEN, FROZEN_IN_PROCESS, J3A or J3B ? : [{}]", unit, hasStatus(OPEN, J3A, J3B, FROZEN, FROZEN_IN_PROCESS)); + return hasStatus(OPEN, J3A, J3B, FROZEN, FROZEN_IN_PROCESS); + } else { + LOGGER.debug("Unit [{}] has status OPEN ? : [{}]", unit, hasStatus(OPEN)); + return hasStatus(OPEN); + } + } + + /** Get unit revision "item_revision_id" attribute */ + public String getUnitRev() { + session.loadProperties(itemRevision, "item_revision_id"); + return itemRevision.get_item_revision_id(); + } + + public enum Order implements Comparator { + BY_FROZEN_RELEASE_DATE() { + @Override + public int compare(final TcUnitRevision unitRevision1, final TcUnitRevision unitRevision2) { + TcReleaseStatus frozenStatus1 = unitRevision1.frozenStatus(); + TcReleaseStatus frozenStatus2 = unitRevision2.frozenStatus(); + return TcReleaseStatus.Order.BY_RELEASE_DATE.compare(frozenStatus1, frozenStatus2); + } + }, + BY_RELEASE_DATE() { + @Override + public int compare(final TcUnitRevision unitRevision1, final TcUnitRevision unitRevision2) { + return unitRevision1.dateReleased().compareTo(unitRevision2.dateReleased()); + } + }, + BY_UNIT_NUMBER() { + @Override + public int compare(final TcUnitRevision unitRevision1, final TcUnitRevision unitRevision2) { + try { + return Integer.compare(unitRevision1.unitNumber(), unitRevision2.unitNumber()); + } + catch (KurtException e) { + return -1; + } + } + } + } +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/runtime/TcBomLine.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/runtime/TcBomLine.java new file mode 100644 index 0000000..ac335bd --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/runtime/TcBomLine.java @@ -0,0 +1,23 @@ +package com.capgemini.framework.teamcenter.object.runtime; + +import com.teamcenter.soa.client.model.strong.BOMLine; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class TcBomLine implements TcRuntimeBusinessObject { + private static final Logger LOGGER = LoggerFactory.getLogger(TcBomLine.class); + private static final String NO_FILTER = "None2"; + + private final BOMLine bomLine; + + + public TcBomLine(final BOMLine bomLine) { + this.bomLine = bomLine; + } + + @Override + public String toString() { + return "TcBomLine{bomLine=" + bomLine.getUid() + '}'; + } + +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/runtime/TcBomWindow.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/runtime/TcBomWindow.java new file mode 100644 index 0000000..bb52aba --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/runtime/TcBomWindow.java @@ -0,0 +1,32 @@ +package com.capgemini.framework.teamcenter.object.runtime; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.EmptyNomenclatureException; +import com.teamcenter.soa.client.model.strong.BOMLine; +import com.teamcenter.soa.client.model.strong.BOMWindow; + +public class TcBomWindow implements TcRuntimeBusinessObject, AutoCloseable { + + private final BOMWindow bomWindow; + private final TcSession session; + + public TcBomWindow(final TcSession session, final BOMWindow bomWindow) { + this.session = session; + this.bomWindow = bomWindow; + } + + public BOMLine topLine() throws EmptyNomenclatureException { + session.loadProperties(bomWindow, "top_line"); + BOMLine topLine = (BOMLine) bomWindow.get_top_line(); + session.loadProperties(topLine, "bl_line_object"); + if (topLine == null || topLine.get_bl_line_object() == null) { + throw new EmptyNomenclatureException("The top item provided does not seem to be effective under the selected configuration"); + } + return topLine; + } + + @Override + public void close() { + session.getStructureManagementService().closeBOMWindows(new BOMWindow[]{bomWindow}); + } +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/runtime/TcBomWindowConfiguration.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/runtime/TcBomWindowConfiguration.java new file mode 100644 index 0000000..63cc306 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/runtime/TcBomWindowConfiguration.java @@ -0,0 +1,30 @@ +package com.capgemini.framework.teamcenter.object.runtime; + +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcBomObject; +import com.teamcenter.services.strong.cad._2013_05.StructureManagement.CreateWindowsInfo2; +import com.teamcenter.soa.client.model.strong.PSBOMView; + +public class TcBomWindowConfiguration { + private final TcBomObject topLineObject; + private final PSBOMView bomview; + private final TcRevisionRulesConfiguration tcRevisionRulesConfiguration; + + public TcBomWindowConfiguration(final TcBomObject topLineObject, final TcRevisionRulesConfiguration tcRevisionRulesConfiguration) { + this(topLineObject, null, tcRevisionRulesConfiguration); + } + + public TcBomWindowConfiguration(final TcBomObject topLineObject, final PSBOMView bomview, final TcRevisionRulesConfiguration tcRevisionRulesConfiguration) { + this.topLineObject = topLineObject; + this.bomview = bomview; + this.tcRevisionRulesConfiguration = tcRevisionRulesConfiguration; + } + + public CreateWindowsInfo2[] toTcInfo() { + CreateWindowsInfo2[] createBOMWindowsInfo = new CreateWindowsInfo2[1]; + createBOMWindowsInfo[0] = new CreateWindowsInfo2(); + topLineObject.addInfo(createBOMWindowsInfo[0]); + tcRevisionRulesConfiguration.addInfo(createBOMWindowsInfo[0].revRuleConfigInfo); + createBOMWindowsInfo[0].bomView = bomview; + return createBOMWindowsInfo; + } +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/runtime/TcBomWindowFactory.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/runtime/TcBomWindowFactory.java new file mode 100644 index 0000000..fcf37f5 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/runtime/TcBomWindowFactory.java @@ -0,0 +1,27 @@ +package com.capgemini.framework.teamcenter.object.runtime; + +import com.capgemini.framework.teamcenter.ServiceDataHelper; +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.teamcenter.services.strong.cad._2007_01.StructureManagement.CreateBOMWindowsOutput; +import com.teamcenter.services.strong.cad._2007_01.StructureManagement.CreateBOMWindowsResponse; + +public class TcBomWindowFactory { + private final TcBomWindowConfiguration bomWindowConfiguration; + private final TcSession session; + + public TcBomWindowFactory(final TcSession session, final TcBomWindowConfiguration bomWindowConfiguration) { + this.session = session; + this.bomWindowConfiguration = bomWindowConfiguration; + } + + public TcBomWindow create() throws KurtException { + CreateBOMWindowsResponse createBOMWindowsResponse = session.getStructureManagementService().createBOMWindows2(bomWindowConfiguration.toTcInfo()); + if (ServiceDataHelper.hasErrors(createBOMWindowsResponse.serviceData)) { + ServiceDataHelper.displayErrors(createBOMWindowsResponse.serviceData); + throw new KurtException("Error while creating bom window."); + } + CreateBOMWindowsOutput bomWindowsOutput = createBOMWindowsResponse.output[0]; + return new TcBomWindow(session, bomWindowsOutput.bomWindow); + } +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/runtime/TcRevisionRulesConfiguration.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/runtime/TcRevisionRulesConfiguration.java new file mode 100644 index 0000000..5ee9c61 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/runtime/TcRevisionRulesConfiguration.java @@ -0,0 +1,27 @@ +package com.capgemini.framework.teamcenter.object.runtime; + +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcRevisionRule; +import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcRevisionRuleProperties; +import com.teamcenter.services.strong.cad._2007_01.StructureManagement.RevisionRuleConfigInfo; + +public class TcRevisionRulesConfiguration { + + private final TcRevisionRule revisionRule; + private final TcRevisionRuleProperties revisionRuleProperties; + + public TcRevisionRulesConfiguration(final TcRevisionRule revisionRule) { + this(revisionRule, null); + } + + public TcRevisionRulesConfiguration(final TcRevisionRule revisionRule, final TcRevisionRuleProperties revisionRuleProperties) { + this.revisionRule = revisionRule; + this.revisionRuleProperties = revisionRuleProperties; + } + + public void addInfo(final RevisionRuleConfigInfo revRuleConfigInfo) { + revisionRule.addInfo(revRuleConfigInfo); + if (revisionRuleProperties != null) { + revisionRuleProperties.addInfo(revRuleConfigInfo); + } + } +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/runtime/TcRuntimeBusinessObject.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/runtime/TcRuntimeBusinessObject.java new file mode 100644 index 0000000..52b85f1 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/runtime/TcRuntimeBusinessObject.java @@ -0,0 +1,6 @@ +package com.capgemini.framework.teamcenter.object.runtime; + +import com.capgemini.framework.teamcenter.object.TcBusinessObject; + +public interface TcRuntimeBusinessObject extends TcBusinessObject { +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/types/SnecmaObjectTypes.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/types/SnecmaObjectTypes.java new file mode 100644 index 0000000..e63b8cb --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/object/types/SnecmaObjectTypes.java @@ -0,0 +1,465 @@ +package com.capgemini.framework.teamcenter.object.types; + +import com.capgemini.framework.teamcenter.TeamcenterObjectTypes; +import com.google.common.base.Joiner; + +import java.util.regex.Pattern; + +/** + * Class regrouping all the used type of Teamcenter Revision objects. + */ +public final class SnecmaObjectTypes extends TeamcenterObjectTypes { + + /** + * The Teamcenter type for an Effectivity. + */ + public static final String EFFECTIVITY = "Effectivity"; + /** + * The Teamcenter type for a Product. + */ + public static final String PRODUCT = "Product"; + /** + * The Teamcenter type for a Product Revision. + */ + public static final String PRODUCT_REVISION = PRODUCT + REVISION; + /** + * The Teamcenter type for a Product Revision Master. + */ + public static final String PRODUCT_REVISION_MASTER = PRODUCT + REVISION + MASTER; + /** + * The Teamcenter type for a Generic. + */ + public static final String GENERIC = "Generic"; + /** + * The Teamcenter type for a Generic Revision. + */ + public static final String GENERIC_REVISION = GENERIC + REVISION; + /** + * The Teamcenter type for a SuperModel Revision. + */ + public static final String SUPERMODEL = "Super Model"; + /** + * The Teamcenter type for a SuperModel Revision. + */ + public static final String SUPERMODEL_REVISION = SUPERMODEL + REVISION; + /** + * The Teamcenter type for a Generic Assemb. + */ + public static final String GENERIC_ASSEMB = "Generic Assemb"; + /** + * The Teamcenter type for a Generic Assemb Revision. + */ + public static final String GENERIC_ASSEMB_REVISION = GENERIC_ASSEMB + REVISION; + /** + * The Teamcenter type for a Generic PV Revision Master (for both Generic and Generic Assemb). + */ + public static final String GENERIC_PV_REVISION_MASTER = "Generic PV Revision Master"; + /** + * The Teamcenter type for a RF Generic. + */ + public static final String RF_GENERIC = "RF Generic"; + /** + * The Teamcenter type for a RF Generic Revision. + */ + public static final String RF_GENERIC_REVISION = RF_GENERIC + REVISION; + /** + * The Teamcenter type for a RF Part. + */ + public static final String RF_PART = "RF Part"; + /** + * The Teamcenter type for a RF Part Revision. + */ + public static final String RF_PART_REVISION = RF_PART + REVISION; + /** + * The Teamcenter type for a RF Part Assemb. + */ + public static final String RF_PART_ASSEMB = "RF Part Assemb"; + /** + * The Teamcenter type for a RF Part Assemb Revision. + */ + public static final String RF_PART_ASSEMB_REVISION = RF_PART_ASSEMB + REVISION; + /** + * The Teamcenter type for a RF Admin 1 Revision Master. + */ + public static final String RF_ADMIN_1_REVISION_MASTER = "RF Admin 1 Revision Master"; + /** + * The Teamcenter type for a RF Admin. + */ + public static final String RF_ADMIN = "RF Admin"; + /** + * The Teamcenter type for a RF Master. + */ + public static final String RF_MASTER = "RF Master"; + /** + * The Teamcenter type for a RF Admin Revision. + */ + public static final String RF_ADMIN_REVISION = RF_ADMIN + REVISION; + /** + * The Teamcenter type for a RF Admin Revision Master. + */ + public static final String RF_ADMIN_REVISION_MASTER = RF_ADMIN_REVISION + MASTER; + + /** + * The Teamcenter type for a RF Admin A Revision. + */ + public static final String RF_ADMIN_A_REVISION = "RF Admin A Revision"; + + /** + * The Teamcenter type for a RF Admin AP Revision. + */ + public static final String RF_ADMIN_AP_REVISION = "RF Admin AP Revision"; + /** + * The Teamcenter type for a RF Admin AG Revision. + */ + public static final String RF_ADMIN_AG_REVISION = "RF Admin AG Revision"; + /** + * The Teamcenter type for a Descriptif. + */ + public static final String DESCRIPTIF = "Descriptif"; + /** + * The Teamcenter type for a Descriptif Revision. + */ + public static final String DESCRIPTIF_REVISION = DESCRIPTIF + REVISION; + /** + * The Teamcenter type for a Alternate. + */ + public static final String ALTERNATE = "Alternate"; + /** + * The Teamcenter type for a Alternate Revision. + */ + public static final String ALTERNATE_REVISION = ALTERNATE + REVISION; + /** + * The Teamcenter type for a DET. + */ + public static final String DET = "DET"; + /** + * The Teamcenter type for a DET Revision. + */ + public static final String DET_REVISION = DET + REVISION; + /** + * The Teamcenter type for a Part Aero. + */ + public static final String PART_AERO = "Part Aero"; + /** + * The Teamcenter type for a Part Aero Revision. + */ + public static final String PART_AERO_REVISION = PART_AERO + REVISION; + /** + * The Teamcenter type for a Part No Aero. + */ + public static final String PART_NO_AERO = "Part No Aero"; + /** + * The Teamcenter type for a Part No Aero Revision. + */ + public static final String PART_NO_AERO_REVISION = PART_NO_AERO + REVISION; + /** + * The Teamcenter type for a Part Assemb. + */ + public static final String PART_ASSEMB = "Part Assemb"; + /** + * The Teamcenter type for a Part Assemb Revision. + */ + public static final String PART_ASSEMB_REVISION = PART_ASSEMB + REVISION; + /** + * The Teamcenter type for a Part Assemb Revision Master. + */ + public static final String PART_ASSEMB_REVISION_MASTER = PART_ASSEMB_REVISION + MASTER; + /** + * The Teamcenter type for a Part Mat. + */ + public static final String PART_MAT = "Part Mat"; + /** + * The Teamcenter type for a Part Mat Revision. + */ + public static final String PART_MAT_REVISION = PART_MAT + REVISION; + /** + * The Teamcenter type for a Part Mat Revision Master. + */ + public static final String PART_MAT_REVISION_MASTER = PART_MAT_REVISION + MASTER; + /** + * The Teamcenter type for a Standard. + */ + public static final String STANDARD = "Standard"; + /** + * The Teamcenter type for a Standard Revision. + */ + public static final String STANDARD_REVISION = STANDARD + REVISION; + /** + * The Teamcenter type for a Standard Revision. + */ + public static final String STANDARD_REVISION_MASTER = STANDARD_REVISION + MASTER; + /** + * The Teamcenter type for a UnitRevision. + */ + public static final String UNIT_REVISION = "Unit Revision"; + /** + * The Teamcenter type for the Master Form of a UnitRevision. + */ + public static final String UNIT_REVISION_MASTER = UNIT_REVISION + MASTER; + /** + * The Teamcenter type for a geomertry. + */ + public static final String GEOMETRY = "Geometry"; + /** + * The Teamcenter type for a geomertry REVISION. + */ + public static final String GEOMETRY_REVISION = GEOMETRY + REVISION; + /** + * The Teamcenter type for a geomertry Revision Master. + */ + public static final String GEOMETRY_REVISION_MASTER = GEOMETRY_REVISION + MASTER; + /** + * The Teamcenter type for a changeRequest of type MACE. + */ + public static final String PV4_MACE_REVISION = "PV4_MACERevision"; + /** + * The Teamcenter type for a changeRequest of type DCAD. + */ + public static final String PV4_DCAD_REVISION = "PV4_DCADRevision"; + /** + * The Teamcenter type for a changeRequest of type CAD SCR (with effectivity). + */ + public static final String PV4_CAD_SCR_REVISION = "PV4_CAD_SCRRevision"; + /** + * The Teamcenter type for a changeRequest of type CAD ACR (without effectivity). + */ + public static final String PV4_CAD_ACR_REVISION = "PV4_CAD_ACRRevision"; + /** + * The Teamcenter type for a (Deprecated) changeRequest of type CR Deprec. + */ + public static final String PV4_CR_DEPREC = "PV4_CR_DEPREC"; + /** + * The Teamcenter type for a CN Deprecié Revision. + */ + public static final String CN_DEPRECIE_REVISION = "CN Déprécié Revision"; + /** + * The Teamcenter type for a CR Deprecié Revision. + */ + public static final String CR_DEPRECIE_REVISION = "CR Déprécié Revision"; + /** + * The Teamcenter type for a PV4_CN_DEPRECRevision. + */ + public static final String PV4_CN_DEPREC_REVISION = "PV4_CN_DEPRECRevision"; // No space! + /** + * The Teamcenter type for a PV4_CR_DEPRECRevision. + */ + public static final String PV4_CR_DEPREC_REVISION = "PV4_CR_DEPRECRevision"; // No space! + /** + * The Teamcenter type for a Revision EngChange. + */ + public static final String REVISION_ENG_CHANGE = "Revision EngChange"; + /** + * The Teamcenter type for a FPP Revision. + */ + public static final String FPP_REVISION = "PV4_FPPRevision"; + /** + * The Teamcenter Father type of all Documents. + */ + public static final String DOC_PV_REVISION = "Doc PV Revision"; + /** + * The Teamcenter type for a DocTechnic. + */ + public static final String DOC_TECHNIC = "DocTechnic"; + /** + * The Teamcenter type for a DocTechnic Revision. + */ + public static final String DOC_TECHNIC_REVISION = "DocTechnic Revision"; + /** + * The Teamcenter type for a DocTechnic Revision Master. + */ + public static final String DOC_TECHNIC_REVISION_MASTER = DOC_TECHNIC_REVISION + MASTER; + /** + * The Teamcenter type for a Geometry. + */ + public static final String DOC_GEOMETRY = "Geometry"; + /** + * The Teamcenter type for a Geometry Revision. + */ + public static final String DOC_GEOMETRY_REVISION = "Geometry Revision"; + /** + * The Teamcenter type for a DocDrawing. + */ + public static final String DOC_DRAWING = "DocDrawing"; + /** + * The Teamcenter type for a DocDrawing Revision. + */ + public static final String DOC_DRAWING_REVISION = "DocDrawing Revision"; + /** + * The Teamcenter type for a DocDrawing Revision Master. + */ + public static final String DOC_DRAWING_REVISION_MASTER = "DocDrawing Revision Master"; + /** + * The Teamcenter type for a doc PV Revision Master. + */ + public static final String DOC_PV_REVISION_MASTER = "Doc PV Revision Master"; + /** + * The Teamcenter type for a DocNorm. + */ + public static final String DOC_NORM = "DocNorm"; + /** + * The Teamcenter type for a DocNorm Revision. + */ + public static final String DOC_NORM_REVISION = DOC_NORM + REVISION; + /** + * The Teamcenter type for a DocNorm Master. + */ + public static final String DOC_NORM_MASTER = DOC_NORM + MASTER; + /** + * The Teamcenter type for a DocNorm Master. + */ + public static final String DOC_NORM_REVISION_MASTER = DOC_NORM_REVISION + MASTER; + /** + * The Teamcenter type for a DocDrawing Revision Master. + */ + public static final String DOC_NORM_STANDARD = "DocNormStandard"; + /** + * The Teamcenter type for a DocDrawing Revision Master. + */ + public static final String DOC_NORM_STANDARD_REVISION = DOC_NORM_STANDARD + REVISION; + /** + * The Teamcenter type for an Approbation SO. + */ + public static final String APPROBATION_SO = "Approbation SO"; + /** + * The Teamcenter type IMAN Relation: REACH Documents. + */ + public static final String FOLDER_PV_REACH_DOCS = "_PV_reach_docs"; + /** + * The Teamcenter type IMAN Relation: ITAR Documents. + */ + public static final String FOLDER_PV_ITAR_DOCS = "_PV_itar_docs"; + /** + * The Teamcenter type IMAN Relation: Definition Documents. + */ + public static final String FOLDER_PV_DEFINITION_DOCS = "_PV_definition_docs"; + /** + * The Teamcenter type IMAN Relation: Reference Documents. + */ + public static final String FOLDER_REFERENCED_DOCS = "_PV_reference_docs"; + public static final Pattern PART_REVISION_PATTERN = Pattern.compile("^((" + Joiner.on(")|(").join(PART_AERO_REVISION, PART_ASSEMB_REVISION, + PART_NO_AERO_REVISION, ALTERNATE_REVISION, DET_REVISION, PART_MAT_REVISION, STANDARD_REVISION) + "))$"); + public static final Pattern ALT_OR_DET_PATTERN = Pattern.compile("^((" + ALTERNATE_REVISION + ")|(" + DET_REVISION + "))$"); + public static final Pattern PART_PATTERN = Pattern.compile("^((" + Joiner.on(")|(").join(PART_AERO, PART_ASSEMB, + PART_NO_AERO, ALTERNATE, DET, PART_MAT, STANDARD) + "))$"); + public static final Pattern GENERIC_PATTERN = Pattern.compile("^((" + Joiner.on(")|(").join(GENERIC_REVISION, + GENERIC_ASSEMB_REVISION) + "))$"); + public static final Pattern SUPERMODEL_PATTERN = Pattern.compile("^((" + Joiner.on(")|(").join(SUPERMODEL, + SUPERMODEL_REVISION) + "))$"); + public static final Pattern PRODUCT_REV_PATTERN = Pattern.compile("^((" + PRODUCT_REVISION + "))$"); + public static final Pattern RF_REV_PATTERN = Pattern.compile("^((" + Joiner.on(")|(").join(RF_PART_ASSEMB_REVISION, + RF_PART_REVISION) + "))$"); + + private SnecmaObjectTypes() { + super(); + // Move along, nothing to see + } + + public static boolean isAltOrDet(final String objectType) { + return isAlt(objectType) || isDet(objectType); + } + + public static boolean isDet(final String objectType) { + return DET_REVISION.equals(objectType); + } + + public static boolean isAlt(final String objectType) { + return ALTERNATE_REVISION.equals(objectType); + } + + /** + * Returns true if the provided object type String matches a Part Revision.
    + * Any of the following will be a match: + *
      + *
    • Part Aero Revision
    • + *
    • Part No Aero Revision
    • + *
    • Part Assemb Revision
    • + *
    • Part Mat Revision
    • + *
    • Alternate Revision
    • + *
    • Standard Revision
    • + *
    • DET Revision
    • + *
    + * + * @param objectType the String describing the object type to be tested + * @return true if the object type matches a Part, false otherwise + */ + public static boolean isPartRevision(final String objectType) { + return PART_REVISION_PATTERN.matcher(objectType).matches(); + } + + /** + * Returns true if the provided object type String matches a Part.
    + * Any of the following will be a match: + *
      + *
    • Part Aero
    • + *
    • Part No Aero
    • + *
    • Part Assemb
    • + *
    • Part Mat
    • + *
    • Alternate
    • + *
    • Standard
    • + *
    • DET
    • + *
    + * + * @param objectType the String describing the object type to be tested + * @return true if the object type matches a Part, false otherwise + */ + public static boolean isPart(final String objectType) { + return PART_PATTERN.matcher(objectType).matches(); + } + + /** + * Returns true if the provided object type String matches a Generic.
    + * Any of the following will be a match: + *
      + *
    • Generic Revision
    • + *
    • Generic Assemb Revision
    • + *
    + * + * @param objectType the String describing the object type to be tested + * @return true if the object type matches a Generic, false otherwise + */ + public static boolean isGenericRevision(final String objectType) { + return GENERIC_PATTERN.matcher(objectType).matches(); + } + + /** + * Returns true if the provided object type String matches a SuperModel.
    + * Any of the following will be a match: + *
      + *
    • SuperModel Revision
    • + *
    + * + * @param objectType the String describing the object type to be tested + * @return true if the object type matches a Generic, false otherwise + */ + public static boolean isSuperModelRevision(final String objectType) { + return SUPERMODEL_PATTERN.matcher(objectType).matches(); + } + + /** + * Returns true if the provided object type String matches a Product.
    + * Any of the following will be a match: + *
      + *
    • Product Revision
    • + *
    + * + * @param objectType the String describing the object type to be tested + * @return true if the object type matches a Product Revision, false otherwise + */ + public static boolean isProductRevision(final String objectType) { + return PRODUCT_REV_PATTERN.matcher(objectType).matches(); + } + + /** + * Returns true if the provided object type String matches a Product.
    + * Any of the following will be a match: + *
      + *
    • Product Revision
    • + *
    + * + * @param objectType the String describing the object type to be tested + * @return true if the object type matches a Product Revision, false otherwise + */ + public static boolean isRFRevision(final String objectType) { + return RF_REV_PATTERN.matcher(objectType).matches(); + } +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/policies/PolicyLocation.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/policies/PolicyLocation.java new file mode 100644 index 0000000..c88dac8 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/policies/PolicyLocation.java @@ -0,0 +1,53 @@ +package com.capgemini.framework.teamcenter.policies; + +import lombok.Getter; + +/** + * Simple storage class to represent a policy.
    + * Contains: + *
      + *
    • A policy IDENTIFIER (to tell Teamcenter which file to load)
    • + *
    • A file PATH to a policy file for the xmlDomParser
    • + *
    + */ +public final class PolicyLocation { + + /** The identifier of the policy as it exists on the TC servers. */ + @Getter + private final String identifier; + /** The file path to the policy within the "src/main/resources" folder. */ + @Getter + private final String location; + + /** + * Makes a policyLocation object. + * + * @param identifier the Id of the policy as it exists on the TC servers + * @param location the file path to the policy within the "src/main/resources" folder + * @return the PolicyLocation created. + */ + public static PolicyLocation make(final String identifier, final String location) { + return new PolicyLocation(identifier, location); + } + + private PolicyLocation(final String identifier, final String location) { + this.identifier = identifier == null ? "" : identifier; + this.location = location == null ? "" : location; + } + + @Override + public boolean equals(final Object obj) { + if (obj == null || getClass() != obj.getClass()) { + return false; + } + PolicyLocation other = (PolicyLocation) obj; + return identifier.equals(other.identifier) && location.equals(other.location); + } + + @Override + public int hashCode() { + return identifier.hashCode() ^ location.hashCode(); + + } + +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/queries/saved/AbstractReplicatedQuery.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/queries/saved/AbstractReplicatedQuery.java new file mode 100644 index 0000000..327b5e7 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/queries/saved/AbstractReplicatedQuery.java @@ -0,0 +1,157 @@ +package com.capgemini.framework.teamcenter.queries.saved; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.teamcenter.soa.client.model.ModelObject; +import com.teamcenter.soa.client.model.strong.Item; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import lombok.extern.slf4j.Slf4j; + +/** + * This class is able to look for some objects in Teamcenter using replicated queries with custom name that CANNOT be translated by Teamcenter before evaluation. + * + * @param the expected type of the Object: either {@link Item} or {@link ItemRevision} + * @param The type of the actual daughter class. Provided to chain requests. + */ +@Slf4j +public abstract class AbstractReplicatedQuery> + extends AbstractSavedQuery { + + // Reporting prefix convention + /** + * Common prefix for all columns used by replicated queries for reports. + **/ + protected static final String REPCOL_PREFIX = "report_"; + /** + * Keyword for query parameter: Item ID. + */ + protected static final String PARAM_ITEM_ID = REPCOL_PREFIX + "item_id"; + + // Parameter name suffixes + /** + * Keyword for query parameter: object name. + */ + protected static final String PARAM_OBJECT_NAME = REPCOL_PREFIX + "Name"; + /** + * Keyword for query parameter: Product type name. + */ + protected static final String PARAM_NOM_TYPE_PRODUIT = REPCOL_PREFIX + "pv_nom_type_produit"; + /** + * Common prefix for all replicated queries used by reports. + **/ + private static final String REPQUERY_PREFIX = "__Report_"; + /** + * Keyword for query parameter: Revision. + */ + private static final String PARAM_ITEM_REVISION_ID = REPCOL_PREFIX + "Revision"; + /** + * Keyword for query parameter: object ID. + */ + private static final String PARAM_END_ITEM_ID = REPCOL_PREFIX + "end_item_id"; + /** + * Keyword for query parameter: Effectivity Unit of introduction. + */ + private static final String PARAM_EFFECTIVITY_UNITS_INTRO = REPCOL_PREFIX + "effectivity_units_intro"; + /** + * Keyword for query parameter: Creation Date before. + */ + private static final String PARAM_DATE_AVANT = REPCOL_PREFIX + "cree_avant"; + /** + * Keyword for query parameter: Creation Date after. + */ + private static final String PARAM_DATE_APRES = REPCOL_PREFIX + "cree_apres"; + + protected AbstractReplicatedQuery(final TcSession session, final String queryNameSuffix, final int maxQueries, final int paging) { + super(session, REPQUERY_PREFIX + queryNameSuffix, maxQueries, paging); + } + + protected AbstractReplicatedQuery(final TcSession session, final String queryNameSuffix) { + super(session, REPQUERY_PREFIX + queryNameSuffix); + } + + @Override + public QUERY searchID(final String itemID) { + return this.addParam(PARAM_ITEM_ID, itemID); + } + + @Override + public QUERY searchRevision(final String revision) { + return this.addParam(PARAM_ITEM_REVISION_ID, revision); + } + + @Override + public QUERY searchName(final String itemName) { + return this.addParam(PARAM_OBJECT_NAME, itemName); + } + + /** + * Search all the possible objects within limitation of number of retrieved elements (no return limit). + * + * @return this QUERY, updated to return the list of all the OBJECT elements + */ + public QUERY searchAllObjects() { + this.searchID("*"); + this.changeMaxNumberValues(-1); + return selfCast(); + } + + /** + * Specify an end item Identifier. The returned objects will be below this end item. + * + * @param endItemID the end item identifier (a {@link String}) + * @return the same query + */ + public AbstractReplicatedQuery addEndItemID(final String endItemID) { + parameters.put(PARAM_END_ITEM_ID, endItemID); + return this; + } + + /** + * Specify an Unit of introduction. + * + * @param effectivityUnit the unit (a {@link String}) + * @return the same query + */ + public AbstractReplicatedQuery addEffectivityUnitIntro(final String effectivityUnit) { + parameters.put(PARAM_EFFECTIVITY_UNITS_INTRO, effectivityUnit); + return this; + } + + /** + * Specify a before date.
    + * The objects should be create BEFORE this date. + * + * @param date the date (a {@link String}) + * @return the same query + */ + public AbstractReplicatedQuery addBeforeDate(final String date) { + parameters.put(PARAM_DATE_AVANT, date); + return this; + } + + /** + * Specify an after date.
    + * The objects should be create AFTER this date. + * + * @param date the date (a {@link String}) + * @return the same query + */ + public AbstractReplicatedQuery addAfterDate(final String date) { + parameters.put(PARAM_DATE_APRES, date); + return this; + } + + @Override + public QUERY addParam(final String aParamName, final String aParamValue) { + // Check if current query is specific for reports + // For these queries, all columns should begin by the "report_" prefix + if (!savedQueryName.startsWith(REPQUERY_PREFIX) || !aParamName.startsWith(REPCOL_PREFIX)) { + log.error("The current parameter is not compliant with report queries structure: " + aParamName); + } else { + parameters.put(aParamName, aParamValue); + } + return selfCast(); + } + + protected abstract QUERY selfCast(); + +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/queries/saved/AbstractSavedQuery.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/queries/saved/AbstractSavedQuery.java new file mode 100644 index 0000000..fa61070 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/queries/saved/AbstractSavedQuery.java @@ -0,0 +1,249 @@ +package com.capgemini.framework.teamcenter.queries.saved; + +import com.capgemini.framework.teamcenter.ServiceDataHelper; +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.exceptions.QueryDoesNotExist; +import com.teamcenter.schemas.soa._2006_03.exceptions.ServiceException; +import com.teamcenter.services.strong.query.SavedQueryService; +import com.teamcenter.services.strong.query._2006_03.SavedQuery.GetSavedQueriesResponse; +import com.teamcenter.services.strong.query._2006_03.SavedQuery.SavedQueryObject; +import com.teamcenter.services.strong.query._2007_09.SavedQuery.QueryResults; +import com.teamcenter.services.strong.query._2007_09.SavedQuery.SavedQueriesResponse; +import com.teamcenter.services.strong.query._2008_06.SavedQuery.QueryInput; +import com.teamcenter.soa.client.model.ModelObject; +import com.teamcenter.soa.client.model.strong.ImanQuery; +import com.teamcenter.soa.client.model.strong.Item; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.*; +import java.util.Map.Entry; + +/** + * Setup Teamcenter Search objects, using names, IdDs atc. as parameters.
    + * Additional search parameters are available. Uses Teamcenter SavedQueries. + * + * @param The type of TC objets request (generally {@link Item} or {@link ItemRevision}). Must be a sub-type of {@link ModelObject}. + * @param The type of the actual daughter class. Provided to chain requests. + */ +public abstract class AbstractSavedQuery> { + private static final Logger LOGGER = LoggerFactory.getLogger(AbstractSavedQuery.class); + + private static final int DEFAULT_QUERY_RESULT_PAGING = 1000; + private static final int DEFAULT_MAX_QUERY_RESULTS = -1; // NO limit! + private static final String UNABLE_TO_FIND_THE_ITEM = "Unable to find the Item: "; + protected final Map parameters; + protected final TcSession session; + final String savedQueryName; + private final SavedQueryService savedQueryService; + private final int paging; + /** + * Maximum number of results for this query. + */ + private int maxQueries; + + /** + * Basic constructor. Caps the number of results. + * + * @param session Required to setup the search services. + * @param savedQueryName the name of the request to obtain from Tc. + * @param maxQueries the cap on maximum number of results + * @param paging stepping through the result list + */ + protected AbstractSavedQuery(final TcSession session, final String savedQueryName, final int maxQueries, final int paging) { + this.session = session; + this.savedQueryService = session.getSavedQueryService(); + this.parameters = new HashMap<>(); + this.savedQueryName = savedQueryName; + this.maxQueries = maxQueries; + this.paging = paging; + } + + /** + * Basic constructor. + * + * @param session Required to setup the search services. + * @param savedQueryName the name of the request to obtain from Tc. + */ + protected AbstractSavedQuery(final TcSession session, final String savedQueryName) { + this.session = session; + this.savedQueryService = session.getSavedQueryService(); + this.parameters = new HashMap<>(); + this.savedQueryName = savedQueryName; + this.maxQueries = DEFAULT_MAX_QUERY_RESULTS; + this.paging = DEFAULT_QUERY_RESULT_PAGING; + } + + /** + * Adds some search parameter (Revision, unit, date, owner...). + * + * @param aParamName Le type de parametre a utiliser + * @param aParamValue La valeur que le parametre impose doit respecter. + * @return This same request, to chain the requests + */ + protected abstract QUERY addParam(final String aParamName, final String aParamValue); + + /** + * Request that the objects match the specified Identifier. + * + * @param itemID The requested identifier (ex: "ND0000") + * @return This same request, to chain the requests. + */ + public abstract QUERY searchID(final String itemID); + + /** + * Request that the objects match the specified revision. + * + * @param revisionID the requested revision. (ex: "B") + * @return This same request, to chain the requests. + */ + public abstract QUERY searchRevision(final String revisionID); + + /** + * Request that the objects match both the specified Identifier and revision. + * + * @param itemID the requested identifier. (ex: "ND0000") + * @param revisionID the requested revision. (ex: "B") + * @return This same request, to chain the requests. + */ + public QUERY searchIDAndRevision(final String itemID, final String revisionID) { + return this.searchID(itemID).searchRevision(revisionID); + } + + /** + * Request that the objects match the specified object name. + * + * @param itemName the requested object name. (ex: "GE90 M10 MOTEUR ASSEMBLE") + * @return This same request, to chain the requests. + */ + public abstract QUERY searchName(final String itemName); + + /** + * Impose a maximum number of returned values. + * + * @param maxValues the maximum number of results + */ + public void changeMaxNumberValues(final int maxValues) { + maxQueries = maxValues; + } + + /** + * Returns the result of the query. + * + * @return the matching element. + */ + public OBJ find() throws KurtException { + List list = findAll(); + if (!list.isEmpty()) { + OBJ obj = list.get(0); + if (obj != null) { + return obj; + } + } + throw new KurtException(UNABLE_TO_FIND_THE_ITEM); + } + + /** + * Returns the result of the query. + * + * @return a list containing all matching elements. This list may not be {@code null}, but it may be empty. + */ + public List findAll() { + ImanQuery query; + // Get the service stub. + try { + query = getSavedQuery(); + } catch (QueryDoesNotExist e) { + LOGGER.error("Query does not exist", e); + return new ArrayList<>(); + } catch (ServiceException e) { + LOGGER.error("Unable to contact the servers to perform the query", e); + return new ArrayList<>(); + } + List foundObjs; + if (query == null) { + LOGGER.warn("No query named \"{}\" were found.", savedQueryName); + foundObjs = new ArrayList<>(); + } else { + QueryInput[] savedQueryInput = setQueryParameters(query); + + // ***************************** + // Execute the service operation + // ***************************** + SavedQueriesResponse savedQueryResult = savedQueryService.executeSavedQueries(savedQueryInput); + if (ServiceDataHelper.hasErrors(savedQueryResult.serviceData)) { + ServiceDataHelper.displayErrors(savedQueryResult.serviceData); + LOGGER.warn("The following query has failed: {} with arguments:\n{}", savedQueryName, parameters.toString()); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("Accepted properties: {}", Arrays.toString(query.getPropertyNames())); + LOGGER.debug("Query clauses: {}", Arrays.toString(query.get_query_clauses())); + } + } + + QueryResults found = savedQueryResult.arrayOfResults[0]; + + foundObjs = parseResults(found); + } + return foundObjs; + } + + private List parseResults(final QueryResults found) { + List foundObjs = new ArrayList<>(); + LOGGER.debug("Loading {} UIDs", found.objectUIDS.length); + + for (int pageStart = 0; pageStart < found.objectUIDS.length; pageStart = pageStart + paging) { + int pageSize = (pageStart + paging < found.objectUIDS.length) ? paging : found.objectUIDS.length - pageStart; + String[] uidsOnPage = new String[pageSize]; + System.arraycopy(found.objectUIDS, pageStart, uidsOnPage, 0, pageSize); + if (LOGGER.isTraceEnabled()) { + int pageEnd = pageStart + pageSize; + LOGGER.trace("-Loading UID page [{}-{}[\t: {}", pageStart, pageEnd, Arrays.toString(uidsOnPage)); + } + foundObjs.addAll(session.loadObjects(uidsOnPage)); + } + return foundObjs; + } + + /** + * Obtain the TC Query Object. + */ + private ImanQuery getSavedQuery() throws QueryDoesNotExist, ServiceException { + GetSavedQueriesResponse savedQueries; + savedQueries = savedQueryService.getSavedQueries(); + if (ServiceDataHelper.hasErrors(savedQueries.serviceData)) { + ServiceDataHelper.displayErrors(savedQueries.serviceData); + } + if (savedQueries.queries.length == 0) { + throw new QueryDoesNotExist("There are no saved queries in the system."); + } + for (SavedQueryObject query : savedQueries.queries) { + if (savedQueryName.equals(query.name)) { + return query.query; + } + } + throw new QueryDoesNotExist("No saved queries found with name \"" + savedQueryName + "\""); + } + + private QueryInput[] setQueryParameters(final ImanQuery query) { + QueryInput[] savedQueryInput = new QueryInput[1]; + savedQueryInput[0] = new QueryInput(); + savedQueryInput[0].query = query; + savedQueryInput[0].maxNumToReturn = maxQueries; // -1 for ALL + savedQueryInput[0].limitList = new ModelObject[0]; + int nbParam = parameters.size(); + String[] paramTypes = new String[nbParam]; + String[] paramValues = new String[nbParam]; + int num = 0; + for (Entry param : parameters.entrySet()) { + paramTypes[num] = param.getKey(); + paramValues[num] = param.getValue(); + num++; + } + savedQueryInput[0].entries = paramTypes; + savedQueryInput[0].values = paramValues; + return savedQueryInput; + } + +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/queries/saved/modelobject/AbstractModelObjectQuery.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/queries/saved/modelobject/AbstractModelObjectQuery.java new file mode 100644 index 0000000..1ed89f6 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/queries/saved/modelobject/AbstractModelObjectQuery.java @@ -0,0 +1,80 @@ +package com.capgemini.framework.teamcenter.queries.saved.modelobject; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.queries.saved.AbstractReplicatedQuery; +import com.teamcenter.soa.client.model.ModelObject; +import com.teamcenter.soa.client.model.strong.Item; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +/** + * Looks for a ModelObject in Teamcenter. + * + * @param the type of the actual daughter class. Provided to chain requests. + * @param the expected type of the Object: either {@link Item} or {@link ItemRevision} + */ +public abstract class AbstractModelObjectQuery> + extends AbstractReplicatedQuery { + private static final String PARAM_OBJECT_TYPE = "Type"; + private static final String VALUE_OBJECT_TYPE_PRODUCT = "Product"; + private static final String VALUE_OBJECT_TYPE_GENERIC = "Generic"; + private static final String VALUE_OBJECT_TYPE_GENERIC_ASSEMB = "Generic Assemb"; + + protected AbstractModelObjectQuery(final TcSession session, final String queryNameSuffix) { + super(session, queryNameSuffix); + } + + /** + * Demande a cette requete de rechercher un objet d'un certain type. + * + * @param requestedType the constraint on object type + * @return Cette meme requete, pour chainer les parametres. + */ + public QUERY searchType(final String requestedType) { + return this.addParam(PARAM_OBJECT_TYPE, requestedType); + } + + /** + * Demande a cette requete de rechercher un Generic. + * + * @return Cette meme requete, pour chainer les parametres. + */ + public QUERY searchGeneric() { + return this.addParam(PARAM_OBJECT_TYPE, VALUE_OBJECT_TYPE_GENERIC); + } + + /** + * Demande a cette requete de rechercher un Generic Assemb. + * + * @return Cette meme requete, pour chainer les parametres. + */ + public QUERY searchGenericAssemb() { + return this.addParam(PARAM_OBJECT_TYPE, VALUE_OBJECT_TYPE_GENERIC_ASSEMB); + } + + /** + * Demande a cette requete de rechercher un Product. + * + * @return Cette meme requete, pour chainer les parametres. + */ + public QUERY searchProduct() { + return this.addParam(PARAM_OBJECT_TYPE, VALUE_OBJECT_TYPE_PRODUCT); + } + + /** + * Demande a cette requete de rechercher le nom d'objet fourni.. + * + * @param itemName Le nom a rechercher. (exemple: "M88 MOTEUR ASSEMBLE") + * @return Cette meme requete, pour chainer les parametres. + */ + @Override + public QUERY searchName(final String itemName) { + return this.addParam(PARAM_OBJECT_NAME, itemName); + } + + @Override + public QUERY addParam(final String aParamName, final String aParamValue) { + super.parameters.put(aParamName, aParamValue); + return selfCast(); + } + +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/queries/saved/modelobject/IMANRelationQuery.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/queries/saved/modelobject/IMANRelationQuery.java new file mode 100644 index 0000000..0d921fc --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/queries/saved/modelobject/IMANRelationQuery.java @@ -0,0 +1,69 @@ +package com.capgemini.framework.teamcenter.queries.saved.modelobject; + +import com.capgemini.framework.teamcenter.TeamcenterObjectTypes; +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.queries.saved.AbstractReplicatedQuery; +import com.teamcenter.soa.client.model.strong.ImanRelation; + +import java.util.List; + +/** + * A Tc Query that can be used to search exisitng relations between a primary and a secondary object. + */ +public class IMANRelationQuery { + private final TcSession session; + + /** + * Creates an instance that is able to perform queries. + * + * @param session an active session + */ + public IMANRelationQuery(final TcSession session) { + this.session = session; + } + + /** + * Returns all {@link ImanRelation} referenced datasets (in a {@link List}) of an item. + * + * @param itemId the Item's ID + * @param datasetName the dataset name + * @return a List of ImanRelation + */ + public List find(final String itemId, final String datasetName) { + TheInternalRelationQuery query = new TheInternalRelationQuery(session); + return query.find(itemId, datasetName); + } + + private static final class TheInternalRelationQuery extends AbstractReplicatedQuery { + private static final String QUERY_SUFFIX = "Relationship"; + + private static final String KEY_DATASET_NAME = REPCOL_PREFIX + "dataset_name"; + private static final String KEY_ITEM_ID = REPCOL_PREFIX + "item_id"; + private static final String KEY_RELATIONSHIP = REPCOL_PREFIX + "relationship"; + + protected TheInternalRelationQuery(final TcSession session) { + super(session, QUERY_SUFFIX); + } + + /** + * Finds an {@link ImanRelation} between an item and a dataset. + * + * @param itemId the ID of the Item + * @param datasetName the name of the dataset + * @return a {@link List} of all the {@link ImanRelation}s found + */ + public List find(final String itemId, final String datasetName) { + addParam(KEY_RELATIONSHIP, TeamcenterObjectTypes.IMAN_REFERENCE); + addParam(KEY_ITEM_ID, itemId); + addParam(KEY_DATASET_NAME, datasetName); + return this.findAll(); + } + + @Override + protected TheInternalRelationQuery selfCast() { + return this; + } + + } + +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/queries/saved/modelobject/ItemQuery.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/queries/saved/modelobject/ItemQuery.java new file mode 100644 index 0000000..c61a6ce --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/queries/saved/modelobject/ItemQuery.java @@ -0,0 +1,25 @@ +package com.capgemini.framework.teamcenter.queries.saved.modelobject; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.teamcenter.soa.client.model.strong.Item; + +/** Searches an Item. */ +public class ItemQuery extends AbstractModelObjectQuery { + + private static final String QUERY_NAME_SUFFIX = "Item"; + + /** + * Creates a request for Tc to return an Item. + * + * @param session an active session + */ + public ItemQuery(final TcSession session) { + super(session, QUERY_NAME_SUFFIX); + } + + @Override + protected ItemQuery selfCast() { + return this; + } + +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/queries/saved/modelobject/ItemRevisionQuery.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/queries/saved/modelobject/ItemRevisionQuery.java new file mode 100644 index 0000000..00df621 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/queries/saved/modelobject/ItemRevisionQuery.java @@ -0,0 +1,26 @@ +package com.capgemini.framework.teamcenter.queries.saved.modelobject; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +/** Searches an ItemRevision. */ +public class ItemRevisionQuery extends AbstractModelObjectQuery { + + private static final String QUERY_NAME_SUFFIX = "ItemRevision"; + + /** + * Creates a request for Tc to return an ItemRevision. + * + * @param session an active session + */ + public ItemRevisionQuery(final TcSession session) { + super(session, QUERY_NAME_SUFFIX); + } + + + @Override + protected ItemRevisionQuery selfCast() { + return this; + } + +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/resolution/filtering/AllFilter.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/resolution/filtering/AllFilter.java new file mode 100644 index 0000000..8584be3 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/resolution/filtering/AllFilter.java @@ -0,0 +1,33 @@ +package com.capgemini.framework.teamcenter.resolution.filtering; + +/** + * Filter that accepts everything. obtain an instance through {@link AllFilter#getInstance()}. + */ +public final class AllFilter implements ITcTypeFilter { + + private static final AllFilter INSTANCE = new AllFilter(); + + private AllFilter() { + // Just making it singleton + } + + /** + * Returns the (unique) instance of this filter, which accepts everything. + * + * @return the instance of {@link AllFilter}. + */ + public static AllFilter getInstance() { + return INSTANCE; + } + + @Override + public boolean isExcluded(final String type) { + return false; + } + + @Override + public boolean isIncluded(final String type) { + return true; + } + +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/resolution/filtering/AndFilter.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/resolution/filtering/AndFilter.java new file mode 100644 index 0000000..490883b --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/resolution/filtering/AndFilter.java @@ -0,0 +1,22 @@ +package com.capgemini.framework.teamcenter.resolution.filtering; + +import lombok.AllArgsConstructor; + +/** {@link ITcTypeFilter} class that combines two sub-{@link ITcTypeFilter} into a logical AND. */ +@AllArgsConstructor +public class AndFilter implements ITcTypeFilter { + + private final ITcTypeFilter filter1; + private final ITcTypeFilter filter2; + + @Override + public boolean isExcluded(final String type) { + return filter1.isExcluded(type) || filter2.isExcluded(type); + } + + @Override + public boolean isIncluded(final String type) { + return filter1.isIncluded(type) && filter2.isIncluded(type); + } + +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/resolution/filtering/ITcTypeFilter.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/resolution/filtering/ITcTypeFilter.java new file mode 100644 index 0000000..e82ad3d --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/resolution/filtering/ITcTypeFilter.java @@ -0,0 +1,22 @@ +package com.capgemini.framework.teamcenter.resolution.filtering; + +/** Interface for a filter that act on an item's type. */ +public interface ITcTypeFilter { + + /** + * Returns true if the type provided should be excluded by this filter. + * + * @param type the type to assess + * @return true if the type is to be excluded, false otherwise. + */ + boolean isExcluded(final String type); + + /** + * Returns true if the type provided should be included by this filter. + * + * @param type the type to assess + * @return true if the type is to be included, false if it is to be excluded. + */ + boolean isIncluded(final String type); + +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/resolution/filtering/OrFilter.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/resolution/filtering/OrFilter.java new file mode 100644 index 0000000..a3d34f0 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/resolution/filtering/OrFilter.java @@ -0,0 +1,21 @@ +package com.capgemini.framework.teamcenter.resolution.filtering; + +import lombok.AllArgsConstructor; + +/** {@link ITcTypeFilter} class that combines two sub-{@link ITcTypeFilter} into a logical OR. */ +@AllArgsConstructor +public class OrFilter implements ITcTypeFilter { + + private final ITcTypeFilter filter1; + private final ITcTypeFilter filter2; + + @Override + public boolean isExcluded(final String type) { + return filter1.isExcluded(type) && filter2.isExcluded(type); + } + + @Override + public boolean isIncluded(final String type) { + return filter1.isIncluded(type) || filter2.isIncluded(type); + } +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/resolution/filtering/TcTypeExclusionFilter.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/resolution/filtering/TcTypeExclusionFilter.java new file mode 100644 index 0000000..72fda71 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/resolution/filtering/TcTypeExclusionFilter.java @@ -0,0 +1,30 @@ +package com.capgemini.framework.teamcenter.resolution.filtering; + +import java.util.Arrays; + +/** Exclude objects according to their type. */ +public class TcTypeExclusionFilter implements ITcTypeFilter { + + private final String[] forbidden; + + /** + * Builds a {@link ITcTypeFilter} that will exclude any object of the provided type. + * + * @param forbidden the object types to be excluded + */ + public TcTypeExclusionFilter(final String... forbidden) { + this.forbidden = forbidden; + Arrays.sort(forbidden); + } + + @Override + public boolean isExcluded(final String type) { + return Arrays.binarySearch(forbidden, type) >= 0; + } + + @Override + public boolean isIncluded(final String type) { + return !isExcluded(type); + } + +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/resolution/filtering/TcTypeInclusionFilter.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/resolution/filtering/TcTypeInclusionFilter.java new file mode 100644 index 0000000..189bbb1 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/resolution/filtering/TcTypeInclusionFilter.java @@ -0,0 +1,30 @@ +package com.capgemini.framework.teamcenter.resolution.filtering; + +import java.util.Arrays; + +/** Include objects according to their type. */ +public class TcTypeInclusionFilter implements ITcTypeFilter { + + private final String[] allowedObjects; + + /** + * Builds a {@link ITcTypeFilter} that will ALLOW any object of the provided type. + * + * @param allowedObjects the object types to be included + */ + public TcTypeInclusionFilter(final String... allowedObjects) { + this.allowedObjects = allowedObjects; + Arrays.sort(allowedObjects); + } + + @Override + public boolean isExcluded(final String type) { + return !isIncluded(type); + } + + @Override + public boolean isIncluded(final String type) { + return Arrays.binarySearch(allowedObjects, type) >= 0; + } + +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/resolution/structureservice/AbstractStructureServiceRaw.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/resolution/structureservice/AbstractStructureServiceRaw.java new file mode 100644 index 0000000..174c6a6 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/resolution/structureservice/AbstractStructureServiceRaw.java @@ -0,0 +1,29 @@ +package com.capgemini.framework.teamcenter.resolution.structureservice; + +import com.capgemini.framework.teamcenter.exceptions.EmptyNomenclatureException; +import com.capgemini.framework.teamcenter.resolution.filtering.ITcTypeFilter; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.teamcenter.soa.client.model.ModelObject; +import com.teamcenter.soa.client.model.strong.BOMLine; +import com.teamcenter.soa.client.model.strong.Item; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +interface StructureServiceRaw { + + /** + * Run a resolution from a configuration.
    + * The top {@link ModelObject} should be an {@link Item} or an {@link ItemRevision}.
    + *

    + * There may be several outcomes, depending on the Resolution Mode: + *

      + *
    • SINGLE:In this mode, the explosion is performed throughout only 1 link.
      + * It returns a {@link BOMLine} containing the top item (the one provided for the explosion)
    • + *
    • MONO:In this mode, the explosion is performed throughout 3 consecutive links, usually as part of the Receptor-Repere-Component relationship
      + * It returns a {@link BOMLine} containing the top item (the one provided for the explosion)
    • + *
    • MULTI:In this mode, the explosion is performed throughout all the links, and all the children and grand-children are revealed.
      + * It returns a {@link BOMLine} containing the top item (the one provided for the explosion)
    • + *
    + */ + BOMLineHolder resolve(final BOMLine topBomLine, final ITcTypeFilter filter) throws EmptyNomenclatureException; +} + diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/resolution/structureservice/MultiStructureServiceCallerRaw.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/resolution/structureservice/MultiStructureServiceCallerRaw.java new file mode 100644 index 0000000..e40e67a --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/resolution/structureservice/MultiStructureServiceCallerRaw.java @@ -0,0 +1,85 @@ +package com.capgemini.framework.teamcenter.resolution.structureservice; + +import com.capgemini.framework.teamcenter.ServiceDataHelper; +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.EmptyNomenclatureException; +import com.capgemini.framework.teamcenter.resolution.filtering.ITcTypeFilter; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.teamcenter.services.strong.cad._2008_06.StructureManagement.*; +import com.teamcenter.soa.client.model.strong.BOMLine; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + + +/** + * Helper dedicated to multi levels resolution of configurations. + **/ +public class MultiStructureServiceCallerRaw implements StructureServiceRaw { + private static final Logger LOGGER = LoggerFactory.getLogger(MultiStructureServiceCallerRaw.class); + private static final String NO_FILTER = "None2"; + + private final TcSession session; + + public MultiStructureServiceCallerRaw(final TcSession session) { + this.session = session; + } + + @Override + public BOMLineHolder resolve(final BOMLine topBomLine, final ITcTypeFilter filter) throws EmptyNomenclatureException { + LOGGER.debug("Top line: {}", topBomLine.getUid()); + LOGGER.debug("Start Multi-level BOMLine expansion"); + ExpandPSAllLevelsResponse2 response = session.getStructureManagementService().expandPSAllLevels(expandInfo(topBomLine), expandPref()); + LOGGER.debug("End expand all levels"); + if (ServiceDataHelper.hasErrors(response.serviceData)) { + ServiceDataHelper.displayErrors(response.serviceData); + } + + Map dataByBomLine = new HashMap<>(); + for (ExpandPSAllLevelsOutput output : response.output) { + BOMLine parentBomLine = output.parent.bomLine; + if (parentBomLine != null && output.parent.objectOfBOMLine != null) { + dataByBomLine.put(parentBomLine, output); + } + } + + return toTreeBom(dataByBomLine, topBomLine, filter); + } + + private ExpandPSAllLevelsInfo expandInfo(BOMLine topBomLine) { + ExpandPSAllLevelsInfo info = new ExpandPSAllLevelsInfo(); + info.parentBomLines = new BOMLine[]{topBomLine}; + info.excludeFilter = NO_FILTER; + return info; + } + + private ExpandPSAllLevelsPref expandPref() { + ExpandPSAllLevelsPref pref = new ExpandPSAllLevelsPref(); + pref.expItemRev = false; + return pref; + } + + private BOMLineHolder toTreeBom(final Map dataByBomLine, final BOMLine parentBomLine, final ITcTypeFilter filter) { + ExpandPSAllLevelsOutput parentOutput = dataByBomLine.get(parentBomLine); + List childs = new ArrayList<>(); + for (ExpandPSData currentChildData : parentOutput.children) { + if (currentChildData.objectOfBOMLine != null && filter.isIncluded(currentChildData.objectOfBOMLine.getTypeObject().getName())) { + if (hasChilds(dataByBomLine, currentChildData)) { + childs.add(toTreeBom(dataByBomLine, currentChildData.bomLine, filter)); + } else { + childs.add(new BOMLineHolder(session, currentChildData.bomLine, (ItemRevision) currentChildData.objectOfBOMLine, new ArrayList())); + } + } + } + return new BOMLineHolder(session, parentOutput.parent.bomLine, (ItemRevision) parentOutput.parent.objectOfBOMLine, childs); + } + + private boolean hasChilds(Map dataByBomLine, ExpandPSData currentChildData) { + return dataByBomLine.get(currentChildData.bomLine) != null; + } +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/resolution/structureservice/SingleStructureServiceCallerRaw.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/resolution/structureservice/SingleStructureServiceCallerRaw.java new file mode 100644 index 0000000..00f2aba --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/resolution/structureservice/SingleStructureServiceCallerRaw.java @@ -0,0 +1,136 @@ +package com.capgemini.framework.teamcenter.resolution.structureservice; + +import com.capgemini.framework.teamcenter.ServiceDataHelper; +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.EmptyNomenclatureException; +import com.capgemini.framework.teamcenter.resolution.filtering.ITcTypeFilter; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.teamcenter.services.strong.cad._2008_06.StructureManagement.*; +import com.teamcenter.soa.client.model.strong.BOMLine; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +/** + * Helper dedicated to single level resolution of configurations. + **/ +@Slf4j +public class SingleStructureServiceCallerRaw implements StructureServiceRaw { + private static final String NO_FILTER = "None2"; + private static final String ERROR_MSG_NULL_BOM_LINE_PROVIDED = "Unable to resolve from a null BOMLine."; + private static final String ERROR_MSG_NO_RESULT_FOR_EXPLOSION = "No result for explosion"; + private final TcSession session; + + /** + * Constructor for single level resolution. + */ + public SingleStructureServiceCallerRaw(final TcSession session) { + this.session = session; + } + + + /** + * Run a resolution from a {@link BOMLine}.
    + * In this SINGLE mode, the explosion is performed only 1 link.
    + * The entry {@link BOMLine} cannot have a null TC {@link BOMLine}. + */ + @Override + public BOMLineHolder resolve(final BOMLine aTopBom, final ITcTypeFilter filter) + throws EmptyNomenclatureException { + if (aTopBom != null) { + return expandBom(aTopBom, filter); + } else { + throw new EmptyNomenclatureException(ERROR_MSG_NULL_BOM_LINE_PROVIDED); + } + } + + /** + * Expands a {@link BOMLine} object, by exactly one BOM link.
    + */ + private BOMLineHolder expandBom(final BOMLine topObject, final ITcTypeFilter filter) + throws EmptyNomenclatureException { + // Expand one level + List topObjectList = new ArrayList<>(); + topObjectList.add(topObject); + ExpandPSOneLevelOutput[] expand = expandOneLevel(topObjectList); + + // Expecting only one response because only one BOMLine was provided + if (expand == null || expand.length == 0) { + throw new EmptyNomenclatureException(ERROR_MSG_NO_RESULT_FOR_EXPLOSION); + } + ExpandPSOneLevelOutput output = expand[0]; + + // Browse this BOMLine's children + return extractAllChildren(output, filter); + } + + /** + * Expand ONE level of configuration.
    + * + * @param allTopBomLine Top item {@link BOMLine} + * @return a table of raw {@link ExpandPSOneLevelOutput} each containing parent and its children + */ + private ExpandPSOneLevelOutput[] expandOneLevel(final Collection allTopBomLine) { + if (allTopBomLine == null || allTopBomLine.isEmpty()) { + // Early return + return new ExpandPSOneLevelOutput[0]; + } + log.debug("Start expand one level..."); + BOMLine[] bomLines = allTopBomLine.toArray(new BOMLine[allTopBomLine.size()]); + + ExpandPSOneLevelInfo expandInfo = new ExpandPSOneLevelInfo(); + expandInfo.parentBomLines = bomLines; + expandInfo.excludeFilter = NO_FILTER; + + ExpandPSOneLevelPref expandPref = new ExpandPSOneLevelPref(); + expandPref.expItemRev = false; + + ExpandPSOneLevelResponse2 response = session.getStructureManagementService().expandPSOneLevel(expandInfo, expandPref); + ServiceDataHelper.displayErrors(response.serviceData); + log.debug("End expand one level"); + + return response.output; + } + + /** + * Expands all the topObjects provided, using the {@link ITcTypeFilter}. + */ + public final List expandEach(final Collection topObjects, final ITcTypeFilter filter) + throws EmptyNomenclatureException { + if (topObjects.isEmpty()) { + return new ArrayList<>(); + } + // Expand one level + ExpandPSOneLevelOutput[] expand = expandOneLevel(topObjects); + + if (expand == null || expand.length == 0) { + throw new EmptyNomenclatureException(ERROR_MSG_NO_RESULT_FOR_EXPLOSION); + } + + List result = new ArrayList<>(); + // Browse each BOMLine's children + for (ExpandPSOneLevelOutput output : expand) { + result.add(extractAllChildren(output, filter)); + } + return result; + } + + + private BOMLineHolder extractAllChildren(final ExpandPSOneLevelOutput output, final ITcTypeFilter filter) { + List childList = new ArrayList<>(); + for (ExpandPSData currentChildData : output.children) { + BOMLine bomLine = currentChildData.bomLine; + ItemRevision theObject = (ItemRevision) currentChildData.objectOfBOMLine; + if (bomLine == null || theObject == null) { + continue; + } + if (filter.isIncluded(theObject.getTypeObject().getName())) { + childList.add(new BOMLineHolder(session, bomLine, theObject, new ArrayList())); + } + } + return new BOMLineHolder(session, output.parent.bomLine, (ItemRevision) output.parent.objectOfBOMLine, childList); + } +} diff --git a/teamcenter/src/main/java/com/capgemini/framework/teamcenter/statuating/StatusSetter.java b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/statuating/StatusSetter.java new file mode 100644 index 0000000..2b2a63c --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/framework/teamcenter/statuating/StatusSetter.java @@ -0,0 +1,74 @@ +package com.capgemini.framework.teamcenter.statuating; + +import com.capgemini.framework.teamcenter.ServiceDataHelper; +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.UnableToCreateStatusException; +import com.teamcenter.schemas.soa._2006_03.exceptions.ServiceException; +import com.teamcenter.services.strong.workflow.WorkflowService; +import com.teamcenter.services.strong.workflow._2007_06.Workflow.ReleaseStatusInput; +import com.teamcenter.services.strong.workflow._2007_06.Workflow.ReleaseStatusOption; +import com.teamcenter.services.strong.workflow._2007_06.Workflow.SetReleaseStatusResponse; +import com.teamcenter.soa.client.model.strong.ReleaseStatus; +import com.teamcenter.soa.client.model.strong.WorkspaceObject; + +import java.util.Arrays; + +/** This class can place a Status on a {@link WorkspaceObject}. */ +public class StatusSetter { + private final TcSession session; + + /** + * Creates a instance that is able to create statuses. + * + * @param session an active teamcenter session. + */ + public StatusSetter(final TcSession session) { + this.session = session; + } + + /** + * Creates a status and places it on a {@link WorkspaceObject}. + * @param target the target {@link WorkspaceObject} + * @param statusName the name of the status + * @return the created Tc {@link ReleaseStatus} + * @throws UnableToCreateStatusException if no Status was created + */ + public ReleaseStatus putStatus(WorkspaceObject target, String statusName) throws UnableToCreateStatusException { + WorkspaceObject[] objects = new WorkspaceObject[] {target}; + ReleaseStatusOption[] options = new ReleaseStatusOption[] {makeReleaseStatusOption(statusName)}; + + // Prepare ReleaseStatusInput + ReleaseStatusInput[] inputArray = new ReleaseStatusInput[] {makeReleaseStatusInput(objects, options)}; + + // Execute + WorkflowService wkfService = session.getWorkflowService(); + SetReleaseStatusResponse response; + try { + response = wkfService.setReleaseStatus(inputArray); + } catch (ServiceException e) { + throw new UnableToCreateStatusException("No status has been created on target object " + target.getUid(), e); + } + if (ServiceDataHelper.hasErrors(response.serviceData)) { + ServiceDataHelper.displayErrors(response.serviceData); + } + if (response.serviceData.sizeOfCreatedObjects() <= 0) { + throw new UnableToCreateStatusException("No status has been created on target object " + target.getUid()); + } + return (ReleaseStatus) response.serviceData.getCreatedObject(0); + } + + private ReleaseStatusInput makeReleaseStatusInput(WorkspaceObject[] objects, ReleaseStatusOption[] options) { + ReleaseStatusInput input = new ReleaseStatusInput(); + input.objects = objects == null ? new WorkspaceObject[0] : Arrays.copyOf(objects, objects.length); + input.operations = options == null ? new ReleaseStatusOption[0] : Arrays.copyOf(options, options.length); + return input; + } + + private ReleaseStatusOption makeReleaseStatusOption(String statusName) { + ReleaseStatusOption option = new ReleaseStatusOption(); + option.existingreleaseStatusTypeName = ""; + option.newReleaseStatusTypeName = statusName; + option.operation = "Append"; // The only supported operation :'( + return option; + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/ItemRevisionComparator.java b/teamcenter/src/main/java/com/capgemini/reports/ItemRevisionComparator.java new file mode 100644 index 0000000..533477b --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/ItemRevisionComparator.java @@ -0,0 +1,21 @@ +package com.capgemini.reports; + +import com.teamcenter.soa.client.model.strong.ItemRevision; + +import java.io.Serializable; +import java.util.Comparator; + +/** + * Helper class to compare compares two itemRevision by concatenating their properties item_id, item_revision_id,sequence_id, ex: 002605B1. * + */ +public class ItemRevisionComparator implements Comparator, Serializable { + private static final long serialVersionUID = -1094043465048885249L; + + @Override + public int compare(ItemRevision obj1, ItemRevision obj2) { + String itemRevision1 = obj1.get_item_id() + obj1.get_item_revision_id() + obj1.get_sequence_id(); + String itemRevision2 = obj2.get_item_id() + obj2.get_item_revision_id() + obj2.get_sequence_id(); + return itemRevision1.compareTo(itemRevision2); + } + +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/BOMLineHolder.java b/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/BOMLineHolder.java new file mode 100644 index 0000000..25b2ae3 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/BOMLineHolder.java @@ -0,0 +1,422 @@ +package com.capgemini.reports.bomlineholder; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.reports.bomlineholder.processor.IBOMLineHolderProcessor; +import com.capgemini.reports.bomlineholder.visitor.IBOMLineHolderExtractor; +import com.capgemini.reports.snecmaobjects.ISnecmaObject; +import com.capgemini.reports.snecmaobjects.part.AbstractAltOrDetRevision; +import com.capgemini.reports.teamcenter.ObjectInfoHelper; +import com.teamcenter.soa.client.model.ModelObject; +import com.teamcenter.soa.client.model.strong.BOMLine; +import com.teamcenter.soa.client.model.strong.Form; +import com.teamcenter.soa.client.model.strong.Item; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import lombok.AccessLevel; +import lombok.EqualsAndHashCode; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.util.ArrayList; +import java.util.List; + +/** + * Container for BOM line and their BOM line children.
    + * The BOM line holder also contains the corresponding ModelObject and/or the corresponding ISnecmaObject. + *

    + *

    + * Note:To save memory space, the BOMLineHolder will go through th following life phases:
    + *

      + *
    1. {@link BOMLineHolderState#RAW} mode
      + * The BOMLineHolder only contains raw Teamcenter data, namely: + *
        + *
      • A {@link BOMLine} called {@code BOMLineObject}
      • + *
      • A {@link List} of {@link ModelObject}s containing all {@link Item}s found in an eventual pseudo-folder.
      • + *
      • A {@link List} of children {@link BOMLineHolder}s called {@code bomChilds}, all of which are in the same state ({@link BOMLineHolderState#RAW})
      • + *
      + *

      + *

    2. {@link BOMLineHolderState#PROCESSING} mode
      + * The BOMLineHolder contains both the RAW Teamcenter data, and their {@link ISnecmaObject} representation.
      + * In this state, some processing can be performed to extract data from the TC object and dump it into an ISnecmaObject as appropriate: + *
        + *
      • A {@link BOMLine} called {@code BOMLineObject}
      • + *
      • A {@link List} of {@link ModelObject}s containing all {@link Item}s found in an eventua pseudo-folder.
      • + *
      • A {@link List} of children {@link BOMLineHolder}s called {@code bomChilds}, all of which are in the same state ({@link BOMLineHolderState#PROCESSING})
      • + *
      • A {@link ISnecmaObject} containing a representation of data from the ItemRevision held by the BomLine
      • + *
      + *

      + *

      + *

    3. {@link BOMLineHolderState#FROZEN}
      + * The BOMLineHolder contains no more Teamcenter objects (they are null) but instead contains some strongly-typed {@link ISnecmaObject}s holding all the relevant data: + *
        + *
      • A {@link ISnecmaObject} containing a representation of data from the ItemRevision held by the BomLine
      • + *
      • A {@link List} of children {@link BOMLineHolder}s called {@code bomChilds}, all of which are in the same state ({@link BOMLineHolderState#FROZEN})
      • + *
      + *
    + *

    + *

    + * To findAll into PROCESSING mode, use the {@link BOMLineHolderFactory} + */ +@Slf4j +@EqualsAndHashCode(exclude = {"parentBomLine"}) +public class BOMLineHolder implements IBOMTree, Comparable { + private static final long serialVersionUID = 5317661727930642676L; + + private TcSession session; + /** + * Current line in the BOM. + **/ + private transient BOMLine bomLineObject; + /** + * Item Revision of the current {@link BOMLine}. + */ + private transient ItemRevision itemRevision; + /** + * Wrapper for Model object (set as null by default). + **/ + private ISnecmaObject snecmaObject; + /** + * Map of BOMLine IDs to the children BOM lines for the current BOM line. + **/ + private List bomChilds = new ArrayList<>(); + private IBOMTree parentBomLine; + + /** + * State of the BOMLIneHolder. + */ + @Setter(value = AccessLevel.NONE) + private BOMLineHolderState state = BOMLineHolderState.RAW; + + /** + * Constructor using a simple BOM line.
    + * If you also have the ItemRevision already, use the other constructor: {@link BOMLineHolder#BOMLineHolder(BOMLine, ItemRevision)}. This should ONLY be used for the top BomLine. + * + * @param bomLine the BOMLine represented by this {@link BOMLineHolder} + */ + public BOMLineHolder(final BOMLine bomLine) { + this.bomLineObject = bomLine; + + // Get the TC ModelObject + ModelObject theTopMo = bomLine.get_bl_line_object(); + // Build the embedded SnecmaObject + if (theTopMo != null) { + if (theTopMo instanceof ItemRevision) { + this.itemRevision = (ItemRevision) theTopMo; + return; + } + else { + log.error("No ItemRevision found in the ModelObject"); + } + } + else { + log.debug("BOMlineHolder built from a BomLine which does not have a ModelObjec: BomLine UID=" + bomLine.getUid()); + } + + // If not available, try to use the BomLine's UID (wich may change from one execution to the next + this.itemRevision = null; + } + + /** + * Constructor using a simple BOM line. + * + * @param bomLine the BOMLine represented by this {@link BOMLineHolder} + * @param itemRev the ItemRevision managed by this holder + */ + public BOMLineHolder(final BOMLine bomLine, final ItemRevision itemRev) { + this.bomLineObject = bomLine; + this.itemRevision = itemRev; + } + + + /** + * Constructor building a BOMLineHolder from another BOMLineHolder. Exact same copy, same UID. + * + * @param aBom BOMLineHolder + */ + public BOMLineHolder(final IBOMTree aBom) { + this.bomLineObject = aBom.getBomLineObject(); + this.itemRevision = aBom.getItemRevision(); + this.snecmaObject = aBom.getSnecmaObject(); + this.parentBomLine = aBom.getParentBomLine(); + this.bomChilds = aBom.getBomChilds(); + } + + /** + * Constructor for {@link ItemRevision}s obtained without a {@link BOMLine} like extracted from a pseudo-folder. + **/ + protected BOMLineHolder(final ItemRevision itemRevision) { + this.bomLineObject = null; + this.itemRevision = itemRevision; + } + + public BOMLineHolder(final TcSession session, final BOMLine bomLine, final ItemRevision itemRevision, final List bomChilds) { + this.session = session; + this.bomLineObject = bomLine; + this.itemRevision = itemRevision; + this.bomChilds = bomChilds; + } + + /** + * This methods "freezes" the BOMLineholder by removing all its references to Teamcenter data.
    + * Should be called after it was fully built. + */ + public void freeze() { + this.state = BOMLineHolderState.FROZEN; + } + + @Override + public void process(final IBOMLineHolderProcessor aBOMLineHolderProcessor) { + switch (this.state) { + case RAW: + log.warn("Skipping processing of a RAW BomLineHolder"); + break; + case PROCESSING: + aBOMLineHolderProcessor.process(this); // Perform the unit work + for (BOMLineHolder child : bomChilds) { + child.process(aBOMLineHolderProcessor); // Browse children recursively + } + break; + case FROZEN: + throw new IllegalStateException("Processing a BOMLineHolder which has been FROZEN is not allowed."); + default: + break; + } + } + + @Override + public T accept(final IBOMLineHolderExtractor aBOMLineHolderExtractor) { + if (this.state != BOMLineHolderState.FROZEN) { + throw new IllegalStateException("Visiting a BOMLineHolder which has not been FROZEN is not allowed. Use the BOMLineHolderFactory on it first."); + } + return aBOMLineHolderExtractor.visitTopReceptorBom(this); + } + + @Override + public IBOMTree getParentBomLine() { + return parentBomLine; + } + + @Override + public List getBomChilds() { + return bomChilds; + } + + @Override + public void setParent(final BOMLineHolder aParentBomLine) { + this.parentBomLine = aParentBomLine; + } + + @Override + public BOMLine getBomLineObject() { + return bomLineObject; + } + + /** + * Assign a child BOM line to the current line and create a reference to its parent. A null child will not be added. + */ + @Override + public void addChild(final BOMLineHolder aChildBomLine) { + if (aChildBomLine != null) { + this.bomChilds.add(aChildBomLine); + aChildBomLine.setParent(this); + } + } + + /** + * Return the type of the object carried. + * + * @return a String containing the Type. + */ + @Override + public String getObjectType() { + String type; + switch (state) { + case RAW: + type = getRawType(); + break; + case PROCESSING: + case FROZEN: + type = snecmaObject.getType(); + break; + default: + type = "Unknown State: " + state.toString(); + break; + } + return type; + } + + private String getRawType() { + return itemRevision.getTypeObject().getName(); + } + + /** + * Generate unique key for BOM line using item_id + item_revision_id.
    + * This is used by the child tree map for sorting purpose. + * + * @return Unique key + */ + @Override + public String getKey() { + return getUid(); + } + + @Override + public ISnecmaObject getSnecmaObject() { + return snecmaObject; + } + + /** + * This methods sets the SnecmaObject of this BomLineHolder. It also makes it processable if it was {@link BOMLineHolderState#RAW}. + * + * @param obj the {@link ISnecmaObject} + */ + void setSnecmaObject(final ISnecmaObject obj) { + this.snecmaObject = obj; + if (state == BOMLineHolderState.RAW) { + this.state = BOMLineHolderState.PROCESSING; + } + } + + @Override + public String getUid() { + return bomLineObject.getUid(); + } + + @Override + public int compareTo(final BOMLineHolder other) { + return getUid().compareTo(other.getUid()); + } + + private void readObject(final ObjectInputStream stream) throws IOException, ClassNotFoundException { + stream.defaultReadObject(); // Deserialize the non-transient data + } + + @Override + public String toString() { + switch (state) { + case RAW: + return toStringRaw(); + case PROCESSING: + return toStringProcessing(); + case FROZEN: + return toStringFrozen(); + default: + return toStringDefault(); + } + } + + private String toStringProcessing() { + return String.format("BOMLineHolder %s (PROCESSING) with a %s whose ID=\"%s\"", getUid(), snecmaObject.getType(), snecmaObject.getItemId()); + } + + private String toStringDefault() { + return String.format("BOMLineHolder %s in unknown state: \"%s\"", getUid(), state.toString()); + } + + private String toStringFrozen() { + return String.format("BOMLineHolder %s (FROZEN) with a %s whose ID=\"%s\"", getUid(), snecmaObject.getType(), snecmaObject.getItemId()); + } + + private String toStringRaw() { + StringBuilder builder = new StringBuilder("BOMLineHolder "); + builder.append(getUid()).append(" (RAW) with a "); + if (itemRevision == null) { + builder.append("null object inside its BOMLine"); + } + else { + String itemId = itemRevision.get_item_id(); + String itemType = itemRevision.getTypeObject().getName(); + builder.append(itemType).append(" whose ID=\"").append(itemId).append("\""); + } + return builder.toString(); + } + + public ItemRevision getItemRevision() { + return itemRevision; + } + + public BOMLineHolderState getState() { + return state; + } + + public String getBomAlt() { + return bomLineObject.getPropertyObject("ALT").getStringValue(); + } + + public String getBomSb() { + return bomLineObject.getPropertyObject("SB").getStringValue(); + } + + public String getBomQty() { + return bomLineObject.getPropertyObject("bl_quantity").getStringValue(); + } + + public String getBomQtyCumul() { + return bomLineObject.getPropertyObject("Qte cumulee").getStringValue(); + } + + public String getBomPanache() { + return bomLineObject.getPropertyObject("Panachage").getStringValue(); + } + + public String getUin() { + return bomLineObject.getPropertyObject("UIN").getStringValue(); + } + + public String getBomConfig() { + return bomLineObject.get_bl_config_string(); + } + + public List getPseudoFolder() { + // Now this BomLineHolder may be a Alt or Det, which may require to have its pseudo-Folder setup. + log.debug(" - Alt or DET found: investigating its pseudo-folder..."); + return ObjectInfoHelper.getPartsInPseudoFolderOfAltOrDetRevision(session, itemRevision); + + } + + public List

    getAllItemRevMasters() { + List bomObjects = new ArrayList<>(); + bomObjects.add(itemRevision.get_item_master_tag()); + for (BOMLineHolder bomChild : bomChilds) { + bomObjects.addAll(bomChild.getAllItemRevMasters()); + } + return bomObjects; + } + + + /** + * Represents the lifecycle of a {@link BOMLineHolder}.
    + * This cycle is the following sequence: {@link BOMLineHolderState #RAW RAW} --> {@link BOMLineHolderState #PROCESSING PROCESSED} --> {@link BOMLineHolderState #FROZEN FROZEN} + */ + public enum BOMLineHolderState { + /** + * In this state the BOMLineHolder contains raw Teamcenter data. + *
      + *
    • A {@link BOMLine} called {@code BOMLineObject}
    • + *
    • A {@link List} of children {@link BOMLineHolder}s called {@code bomChilds}, all of which are in the same state (RAW)
    • + *
    • A pseudo-folder (a {@link List} of {@link ModelObject}s) containing some {@link Item}s
    • + *
    + */ + RAW, + + /** + * In this state the BOMLineHolder contains processed Teamcenter data. + *
      + *
    • A {@link BOMLine} called {@code BOMLineObject}
    • + *
    • A {@link List} of children {@link BOMLineHolder}s called {@code bomChilds}, all of which are in the same state (PROCESSED)
    • + *
    • A pseudo-folder (a {@link List} of {@link ModelObject}s) containing all the correct {@link ItemRevision}s, obtained from their {@link Item}s earlier
    • + *
    + */ + PROCESSING, + + /** + * In this state the BOMLineHolder contains no more Teamcenter objects (they are null) but instead contains some strongly-typed {@link ISnecmaObject}s. + *
      + *
    • A {@link List} of children {@link BOMLineHolder}s called {@code bomChilds}, all of which are in the same state (FROZEN)
    • + *
    + * Note : any {@link ISnecmaObject} of type {@link AbstractAltOrDetRevision} will have a pseudo-folder loaded with children {@link ISnecmaObject}s. + */ + FROZEN + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/BOMLineHolderFactory.java b/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/BOMLineHolderFactory.java new file mode 100644 index 0000000..1c2cae6 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/BOMLineHolderFactory.java @@ -0,0 +1,114 @@ +package com.capgemini.reports.bomlineholder; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.EmptyNomenclatureException; +import com.capgemini.reports.bomlineholder.BOMLineHolder.BOMLineHolderState; +import com.capgemini.reports.exceptions.NotSupportedException; +import com.capgemini.reports.filter.IFilterExplosionNomenclature; +import com.capgemini.reports.snecmaobjects.ISnecmaObject; +import com.capgemini.reports.snecmaobjects.SnecmaObjectFactory; +import com.teamcenter.soa.client.model.ModelObject; +import com.teamcenter.soa.client.model.Type; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import lombok.extern.slf4j.Slf4j; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +/** + * Build a BOMLineHolder. + */ +@Slf4j +public final class BOMLineHolderFactory { + + private BOMLineHolderFactory() { + // Hiding this constructor to make the class static. + } + + /** + * Build an expansion of BOM. + */ + public static BOMLineHolder buildTopBom(final TcSession session, final BOMLineHolder aTopBomLine, + final IFilterExplosionNomenclature filter) throws EmptyNomenclatureException { + // Map containing all the SnecmaObject ever built (starting empty) + Map snecmaObjectMap = new HashMap<>(); + log.debug("Starting to build top Item."); + try { + buildExpansionBomChildRec(session, aTopBomLine, snecmaObjectMap, filter); + } catch (NotSupportedException e) { + log.error("Unable to build the topLine of the expansion BOM", e); + } + return aTopBomLine; + } + + /** + * Builds a {@link BOMLineHolder}. Its {@link ISnecmaObject} will be created using the provided {@link ItemRevision}. + */ + public static BOMLineHolder buildTopBom(final TcSession session, final BOMLineHolder aTopBomLine) { + try { + loadItemProperties(session, aTopBomLine, new HashMap()); + } catch (NotSupportedException e) { + log.error("Unable to build the Snecmaobject: Type Not Supported", e); + } + return aTopBomLine; + } + + /** + * Build recursively an expansion of BOM. + */ + private static void buildExpansionBomChildRec(final TcSession session, final BOMLineHolder aBomLineHolder, final Map snecmaObjectMap, final IFilterExplosionNomenclature filter) throws NotSupportedException { + buildThisBOMLineHolder(session, aBomLineHolder, snecmaObjectMap); + // Build the children + for (Iterator bomIterator = aBomLineHolder.getBomChilds().iterator(); bomIterator.hasNext(); ) { + BOMLineHolder child = bomIterator.next(); + ItemRevision childItemRev = child.getItemRevision(); + if (childItemRev == null) { + continue; + } + Type objectType = childItemRev.getTypeObject(); + if (objectType != null && !filter.isExcluded(session, child)) { + try { + buildExpansionBomChildRec(session, child, snecmaObjectMap, filter); + child.setParent(aBomLineHolder); + } catch (NotSupportedException e) { + log.error("Unable to build the Snecmaobject: Type Not Supported. Removing the object from the BOM...", e); + bomIterator.remove(); + } + } else { + bomIterator.remove(); // remove unwanted objects or objects which are null (no access rights etc.) + } + } + } + + /** + * Builds a BOMLineHolder by creating a {@link ISnecmaObject} for every TC {@link ModelObject} found in this {@link } and its children.
    + * The BOMLineHolder will therefore be {@link BOMLineHolderState#PROCESSING}. + */ + private static void buildThisBOMLineHolder(final TcSession session, final BOMLineHolder aTopBomLine, + final Map snecmaObjectMap) throws NotSupportedException { + loadItemProperties(session, aTopBomLine, snecmaObjectMap); + //aTopBomLine.retrieveAltOrDetPseudoFolder(session, aTopBomLine.getItemRevision()); + } + + + /** + * Loads properties that are specific to the {@link ItemRevision} carried by the bomLine.
    + * Will attach a {@link ISnecmaObject} to the {@link BOMLineHolder} and make its state {@link BOMLineHolderState#PROCESSING}. + */ + private static void loadItemProperties(final TcSession session, final BOMLineHolder aTopBomLine, + final Map snecmaObjectMap) throws NotSupportedException { + ItemRevision theTopItemRev = aTopBomLine.getItemRevision(); + // Try to retrieve an already built SnecmaObject in the cache + ISnecmaObject theSnecmaObject = snecmaObjectMap.get(theTopItemRev.getUid()); + + if (theSnecmaObject == null) { + // The object did not exist in the cache, now build it and update the cache + theSnecmaObject = SnecmaObjectFactory.build(session, theTopItemRev); + snecmaObjectMap.put(theTopItemRev.getUid(), theSnecmaObject); + } + + // The object has been obtained (either with the cache or from scratch), now put it in its BOMLineHolder + aTopBomLine.setSnecmaObject(theSnecmaObject); + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/BOMLineHolderHelper.java b/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/BOMLineHolderHelper.java new file mode 100644 index 0000000..91fb7ec --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/BOMLineHolderHelper.java @@ -0,0 +1,138 @@ +package com.capgemini.reports.bomlineholder; + +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.capgemini.reports.bomlineholder.BOMLineHolder.BOMLineHolderState; +import com.capgemini.reports.exceptions.InvalidInputException; +import com.capgemini.reports.exceptions.MalformedNomenclatureException; +import com.capgemini.reports.exceptions.NotFoundException; +import com.capgemini.reports.snecmaobjects.admin.RFAdminAPRevision; +import com.capgemini.reports.snecmaobjects.admin.RFAdminARevision; +import com.capgemini.reports.snecmaobjects.admin.RFAdminRevision; + +import java.util.ArrayList; +import java.util.List; + +/** + * Helps find data inside a {@link BOMLineHolder}. + */ +public final class BOMLineHolderHelper { + + private BOMLineHolderHelper() { + // Nothing + } + + /** + * Finds the first instance of the requested type, amongst a {@link BOMLineHolder}'s children. + * + * @param bomLineHolder the BOMLineHolder. If null an {@link InvalidInputException} will be raised + * @param requestedType the requested Child Type + * @return the first child matching the requested type + * @throws NotFoundException when no child of the type could be found + * @throws InvalidInputException if the input BOMLineHolder was null + */ + public static BOMLineHolder findFirst(final BOMLineHolder bomLineHolder, final String requestedType) throws NotFoundException, + InvalidInputException { + if (bomLineHolder == null) { + throw nullBomLineProvided(requestedType); + } + if (bomLineHolder.getState() == BOMLineHolderState.RAW) { + for (BOMLineHolder child : bomLineHolder.getBomChilds()) { + if (requestedType.equals(child.getItemRevision().getTypeObject().getName())) { + return child; + } + } + // If we findAll here, no object was found, so we'll raise an exception + String fatherType = bomLineHolder.getObjectType(); + String fatherID = bomLineHolder.getItemRevision().get_item_id(); + throw new NotFoundException("No " + requestedType + " found below RAW BOMLineHolder: " + fatherType + " (" + fatherID + ")"); + } else { + for (BOMLineHolder child : bomLineHolder.getBomChilds()) { + if (requestedType.equals(child.getSnecmaObject().getType())) { + return child; + } + } + throw new NotFoundException("No " + requestedType + " found below : " + bomLineHolder.getSnecmaObject().getItemId()); + } + } + + /** + * Finds the all the instances of the requested type, amongst a {@link BOMLineHolder}'s children. + * + * @param bomLineHolder the BOMLineHolder. If null an {@link InvalidInputException} will be raised + * @param requestedType the requested Child Type + * @return a {@link List} containing every Child whose type is the one searched for + * @throws InvalidInputException if the input BOMLineHolder was null + */ + public static List findAll(final BOMLineHolder bomLineHolder, final String requestedType) throws InvalidInputException { + if (bomLineHolder == null) { + throw nullBomLineProvided(requestedType); + } + List list = new ArrayList<>(); + for (BOMLineHolder child : bomLineHolder.getBomChilds()) { + if (requestedType.equals(child.getSnecmaObject().getType())) { + list.add(child); + } + } + return list; + } + + /** + * Finds and returns the first child which is a 'RF Admin A', amongst a RF's children. + * + * @param aRF the RF + * @return the first child which is a 'RF Admin A' + * @throws NotFoundException when no child of the type could be found + * @throws InvalidInputException if the input BOMLineHolder was null + */ + public static RFAdminARevision findRfAdminA(final BOMLineHolder aRF) throws NotFoundException, InvalidInputException { + return (RFAdminARevision) findFirst(aRF, SnecmaObjectTypes.RF_ADMIN_A_REVISION).getSnecmaObject(); + } + + /** + * Finds and returns the first child which is a 'RF Admin AP', amongst a RF's children. + * + * @param aRF the RF + * @return the first child which is a 'RF Admin AP' + * @throws NotFoundException when no child of the type could be found + * @throws InvalidInputException if the input BOMLineHolder was null + */ + public static RFAdminAPRevision findRfAdminAP(final BOMLineHolder aRF) throws NotFoundException, InvalidInputException { + return (RFAdminAPRevision) findFirst(aRF, SnecmaObjectTypes.RF_ADMIN_AP_REVISION).getSnecmaObject(); + } + + /** + * Finds and returns the first child which is a 'RF Admin', amongst a RF's children. + * + * @param aRF the RF + * @return the first child which is a 'RF Admin' + * @throws NotFoundException when no child of the type could be found + * @throws InvalidInputException if the input BOMLineHolder was null + */ + public static RFAdminRevision findRfAdmin(final BOMLineHolder aRF) throws NotFoundException, InvalidInputException { + return (RFAdminRevision) findFirst(aRF, SnecmaObjectTypes.RF_ADMIN_REVISION).getSnecmaObject(); + } + + /** + * Finds and returns the 'RF Generic', of a Generic. + * + * @param aGeneric the Generic + * @return the first child which is a 'RF Generic' + * @throws MalformedNomenclatureException when no child of the type could be found (there SHOULD be one) + * @throws InvalidInputException if the input BOMLineHolder was null + */ + public static BOMLineHolder findRfGenericBL(final BOMLineHolder aGeneric) throws InvalidInputException, MalformedNomenclatureException { + try { + return findFirst(aGeneric, SnecmaObjectTypes.RF_GENERIC_REVISION); + } catch (NotFoundException e) { + if (aGeneric.getState() == BOMLineHolderState.RAW) { + throw new MalformedNomenclatureException("No RF Generic found below RAW Generic: " + aGeneric.getBomLineObject().getUid(), e); + } else { + throw new MalformedNomenclatureException("No RF Generic found below Generic: " + aGeneric.getSnecmaObject().getItemId(), e); + } + } + } + + private static InvalidInputException nullBomLineProvided(final String requestedType) { + return new InvalidInputException("Unable to find a '" + requestedType + "' because the BomLineHolder was null"); + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/IBOMTree.java b/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/IBOMTree.java new file mode 100644 index 0000000..311244f --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/IBOMTree.java @@ -0,0 +1,92 @@ +package com.capgemini.reports.bomlineholder; + +import com.capgemini.reports.bomlineholder.processor.IBOMLineHolderProcessor; +import com.capgemini.reports.bomlineholder.visitor.IBOMLineHolderExtractor; +import com.capgemini.reports.snecmaobjects.ISnecmaObject; +import com.teamcenter.soa.client.model.strong.BOMLine; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +import java.io.Serializable; +import java.util.List; + +/** + * Common interface for tree structure like BOM lines. + **/ +public interface IBOMTree extends Serializable { + + /** + * All the BOMLineHolder must accept a Processor which may alter its content (i.e. load extra data, or remove some branches, etc). + * + * @param aBOMLineHolderProcessor aBOMLineHolderProcessor + */ + void process(final IBOMLineHolderProcessor aBOMLineHolderProcessor); + + /** + * All the BOMLineHolder must accept an Extractor object to make the different reports. + * + * @param any kind of output expected from the extractor + * @param aBOMLineHolderExtractor aBOMLineHolderExtractor + * @return an object of type T + */ + T accept(final IBOMLineHolderExtractor aBOMLineHolderExtractor); + + /** + * Getter for the parent BOM line of the current BOM node. + * + * @return The parent BOM line + */ + IBOMTree getParentBomLine(); + + /** + * Getter for the list of children BOM lines. + * + * @return {@link List} of children BOM lines + */ + List getBomChilds(); + + /** + * Assign a child BOM line to the current line and create a reference to its parent. + * + * @param aChild New child BOM line. + */ + void addChild(final BOMLineHolder aChild); + + /** + * Assign a parent BOM line to the current line. + * + * @param aParentBomLine New parent BOM line. + */ + void setParent(final BOMLineHolder aParentBomLine); + + /** + * Getter for the managed BOM Model object of the current BOM line. + * + * @return BOM Model Object + */ + BOMLine getBomLineObject(); + + /** + * Generate unique key using item_id + item_revision_id for children BOM lines. + * + * @return Unique key for sorting purpose + */ + String getKey(); + + /** + * Getter for the SnecmaObject. + * + * @return the SnecmaObject + */ + ISnecmaObject getSnecmaObject(); + + /** + * Getter for the unique identifier. + * + * @return the uid + */ + String getUid(); + + String getObjectType(); + + ItemRevision getItemRevision(); +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/ISnecmaLineProcessor.java b/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/ISnecmaLineProcessor.java new file mode 100644 index 0000000..a998cb0 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/ISnecmaLineProcessor.java @@ -0,0 +1,106 @@ +package com.capgemini.reports.bomlineholder; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.reports.snecmaobjects.part.AbstractPart; + +/** + * Interface for objects who can perform an action on a Snecma Bom.
    + * Provides special methods that act on every possible representation of a Snecma Bom Line, usually comprised of at least a Receptor and a Component. + */ +public interface ISnecmaLineProcessor { + /** + * Behaviour to be defined for the very first element of the nomenclature, which usually doen't have a Repere, etc. + * + * @param aTopBom the {@link BOMLineHolder} holding the top Object (usually a Generic, or a Product, sometimes a Part. + */ + void visitTopBom(final BOMLineHolder aTopBom); + + /** + * Behaviour to be defined when a 'full' line of objects is found.
    + * A 'full' line consists of: + *
      + *
    1. a Receptor like a Part, a Generic or a Product + *
    2. a Repere Fonctionnel associated with the receptor + *
    3. a Component like a Generic or a Part + *
    4. a Repere Fonctionnel associated with the component + *
    + * + * @param receptor the Receptor inside its {@link BOMLineHolder} + * @param rfReceptor the Receptor's repere inside its {@link BOMLineHolder} + * @param component the Component inside its {@link BOMLineHolder} + * @param rfComponent the Component's repere inside its {@link BOMLineHolder} + */ + void visitQuad(final BOMLineHolder receptor, final BOMLineHolder rfReceptor, final BOMLineHolder component, final BOMLineHolder rfComponent); + + + /** + * Behaviour to be defined when a Product-Generic-RF Generic line is found.
    + * + * @param productReceptor the Receptor inside its {@link BOMLineHolder} + * @param genericComponent the Component inside its {@link BOMLineHolder} + * @param rfGenericComponent the Component's repere inside its {@link BOMLineHolder} + */ + void visitProductGeneric(final BOMLineHolder productReceptor, final BOMLineHolder genericComponent, final BOMLineHolder rfGenericComponent); + + /** + * Behaviour to be defined when a PartNumber is encountered.
    + * A Part Number if always found in this structure (and only in this structure): + *
      + *
    1. a GenericReceptor + *
    2. an only RF Generic below the Generic + *
    3. an only PartAero below the RF Generic + *
    + * Note the Generic may have other children than the RF Generic, like some RF Parts..
    + * Also not the RF Generic should have other children than the PrtAero, like RF Admins (who own additional data on the RF Generic), etc. + * + * @param genericReceptor + * @param rfGeneric + * @param child + */ + void visitPartNumber(final BOMLineHolder genericReceptor, final BOMLineHolder rfGeneric, final BOMLineHolder child); + + /** + * Behaviour to be defined when the top object is a Part (therefore without an RF Part) points to an RF Part which owns a Part.
    + * This method is only encountered (once) when the nomenclature explosion begins on as Part. + * + * @param part the father Part + * @param rfPart a RF Part below the father Part + * @param child a Part below the RF Part + */ + void visitPartAsComponent(final BOMLineHolder part, final BOMLineHolder rfPart, final BOMLineHolder child); + + /** + * Behaviour to be defined a Part poitns to an other Part in the nomenclature.
    + * At the lower levels of nomenclature, Parts can have Parts as their direct children, whith neither having a RF Part. + * + * @param fatherPart the father Part + * @param childPart the child Part + */ + void visitPartPart(final BOMLineHolder fatherPart, final BOMLineHolder childPart); + + /** + * Behaviour to be defined when encountering an Alt or a DET, which contain a Part in its pseudo-folders.
    + * This method is invoked only when visitPartsInPseudoFolderw is set to true. + * + * @param aPart the Alt or DET part + * @param child a child Part found in the pseudo-folder + */ + void visitPartsInPseudoFolder(final BOMLineHolder aPart, final AbstractPart child); + + /** + * Behaviour to be defined when encountering a Receptor which has a Rf, but this Rf links to no component. + * + * @param part the part receptor + * @param rfPart the RfPart + */ + void visitReceptorWithoutComponent(final BOMLineHolder part, final BOMLineHolder rfPart); + + /** + * Behaviour to be defined when we need only a Receptor and a repere. + * + * @param session + * @param anObject anObject can be a part or generic or a product + * @param aRf can be any kind of repair + */ + void visitReceptorRepere(TcSession session, final BOMLineHolder anObject, final BOMLineHolder aRf); +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/comparison/AbstractDualBomLineFlattener.java b/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/comparison/AbstractDualBomLineFlattener.java new file mode 100644 index 0000000..2d1d721 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/comparison/AbstractDualBomLineFlattener.java @@ -0,0 +1,214 @@ +package com.capgemini.reports.bomlineholder.comparison; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.bomlineholder.flattener.line.*; +import com.capgemini.reports.releasestatus.EffectivityBehaviourHelper; +import com.capgemini.reports.snecmaobjects.ISnecmaObject; +import com.capgemini.reports.snecmaobjects.part.AbstractPart; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.Setter; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Comparator; +import java.util.List; + +/** + * This class analyses two {@link BOMLineHolder} and recursively flattens their tree structure into a {@link List} of Receptor-component links.
    + * Each Receptor-component relationship can be expressed with a {@link SnecmaLine} object like {@link AbstractQuad}, {@link AbstractTopLine}, {@link AbstractPartNumber}, {@link AbstractPartRfPart}, {@link AbstractPartPart}, {@link AbstractReceptorLine}, {@link AbstractProductGeneric}.
    + * These {@link SnecmaLine}s are all able to receive a transformer object of type U, and produce a result of type T.
    + * The result is two {@link List}s of {@link SnecmaLine}s which can be obtained with {@link AbstractDualBomLineFlattener#getConfig1()} and {@link AbstractDualBomLineFlattener#getConfig2()}. + * + * @param a Transformer object for transforming each {@link SnecmaLine} and producing results of type U. + * @param the type of results, as an outcome of a transformation by object of type T. + */ +@Getter +public abstract class AbstractDualBomLineFlattener extends DualBomLineBrowser implements IDualSnecmaLineProcessor { + + private final List> config1 = new ArrayList<>(); + private final List> config2 = new ArrayList<>(); + @Setter(value = AccessLevel.PROTECTED) + private DealWithAltOrDetPseudoFolder pseudoFolderBehaviour; + + /** + * Constructs a BomLineFlattener with the specified behaviour regarding effectivity, parts in pseudo-folders, part numbers, etc. + * + * @param effectivityBehaviour the behaviour to be had when having to resolve the effectivity of a Part (i.e. should a part that is managed by date visited?) + * @param visitPartsInPseudoFolder the behaviour to be had when encountering a pseudo-folder: should it be looked at, or not at all? + * @param retrievePartNumberUnderRfGeneric the behaviour to be had when encountering a Generic/RF Generic/Part: should it be looked at, or not at all? + * @param visitPartBelowPart the behaviour to be had when encountering a Part right below an other (without RF in-between): should it be looked at, or not at all? + * @param pseudoFolderBehaviour the behaviour to be had when encountering a psuedo-folder. Can produce useful objects when invoked on one + * @param bomComparator {@link Comparator} for {@link BOMLineHolder}s, to know which bomlines are matching accross configurations + * @param itemComparator {@link Comparator} for {@link ISnecmaObject}s, to know which items are matching in pseudo-folders accross configurations + * @param generateBrotherLinesBeforeRecursion if true, then all brother lines of a parent object will be generated before recursing through the brothers' children + */ + public AbstractDualBomLineFlattener(final EffectivityBehaviourHelper effectivityBehaviour, final boolean visitPartsInPseudoFolder, + final boolean retrievePartNumberUnderRfGeneric, final boolean visitPartBelowPart, + final DealWithAltOrDetPseudoFolder pseudoFolderBehaviour, final Comparator bomComparator, + final Comparator itemComparator, final boolean generateBrotherLinesBeforeRecursion) { + super(effectivityBehaviour, visitPartsInPseudoFolder, retrievePartNumberUnderRfGeneric, visitPartBelowPart, bomComparator, itemComparator); + this.pseudoFolderBehaviour = pseudoFolderBehaviour; + if (generateBrotherLinesBeforeRecursion) { + this.setPreProcessor(this); + } else { + this.setProcessor(this); + } + } + + @Override + public void visitPartsInPseudoFolder(final OptionalBomPair aPart, final OptionalPartPair child) { + if (aPart.firstExists() && child.firstExists()) { + Collection> setFromPseudoFolder = pseudoFolderBehaviour.dealWithIt(aPart.getFirst(), child.getFirst()); + config1.addAll(setFromPseudoFolder); + } + if (aPart.secondExists() && child.secondExists()) { + Collection> setFromPseudoFolder = pseudoFolderBehaviour.dealWithIt(aPart.getSecond(), child.getSecond()); + config2.addAll(setFromPseudoFolder); + } + } + + @Override + public void visitQuad(final TcSession session, final OptionalBomPair receptor, final OptionalBomPair rfReceptor, final OptionalBomPair component, + final OptionalBomPair rfComponent) { + if (receptor.firstExists() && rfReceptor.firstExists() && component.firstExists() && rfComponent.firstExists()) { + config1.add(makeQuad(session, receptor.getFirst(), rfReceptor.getFirst(), component.getFirst(), rfComponent.getFirst())); + } + if (receptor.secondExists() && rfReceptor.secondExists() && component.secondExists() && rfComponent.secondExists()) { + config2.add(makeQuad(session, receptor.getSecond(), rfReceptor.getSecond(), component.getSecond(), rfComponent.getSecond())); + } + } + + @Override + public void visitTopBom(final OptionalBomPair aTopBomLine) { + AbstractTopLine topLine1 = maketopline(aTopBomLine.getFirst()); + AbstractTopLine topLine2 = maketopline(aTopBomLine.getSecond()); + if (topLine1 != null && topLine2 != null) { + config1.add(topLine1); + config2.add(topLine2); + } + } + + @Override + public void visitProductGeneric(final TcSession session, final OptionalBomPair productReceptor, final OptionalBomPair genericComponent, + final OptionalBomPair rfGenericComponent) { + if (productReceptor.firstExists() && genericComponent.firstExists() && rfGenericComponent.firstExists()) { + AbstractProductGeneric productGeneric1 = + makeProductGeneric(session, productReceptor.getFirst(), genericComponent.getFirst(), rfGenericComponent.getFirst()); + if (productGeneric1 != null) { + config1.add(productGeneric1); + } + } + if (productReceptor.secondExists() && genericComponent.secondExists() && rfGenericComponent.secondExists()) { + AbstractProductGeneric productGeneric2 = + makeProductGeneric(session, productReceptor.getSecond(), genericComponent.getSecond(), rfGenericComponent.getSecond()); + if (productGeneric2 != null) { + config2.add(productGeneric2); + } + } + } + + @Override + public void visitPartNumber(final OptionalBomPair genericReceptor, final OptionalBomPair rfGeneric, final OptionalBomPair partNumber) { + if (genericReceptor.firstExists() && rfGeneric.firstExists() && partNumber.firstExists()) { + AbstractPartNumber partNumberLine1 = makePartNumber(genericReceptor.getFirst(), rfGeneric.getFirst(), partNumber.getFirst()); + if (partNumberLine1 != null) { + config1.add(partNumberLine1); + } + } + if (genericReceptor.secondExists() && rfGeneric.secondExists() && partNumber.secondExists()) { + AbstractPartNumber partNumberLine2 = makePartNumber(genericReceptor.getSecond(), rfGeneric.getSecond(), partNumber.getSecond()); + if (partNumberLine2 != null) { + config2.add(partNumberLine2); + } + } + } + + @Override + public void visitPartAsComponent(final TcSession session, final OptionalBomPair partReceptor, final OptionalBomPair rfPartComponent, final OptionalBomPair partComponent) { + if (partReceptor.firstExists() && rfPartComponent.firstExists() && partComponent.firstExists()) { + AbstractPartRfPart partRfPart1 = makePartRfPart(session, partReceptor.getFirst(), rfPartComponent.getFirst(), partComponent.getFirst()); + if (partRfPart1 != null) { + config1.add(partRfPart1); + } + } + if (partReceptor.secondExists() && rfPartComponent.secondExists() && partComponent.secondExists()) { + AbstractPartRfPart partRfPart2 = makePartRfPart(session, partReceptor.getSecond(), rfPartComponent.getSecond(), partComponent.getSecond()); + if (partRfPart2 != null) { + config2.add(partRfPart2); + } + } + } + + @Override + public void visitPartPart(final OptionalBomPair partReceptor, final OptionalBomPair partComponent) { + if (partReceptor.firstExists() && partComponent.firstExists()) { + AbstractPartPart partPart1 = makePartPart(partReceptor.getFirst(), partComponent.getFirst()); + if (partPart1 != null) { + config1.add(partPart1); + } + } + if (partReceptor.secondExists() && partComponent.secondExists()) { + AbstractPartPart partPart2 = makePartPart(partReceptor.getSecond(), partComponent.getSecond()); + if (partPart2 != null) { + config2.add(partPart2); + } + } + } + + @Override + public void visitReceptorWithoutComponent(final TcSession session, final OptionalBomPair part, final OptionalBomPair rfPart) { + if (part.firstExists() && rfPart.firstExists()) { + AbstractReceptorLine receptorLine = makeReceptorLine(session, part.getFirst(), rfPart.getFirst()); + if (receptorLine != null) { + config1.add(receptorLine); + } + } + if (part.secondExists() && rfPart.secondExists()) { + AbstractReceptorLine receptorLine = makeReceptorLine(session, part.getSecond(), rfPart.getSecond()); + if (receptorLine != null) { + config2.add(receptorLine); + } + } + } + + protected abstract AbstractQuad makeQuad(TcSession session, final BOMLineHolder receptor, final BOMLineHolder rfReceptor, final BOMLineHolder component, + final BOMLineHolder rfComponent); + + protected abstract AbstractTopLine maketopline(final BOMLineHolder aTopBomLine); + + protected abstract AbstractPartNumber makePartNumber(final BOMLineHolder genericReceptor, final BOMLineHolder rfGeneric, + final BOMLineHolder partAero); + + protected abstract AbstractPartRfPart makePartRfPart(TcSession session, final BOMLineHolder partReceptor, final BOMLineHolder rfPartComponent, + final BOMLineHolder partComponent); + + protected abstract AbstractPartPart makePartPart(final BOMLineHolder partReceptor, final BOMLineHolder partComponent); + + protected abstract AbstractReceptorLine makeReceptorLine(TcSession session, final BOMLineHolder part, final BOMLineHolder rfPart); + + protected abstract AbstractProductGeneric makeProductGeneric(TcSession session, final BOMLineHolder productReceptor, final BOMLineHolder genericComponent, + final BOMLineHolder rfGenericComponent); + + /** + * Behaviour to be had when encountering a pseudoFolder.
    + * The objective of the behaviour is to produce a set of objects representing the contents of the pseudofolder, as a {@link Collection} of {@link SnecmaLine}.
    + * A {@link SnecmaLine} can produce an object of type T when submitted to a transformaer object of Type U. + * + * @param the type of object the {@link SnecmaLine}s can produce + * @param the type of Transformer that can be applied to the SnecmaLine + */ + public interface DealWithAltOrDetPseudoFolder { + + /** + * Deals with a {@link BOMLineHolder} holding reference to an Alt or a DET. + * + * @param bomLineHolder + * @param iSnecmaObject + * @return a collections of return objects. + */ + Collection> dealWithIt(final BOMLineHolder bomLineHolder, final AbstractPart iSnecmaObject); + } + +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/comparison/DualBomLineBrowser.java b/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/comparison/DualBomLineBrowser.java new file mode 100644 index 0000000..c6a2b79 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/comparison/DualBomLineBrowser.java @@ -0,0 +1,588 @@ +package com.capgemini.reports.bomlineholder.comparison; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.bomlineholder.BOMLineHolderHelper; +import com.capgemini.reports.exceptions.InvalidInputException; +import com.capgemini.reports.exceptions.MalformedNomenclatureException; +import com.capgemini.reports.releasestatus.EffectivityBehaviourHelper; +import com.capgemini.reports.snecmaobjects.ISnecmaObject; +import com.capgemini.reports.snecmaobjects.part.AbstractAltOrDetRevision; +import com.capgemini.reports.snecmaobjects.part.AbstractPart; +import com.capgemini.reports.snecmaobjects.part.AlternateRevision; +import com.capgemini.reports.snecmaobjects.part.DETRevision; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; + +import java.util.*; + +/** + * Browse a {@link BOMLineHolder} tree, and presents methods for dealing with a coherent set of objects + * having a strong relationship in the Bom, like Generic-RfGeneric-PartAero.
    + * The various abstract methods each expose such coherent sets of objects, and are called in the browsing order. + */ +@Slf4j +@Getter +public class DualBomLineBrowser { + + // Sub-components that define the behaviour of this Visitor + private final EffectivityBehaviourHelper effectivityBehaviour; + private final boolean doRetrievePartNumberUnderRfGeneric; + private final boolean doVisitPartBelowPart; + private final boolean doVisitPartsInPseudoFolder; + private final Comparator bomComparator; + private final Comparator itemComparator; + + @Setter(value = AccessLevel.PROTECTED) + private IDualSnecmaLineProcessor preProcessor; + @Setter(value = AccessLevel.PROTECTED) + private IDualSnecmaLineProcessor processor; + + /** + * Constructor. + * + * @param effectivityBehaviour : the behaviour regarding Effectivities + * @param visitPartsInPseudoFolder : the behaviour regarding pseudofolders of {@link AlternateRevision} or {@link DETRevision} parts. + * @param retrievePartNumberUnderRfGeneric boolean Take true if we retrieve the Part number under the RF Generic. Take false else. + * @param visitPartBelowPart tells the Visitor weather it should visit a Part that is below another Part + * @param bomComparator {@link Comparator} for {@link BOMLineHolder}s, to know which bomlines are matching accross configurations + * @param itemComparator {@link Comparator} for {@link ISnecmaObject}s, to know which items are matching in pseudo-folders accross configurations + */ + public DualBomLineBrowser(final EffectivityBehaviourHelper effectivityBehaviour, final boolean visitPartsInPseudoFolder, + final boolean retrievePartNumberUnderRfGeneric, final boolean visitPartBelowPart, final Comparator bomComparator, + final Comparator itemComparator) { + this.effectivityBehaviour = effectivityBehaviour; + this.doVisitPartsInPseudoFolder = visitPartsInPseudoFolder; + this.doRetrievePartNumberUnderRfGeneric = retrievePartNumberUnderRfGeneric; + this.doVisitPartBelowPart = visitPartBelowPart; + this.bomComparator = bomComparator; + this.itemComparator = itemComparator; + this.processor = new PassiveProcessor(); + } + + private static AbstractPart nextPartOrNull(final Iterator iterator) { + if (!iterator.hasNext()) { + return null; + } else { + return iterator.next(); + } + } + + private static List getCommonChildren(final List conf1, final List conf2, + final Comparator itemComparator) { + List pairs = new ArrayList<>(); + Iterator iterator1 = conf1.iterator(); + Iterator iterator2 = conf2.iterator(); + AbstractPart child1 = nextPartOrNull(iterator1); + AbstractPart child2 = nextPartOrNull(iterator2); + while (child1 != null || child2 != null) { + if (child1 != null && child2 != null) { + int cmp = itemComparator.compare(child1, child2); + if (cmp == 0) { + pairs.add(new OptionalPartPair(child1, child2)); + child1 = nextPartOrNull(iterator1); + child2 = nextPartOrNull(iterator2); + } else if (cmp > 0) { + pairs.add(new OptionalPartPair(child1, null)); + child1 = nextPartOrNull(iterator1); + } else { + pairs.add(new OptionalPartPair(null, child2)); + child2 = nextPartOrNull(iterator2); + } + } else if (child1 != null) { + pairs.add(new OptionalPartPair(child1, null)); + child1 = nextPartOrNull(iterator1); + } else { + pairs.add(new OptionalPartPair(null, child2)); + child2 = nextPartOrNull(iterator2); + } + } + return pairs; + } + + /** + * Visit a Top BOMLineHolder and expand all the children to retrieve the properties. + */ + public void visitTopReceptorBom(final TcSession session, final BOMLineHolder aTopBomLineConf1, final BOMLineHolder aTopBomLineConf2) + throws MalformedNomenclatureException { + // Create a Specific first line + OptionalBomPair topPair = new OptionalBomPair(aTopBomLineConf1, aTopBomLineConf2); + preProcessor.visitTopBom(topPair); + + // Analyze the type of the SnecmaObject and visit it according to this type + ISnecmaObject theSnecmaObject1 = aTopBomLineConf1.getSnecmaObject(); + ISnecmaObject theSnecmaObject2 = aTopBomLineConf2.getSnecmaObject(); + if (theSnecmaObject1 != null && theSnecmaObject2 != null) { + if (theSnecmaObject1.getType().compareTo(theSnecmaObject2.getType()) != 0) { + throw new MalformedNomenclatureException("Top BomLines have differing types"); + } + if (theSnecmaObject1.isProduct()) { + visitProductAsReceptor(session, topPair); + } else if (theSnecmaObject1.isGeneric()) { + visitGenericAsReceptor(session, topPair); + } else if (theSnecmaObject1.isPart()) { + visitPartAsReceptor(session, topPair); + } else { + throw new MalformedNomenclatureException("Unupported bom: topLine " + aTopBomLineConf1.getSnecmaObject().getItemId() + + " is not a Generic, a Product, or a Part. It is a " + aTopBomLineConf1.getSnecmaObject().getType()); + } + } else { + throw new MalformedNomenclatureException("Empty top BomLine"); + } + } + + private void visitPartAsReceptor(final TcSession session, final OptionalBomPair aPart) { + List commonChildren = getCommonChildren(aPart, bomComparator); + // Pre - processing + if (preProcessor != null) { + + for (OptionalBomPair child : commonChildren) { + if (doVisitPartBelowPart && child.isPart()) { + preProcessor.visitPartPart(aPart, child); // Non-recursive + } + if (child.isRFPartOrPartAssemb()) { + preProcessRfPart(session, aPart, child); + } + } + if (SnecmaObjectTypes.isAltOrDet(aPart.getType()) && doVisitPartsInPseudoFolder) { // Specific treatment of Alt or Det Receptor + List pseudoFolder1; + if (aPart.firstExists()) { + pseudoFolder1 = ((AbstractAltOrDetRevision) aPart.getFirst().getSnecmaObject()).getPseudoFolder(); + } else { + pseudoFolder1 = new ArrayList<>(); + } + List pseudoFolder2; + if (aPart.secondExists()) { + pseudoFolder2 = ((AbstractAltOrDetRevision) aPart.getSecond().getSnecmaObject()).getPseudoFolder(); + } else { + pseudoFolder2 = new ArrayList<>(); + } + for (OptionalPartPair child : getCommonChildren(pseudoFolder1, pseudoFolder2, itemComparator)) { + // Visit the pseudo-folder + preProcessor.visitPartsInPseudoFolder(aPart, child); + } + } + } + + + // There may be other children, like some Parts, RF Parts + for (OptionalBomPair child : commonChildren) { + if (doVisitPartBelowPart && child.isPart()) { + processor.visitPartPart(aPart, child); + visitPartAsReceptor(session, child); // Recursive + } + if (child.isRFPartOrPartAssemb()) { + visitRfPart(session, aPart, child); + } + } + if (SnecmaObjectTypes.isAltOrDet(aPart.getType()) && doVisitPartsInPseudoFolder) { // Specific treatment of Alt or Det Receptor + List pseudoFolder1; + if (aPart.firstExists()) { + pseudoFolder1 = ((AbstractAltOrDetRevision) aPart.getFirst().getSnecmaObject()).getPseudoFolder(); + } else { + pseudoFolder1 = new ArrayList<>(); + } + List pseudoFolder2; + if (aPart.secondExists()) { + pseudoFolder2 = ((AbstractAltOrDetRevision) aPart.getSecond().getSnecmaObject()).getPseudoFolder(); + } else { + pseudoFolder2 = new ArrayList<>(); + } + for (OptionalPartPair child : getCommonChildren(pseudoFolder1, pseudoFolder2, itemComparator)) { + // Visit the pseudo-folder + processor.visitPartsInPseudoFolder(aPart, child); + } + } + } + + private void preProcessRfPart(final TcSession session, final OptionalBomPair aPart, final OptionalBomPair rfPart) { + boolean partFound = false; + for (OptionalBomPair child : getCommonChildren(rfPart, bomComparator)) { + if (child.isPart()) { + preProcessor.visitPartAsComponent(session, aPart, rfPart, child); + partFound = true; + } + } + if (!partFound) { + preProcessor.visitReceptorWithoutComponent(session, aPart, rfPart); + } + } + + private void visitRfPart(final TcSession session, final OptionalBomPair aPart, final OptionalBomPair rfPart) { + boolean partFound = false; + for (OptionalBomPair child : getCommonChildren(rfPart, bomComparator)) { + if (child.isPart()) { + processor.visitPartAsComponent(session, aPart, rfPart, child); + visitPartAsReceptor(session, child); + partFound = true; + } + } + if (!partFound) { + processor.visitReceptorWithoutComponent(session, aPart, rfPart); + } + } + + private void visitProductAsReceptor(final TcSession session, final OptionalBomPair productReceptors) throws MalformedNomenclatureException { + // Pre - processing : fetch all PRoduct - Gen - RF Gen + List commonChildren = getCommonChildren(productReceptors, bomComparator); + if (preProcessor != null) { + for (OptionalBomPair child : commonChildren) { + if (child.isGeneric()) { + OptionalBomPair rfGenericComponent = extractRfGeneric(child); + preProcessor.visitProductGeneric(session, productReceptors, child, rfGenericComponent); + } + } + } + + // Recursive processing + for (OptionalBomPair child : commonChildren) { + if (child.isGeneric()) { + // According to the MDD, there is one and only one RF Generic below any Generic. + OptionalBomPair rfGenericComponent = extractRfGeneric(child); + processor.visitProductGeneric(session, productReceptors, child, rfGenericComponent); + + // Now the component becomes receptor + visitGenericAsReceptor(session, child); + } + } + } + + private void visitGenericAsReceptor(final TcSession session, final OptionalBomPair genericReceptor) throws MalformedNomenclatureException { + // According to the MDD, there is one and only one RF Generic below any Generic. + OptionalBomPair rfGeneric = extractRfGeneric(genericReceptor); + List commonChildren = getCommonChildren(genericReceptor, bomComparator); + + if (preProcessor != null) { + // Pre-processing + if (doRetrievePartNumberUnderRfGeneric) { + // Go ahead and extract the generic / Rf Generic / Part + visitRfGeneric(genericReceptor, rfGeneric, preProcessor); + } + // There may be other children, like some RF parts + for (OptionalBomPair child : commonChildren) { + if (child.isRFPartOrPartAssemb()) { + visitRfPartAsComponentNoRec(session, genericReceptor, rfGeneric, child); + } else if (child.isGeneric()) { + visitGenericAsComponentNoRec(session, genericReceptor, rfGeneric, child); + } + } + } + + // Recursive treatment now + if (doRetrievePartNumberUnderRfGeneric) { + // Go ahead and extract the generic / Rf Generic / Part + visitRfGeneric(genericReceptor, rfGeneric, processor); + } + // There may be other children, like some RF parts + for (OptionalBomPair child : commonChildren) { + if (child.isRFPartOrPartAssemb()) { + visitRfPartAsComponentRec(session, genericReceptor, rfGeneric, child); + } else if (child.isGeneric()) { + processor.visitQuad(session, genericReceptor, rfGeneric, child, extractRfGeneric(child)); + visitGenericAsReceptor(session, child); + } + } + } + + private void visitGenericAsComponentNoRec(final TcSession session, final OptionalBomPair genericReceptor, final OptionalBomPair rfGenericReceptor, + final OptionalBomPair genericComponent) throws MalformedNomenclatureException { + // According to the MDD, there is one and only one RF Generic below any Generic. + OptionalBomPair rfGenericComponent = extractRfGeneric(genericComponent); + preProcessor.visitQuad(session, genericReceptor, rfGenericReceptor, genericComponent, rfGenericComponent); + } + + private void visitRfPartAsComponentNoRec(final TcSession session, final OptionalBomPair receptor, final OptionalBomPair rfReceptor, final OptionalBomPair rfPart) { + boolean partFound = false; + for (OptionalBomPair child : getCommonChildren(rfPart, bomComparator)) { + if (child.isPart()) { + preProcessor.visitQuad(session, receptor, rfReceptor, child, rfPart); + partFound = true; + } + } + if (!partFound) { + preProcessor.visitReceptorWithoutComponent(session, receptor, rfPart); + } + } + + private void visitRfPartAsComponentRec(final TcSession session, final OptionalBomPair receptor, final OptionalBomPair rfReceptor, final OptionalBomPair rfPart) { + // Recursivity + boolean partFound = false; + for (OptionalBomPair child : getCommonChildren(rfPart, bomComparator)) { + if (child.isPart()) { + processor.visitQuad(session, receptor, rfReceptor, child, rfPart); + visitPartAsReceptor(session, child); + partFound = true; + } + } + if (!partFound) { + processor.visitReceptorWithoutComponent(session, receptor, rfPart); + } + } + + // RF Generics have a single PartAero below them. Also below , RF Admin(s) carry data about this RfGeneric + private void visitRfGeneric(final OptionalBomPair genericReceptor, final OptionalBomPair rfGeneric, final IDualSnecmaLineProcessor proc) + throws MalformedNomenclatureException { + for (OptionalBomPair child : getCommonChildren(rfGeneric, bomComparator)) { + if (child.isPart()) { + proc.visitPartNumber(genericReceptor, rfGeneric, child); + return; + } + } + throw new MalformedNomenclatureException("No part aero found below RfGeneric"); + } + + private OptionalBomPair extractRfGeneric(final OptionalBomPair aGeneric) throws MalformedNomenclatureException { + BOMLineHolder rfGeneric1; + try { + rfGeneric1 = BOMLineHolderHelper.findRfGenericBL(aGeneric.first); + } catch (InvalidInputException e) { + log.trace("null Generic in conf 1 ", e); // This is OK, it is exclusive to conf2 + rfGeneric1 = null; + } + BOMLineHolder rfGeneric2; + try { + rfGeneric2 = BOMLineHolderHelper.findRfGenericBL(aGeneric.second); + } catch (InvalidInputException e) { + log.trace("null Generic in conf 2 ", e); // This is OK, it is exclusive to conf1 + rfGeneric2 = null; + } + return new OptionalBomPair(rfGeneric1, rfGeneric2); + } + + /** + * Sort the children of a BomLineHolder. + * + * @param bomHolder IBOMTree + * @param comparator the comparator to be used for sorting. The comparator must be resilient to null. Any two elements deemed equal according to this comparator will be kept in the same order as they are found. + */ + private List sortBomChildren(final BOMLineHolder bomHolder, final Comparator comparator) { + if (bomHolder == null) { + return Collections.emptyList(); + } + List copy = new ArrayList<>(bomHolder.getBomChilds()); + removeIllConditioned(copy); // Remove all null elements for safety + Collections.sort(copy, comparator); + return copy; + } + + private void removeIllConditioned(final List list) { + Iterator iterator = list.iterator(); + while (iterator.hasNext()) { + BOMLineHolder blh = iterator.next(); + if (blh == null || blh.getSnecmaObject() == null) { + iterator.remove(); + } + } + } + + /** + * Returns a List of comparison pairs from both configurations. All RF that have the wrong effectivity are ignored in the ouput.
    + * A resulting child pair can be: + *
      + *
    • one-sided: item is found only in one of the two configurations, no object from the other conf is equal according to the provided {@link Comparator} or maybe the other item is a RF with wrong effectivity (date etc.)
    • + *
    • Two-sided: an item from either configuration is found, and the provided {@link Comparator} finds them equal.
    • + *
    + * + * @param pair pair the original pair of objects to be compared. + * @param dualComparator the comparator to be used for sorting. The comparator must be resilient to null. Any two elements deemed equal according to this comparator will be kept in the same order as they are found. + */ + private List getCommonChildren(final OptionalBomPair pair, final Comparator dualComparator) { + List pairs = new ArrayList<>(); + Iterator iterator1 = sortBomChildren(pair.getFirst(), dualComparator).iterator(); // Sort both boms according to the comparator's sense of order + Iterator iterator2 = sortBomChildren(pair.getSecond(), dualComparator).iterator(); // Sort both boms according to the comparator's sense of order + BOMLineHolder child1 = nextOrNull(iterator1); + BOMLineHolder child2 = nextOrNull(iterator2); + while (child1 != null || child2 != null) { + if (child1 != null && child2 != null) { + // Both lists are not empty... + int cmp = dualComparator.compare(child1, child2); + if (cmp == 0) { + pairs.add(new OptionalBomPair(child1, child2)); + child1 = nextOrNull(iterator1); + child2 = nextOrNull(iterator2); + } else if (cmp < 0) { + pairs.add(new OptionalBomPair(child1, null)); + child1 = nextOrNull(iterator1); + } else { + pairs.add(new OptionalBomPair(null, child2)); + child2 = nextOrNull(iterator2); + } + } else if (child1 != null) { + pairs.add(new OptionalBomPair(child1, null)); + child1 = nextOrNull(iterator1); + } else { + pairs.add(new OptionalBomPair(null, child2)); + child2 = nextOrNull(iterator2); + } + } + return pairs; + } + + private BOMLineHolder nextOrNull(final Iterator iterator) { + if (!iterator.hasNext()) { + return null; // No more elements in this iterator + } + BOMLineHolder next = iterator.next(); + if (next.getSnecmaObject().isRF() && !effectivityBehaviour.shouldVisit(next)) { + next = nextOrNull(iterator); // Next element is a RF, wich should not be visited, so we'll jump it + } + return next; + } + + private static class PassiveProcessor implements IDualSnecmaLineProcessor { + + @Override + public void visitTopBom(final OptionalBomPair aTopBom) { + // Nothing to do + } + + @Override + public void visitReceptorWithoutComponent(TcSession session, final OptionalBomPair part, final OptionalBomPair rfPart) { + // Nothing to do + } + + @Override + public void visitQuad(TcSession session, final OptionalBomPair receptor, final OptionalBomPair rfReceptor, final OptionalBomPair component, + final OptionalBomPair rfComponent) { + // Nothing to do + } + + @Override + public void visitProductGeneric(TcSession session, final OptionalBomPair productReceptor, final OptionalBomPair genericComponent, + final OptionalBomPair rfGenericComponent) { + // Nothing to do + } + + @Override + public void visitPartsInPseudoFolder(final OptionalBomPair aPart, final OptionalPartPair child) { + // Nothing to do + } + + @Override + public void visitPartPart(final OptionalBomPair fatherPart, final OptionalBomPair childPart) { + // Nothing to do + } + + @Override + public void visitPartNumber(final OptionalBomPair genericReceptor, final OptionalBomPair rfGeneric, final OptionalBomPair child) { + // Nothing to do + } + + @Override + public void visitPartAsComponent(TcSession session, final OptionalBomPair part, final OptionalBomPair rfPart, final OptionalBomPair child) { + // Nothing to do + } + } + + /** + * Can hold a pair of snecma {@link ISnecmaObject} from either conf, which are deemed similar to each other. Either one may be null, or none. + */ + @Getter + @AllArgsConstructor + public static class OptionalPartPair { + + private final AbstractPart first; + private final AbstractPart second; + + /** + * True if the object of the 1st conf is undefined. + * + * @return True if the bomLineHolder of the 1st conf is undefined + */ + public boolean firstExists() { + return first != null; + } + + /** + * True if the object of the 2nd conf is undefined. + * + * @return True if the bomLineHolder of the 2nd conf is undefined + */ + public boolean secondExists() { + return second != null; + } + } + + /** + * Can hold a pair of {@link BOMLineHolder}s from either conf, which are deemed similar to each other. Either one may be null, or none. + */ + @Getter + @AllArgsConstructor + public static class OptionalBomPair { + private final BOMLineHolder first; + private final BOMLineHolder second; + + /** + * Returns the common type of both held objects. + * + * @return a String containing the object type. + */ + public String getType() { + return first == null ? second.getSnecmaObject().getType() : first.getSnecmaObject().getType(); + } + + /** + * Return true if it is a RF Generic. + * + * @return the boolean + */ + public boolean isRFGeneric() { + return first == null ? second.getSnecmaObject().isRFGeneric() : first.getSnecmaObject().isRFGeneric(); + } + + /** + * Return true if it is a RF Part or a RF PArt Assemb. + * + * @return the boolean + */ + public boolean isRFPartOrPartAssemb() { + return first == null ? second.getSnecmaObject().isRFPartOrPartAssemb() : first.getSnecmaObject().isRFPartOrPartAssemb(); + } + + /** + * Return true if it is a Part. + * + * @return the boolean + */ + public boolean isPart() { + return first == null ? second.getSnecmaObject().isPart() : first.getSnecmaObject().isPart(); + } + + /** + * Return true if it is a Generic. + * + * @return the boolean + */ + public boolean isGeneric() { + return first == null ? second.getSnecmaObject().isGeneric() : first.getSnecmaObject().isGeneric(); + } + + /** + * True if the bomLineHolder of the 1st conf is undefined. + * + * @return True if the bomLineHolder of the 1st conf is undefined + */ + public boolean firstExists() { + return first != null; + } + + /** + * True if the bomLineHolder of the 2nd conf is undefined. + * + * @return True if the bomLineHolder of the 2nd conf is undefined + */ + public boolean secondExists() { + return second != null; + } + + @Override + public String toString() { + return "Pair: " + (firstExists() ? first.toString() : "") + " <-> " + (secondExists() ? second.toString() : ""); + } + } + +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/comparison/IDualSnecmaLineProcessor.java b/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/comparison/IDualSnecmaLineProcessor.java new file mode 100644 index 0000000..0510157 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/comparison/IDualSnecmaLineProcessor.java @@ -0,0 +1,105 @@ +package com.capgemini.reports.bomlineholder.comparison; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.bomlineholder.comparison.DualBomLineBrowser.OptionalBomPair; +import com.capgemini.reports.bomlineholder.comparison.DualBomLineBrowser.OptionalPartPair; + +/** + * Interface for objects who can process an {@link OptionalBomPair} from a Bom comparison. + */ +public interface IDualSnecmaLineProcessor { + + /** + * Behaviour to be defined for the very first element of the nomenclature, which usually doen't have a Repere, etc. + * + * @param aTopBom the {@link BOMLineHolder} holding the top Object (usually a Generic, or a Product, sometimes a Part. + */ + void visitTopBom(final OptionalBomPair aTopBom); + + /** + * Behaviour to be defined when a 'full' line of objects is found.
    + * A 'full' line consists of: + *
      + *
    1. a Receptor like a Part, a Generic or a Product + *
    2. a Repere Fonctionnel associated with the receptor + *
    3. a Component like a Generic or a Part + *
    4. a Repere Fonctionnel associated with the component + *
    + * + * @param session + * @param receptor the Receptor inside its {@link BOMLineHolder} + * @param rfReceptor the Receptor's repere inside its {@link BOMLineHolder} + * @param component the Component inside its {@link BOMLineHolder} + * @param rfComponent the Component's repere inside its {@link BOMLineHolder} + */ + void visitQuad(TcSession session, final OptionalBomPair receptor, final OptionalBomPair rfReceptor, final OptionalBomPair component, + final OptionalBomPair rfComponent); + + + /** + * Behaviour to be defined when a Product-Generic-RF Generic line is found.
    + * + * @param session + * @param productReceptor the Receptor inside its {@link BOMLineHolder} + * @param genericComponent the Component inside its {@link BOMLineHolder} + * @param rfGenericComponent the Component's repere inside its {@link BOMLineHolder} + */ + void visitProductGeneric(TcSession session, final OptionalBomPair productReceptor, final OptionalBomPair genericComponent, final OptionalBomPair rfGenericComponent); + + /** + * Behaviour to be defined when a PartNumber is encountered.
    + * A Part Number if always found in this structure (and only in this structure): + *
      + *
    1. a GenericReceptor + *
    2. an only RF Generic below the Generic + *
    3. an only PartAero below the RF Generic + *
    + * Note the Generic may have other children than the RF Generic, like some RF Parts..
    + * Also not the RF Generic should have other children than the PrtAero, like RF Admins (who own additional data on the RF Generic), etc. + * + * @param genericReceptor + * @param rfGeneric + * @param child + */ + void visitPartNumber(final OptionalBomPair genericReceptor, final OptionalBomPair rfGeneric, final OptionalBomPair child); + + /** + * Behaviour to be defined when the top object is a Part (therefore without an RF Part) points to an RF Part which owns a Part.
    + * This method is only encountered (once) when the nomenclature explosion begins on as Part. + * + * @param session + * @param part the father Part + * @param rfPart a RF Part below the father Part + * @param child a Part below the RF Part + */ + void visitPartAsComponent(TcSession session, final OptionalBomPair part, final OptionalBomPair rfPart, final OptionalBomPair child); + + /** + * Behaviour to be defined a Part poitns to an other Part in the nomenclature.
    + * At the lower levels of nomenclature, Parts can have Parts as their direct children, whith neither having a RF Part. + * + * @param fatherPart the father Part + * @param childPart the child Part + */ + void visitPartPart(final OptionalBomPair fatherPart, final OptionalBomPair childPart); + + /** + * Behviour to be defined when encountering an Alt or a DET, which contain a Part in its pseudo-folders.
    + * This method is invoked only when visitPartsInPseudoFolderw is set to true. + * + * @param aPart the Alt or DET part + * @param child a child Part found in the pseudo-folder + */ + void visitPartsInPseudoFolder(final OptionalBomPair aPart, final OptionalPartPair child); + + /** + * Behviour to be defined when encountering a Receptor which has a Rf, but this Rf links to no component. + * + * @param session + * @param part the part receptor + * @param rfPart the RfPart + */ + void visitReceptorWithoutComponent(TcSession session, final OptionalBomPair part, final OptionalBomPair rfPart); + +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/flattener/AbstractBomLineFlattener.java b/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/flattener/AbstractBomLineFlattener.java new file mode 100644 index 0000000..0c9ab1d --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/flattener/AbstractBomLineFlattener.java @@ -0,0 +1,158 @@ +package com.capgemini.reports.bomlineholder.flattener; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.bomlineholder.ISnecmaLineProcessor; +import com.capgemini.reports.bomlineholder.flattener.line.*; +import com.capgemini.reports.bomlineholder.visitor.BomLineBrowser; +import com.capgemini.reports.releasestatus.EffectivityBehaviourHelper; +import com.capgemini.reports.snecmaobjects.part.AbstractPart; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.Setter; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +/** + * This class analyses a {@link BOMLineHolder} and flattens its tree structure into a {@link List} of Receptor-component links.
    + * Each Receptor-component relationship can be expressed with a {@link SnecmaLine} object like {@link AbstractQuad}, {@link AbstractTopLine}, {@link AbstractPartNumber}, {@link AbstractPartRfPart}, {@link AbstractPartPart}, {@link AbstractReceptorLine}, {@link AbstractProductGeneric}.
    + * These {@link SnecmaLine}s are all able to receive a transformer object of type U, and procude a result of type T. + * + * @param a Transformer object for transforming each line and producing results of type U. + * @param the type of results, as an outcome of a transformation by object of type T. + */ +@Getter +public abstract class AbstractBomLineFlattener extends BomLineBrowser implements ISnecmaLineProcessor { + + private final List> config = new ArrayList<>(); + @Setter(value = AccessLevel.PROTECTED) + private DealWithAltOrDetPseudoFolder pseudoFolderBehaviour; + + /** + * Constructs a BomLineFlattener with the specified behaviour regarding effectivity, parts in psuedo-folders, part numbers, etc. + * + * @param effectivityBehaviour the behaviour to be had when having to resolve the effectivity of a Part (i.e. should a part that is managed by date visited?) + * @param visitPartsInPseudoFolder the behaviour to be had when encountering a pseudo-folder: should it be looked at, or not at all? + * @param retrievePartNumberUnderRfGeneric the behaviour to be had when encountering a Generic/RF Generic/Part: should it be looked at, or not at all? + * @param visitPartBelowPart the behaviour to be had when encountering a Part right below an other (without RF in-between): should it be looked at, or not at all? + * @param pseudoFolderBehaviour the behaviour to be had when encountering a pseudo-folder. Can produce useful objects when invoked on an Alternate/DET + * @param generateBrotherLinesBeforeRecursion if true, then all the children will be visited without recursion first, then again with recursion. + */ + public AbstractBomLineFlattener(final EffectivityBehaviourHelper effectivityBehaviour, final boolean visitPartsInPseudoFolder, + final boolean retrievePartNumberUnderRfGeneric, final boolean visitPartBelowPart, + final DealWithAltOrDetPseudoFolder pseudoFolderBehaviour, final boolean generateBrotherLinesBeforeRecursion) { + super(effectivityBehaviour, visitPartsInPseudoFolder, retrievePartNumberUnderRfGeneric, visitPartBelowPart); + this.pseudoFolderBehaviour = pseudoFolderBehaviour; + if (generateBrotherLinesBeforeRecursion) { + this.setPreProcessor(this); + } else { + this.setProcessor(this); + } + } + + @Override + public void visitPartsInPseudoFolder(final BOMLineHolder aPart, final AbstractPart child) { + Collection> setFromPseudoFolder = pseudoFolderBehaviour.dealWithIt(aPart, child); + config.addAll(setFromPseudoFolder); + } + + @Override + public void visitQuad(final BOMLineHolder receptor, final BOMLineHolder rfReceptor, final BOMLineHolder component, + final BOMLineHolder rfComponent) { + config.add(makeQuad(receptor, rfReceptor, component, rfComponent)); + } + + @Override + public void visitTopBom(final BOMLineHolder aTopBomLine) { + AbstractTopLine topLine = makeTopline(aTopBomLine); + if (topLine != null) { + config.add(makeTopline(aTopBomLine)); + } + } + + @Override + public void visitProductGeneric(final BOMLineHolder productReceptor, final BOMLineHolder genericComponent, + final BOMLineHolder rfGenericComponent) { + AbstractProductGeneric productGeneric = makeProductGeneric(productReceptor, genericComponent, rfGenericComponent); + if (productGeneric != null) { + config.add(productGeneric); + } + } + + @Override + public void visitPartNumber(final BOMLineHolder genericReceptor, final BOMLineHolder rfGeneric, final BOMLineHolder child) { + AbstractPartNumber partNumber = makePartNumber(genericReceptor, rfGeneric, child); + if (partNumber != null) { + config.add(partNumber); + } + } + + @Override + public void visitPartAsComponent(final BOMLineHolder partReceptor, final BOMLineHolder rfPartComponent, final BOMLineHolder partComponent) { + AbstractPartRfPart partRfPart = makePartRfPart(partReceptor, rfPartComponent, partComponent); + if (partRfPart != null) { + config.add(partRfPart); + } + } + + @Override + public void visitPartPart(final BOMLineHolder partReceptor, final BOMLineHolder partComponent) { + AbstractPartPart partPart = makePartPart(partReceptor, partComponent); + if (partPart != null) { + config.add(partPart); + } + } + + @Override + public void visitReceptorWithoutComponent(final BOMLineHolder part, final BOMLineHolder rfPart) { + AbstractReceptorLine receptorLine = makeReceptorLine(part, rfPart); + if (receptorLine != null) { + config.add(receptorLine); + } + } + + @Override + public final void visitReceptorRepere(TcSession session, final BOMLineHolder anObject, final BOMLineHolder aRF) { + // Nothing to do here! If you want a Receptor-Repere, use the AbstractRepereFlattener + } + + protected abstract AbstractQuad makeQuad(final BOMLineHolder receptor, final BOMLineHolder rfReceptor, final BOMLineHolder component, + final BOMLineHolder rfComponent); + + protected abstract AbstractTopLine makeTopline(final BOMLineHolder aTopBomLine); + + protected abstract AbstractPartNumber makePartNumber(final BOMLineHolder genericReceptor, final BOMLineHolder rfGeneric, + final BOMLineHolder partAero); + + protected abstract AbstractPartRfPart makePartRfPart(final BOMLineHolder partReceptor, final BOMLineHolder rfPartComponent, + final BOMLineHolder partComponent); + + protected abstract AbstractPartPart makePartPart(final BOMLineHolder partReceptor, final BOMLineHolder partComponent); + + protected abstract AbstractReceptorLine makeReceptorLine(final BOMLineHolder part, final BOMLineHolder rfPart); + + protected abstract AbstractProductGeneric makeProductGeneric(final BOMLineHolder productReceptor, final BOMLineHolder genericComponent, + final BOMLineHolder rfGenericComponent); + + /** + * Behaviour to be had when encountering a pseudoFolder.
    + * The objective of the behaviour is to produce a set of objects representing the contents of the pseudofolder, as a {@link Collection} of {@link SnecmaLine}.
    + * A {@link SnecmaLine} can produce an object of type T when submitted to a transformaer object of Type U. + * + * @param the type of object the {@link SnecmaLine}s can produce + * @param the type of Transformer that can be applied to the snecmaLine + */ + public interface DealWithAltOrDetPseudoFolder { + /** + * Deals with a {@link BOMLineHolder} holding reference to an Alt or a DET. + * + * @param alt a Alt {@link BOMLineHolder} + * @param partInPseudoFolder a Part in the pseudo folder of the Alt + * @return a collections of return objects. + */ + Collection> dealWithIt(final BOMLineHolder alt, final AbstractPart partInPseudoFolder); + } + +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/flattener/AbstractRepereFlattener.java b/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/flattener/AbstractRepereFlattener.java new file mode 100644 index 0000000..d06a7c4 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/flattener/AbstractRepereFlattener.java @@ -0,0 +1,104 @@ +package com.capgemini.reports.bomlineholder.flattener; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.bomlineholder.ISnecmaLineProcessor; +import com.capgemini.reports.bomlineholder.flattener.line.AbstractReceptorRepere; +import com.capgemini.reports.bomlineholder.flattener.line.SnecmaLine; +import com.capgemini.reports.bomlineholder.visitor.BomLineBrowser; +import com.capgemini.reports.releasestatus.EffectivityBehaviourHelper; +import com.capgemini.reports.snecmaobjects.part.AbstractPart; +import lombok.Getter; + +import java.util.ArrayList; +import java.util.List; + +/** + * This class implements the interface {@link ISnecmaLineProcessor} and inherits of {@link BomLineBrowser}. It defines what kind of behavior it will adopt during the exploration of data. + * + * @param a class representing a, {@link AbstractReceptorRepere} + */ +@Getter +public abstract class AbstractRepereFlattener> extends BomLineBrowser implements ISnecmaLineProcessor { + + private final List config = new ArrayList<>(); + + /** + * Constructor. + * + * @param effectivityBehaviour + * @param visitPartsInPseudoFolder + * @param retrievePartNumberUnderRfGeneric + * @param visitPartBelowPart + * @param deeplyExplosion + */ + public AbstractRepereFlattener(final EffectivityBehaviourHelper effectivityBehaviour, final boolean visitPartsInPseudoFolder, + final boolean retrievePartNumberUnderRfGeneric, final boolean visitPartBelowPart, final boolean deeplyExplosion) { + super(effectivityBehaviour, visitPartsInPseudoFolder, retrievePartNumberUnderRfGeneric, visitPartBelowPart); + if (deeplyExplosion) { + this.setProcessor(this); + } else { + this.setPreProcessor(this); + } + } + + @Override + public final void visitTopBom(final BOMLineHolder aTopBom) { + // Nothing to do + } + + @Override + public final void visitQuad(final BOMLineHolder receptor, final BOMLineHolder rfReceptor, final BOMLineHolder component, + final BOMLineHolder rfComponent) { + // Nothing to do + } + + @Override + public final void visitProductGeneric(final BOMLineHolder productReceptor, final BOMLineHolder genericComponent, + final BOMLineHolder rfGenericComponent) { + // Nothing to do + } + + @Override + public final void visitPartNumber(final BOMLineHolder genericReceptor, final BOMLineHolder rfGeneric, final BOMLineHolder child) { + // Nothing to do + } + + @Override + public final void visitPartAsComponent(final BOMLineHolder part, final BOMLineHolder rfPart, final BOMLineHolder child) { + // Nothing to do + } + + @Override + public final void visitPartPart(final BOMLineHolder fatherPart, final BOMLineHolder childPart) { + // Nothing to do + } + + @Override + public final void visitPartsInPseudoFolder(final BOMLineHolder aPart, final AbstractPart child) { + // Nothing to do + } + + @Override + public final void visitReceptorWithoutComponent(final BOMLineHolder part, final BOMLineHolder rfPart) { + // Nothing to do + } + + @Override + public void visitReceptorRepere(final TcSession session, final BOMLineHolder anObject, final BOMLineHolder aRF) { + RR receptorRepere = makeRepairReceptorLine(session, anObject, aRF); + if (receptorRepere != null) { + config.add(receptorRepere); + } + } + + /** + * Method which allow to make a receptor-repere {@link SnecmaLine}. + * + * @param session + * @param anObject an object + * @param functionnalRepere its RF + * @return the {@link AbstractReceptorRepere} + */ + public abstract RR makeRepairReceptorLine(final TcSession session, final BOMLineHolder anObject, final BOMLineHolder functionnalRepere); +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/flattener/line/AbstractAltPart.java b/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/flattener/line/AbstractAltPart.java new file mode 100644 index 0000000..7177d93 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/flattener/line/AbstractAltPart.java @@ -0,0 +1,254 @@ +package com.capgemini.reports.bomlineholder.flattener.line; + +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.snecmaobjects.part.*; +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * Represents a direct Part/Part link. No RFs in-between. + * + * @param a Transformer object producing results of type T + * @param the result of a transformation by object of type U + */ +@AllArgsConstructor +@Getter +public abstract class AbstractAltPart implements SnecmaLine { + + private static final String NON = "Non"; + private static final String OUI = "Oui"; + private static final String EMPTY = ""; + + private final BOMLineHolder altBL; + private final AbstractPart child; + private final int lineNumber; + + @Override + public int compareTo(final SnecmaLine other) { + if (this.getClass().isAssignableFrom(other.getClass())) { + return compareTo((AbstractAltPart) other); + } else { + return getLineId().compareTo(other.getLineId()); + } + } + + /** + * Compares this {@link AbstractPartPart} to an other one. + * + * @param other the other {@link AbstractPartPart} + * @return a difference number. 0 if equal. + */ + public int compareTo(final AbstractAltPart other) { + int cmp = altBL.getSnecmaObject().getItemId().compareTo(other.altBL.getSnecmaObject().getItemId()); + if (cmp != 0) { + return cmp; + } else { + return child.getItemId().compareTo(other.child.getItemId()); + } + } + + @Override + public String toString() { + return "AltPart(" + getLineId() + ")"; + } + + @Override + public String getLineId() { + return altBL.getSnecmaObject().getItemId() + "/" + child.getItemId(); + } + + @Override + public String getIDReceptor() { + return altBL.getSnecmaObject().getItemId(); + } + + @Override + public String getNameReceptor() { + return altBL.getSnecmaObject().getName(); + } + + @Override + public String getRevisionReceptor() { + return altBL.getSnecmaObject().getRevisionId(); + } + + @Override + public String getRepereName() { + return EMPTY; + } + + @Override + public String getRepereRevision() { + return EMPTY; + } + + @Override + public String getResponsableRepere() { + return EMPTY; + } + + @Override + public String getSuiviMontage() { + return EMPTY; + } + + @Override + public String getIDComponent() { + return this.getChild().getItemId(); + } + + @Override + public String getIDRevisionComponent() { + return this.getChild().getRevisionId(); + } + + @Override + public String getTypeReference() { + return PartTypeExtractorHelper.extractType(this.getChild()); + } + + @Override + public String getNameReference() { + return this.getChild().getName(); + } + + @Override + public String getReferenceConceptor() { + if (this.getChild().isPart()) { + return this.getChild().getRefCompleteConcepteur(); + } + return EMPTY; + } + + @Override + public String getReferenceTransposed() { + if (this.getChild().isPart()) { + return this.getChild().getRefTransposeeSnecma(); + } + return EMPTY; + } + + @Override + public String getReferenceAssociated() { + if (this.getChild().isPart()) { + return this.getChild().getRefAssociee(); + } + return EMPTY; + } + + @Override + public String getResponsableConception() { + if (this.getChild().isPart()) { + return this.getChild().getResponsableConception(); + } + return EMPTY; + } + + @Override + public String getArticleGestion() { + if (SnecmaObjectTypes.isA(this.getChild().getType(), SnecmaObjectTypes.DET_REVISION, SnecmaObjectTypes.ALTERNATE_REVISION, + SnecmaObjectTypes.PART_ASSEMB_REVISION)) { + return OUI; + } + return EMPTY; + } + + @Override + public String getClassement() { + if (this.getChild().isPart()) { + if ("Part Mat Revision".equals(this.getChild().getType())) { + return ((PartMatRevision) this.getChild()).getClassementMat(); + } else { + return this.getChild().getClassement(); + } + + } + return EMPTY; + } + + @Override + public String getSuiviUtilisation() { + if (this.getChild().isPart()) { + return this.getChild().getSuiviUtilisation(); + } + return OUI; + } + + @Override + public String getSuiviDureeVie() { + if (this.getChild().isPart()) { + return this.getChild().getSuiviDureeVie(); + } + return NON; + } + + @Override + public String[] getSuppliersList() { + String type = this.getChild().getType(); + if (this.getChild().isPart() && !SnecmaObjectTypes.PART_NO_AERO_REVISION.equals(type)) { + String[] lst; + if (SnecmaObjectTypes.PART_AERO_REVISION.equals(type)) { + lst = ((PartAeroRevision) this.getChild()).getLstFournisseurs(); + } else if (SnecmaObjectTypes.PART_MAT_REVISION.equals(type)) { + lst = ((PartMatRevision) this.getChild()).getLstFournisseurs(); + } else if (SnecmaObjectTypes.STANDARD_REVISION.equals(type)) { + lst = ((StandardRevision) this.getChild()).getLstFournisseurs(); + } else if (SnecmaObjectTypes.DET_REVISION.equals(type)) { + lst = ((DETRevision) this.getChild()).getLstFournisseurs(); + } else if (SnecmaObjectTypes.ALTERNATE_REVISION.equals(type)) { + lst = ((AlternateRevision) this.getChild()).getLstFournisseurs(); + } else { + lst = new String[0]; + } + return lst; + } + return new String[0]; + } + + @Override + public String getALT() { + return EMPTY; + } + + @Override + public String getSB() { + return EMPTY; + } + + @Override + public String getQuantiteCumulee() { + return EMPTY; + } + + @Override + public String getPanachage() { + return EMPTY; + } + + @Override + public String getQuantite() { + return EMPTY; + } + + @Override + public String getMaquetteInterneExterne() { + return EMPTY; + } + + @Override + public Double getMass() { + return child.getMass(); + } + + @Override + public String getMassUnit() { + return child.getMassUnit(); + } + + @Override + public String getDesignationENG() { + return child.getDesignationEN(); + } + +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/flattener/line/AbstractPartNumber.java b/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/flattener/line/AbstractPartNumber.java new file mode 100644 index 0000000..f875883 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/flattener/line/AbstractPartNumber.java @@ -0,0 +1,80 @@ +package com.capgemini.reports.bomlineholder.flattener.line; + +import com.capgemini.framework.common.StringHelper; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.snecmaobjects.part.AbstractPart; +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * Represents a Generic/RF Generic/Part Number structure. + * + * @param a Transformer object producing results of type T + * @param the result of a transformation by object of type U + */ +@AllArgsConstructor +@Getter +public abstract class AbstractPartNumber implements SnecmaLine { + + private final BOMLineHolder generic; + private final BOMLineHolder rfGeneric; + private final BOMLineHolder partAero; + private final int lineNumber; + + @Override + public int compareTo(final SnecmaLine other) { + if (this.getClass().isAssignableFrom(other.getClass())) { + return compareTo((AbstractPartNumber) other); + } else { + return getLineId().compareTo(other.getLineId()); + } + } + + /** + * Compares this {@link AbstractPartNumber} to an other one. + * + * @param other the other {@link AbstractPartNumber} + * @return a difference number. 0 if equal. + */ + public int compareTo(final AbstractPartNumber other) { + int cmp = generic.getSnecmaObject().getItemId().compareTo(other.generic.getSnecmaObject().getItemId()); + if (cmp == 0) { + cmp = rfGeneric.getSnecmaObject().getName().compareTo(other.rfGeneric.getSnecmaObject().getName()); + if (cmp == 0) { + if (partAero == null) { + return other.partAero == null ? 0 : 1; + } else { + return partAero.getSnecmaObject().getItemId().compareTo(other.partAero.getSnecmaObject().getItemId()); + } + } + } + return cmp; + } + + @Override + public String toString() { + return "PartNumber(" + getLineId() + ")"; + } + + @Override + public String getLineId() { + return generic.getSnecmaObject().getItemId() + "/" + rfGeneric.getSnecmaObject().getName() + "/" + partAero.getSnecmaObject().getItemId(); + } + + @Override + public Double getMass() { + if (partAero.getSnecmaObject().isPart()) { + return ((AbstractPart) partAero.getSnecmaObject()).getMass(); + } + return null; + } + + @Override + public String getMassUnit() { + if (partAero.getSnecmaObject().isPart()) { + return ((AbstractPart) partAero.getSnecmaObject()).getMassUnit(); + } + return StringHelper.EMPTY; + } + +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/flattener/line/AbstractPartPart.java b/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/flattener/line/AbstractPartPart.java new file mode 100644 index 0000000..4365afa --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/flattener/line/AbstractPartPart.java @@ -0,0 +1,73 @@ +package com.capgemini.reports.bomlineholder.flattener.line; + +import com.capgemini.framework.common.StringHelper; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.snecmaobjects.part.AbstractPart; +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * Represents a direct Part/Part link. No RFs in-between. + * + * @param a Transformer object producing results of type T + * @param the result of a transformation by object of type U + */ +@AllArgsConstructor +@Getter +public abstract class AbstractPartPart implements SnecmaLine { + + private final BOMLineHolder partReceptor; + private final BOMLineHolder partComponent; + private final int lineNumber; + + @Override + public int compareTo(final SnecmaLine other) { + if (this.getClass().isAssignableFrom(other.getClass())) { + return compareTo((AbstractPartPart) other); + } else { + return getLineId().compareTo(other.getLineId()); + } + } + + /** + * Compares this {@link AbstractPartPart} to an other one. + * + * @param other the other {@link AbstractPartPart} + * @return a difference number. 0 if equal. + */ + public int compareTo(final AbstractPartPart other) { + int cmp = partReceptor.getSnecmaObject().getItemId().compareTo(other.partReceptor.getSnecmaObject().getItemId()); + if (cmp != 0) { + return cmp; + } else { + return partComponent.getSnecmaObject().getItemId().compareTo(other.partComponent.getSnecmaObject().getItemId()); + } + } + + @Override + public String toString() { + return "PartPart(" + getLineId() + ")"; + } + + @Override + public String getLineId() { + return partReceptor.getSnecmaObject().getItemId() + "/" + partComponent.getSnecmaObject().getItemId(); + } + + @Override + public Double getMass() { + if (partComponent.getSnecmaObject().isPart()) { + return ((AbstractPart) partComponent.getSnecmaObject()).getMass(); + } + return null; + } + + @Override + public String getMassUnit() { + if (partComponent.getSnecmaObject().isPart()) { + return ((AbstractPart) partComponent.getSnecmaObject()).getMassUnit(); + } + return StringHelper.EMPTY; + } + +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/flattener/line/AbstractPartRfPart.java b/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/flattener/line/AbstractPartRfPart.java new file mode 100644 index 0000000..3238d9c --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/flattener/line/AbstractPartRfPart.java @@ -0,0 +1,293 @@ +package com.capgemini.reports.bomlineholder.flattener.line; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.bomlineholder.BOMLineHolderHelper; +import com.capgemini.reports.snecmaobjects.part.*; +import com.capgemini.reports.snecmaobjects.rf.AbstractRF; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; + +/** + * Represents a Part/RF Part/Part. + * + * @param the result of a transformation by object of type U + * @param a Transformer object producing results of type T + */ +@Getter +@Slf4j +public abstract class AbstractPartRfPart implements SnecmaLine { + + private static final String NON = "Non"; + private static final String OUI = "Oui"; + private static final String EMPTY = ""; + + private final BOMLineHolder partReceptorBL; + private final BOMLineHolder rfPartComponentBL; + private final BOMLineHolder partComponentBL; + private final int lineNumber; + + private final AbstractPart partReceptor; + private final AbstractRF rfPartComponent; + private final AbstractPart partComponent; + protected final TcSession session; + + /** + * Constructor using a Part receptor, a RF Part component , and a Part component (all bomLineHolders). + * + * @param session + * @param partReceptor the receptor Part + * @param rfPartComponent the RF Part + * @param partComponent the Component Part + * @param lineNumber a line number, identifying uniquely and orderly this triplet in the configuration. + */ + public AbstractPartRfPart(final TcSession session, final BOMLineHolder partReceptor, final BOMLineHolder rfPartComponent, final BOMLineHolder partComponent, + final int lineNumber) { + this.session = session; + this.partReceptorBL = partReceptor; + this.rfPartComponentBL = rfPartComponent; + this.partComponentBL = partComponent; + this.lineNumber = lineNumber; + this.partReceptor = (AbstractPart) partReceptorBL.getSnecmaObject(); + this.rfPartComponent = (AbstractRF) rfPartComponentBL.getSnecmaObject(); + this.partComponent = (AbstractPart) partComponentBL.getSnecmaObject(); + } + + @Override + public int compareTo(final SnecmaLine other) { + if (this.getClass().isAssignableFrom(other.getClass())) { + return compareTo((AbstractPartRfPart) other); + } else { + return getLineId().compareTo(other.getLineId()); + } + } + + /** + * Compares this {@link AbstractPartRfPart} to an other one. + * + * @param other the other {@link AbstractPartRfPart} + * @return a difference number. 0 if equal. + */ + public int compareTo(final AbstractPartRfPart other) { + int cmp = partReceptor.getItemId().compareTo(other.partReceptor.getItemId()); + if (cmp == 0) { + cmp = rfPartComponent.getName().compareTo(other.rfPartComponent.getName()); + if (cmp == 0) { + if (partComponentBL == null) { + return other.partComponentBL == null ? 0 : 1; + } + return partComponent.getItemId().compareTo(other.partComponent.getItemId()); + } + } + return cmp; + } + + @Override + public String toString() { + return "PartRfPart(" + getLineId() + ")"; + } + + @Override + public String getLineId() { + return partReceptor.getItemId() + "/" + rfPartComponent.getName() + "/" + partComponent.getItemId(); + } + + @Override + public String getIDReceptor() { + return partReceptor.getItemId(); + } + + @Override + public String getNameReceptor() { + return partReceptor.getName(); + } + + @Override + public String getRevisionReceptor() { + return partReceptor.getRevisionId(); + } + + @Override + public String getRepereName() { + return rfPartComponent.getName(); + } + + @Override + public String getRepereRevision() { + return rfPartComponent.getRevisionId(); + } + + @Override + public String getResponsableRepere() { + try { + String resp; + if (SnecmaObjectTypes.RF_PART_ASSEMB_REVISION.equals(rfPartComponent.getType())) { + resp = BOMLineHolderHelper.findRfAdminA(this.getRfPartComponentBL()).getResponsableRepere(); + } else { + resp = BOMLineHolderHelper.findRfAdmin(this.getRfPartComponentBL()).getResponsableRepere(); + } + return resp; + } catch (KurtException e) { + log.warn("Unable to find the correct RF Admins below Rf: " + rfPartComponent.getName(), e); + return EMPTY; + } + } + + @Override + public String getSuiviMontage() { + try { + String suiviMontage; + if (rfPartComponent.isRFGeneric()) { + suiviMontage = NON; + } else if (rfPartComponent.isRFPartOrPartAssemb()) { + if (SnecmaObjectTypes.RF_PART_ASSEMB_REVISION.equals(rfPartComponent.getType())) { + suiviMontage = BOMLineHolderHelper.findRfAdminA(rfPartComponentBL).getSuiviMontage(); + } else { + suiviMontage = BOMLineHolderHelper.findRfAdminAP(rfPartComponentBL).getSuiviMontage(); + } + } else { + suiviMontage = EMPTY; + } + return suiviMontage; + } catch (KurtException e) { + log.warn("Unable to find the correct RF Admins A/AP below Rf Part / RF Part Assemb: " + rfPartComponent.getName(), e); + return EMPTY; + } + } + + @Override + public String getIDComponent() { + return partComponent.getItemId(); + } + + @Override + public String getIDRevisionComponent() { + return partComponent.getRevisionId(); + } + + @Override + public String getTypeReference() { + return PartTypeExtractorHelper.extractType(partComponent); + } + + @Override + public String getNameReference() { + return partComponent.getName(); + } + + @Override + public String getReferenceConceptor() { + return partComponent.getRefCompleteConcepteur(); + } + + @Override + public String getReferenceTransposed() { + return partComponent.getRefTransposeeSnecma(); + } + + @Override + public String getReferenceAssociated() { + return partComponent.getRefAssociee(); + } + + @Override + public String getResponsableConception() { + return partComponent.getResponsableConception(); + } + + @Override + public String getArticleGestion() { + if (SnecmaObjectTypes.isA(partComponent.getType(), SnecmaObjectTypes.DET_REVISION, SnecmaObjectTypes.ALTERNATE_REVISION, + SnecmaObjectTypes.PART_ASSEMB_REVISION)) { + return OUI; + } + return EMPTY; + } + + @Override + public String getClassement() { + if (SnecmaObjectTypes.PART_MAT_REVISION.equals(partComponent.getType())) { + return ((PartMatRevision) partComponent).getClassementMat(); + } else { + return partComponent.getClassement(); + } + } + + @Override + public String getSuiviUtilisation() { + return partComponent.getSuiviUtilisation(); + } + + @Override + public String getSuiviDureeVie() { + return partComponent.getSuiviDureeVie(); + } + + @Override + public String[] getSuppliersList() { + String type = partComponent.getType(); + String[] lst; + if (SnecmaObjectTypes.PART_AERO_REVISION.equals(type)) { + lst = ((PartAeroRevision) partComponent).getLstFournisseurs(); + } else if (SnecmaObjectTypes.PART_MAT_REVISION.equals(type)) { + lst = ((PartMatRevision) partComponent).getLstFournisseurs(); + } else if (SnecmaObjectTypes.STANDARD_REVISION.equals(type)) { + lst = ((StandardRevision) partComponent).getLstFournisseurs(); + } else if (SnecmaObjectTypes.DET_REVISION.equals(type)) { + lst = ((DETRevision) partComponent).getLstFournisseurs(); + } else if (SnecmaObjectTypes.ALTERNATE_REVISION.equals(type)) { + lst = ((AlternateRevision) partComponent).getLstFournisseurs(); + } else { + lst = new String[0]; + } + return lst; + } + + @Override + public String getALT() { + return partComponentBL.getBomAlt(); + } + + @Override + public String getSB() { + return partComponentBL.getBomSb(); + } + + @Override + public String getQuantiteCumulee() { + return partComponentBL.getBomQtyCumul(); + } + + @Override + public String getPanachage() { + return partComponentBL.getBomPanache(); + } + + @Override + public String getQuantite() { + return partComponentBL.getBomQty(); + } + + @Override + public String getMaquetteInterneExterne() { + return EMPTY; + } + + @Override + public Double getMass() { + return partComponent.getMass(); + } + + @Override + public String getMassUnit() { + return partComponent.getMassUnit(); + } + + @Override + public String getDesignationENG() { + return partComponent.getDesignationEN(); + } + +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/flattener/line/AbstractProductGeneric.java b/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/flattener/line/AbstractProductGeneric.java new file mode 100644 index 0000000..ab5731d --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/flattener/line/AbstractProductGeneric.java @@ -0,0 +1,283 @@ +package com.capgemini.reports.bomlineholder.flattener.line; + +import com.capgemini.framework.common.StringHelper; +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.bomlineholder.BOMLineHolderHelper; +import com.capgemini.reports.snecmaobjects.generic.AbstractGenericRevision; +import com.capgemini.reports.snecmaobjects.product.ProductRevision; +import com.capgemini.reports.snecmaobjects.rf.RFGenericRevision; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; + +/** + * Represents a Product/Generic/RfGeneric. + * + * @param a Transformer object producing results of type T + * @param the result of a transformation by object of type U + */ +@Getter +@Slf4j +public abstract class AbstractProductGeneric implements SnecmaLine { + + private static final String NON = "Non"; + private static final String OUI = "Oui"; + private static final String EMPTY = ""; + + private final BOMLineHolder productReceptorBL; + private final BOMLineHolder genericComponentBL; + private final BOMLineHolder rfGenericComponentBL; + private final int lineNumber; + private final ProductRevision productReceptor; + private final AbstractGenericRevision genericComponent; + private final RFGenericRevision rfGenericComponent; + protected final TcSession session; + + /** + * Constructor for a link Product-->Generic-->RF Generic. + * + * @param session + * @param productReceptorBL the product + * @param genericComponentBL the generic + * @param rfGenericComponentBL the RF Generic of the Generic + * @param lineNumber a line number, identifying uniquely and orderly this triplet in the configuration. + */ + public AbstractProductGeneric(TcSession session, final BOMLineHolder productReceptorBL, final BOMLineHolder genericComponentBL, + final BOMLineHolder rfGenericComponentBL, final int lineNumber) { + this.session = session; + this.productReceptorBL = productReceptorBL; + this.genericComponentBL = genericComponentBL; + this.rfGenericComponentBL = rfGenericComponentBL; + this.lineNumber = lineNumber; + this.productReceptor = (ProductRevision) productReceptorBL.getSnecmaObject(); + this.genericComponent = (AbstractGenericRevision) genericComponentBL.getSnecmaObject(); + this.rfGenericComponent = (RFGenericRevision) rfGenericComponentBL.getSnecmaObject(); + } + + @Override + public int compareTo(final SnecmaLine other) { + if (this.getClass().isAssignableFrom(other.getClass())) { + return compareTo((AbstractProductGeneric) other); + } else { + return getLineId().compareTo(other.getLineId()); + } + } + + /** + * Compares this {@link AbstractProductGeneric} to an other one. + * + * @param other the other {@link AbstractProductGeneric} + * @return a difference number. 0 if equal. + */ + public int compareTo(final AbstractProductGeneric other) { + int cmp = productReceptorBL.getSnecmaObject().getItemId().compareTo(other.productReceptorBL.getSnecmaObject().getItemId()); + if (cmp != 0) { + return cmp; + } else { + cmp = rfGenericComponent.getName().compareTo(other.rfGenericComponent.getName()); + if (cmp != 0) { + return cmp; + } else { + return genericComponent.getItemId().compareTo(other.genericComponent.getItemId()); + } + } + } + + @Override + public String toString() { + return "ProductGeneric(" + getLineId() + ")"; + } + + @Override + public String getLineId() { + return productReceptorBL.getSnecmaObject().getItemId() + "/" + rfGenericComponent.getName() + "/" + genericComponent.getItemId(); + } + + @Override + public String getIDReceptor() { + return productReceptorBL.getSnecmaObject().getItemId(); + } + + @Override + public String getNameReceptor() { + return productReceptorBL.getSnecmaObject().getName(); + } + + @Override + public String getRevisionReceptor() { + return productReceptorBL.getSnecmaObject().getRevisionId(); + } + + @Override + public String getRepereName() { + return rfGenericComponent.getName(); + } + + @Override + public String getRepereRevision() { + return rfGenericComponent.getRevisionId(); + } + + @Override + public String getResponsableRepere() { + try { + if (rfGenericComponent.isRFGeneric()) { + return BOMLineHolderHelper.findRfAdmin(rfGenericComponentBL).getResponsableRepere(); + } else if (rfGenericComponent.isRFPartOrPartAssemb()) { + if (SnecmaObjectTypes.RF_PART_ASSEMB_REVISION.equals(rfGenericComponent.getType())) { + return BOMLineHolderHelper.findRfAdminA(rfGenericComponentBL).getResponsableRepere(); + } else { + return BOMLineHolderHelper.findRfAdmin(rfGenericComponentBL).getResponsableRepere(); + } + } + } catch (KurtException e) { + log.warn("Unable to find a RF Admin below Rf " + rfGenericComponent.getName(), e); + return EMPTY; + } + return EMPTY; + } + + @Override + public String getSuiviMontage() { + String suiviMontage; + if (rfGenericComponent.isRFGeneric()) { + suiviMontage = NON; + } else if (rfGenericComponent.isRFPartOrPartAssemb()) { + try { + if (SnecmaObjectTypes.RF_PART_ASSEMB_REVISION.equals(rfGenericComponent.getType())) { + suiviMontage = BOMLineHolderHelper.findRfAdminA(rfGenericComponentBL).getSuiviMontage(); + } else { + suiviMontage = BOMLineHolderHelper.findRfAdminAP(rfGenericComponentBL).getSuiviMontage(); + } + } catch (KurtException e) { + log.warn("Unable to find a RF Admin A/AP below Rf Part / RF Part Assemb: " + rfGenericComponent.getName(), e); + return EMPTY; + } + } else { + suiviMontage = EMPTY; + } + return suiviMontage; + } + + @Override + public String getIDComponent() { + return genericComponent.getItemId(); + } + + @Override + public String getIDRevisionComponent() { + return genericComponent.getRevisionId(); + } + + @Override + public String getTypeReference() { + String type = genericComponent.getType(); + if (SnecmaObjectTypes.GENERIC_REVISION.equals(type)) { + return "Générique"; + } else if (SnecmaObjectTypes.GENERIC_ASSEMB_REVISION.equals(type)) { + return "Générique Montage"; + } + return ""; + } + + @Override + public String getNameReference() { + return genericComponent.getName(); + } + + @Override + public String getReferenceConceptor() { + return EMPTY; + } + + @Override + public String getReferenceTransposed() { + return EMPTY; + } + + @Override + public String getReferenceAssociated() { + return EMPTY; + } + + @Override + public String getResponsableConception() { + if (genericComponent.isGeneric()) { + return genericComponent.getResponsableConception(); + } + return EMPTY; + } + + @Override + public String getArticleGestion() { + return EMPTY; + } + + @Override + public String getClassement() { + return "-"; + } + + @Override + public String getSuiviUtilisation() { + return OUI; + } + + @Override + public String getSuiviDureeVie() { + return NON; + } + + @Override + public String[] getSuppliersList() { + return new String[0]; + } + + @Override + public String getALT() { + return genericComponentBL.getBomAlt(); + } + + @Override + public String getSB() { + return genericComponentBL.getBomSb(); + } + + @Override + public String getQuantiteCumulee() { + return genericComponentBL.getBomQtyCumul(); + } + + @Override + public String getPanachage() { + return genericComponentBL.getBomPanache(); + } + + @Override + public String getQuantite() { + return genericComponentBL.getBomQty(); + } + + @Override + public String getMaquetteInterneExterne() { + return EMPTY; + } + + @Override + public Double getMass() { + return null; + } + + @Override + public String getMassUnit() { + return StringHelper.EMPTY; + } + + @Override + public String getDesignationENG() { + return genericComponent.getDesignationEN(); + } + +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/flattener/line/AbstractQuad.java b/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/flattener/line/AbstractQuad.java new file mode 100644 index 0000000..6fd45eb --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/flattener/line/AbstractQuad.java @@ -0,0 +1,386 @@ +package com.capgemini.reports.bomlineholder.flattener.line; + +import com.capgemini.framework.common.StringHelper; +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.bomlineholder.BOMLineHolderHelper; +import com.capgemini.reports.snecmaobjects.ISnecmaObject; +import com.capgemini.reports.snecmaobjects.admin.RFAdminAPRevision; +import com.capgemini.reports.snecmaobjects.admin.RFAdminARevision; +import com.capgemini.reports.snecmaobjects.admin.RFAdminRevision; +import com.capgemini.reports.snecmaobjects.generic.AbstractGenericRevision; +import com.capgemini.reports.snecmaobjects.part.*; +import com.capgemini.reports.snecmaobjects.product.ProductRevision; +import com.capgemini.reports.snecmaobjects.rf.AbstractRF; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; + +/** + * Represents a Receptor/RF receptor/Component/Rf Component. + * + * @param a Transformer object producing results of type T + * @param the result of a transformation by object of type U + */ +@Getter +@Slf4j +public abstract class AbstractQuad implements SnecmaLine { + + private static final String MSG_NO_RF_ADMIN_A_FOUND = "No RF Admin A Found"; + private static final String MSG_NO_RF_ADMIN_FOUND = "No RF Admin Found"; + private static final String NON = "Non"; + private static final String OUI = "Oui"; + private static final String EMPTY = ""; + + private final BOMLineHolder recepteurBL; + private final BOMLineHolder repereBL; + private final BOMLineHolder composantBL; + private final BOMLineHolder repereComposantBL; + private final int lineNumber; + + private final ISnecmaObject recepteur; + private final AbstractRF repereRecepteur; + private final ISnecmaObject composant; + private final AbstractRF repereComposant; + protected final TcSession session; + + /** + * builds a {@link AbstractQuad} object out of its four constituent {@link BOMLineHolder}s. + * + * @param session + * @param recepteurBL the receptor + * @param repereRecepteurBL the repere of the receptor + * @param composantBL the component + * @param repereComposantBL the repere of the component + * @param lineNum a line number, identifying uniquely and orderly this triplet in the configuration. + */ + public AbstractQuad(final TcSession session, final BOMLineHolder recepteurBL, final BOMLineHolder repereRecepteurBL, final BOMLineHolder composantBL, + final BOMLineHolder repereComposantBL, final int lineNum) { + this.session = session; + this.recepteurBL = recepteurBL; + this.repereBL = repereRecepteurBL; + this.composantBL = composantBL; + this.repereComposantBL = repereComposantBL; + this.lineNumber = lineNum; + this.recepteur = recepteurBL.getSnecmaObject(); + this.repereRecepteur = (AbstractRF) repereRecepteurBL.getSnecmaObject(); + this.composant = composantBL.getSnecmaObject(); + this.repereComposant = (AbstractRF) repereComposantBL.getSnecmaObject(); + } + + @Override + public int compareTo(final SnecmaLine other) { + if (this.getClass().isAssignableFrom(other.getClass())) { + return compareTo((AbstractQuad) other); + } else { + return getLineId().compareTo(other.getLineId()); + } + } + + /** + * Compares this {@link AbstractQuad} to an other one. + * + * @param other the other {@link AbstractQuad} + * @return a difference number. 0 if equal. + */ + public int compareTo(final AbstractQuad other) { + int cmp = recepteur.getItemId().compareTo(other.recepteur.getItemId()); + if (cmp == 0) { + cmp = repereRecepteur.getName().compareTo(other.repereRecepteur.getName()); + if (cmp == 0) { + if (composant == null) { + return other.composant == null ? 0 : 1; + } + return composant.getItemId().compareTo(other.composant.getItemId()); + } + } + return cmp; + } + + @Override + public String toString() { + return "Quad(" + getLineId() + ")"; + } + + @Override + public String getLineId() { + return recepteur.getItemId() + "/" + repereRecepteur.getName() + "/" + + (composant == null ? "null" : composant.getItemId()) + "/" + + (repereComposant == null ? "null" : repereComposant.getName()); + } + + @Override + public String getIDReceptor() { + return recepteur.getItemId(); + } + + @Override + public String getNameReceptor() { + return recepteur.getName(); + } + + @Override + public String getRevisionReceptor() { + return recepteur.getRevisionId(); + } + + @Override + public String getRepereName() { + return repereComposant.getName(); + } + + @Override + public String getRepereRevision() { + return repereComposant.getRevisionId(); + } + + @Override + public String getResponsableRepere() { + String responsableRepere; + try { + if (repereComposant.isRFGeneric()) { + RFAdminRevision rfAdmin = BOMLineHolderHelper.findRfAdmin(repereComposantBL); + responsableRepere = rfAdmin.getResponsableRepere(); + } else if (repereComposantBL.getSnecmaObject().isRFPartOrPartAssemb()) { + if (SnecmaObjectTypes.RF_PART_ASSEMB_REVISION.equals(repereComposantBL.getSnecmaObject().getType())) { + RFAdminARevision rfAdminA = BOMLineHolderHelper.findRfAdminA(repereComposantBL); + responsableRepere = rfAdminA == null ? MSG_NO_RF_ADMIN_A_FOUND : rfAdminA.getResponsableRepere(); + } else { + RFAdminRevision rfAdmin = BOMLineHolderHelper.findRfAdmin(repereComposantBL); + responsableRepere = rfAdmin == null ? MSG_NO_RF_ADMIN_FOUND : rfAdmin.getResponsableRepere(); + } + } else { + responsableRepere = EMPTY; + } + return responsableRepere; + } catch (KurtException e) { + log.warn("Unable to find the correct RF Admins below Rf: " + repereComposantBL.getSnecmaObject().getName(), e); + return EMPTY; + } + } + + @Override + public String getSuiviMontage() { + String suiviMontage; + if (repereComposant.isRFGeneric()) { + suiviMontage = NON; + } else if (repereComposantBL.getSnecmaObject().isRFPartOrPartAssemb()) { + try { + if (SnecmaObjectTypes.RF_PART_ASSEMB_REVISION.equals(repereComposantBL.getSnecmaObject().getType())) { + RFAdminARevision rfAdminA = BOMLineHolderHelper.findRfAdminA(repereComposantBL); + suiviMontage = rfAdminA == null ? MSG_NO_RF_ADMIN_A_FOUND : rfAdminA.getSuiviMontage(); + } else { + RFAdminAPRevision rfAdminAP = BOMLineHolderHelper.findRfAdminAP(repereComposantBL); + suiviMontage = rfAdminAP == null ? MSG_NO_RF_ADMIN_FOUND : rfAdminAP.getSuiviMontage(); + } + } catch (KurtException e) { + log.warn("Unable to find the correct RF Admin A/AP below RF Part / RF PArt Assemb: " + repereComposantBL.getSnecmaObject().getName(), + e); + return EMPTY; + } + } else { + suiviMontage = EMPTY; + } + return suiviMontage; + } + + @Override + public String getIDComponent() { + return composant.getItemId(); + } + + @Override + public String getIDRevisionComponent() { + return composant.getRevisionId(); + } + + @Override + public String getTypeReference() { + String typeReference; + if (composant.isPart()) { + typeReference = PartTypeExtractorHelper.extractType(composant); + } else if (composant.isGeneric()) { + String type = composant.getType(); + if (SnecmaObjectTypes.GENERIC_REVISION.equals(type)) { + typeReference = "Générique"; + } else if (SnecmaObjectTypes.GENERIC_ASSEMB_REVISION.equals(type)) { + typeReference = "Générique Montage"; + } else { + typeReference = EMPTY; + } + } else { + typeReference = EMPTY; + } + return typeReference; + } + + @Override + public String getNameReference() { + return composant.getName(); + } + + @Override + public String getReferenceConceptor() { + if (composant.isPart()) { + return ((AbstractPart) composant).getRefCompleteConcepteur(); + } else { + return EMPTY; + } + } + + @Override + public String getReferenceTransposed() { + if (composant.isPart()) { + return ((AbstractPart) composant).getRefTransposeeSnecma(); + } else { + return EMPTY; + } + } + + @Override + public String getReferenceAssociated() { + if (composant.isPart()) { + return ((AbstractPart) composant).getRefAssociee(); + } else { + return EMPTY; + } + } + + @Override + public String getResponsableConception() { + if (composant.isPart()) { + return ((AbstractPart) composant).getResponsableConception(); + } else if (composant.isGeneric()) { + return ((AbstractGenericRevision) composant).getResponsableConception(); + } else { + return EMPTY; + } + } + + @Override + public String getArticleGestion() { + if (SnecmaObjectTypes.isAltOrDet(composant.getType()) || SnecmaObjectTypes.PART_ASSEMB_REVISION.equals(composant.getType())) { + return OUI; + } + return EMPTY; + } + + @Override + public String getClassement() { + if (composant.isPart()) { + if (SnecmaObjectTypes.PART_MAT_REVISION.equals(composant.getType())) { + return ((PartMatRevision) composant).getClassementMat(); + } else { + return ((AbstractPart) composant).getClassement(); + } + } else { + return EMPTY; + } + } + + @Override + public String getSuiviUtilisation() { + if (composant.isPart()) { + return ((AbstractPart) composant).getSuiviUtilisation(); + } else { + return OUI; + } + } + + @Override + public String getSuiviDureeVie() { + if (composant.isPart()) { + return ((AbstractPart) composant).getSuiviDureeVie(); + } else { + return NON; + } + } + + @Override + public String[] getSuppliersList() { + String[] lst; + if (composant.isPart() && !SnecmaObjectTypes.PART_NO_AERO_REVISION.equals(composant.getType())) { + if (SnecmaObjectTypes.PART_AERO_REVISION.equals(composant.getType())) { + lst = ((PartAeroRevision) composant).getLstFournisseurs(); + } else if (SnecmaObjectTypes.PART_MAT_REVISION.equals(composant.getType())) { + lst = ((PartMatRevision) composant).getLstFournisseurs(); + } else if (SnecmaObjectTypes.STANDARD_REVISION.equals(composant.getType())) { + lst = ((StandardRevision) composant).getLstFournisseurs(); + } else if (SnecmaObjectTypes.DET_REVISION.equals(composant.getType())) { + lst = ((DETRevision) composant).getLstFournisseurs(); + } else if (SnecmaObjectTypes.ALTERNATE_REVISION.equals(composant.getType())) { + lst = ((AlternateRevision) composant).getLstFournisseurs(); + } else { + lst = new String[0]; + } + } else { + lst = new String[0]; + } + return lst; + } + + @Override + public String getALT() { + return composantBL.getBomAlt(); + } + + @Override + public String getSB() { + return composantBL.getBomSb(); + } + + @Override + public String getQuantiteCumulee() { + return composantBL.getBomQtyCumul(); + } + + @Override + public String getPanachage() { + return composantBL.getBomPanache(); + } + + @Override + public String getQuantite() { + return composantBL.getBomQty(); + } + + @Override + public String getMaquetteInterneExterne() { + return EMPTY; + } + + @Override + public Double getMass() { + if (composant.isPart()) { + return ((AbstractPart) composant).getMass(); + } else { + return null; + } + } + + @Override + public String getMassUnit() { + if (composant.isPart()) { + return ((AbstractPart) composant).getMassUnit(); + } else { + return StringHelper.EMPTY; + } + } + + @Override + public String getDesignationENG() { + String designation; + if (composant.isPart()) { + designation = ((AbstractPart) composant).getDesignationEN(); + } else if (composant.isGeneric()) { + designation = ((AbstractGenericRevision) composant).getDesignationEN(); + } else if (composant.isProduct()) { + designation = ((ProductRevision) composant).getDesignationEN(); + } else { + designation = StringHelper.EMPTY; + } + return designation; + } + +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/flattener/line/AbstractReceptorLine.java b/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/flattener/line/AbstractReceptorLine.java new file mode 100644 index 0000000..19b9fb2 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/flattener/line/AbstractReceptorLine.java @@ -0,0 +1,264 @@ +package com.capgemini.reports.bomlineholder.flattener.line; + +import com.capgemini.framework.common.StringHelper; +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.bomlineholder.BOMLineHolderHelper; +import com.capgemini.reports.snecmaobjects.ISnecmaObject; +import com.capgemini.reports.snecmaobjects.rf.AbstractRF; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; + +/** + * Represents a Receptor whose RF does not have any Component. + * + * @param a Transformer object producing results of type T + * @param the result of a transformation by object of type U + */ +@Getter +@Slf4j +public abstract class AbstractReceptorLine implements SnecmaLine { + + private static final String NON = "Non"; + private static final String EMPTY = ""; + + private final BOMLineHolder recepteurBL; + private final BOMLineHolder repereBL; + private final ISnecmaObject recepteur; + private final AbstractRF repere; + private final int lineNumber; + private final TcSession session; + + + /** + * builds a {@link AbstractReceptorLine} object from its Receptor and Repere's {@link BOMLineHolder}. + * + * @param session + * @param recepteurBL the receptor + * @param repereRecepteurBL the repere of the receptor + * @param lineNum the line number in the bom + */ + public AbstractReceptorLine(TcSession session, final BOMLineHolder recepteurBL, final BOMLineHolder repereRecepteurBL, final int lineNum) { + this.session = session; + this.recepteurBL = recepteurBL; + this.repereBL = repereRecepteurBL; + this.recepteur = recepteurBL.getSnecmaObject(); + this.repere = (AbstractRF) repereRecepteurBL.getSnecmaObject(); + this.lineNumber = lineNum; + } + + @Override + public int compareTo(final SnecmaLine other) { + if (this.getClass().isAssignableFrom(other.getClass())) { + return compareTo((AbstractReceptorLine) other); + } else { + return getLineId().compareTo(other.getLineId()); + } + } + + + /** + * Compares this {@link AbstractReceptorLine} to an other one. + * + * @param other the other {@link AbstractReceptorLine} + * @return a difference number. 0 if equal. + */ + public int compareTo(final AbstractReceptorLine other) { + int cmp = recepteur.getItemId().compareTo(other.recepteur.getItemId()); + if (cmp != 0) { + return cmp; + } else { + return repere.getName().compareTo(other.repere.getName()); + } + } + + @Override + public String toString() { + return "Receptor(" + recepteur.getItemId() + "/" + repere.getName(); + } + + @Override + public String getLineId() { + return recepteur.getItemId() + "/" + repere.getName(); + } + + @Override + public String getIDReceptor() { + return this.getRecepteur().getItemId(); + } + + @Override + public String getNameReceptor() { + return this.getRecepteur().getName(); + } + + @Override + public String getRevisionReceptor() { + return this.getRecepteur().getRevisionId(); + } + + @Override + public String getRepereName() { + return this.getRepere().getName(); + } + + @Override + public String getRepereRevision() { + return this.getRepere().getRevisionId(); + } + + @Override + public String getResponsableRepere() { + try { + if (this.getRepere().isRFGeneric()) { + return BOMLineHolderHelper.findRfAdmin(this.getRepereBL()).getResponsableRepere(); + } else if (this.getRepereBL().getSnecmaObject().isRFPartOrPartAssemb()) { + if ("RF Part Assemb Revision".equals(this.getRepereBL().getSnecmaObject().getType())) { + return BOMLineHolderHelper.findRfAdminA(this.getRepereBL()).getResponsableRepere(); + } else { + return BOMLineHolderHelper.findRfAdmin(this.getRepereBL()).getResponsableRepere(); + } + } + } catch (KurtException e) { + log.warn("Unable to find a RF Admin below Rf: " + this.getRepereBL().getSnecmaObject().getName(), e); + return EMPTY; + } + return EMPTY; + } + + @Override + public String getSuiviMontage() { + String response; + if (this.getRepere().isRFGeneric()) { + response = NON; + } else { + try { + if (this.getRepereBL().getSnecmaObject().isRFPartOrPartAssemb()) { + if ("RF Part Assemb Revision".equals(this.getRepereBL().getSnecmaObject().getType())) { + response = BOMLineHolderHelper.findRfAdminA(this.getRepereBL()).getSuiviMontage(); + } else { + response = BOMLineHolderHelper.findRfAdminAP(this.getRepereBL()).getSuiviMontage(); + } + } else { + response = EMPTY; + } + } catch (KurtException e) { + log.warn("Unable to find a RF Admin A/AP below Rf Part / RF Part Assemb: " + this.getRepereBL().getSnecmaObject().getName(), e); + return EMPTY; + } + } + return response; + } + + @Override + public String getIDComponent() { + return EMPTY; + } + + @Override + public String getIDRevisionComponent() { + return EMPTY; + } + + @Override + public String getTypeReference() { + return EMPTY; + } + + @Override + public String getNameReference() { + return EMPTY; + } + + @Override + public String getReferenceConceptor() { + return EMPTY; + } + + @Override + public String getReferenceTransposed() { + return EMPTY; + } + + @Override + public String getReferenceAssociated() { + return EMPTY; + } + + @Override + public String getResponsableConception() { + return EMPTY; + } + + @Override + public String getArticleGestion() { + return EMPTY; + } + + @Override + public String getClassement() { + return EMPTY; + } + + @Override + public String getSuiviUtilisation() { + return EMPTY; + } + + @Override + public String getSuiviDureeVie() { + return EMPTY; + } + + @Override + public String[] getSuppliersList() { + return new String[0]; + } + + @Override + public String getALT() { + return EMPTY; + } + + @Override + public String getSB() { + return EMPTY; + } + + @Override + public String getQuantiteCumulee() { + return EMPTY; + } + + @Override + public String getPanachage() { + return EMPTY; + } + + @Override + public String getQuantite() { + return EMPTY; + } + + @Override + public String getMaquetteInterneExterne() { + return EMPTY; + } + + @Override + public Double getMass() { + return null; + } + + @Override + public String getMassUnit() { + return EMPTY; + } + + @Override + public String getDesignationENG() { + return StringHelper.EMPTY; + } + +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/flattener/line/AbstractReceptorRepere.java b/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/flattener/line/AbstractReceptorRepere.java new file mode 100644 index 0000000..627d6fe --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/flattener/line/AbstractReceptorRepere.java @@ -0,0 +1,207 @@ +package com.capgemini.reports.bomlineholder.flattener.line; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.bomlineholder.BOMLineHolderHelper; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; + +import java.util.Map; + +/** + * Abstract class findAll the informations of receptor and repere. + * + * @param the type of result to be produced: a {@link Map}, a {@link String}... + * @param a Transformer object producing results of type T + */ +@Slf4j +@Getter +public abstract class AbstractReceptorRepere implements SnecmaLine { + + private static final String EMPTY = ""; + + private final BOMLineHolder objectTypeReceptor; + private final BOMLineHolder repereFonctionnel; + private final TcSession session; + + protected AbstractReceptorRepere(final TcSession session, final BOMLineHolder objectTypeReceptor, final BOMLineHolder repereFonctionnel) { + this.session = session; + this.objectTypeReceptor = objectTypeReceptor; + this.repereFonctionnel = repereFonctionnel; + } + + @Override + public String getIDReceptor() { + return objectTypeReceptor.getSnecmaObject().getItemId(); + } + + @Override + public String getNameReceptor() { + return objectTypeReceptor.getSnecmaObject().getName(); + } + + @Override + public String getRevisionReceptor() { + return objectTypeReceptor.getSnecmaObject().getRevisionId(); + } + + @Override + public String getRepereName() { + return repereFonctionnel.getSnecmaObject().getName(); + } + + @Override + public String getRepereRevision() { + return repereFonctionnel.getSnecmaObject().getRevisionId(); + } + + @Override + public String getResponsableRepere() { + try { + if (repereFonctionnel.getSnecmaObject().isRFGeneric()) { + return BOMLineHolderHelper.findRfAdmin(repereFonctionnel).getResponsableRepere(); + } else if (repereFonctionnel.getSnecmaObject().isRFPartOrPartAssemb()) { + if (SnecmaObjectTypes.RF_PART_ASSEMB_REVISION.equals(repereFonctionnel.getSnecmaObject().getType())) { + return BOMLineHolderHelper.findRfAdminA(repereFonctionnel).getResponsableRepere(); + } else { + return BOMLineHolderHelper.findRfAdmin(repereFonctionnel).getResponsableRepere(); + } + } + } catch (KurtException e) { + log.warn("Unable to find the correct RF Admins below Rf: " + repereFonctionnel.getSnecmaObject().getName(), e); + return EMPTY; + } + return EMPTY; + } + + @Override + public String getIDComponent() { + return EMPTY; + } + + @Override + public String getIDRevisionComponent() { + return EMPTY; + } + + @Override + public String getTypeReference() { + return EMPTY; + } + + @Override + public String getNameReference() { + return EMPTY; + } + + @Override + public String getReferenceConceptor() { + return EMPTY; + } + + @Override + public String getReferenceTransposed() { + return EMPTY; + } + + @Override + public String getReferenceAssociated() { + return EMPTY; + } + + @Override + public String getResponsableConception() { + return EMPTY; + } + + @Override + public String getArticleGestion() { + return EMPTY; + } + + @Override + public String getClassement() { + return EMPTY; + } + + @Override + public String getSuiviUtilisation() { + return EMPTY; + } + + @Override + public String getSuiviDureeVie() { + return EMPTY; + } + + @Override + public String[] getSuppliersList() { + return new String[0]; + } + + @Override + public String getALT() { + return EMPTY; + } + + @Override + public String getSB() { + return EMPTY; + } + + @Override + public String getQuantiteCumulee() { + return EMPTY; + } + + @Override + public String getPanachage() { + return EMPTY; + } + + @Override + public String getQuantite() { + return EMPTY; + } + + @Override + public String getSuiviMontage() { + return EMPTY; + } + + @Override + public Double getMass() { + return null; + } + + @Override + public String getMassUnit() { + return EMPTY; + } + + @Override + public String getMaquetteInterneExterne() { + try { + if (repereFonctionnel.getSnecmaObject().isRFGeneric()) { + return BOMLineHolderHelper.findRfAdmin(repereFonctionnel).getMaqIntExt(); + } else if (repereFonctionnel.getSnecmaObject().isRFPartOrPartAssemb()) { + if (SnecmaObjectTypes.RF_PART_ASSEMB_REVISION.equals(repereFonctionnel.getSnecmaObject().getType())) { + return EMPTY; + } else { + return BOMLineHolderHelper.findRfAdmin(repereFonctionnel).getMaqIntExt(); + } + } + } catch (KurtException e) { + log.warn("Unable to find the correct RF Admins below Rf: " + repereFonctionnel.getSnecmaObject().getName(), e); + return EMPTY; + } + return EMPTY; + } + + @Override + public String getDesignationENG() { + return EMPTY; + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/flattener/line/AbstractTopLine.java b/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/flattener/line/AbstractTopLine.java new file mode 100644 index 0000000..c7609e3 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/flattener/line/AbstractTopLine.java @@ -0,0 +1,223 @@ +package com.capgemini.reports.bomlineholder.flattener.line; + +import com.capgemini.framework.common.StringHelper; +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.snecmaobjects.ISnecmaObject; +import com.capgemini.reports.snecmaobjects.generic.AbstractGenericRevision; +import com.capgemini.reports.snecmaobjects.part.AbstractPart; +import com.capgemini.reports.snecmaobjects.product.ProductRevision; +import lombok.Getter; + +/** + * Represents a top object. As a top object, it does not have a fater Receptor. + * + * @param a Transformer object producing results of type T + * @param the result of a transformation by object of type U + */ +@Getter +public abstract class AbstractTopLine implements SnecmaLine { + + private final BOMLineHolder bomLine; + private final ISnecmaObject bomLineObject; + private final int lineNumber; + + /** + * Builds a top Line form its {@link BOMLineHolder}. + * + * @param topBomLine a top {@link BOMLineHolder} + * @param lineNum the line number in the bom + */ + public AbstractTopLine(final BOMLineHolder topBomLine, final int lineNum) { + this.bomLine = topBomLine; + this.bomLineObject = topBomLine.getSnecmaObject(); + this.lineNumber = lineNum; + } + + @Override + public int compareTo(final SnecmaLine other) { + return getLineId().compareTo(other.getLineId()); + } + + @Override + public String toString() { + return "TopLine(Bom=" + bomLine.getUid() + ", obj=" + bomLineObject.getItemId() + ")"; + } + + @Override + public String getLineId() { + return bomLineObject.getItemId(); + } + + @Override + public String getIDReceptor() { + return StringHelper.EMPTY; + } + + @Override + public String getNameReceptor() { + return StringHelper.EMPTY; + } + + @Override + public String getRevisionReceptor() { + return StringHelper.EMPTY; + } + + @Override + public String getRepereName() { + return StringHelper.EMPTY; + } + + @Override + public String getRepereRevision() { + return StringHelper.EMPTY; + } + + @Override + public String getResponsableRepere() { + return StringHelper.EMPTY; + } + + @Override + public String getSuiviMontage() { + return StringHelper.EMPTY; + } + + @Override + public String getIDComponent() { + return bomLineObject.getItemId(); + } + + @Override + public String getIDRevisionComponent() { + return bomLineObject.getRevisionId(); + } + + @Override + public String getTypeReference() { + String typeReference; + if (bomLineObject.isPart()) { + typeReference = PartTypeExtractorHelper.extractType(bomLineObject); + } else if (bomLineObject.isProduct()) { + typeReference = "Produit"; + } else if (bomLineObject.isGeneric()) { + String type = bomLineObject.getType(); + if (SnecmaObjectTypes.GENERIC_REVISION.equals(type)) { + typeReference = "Générique"; + } else if (SnecmaObjectTypes.GENERIC_ASSEMB_REVISION.equals(type)) { + typeReference = "Générique Montage"; + } else { + typeReference = StringHelper.EMPTY; + } + } else { + typeReference = StringHelper.EMPTY; + } + return typeReference; + } + + @Override + public String getNameReference() { + return bomLineObject.getName(); + } + + @Override + public String getReferenceConceptor() { + return StringHelper.EMPTY; + } + + @Override + public String getReferenceTransposed() { + return StringHelper.EMPTY; + } + + @Override + public String getReferenceAssociated() { + return StringHelper.EMPTY; + } + + @Override + public String getResponsableConception() { + return StringHelper.EMPTY; + } + + @Override + public String getArticleGestion() { + return StringHelper.EMPTY; + } + + @Override + public String getClassement() { + return StringHelper.EMPTY; + } + + @Override + public String getSuiviUtilisation() { + return StringHelper.EMPTY; + } + + @Override + public String getSuiviDureeVie() { + return StringHelper.EMPTY; + } + + @Override + public String[] getSuppliersList() { + return new String[0]; + } + + @Override + public String getALT() { + return bomLine.getBomAlt(); + } + + @Override + public String getSB() { + return bomLine.getBomSb(); + } + + @Override + public String getQuantiteCumulee() { + return bomLine.getBomQtyCumul(); + } + + @Override + public String getPanachage() { + return bomLine.getBomPanache(); + } + + @Override + public String getQuantite() { + return bomLine.getBomQty(); + } + + @Override + public String getMaquetteInterneExterne() { + return StringHelper.EMPTY; + } + + @Override + public Double getMass() { + return null; + } + + @Override + public String getMassUnit() { + return StringHelper.EMPTY; + } + + @Override + public String getDesignationENG() { + String designation; + if (bomLineObject.isPart()) { + designation = ((AbstractPart) bomLineObject).getDesignationEN(); + } else if (bomLineObject.isGeneric()) { + designation = ((AbstractGenericRevision) bomLineObject).getDesignationEN(); + } else if (bomLineObject.isProduct()) { + designation = ((ProductRevision) bomLineObject).getDesignationEN(); + } else { + designation = StringHelper.EMPTY; + } + return designation; + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/flattener/line/PartTypeExtractorHelper.java b/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/flattener/line/PartTypeExtractorHelper.java new file mode 100644 index 0000000..92646ec --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/flattener/line/PartTypeExtractorHelper.java @@ -0,0 +1,71 @@ +package com.capgemini.reports.bomlineholder.flattener.line; + +import com.capgemini.framework.common.LanguageHelper; +import com.capgemini.framework.common.StringHelper; +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.capgemini.reports.snecmaobjects.ISnecmaObject; +import com.capgemini.reports.snecmaobjects.part.*; +import lombok.extern.slf4j.Slf4j; + +/** + * Helps to extract the 'type' of a Part. + */ +@Slf4j +public final class PartTypeExtractorHelper { + + private static final String SLASH_SEPARATOR = " / "; + + private PartTypeExtractorHelper() { + // Nothing! + } + + /** + * Helps to extract the 'type' of a Part, sometimes by concatenating several fields.
    + * For instance, a Part Aero's type will be TypePartAero1, TypePartAero2, TypePartAero3 + * + * @param part a Part + * @return the type + */ + public static String extractType(final ISnecmaObject part) { + String thisType = part.getType(); + String returnContent; + if (SnecmaObjectTypes.ALTERNATE_REVISION.equals(thisType)) { + returnContent = extract((AlternateRevision) part); + } else if (SnecmaObjectTypes.DET_REVISION.equals(thisType)) { + returnContent = extract((DETRevision) part); + } else if (SnecmaObjectTypes.PART_AERO_REVISION.equals(thisType)) { + returnContent = extract((PartAeroRevision) part); + } else if (SnecmaObjectTypes.PART_NO_AERO_REVISION.equals(thisType)) { + returnContent = LanguageHelper.french(((PartNoAeroRevision) part).getTypeNoAero()); + } else if (SnecmaObjectTypes.PART_ASSEMB_REVISION.equals(thisType)) { + returnContent = extract((PartAssembRevision) part); + } else if (SnecmaObjectTypes.PART_MAT_REVISION.equals(thisType)) { + returnContent = "Matière"; + } else if (SnecmaObjectTypes.STANDARD_REVISION.equals(thisType)) { + returnContent = LanguageHelper.french(((StandardRevision) part).getTypeStandard()); + } else { + log.warn(StringHelper.concat("Could not extract Type from unsupported Part type: ", part.getItemId(), " of type ", thisType).toString()); + returnContent = ""; + } + return returnContent; + } + + private static String extract(final PartAssembRevision partAssemb) { + return StringHelper.implode(SLASH_SEPARATOR, LanguageHelper.french(partAssemb.getTypePartMontage1()), + LanguageHelper.french(partAssemb.getTypePartMontage2())); + } + + private static String extract(final PartAeroRevision partAero) { + return StringHelper.implode(SLASH_SEPARATOR, LanguageHelper.french(partAero.getTypeAero1()), LanguageHelper.french(partAero.getTypeAero2()), + LanguageHelper.french(partAero.getTypeAero3())); + } + + private static String extract(final DETRevision det) { + return StringHelper.implode(SLASH_SEPARATOR, LanguageHelper.french(det.getTypeDet1()), LanguageHelper.french(det.getTypeDet2())); + } + + private static String extract(final AlternateRevision alt) { + return StringHelper.implode(SLASH_SEPARATOR, LanguageHelper.french(alt.getTypeAlt1()), LanguageHelper.french(alt.getTypeAlt2())); + } + +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/flattener/line/SnecmaLine.java b/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/flattener/line/SnecmaLine.java new file mode 100644 index 0000000..c7c9e78 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/flattener/line/SnecmaLine.java @@ -0,0 +1,241 @@ +package com.capgemini.reports.bomlineholder.flattener.line; + +import java.util.Map; + +/** + * Represents a set of objects having a strong Bom relationship.
    + * This interface is able to produce a result of type T from each type of line available.
    + * This interface extends {@link Comparable}, and by default uses the {@link SnecmaLine#getLineId() getLineId} method return value to compare, so a comparison whith an other line is a comparison of their nomenclature path, or structure. + * + * @param the type of result to be produced: a {@link Map}, a {@link String}... + * @param a Transformer object producing results of type T + */ +public interface SnecmaLine extends Comparable> { + + /** + * An Identifier for the line. Not unique.
    + * Identifies a the structure of this block of objects, for example by appending all their identifiers.
    + * Having the same getLineId is not like being equals, since some lesser important fields may be ignored during identifier creation.
    + * + * @return the Identifier, as a {@link String} + */ + String getLineId(); + + /** + * A counter for the line number in the nomenclature.
    + * + * @return the line number + */ + int getLineNumber(); + + /** + * The main method: produces a T object based on this line's properties. + * + * @param transformer the Transformer object + * @return the output object + */ + T transform(final U transformer); + + /** + * Get the ID of the line's receptor. + * + * @return ID receptor + */ + String getIDReceptor(); + + /** + * Get the receptor's name. + * + * @return receptor's name + */ + String getNameReceptor(); + + /** + * Get the receptor revision. + * + * @return receptor's revision + */ + String getRevisionReceptor(); + + /** + * Get the id of functional marker. + * + * @return ID Receptor Functional Marker + */ + String getRepereName(); + + /** + * Get the revision of functional marker. + * + * @return revision functional marker + */ + String getRepereRevision(); + + /** + * Get the object in charge marker. + * + * @return object in charge marker + */ + String getResponsableRepere(); + + /** + * Get suivi montage of marker. + * + * @return suivi montage of marker + */ + String getSuiviMontage(); + + /** + * Get ID component. + * + * @return ID component + */ + String getIDComponent(); + + /** + * Get ID Revision Component. + * + * @return ID Revision Component + */ + String getIDRevisionComponent(); + + /** + * Get type reference of the component. + * + * @return type reference of the component + */ + String getTypeReference(); + + /** + * Get reference name of component. + * + * @return reference name + */ + String getNameReference(); + + /** + * Get reference name of component, in English. + * + * @return reference name in english + */ + String getDesignationENG(); + + /** + * Get the reference conceptor. + * + * @return reference conceptor + */ + String getReferenceConceptor(); + + /** + * Get the reference transposed. + * + * @return the reference transposed + */ + String getReferenceTransposed(); + + /** + * Get the reference associated. + * + * @return reference associated + */ + String getReferenceAssociated(); + + /** + * Get the object in charge conception. + * + * @return responsable conception + */ + String getResponsableConception(); + + /** + * Get management's article. + * + * @return management's article + */ + String getArticleGestion(); + + /** + * Get classification. + * + * @return classification + */ + String getClassement(); + + /** + * Get use's following. + * + * @return use's following + */ + String getSuiviUtilisation(); + + /** + * Get lifetime's following. + * + * @return lifetime's following + */ + String getSuiviDureeVie(); + + /** + * Get list of suppliers. + * + * @return list of suppliers + */ + String[] getSuppliersList(); + + /** + * Get ALT. + * + * @return ALT + */ + String getALT(); + + /** + * Gett SB. + * + * @return SB + */ + String getSB(); + + /** + * Get quantity cumulated. + * + * @return quantity cumulated + */ + String getQuantiteCumulee(); + + /** + * Get panachage. + * + * @return panachage + */ + String getPanachage(); + + /** + * Get quantity. + * + * @return quantity + */ + String getQuantite(); + + /** + * Get maquette. + * + * @return maquette + */ + String getMaquetteInterneExterne(); + + /** + * Get Mass. + * + * @return mass + */ + Double getMass(); + + /** + * Get Mass Unit. + * + * @return mass unit + */ + String getMassUnit(); +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/processor/AltOrDetBehaviour.java b/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/processor/AltOrDetBehaviour.java new file mode 100644 index 0000000..364c043 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/processor/AltOrDetBehaviour.java @@ -0,0 +1,48 @@ +package com.capgemini.reports.bomlineholder.processor; + +import com.capgemini.reports.snecmaobjects.part.AlternateRevision; +import com.capgemini.reports.snecmaobjects.part.DETRevision; + +import java.io.Serializable; +import java.util.List; +import java.util.Map; + +/** + * This interface presents method for specifying a visitor's behaviour regarding {@link AlternateRevision} and {@link DETRevision} parts.
    + * Produces a {@link List} of {@link Map}s with specified Key and Value types. + * + * @param the Keys Type + * @param the Values Type + */ +public interface AltOrDetBehaviour extends Serializable { + + /** + * Tells the Visitor if the parts in the pseudo-folder of the provided ALt or DET should be visited. + * + * @return true if parts in the pseudo-folder of the provided ALt or DET should be visited. + */ + boolean shouldVisitPartsInPseudoFolder(); + + /** + * Tells the Visitor if the parts below the provided ALt or DET (as part of the usual nomenclature relationship) should be visited. + * + * @return true if parts in below the provided ALt or DET should be visited. + */ + boolean shouldVisitPartsBelowAlt(); + + /** + * Formats the line representing objects that are in the pseudo folder. + * + * @param map the map to fill + */ + void treatPartsInPseudoFolder(final Map map); + + + /** + * Formats the line representing objects that are directyl below an Alt or a Det. + * + * @param receptorMap the map to fill + */ + void treatAlternateOrDETAsReceptor(final Map receptorMap); + +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/processor/DefaultAltOrDetBehaviour.java b/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/processor/DefaultAltOrDetBehaviour.java new file mode 100644 index 0000000..08d54d7 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/processor/DefaultAltOrDetBehaviour.java @@ -0,0 +1,127 @@ +package com.capgemini.reports.bomlineholder.processor; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.bomlineholder.BOMLineHolder.BOMLineHolderState; +import com.capgemini.reports.exceptions.NotSupportedException; +import com.capgemini.reports.releasestatus.DefaultRevisionSelector; +import com.capgemini.reports.releasestatus.RevisionSelector; +import com.capgemini.reports.snecmaobjects.AbstractSnecmaObject; +import com.capgemini.reports.snecmaobjects.ISnecmaObject; +import com.capgemini.reports.snecmaobjects.SnecmaObjectFactory; +import com.capgemini.reports.snecmaobjects.part.AbstractAltOrDetRevision; +import com.capgemini.reports.snecmaobjects.part.AbstractPart; +import com.capgemini.reports.snecmaobjects.part.AlternateRevision; +import com.capgemini.reports.snecmaobjects.part.DETRevision; +import com.teamcenter.soa.client.model.strong.Item; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import lombok.extern.slf4j.Slf4j; + +import java.util.*; + +/** + * This class does nothing specific with {@link AlternateRevision} or {@link DETRevision} parts.
    + * This class does provide some useful static methods like loading parts in pseudo folder, or obtaining the ItemRevision of an Alt or Det.
    + * Several methods should be overriden to do something useful on a as-needed basis, like: + *
      + *
    • {@link AltOrDetBehaviour#treatPartsInPseudoFolder(Map) fillRemainingFieldsOfPseudoFolder()}
    • + *
    • {@link AltOrDetBehaviour#treatAlternateOrDETAsReceptor(Map) treatAltOrDetReceptor()}
    • + *
    + * Can produce a {@link List} of {@link Map}s with specified Key and Value types. + * + * @param the Keys Type + * @param the Values Type + */ +@Slf4j +public class DefaultAltOrDetBehaviour implements AltOrDetBehaviour, IBOMLineHolderProcessor { + private static final long serialVersionUID = 9107530299095760608L; + + protected final transient TcSession session; + + private final RevisionSelector revisionSelector; + + /** + * Constructs a pseudo-folder loader. + * + * @param session an active {@link TcSession} + * @param date the limit date for revision's release date. + */ + public DefaultAltOrDetBehaviour(final TcSession session, final Calendar date) { + this.session = session; + this.revisionSelector = new DefaultRevisionSelector(date); + } + + @Override + public boolean shouldVisitPartsInPseudoFolder() { + return true; + } + + @Override + public boolean shouldVisitPartsBelowAlt() { + return true; + } + + @Override + public void treatPartsInPseudoFolder(final Map map) { + // Don't know what to do here, I'm just the default behaviour... maybe you want to override me and do something useful instead? + } + + @Override + public void treatAlternateOrDETAsReceptor(final Map receptorMap) { + // Don't know what to do here, I'm just the default behaviour... maybe you want to override me and do something useful instead? + } + + /** + * Processes the Pseudo-folder. Each {@link Item} in the pseudo-folder of the {@link BOMLineHolder} will load a corresponding {@link ItemRevision}.
    + * A purpose-built algorithm is provided for electing the 'correct' revision, which is then loaded in a {@link ISnecmaObject} back into the {@link BOMLineHolder} + * + * @param aBomLineHolder a {@link BOMLineHolder} to process + */ + @Override + public void process(final BOMLineHolder aBomLineHolder) { + ISnecmaObject snecmaObject = aBomLineHolder.getSnecmaObject(); + if (aBomLineHolder.getState() == BOMLineHolderState.PROCESSING && snecmaObject != null + && SnecmaObjectTypes.isAltOrDet(snecmaObject.getType())) { + + AbstractAltOrDetRevision altOrDetRevision = (AbstractAltOrDetRevision) snecmaObject; + // Select the revision of each Item + Map item2rev = selectAllRevisions(aBomLineHolder.getPseudoFolder()); + log.debug("Found a pseudo-Folder with {} parts in it. Found {} Revisions for them.", aBomLineHolder.getPseudoFolder().size(), + item2rev.size()); + + // Now build the Revision into a ISnecmaObject + altOrDetRevision.clearPseudoFolder(); + buildSnecmaObject(altOrDetRevision, item2rev.values()); + } + } + + protected Map selectAllRevisions(final List items) { + Map pseudoFolderRev = new HashMap<>(); + // This object has a pseudo-folder, let's find the correct revisions of its content + for (Item item : items) { + ItemRevision itemRev = revisionSelector.selectRevision(session, item).getItemRevision(); + pseudoFolderRev.put(item, itemRev); + } + return pseudoFolderRev; + } + + protected Map buildSnecmaObject(final AbstractAltOrDetRevision altOrDetRevision, + final Collection pseudoFolderRev) { + Map map = new HashMap<>(); + for (ItemRevision itemRev : pseudoFolderRev) { + try { + AbstractSnecmaObject objectInPF = SnecmaObjectFactory.build(session, itemRev); + if (objectInPF.isPart()) { + AbstractPart partInPF = (AbstractPart) objectInPF; + altOrDetRevision.addInPseudoFolder(partInPF); + map.put(itemRev, partInPF); + } + } catch (NotSupportedException e) { + log.error("Could not build one of ModelObjects from the Pseudo-folder of an Alt or Det", e); + } + } + return map; + } + +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/processor/IBOMLineHolderProcessor.java b/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/processor/IBOMLineHolderProcessor.java new file mode 100644 index 0000000..81dcebb --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/processor/IBOMLineHolderProcessor.java @@ -0,0 +1,20 @@ +package com.capgemini.reports.bomlineholder.processor; + +import com.capgemini.reports.bomlineholder.BOMLineHolder; + +import java.io.Serializable; + +/** + * Processes a {@link BOMLineHolder}, altering its content. + */ +public interface IBOMLineHolderProcessor extends Serializable { + + /** + * Unit element of work of the Processor.
    + * This method is called on each BomLineHolder if the {@link BOMLineHolder#process(IBOMLineHolderProcessor)} method is used on the Top BomLineHolder. + * + * @param aBomLineHolder + */ + void process(final BOMLineHolder aBomLineHolder); + +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/visitor/AbstractBOMLineHolderVisitor.java b/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/visitor/AbstractBOMLineHolderVisitor.java new file mode 100644 index 0000000..000a344 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/visitor/AbstractBOMLineHolderVisitor.java @@ -0,0 +1,597 @@ +package com.capgemini.reports.bomlineholder.visitor; + +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.bomlineholder.processor.AltOrDetBehaviour; +import com.capgemini.reports.releasestatus.EffectivityBehaviourHelper; +import com.capgemini.reports.snecmaobjects.ISnecmaObject; +import com.capgemini.reports.snecmaobjects.part.AbstractAltOrDetRevision; +import com.capgemini.reports.snecmaobjects.part.AlternateRevision; +import com.capgemini.reports.snecmaobjects.part.DETRevision; +import com.capgemini.reports.snecmaobjects.visitor.IComponentVisitor; +import com.capgemini.reports.snecmaobjects.visitor.IReceptorVisitor; +import lombok.EqualsAndHashCode; +import lombok.Getter; + +import java.util.*; + +/** + * Visit a {@link BOMLineHolder} tree.
    + * Produces a {@link List} of {@link Map}s with the provided Key and Value types.
    + * The behaviour of this generic visitor is specified by the constructor parameters. + * + * @param the Keys Type + * @param the Values Type + */ +@Getter +@EqualsAndHashCode +public abstract class AbstractBOMLineHolderVisitor implements IBOMLineHolderVisitor { + + private static final long serialVersionUID = 1362803093737028558L; + private static final String VISIT_BOM = "Visit {} Bom: {}"; + + // Sub-components that define the behaviour of this Visitor + protected final IReceptorVisitor> receptorVisitor; + protected final IComponentVisitor> componentVisitor; + /** + * This is the final list containing all entries. + */ + protected final List> theReportTable = new ArrayList<>(); + private final EffectivityBehaviourHelper effectivityBehaviour; + private final AltOrDetBehaviour altOrDetBehaviour; + private final boolean retrieveRepereReceptor; + private final boolean retrievePartNumberUnderRfGeneric; + private final boolean visitPartBelowPart; + + /** + * Constructor. + * + * @param receptorVisitor : specifies behaviour when visiting a Receptor {@link ISnecmaObject}. + * @param componentVisitor : specifies behaviour when visiting a Component {@link ISnecmaObject}. + * @param effectivityBehaviour : the behaviour regarding Effectivities + * @param altOrDetBehaviour : the behaviour regarding {@link AlternateRevision} or {@link DETRevision} parts. + * @param retrieveRepereReceptor boolean Take true if we retrieve the Repere Receptor properties. Else take false. + * @param retrievePartNumberUnderRfGeneric boolean Take true if we retrieve the Part number under the RF Generic. Take false else. + * @param visitPartBelowPart tells the Visitor weather it should visit a Part that is below another Part + */ + public AbstractBOMLineHolderVisitor(final IReceptorVisitor> receptorVisitor, final IComponentVisitor> componentVisitor, + final EffectivityBehaviourHelper effectivityBehaviour, final AltOrDetBehaviour altOrDetBehaviour, + final boolean retrieveRepereReceptor, final boolean retrievePartNumberUnderRfGeneric, final boolean visitPartBelowPart) { + this.receptorVisitor = receptorVisitor; + this.componentVisitor = componentVisitor; + this.effectivityBehaviour = effectivityBehaviour; + this.altOrDetBehaviour = altOrDetBehaviour; + this.retrieveRepereReceptor = retrieveRepereReceptor; + this.retrievePartNumberUnderRfGeneric = retrievePartNumberUnderRfGeneric; + this.visitPartBelowPart = visitPartBelowPart; + } + + /** + * Sort the children. + * + * @param bomHolder IBOMTree + */ + private static List sortBomChildren(final BOMLineHolder bomHolder) { + Collection childrenSet = bomHolder.getBomChilds(); + + // Convert array of elements to sort to a list + List sortedList = new ArrayList<>(childrenSet); + Collections.sort(sortedList, new Comparator() { + @Override + public int compare(final BOMLineHolder arg0, final BOMLineHolder arg1) { + ISnecmaObject snecmaObject0 = arg0.getSnecmaObject(); + String id0 = snecmaObject0 == null ? arg0.getKey() : snecmaObject0.getItemId(); + ISnecmaObject snecmaObject1 = arg1.getSnecmaObject(); + String id1 = snecmaObject1 == null ? arg1.getKey() : snecmaObject1.getItemId(); + return id0.compareTo(id1); + } + }); + return sortedList; + } + + /** + * Visit a Top BOMLineHolder and expand all the children to retrieve the properties. + */ + @Override + public List> visitTopReceptorBom(final BOMLineHolder aTopBomLine) { + // Create a Specific first line + visitSpecificFirstLine(aTopBomLine); + + // Analyze the type of the SnecmaObject and visit it in fonction of this type + analyzeAndVisitTopBom(aTopBomLine); + + return theReportTable; + } + + /** + * Visit a Top BOMLineHolder in fonction of his type. + * + * @param aTopBomLine BOMLineHolder + */ + private void analyzeAndVisitTopBom(final BOMLineHolder aTopBomLine) { + ISnecmaObject theSnecmaObject = aTopBomLine.getSnecmaObject(); + if (theSnecmaObject != null) { + if (theSnecmaObject.isGeneric() || theSnecmaObject.isProduct() || theSnecmaObject.isSuperModel()) { + visitGenericAsReceptor(aTopBomLine); + } + else if (theSnecmaObject.isPart()) { + visitPartAsReceptor(aTopBomLine, new HashMap()); + } + else if (theSnecmaObject.isRFPartOrPartAssemb()) { + visitRFBeforePart(aTopBomLine, new HashMap()); + } + else { + visitRFGenericAfterGenericReceptor(aTopBomLine, new HashMap()); + } + } + } + + /** + * Visit a Generic as a Receptor. + * + * @param aGenericReceptorBomLine BOMLineHolder + */ + private void visitGenericAsReceptor(final BOMLineHolder aGenericReceptorBomLine) { + Map theGenericReceptor = visitThisReceptor(aGenericReceptorBomLine); + + // Modify theGenericReceptor : Associate the generic with his RFGeneric + if (retrieveRepereReceptor) { + for (BOMLineHolder actualChildOfTopBom : sortBomChildren(aGenericReceptorBomLine)) { + if (actualChildOfTopBom.getSnecmaObject() == null) { + continue; + } + if (actualChildOfTopBom.getSnecmaObject().isRFGeneric()) { + visitRFGenericAfterGenericReceptor(actualChildOfTopBom, theGenericReceptor); + } + } + } + // Expand the children and use aGenericReceptorBomLine (Receptor + Repere properties) + for (BOMLineHolder actualChild : sortBomChildren(aGenericReceptorBomLine)) { + if (actualChild.getSnecmaObject() == null) { + continue; + } + if (actualChild.getSnecmaObject().isGeneric() || actualChild.getSnecmaObject().isSuperModel()) { + visitGenericAsComponent(actualChild, theGenericReceptor); + } + else if (actualChild.getSnecmaObject().isRFPartOrPartAssemb()) { + visitRFBeforePart(actualChild, theGenericReceptor); + } + else if (retrievePartNumberUnderRfGeneric && actualChild.getSnecmaObject().isRFGeneric()) { + visitRFGenericAndPartNumber(actualChild, theGenericReceptor); + } + else if (actualChild.getSnecmaObject().isSuperModel()){ + visitSuperModelAsComponent(actualChild, theGenericReceptor); + } + } + } + + /** + * Visit a Generic as a Component. + * + * @param aGenericComponentBomLine BOMLineHolder + * @param theGenericReceptor Map the map with the Generic Receptor and the RFGeneric Receptor properties + */ + private void visitGenericAsComponent(final BOMLineHolder aGenericComponentBomLine, final Map theGenericReceptor) { + // Retrieve the component properties + // May create an eventual receptor in specific reports + Map theGenericComponent = visitThisComponent(aGenericComponentBomLine); + + // Associate the generic with his RFGeneric + for (BOMLineHolder actualChildOfTopBom : sortBomChildren(aGenericComponentBomLine)) { + if (actualChildOfTopBom.getSnecmaObject() == null) { + continue; + } + if (actualChildOfTopBom.getSnecmaObject().isRFGeneric()) { + visitRFGenericAfterGenericComponent(actualChildOfTopBom, theGenericReceptor, theGenericComponent); + } + } + + // aGenericComponentBomLine may be a Receptor for his own children + if (!aGenericComponentBomLine.getBomChilds().isEmpty()) { + visitGenericAsReceptor(aGenericComponentBomLine); + } + } + + /** + * Visit a SuperModel as a Component. + * + * @param aSuperModelComponentBomLine BOMLineHolder + * @param theSuperModelReceptor Map the map with the SuperModel Receptor and the RFGeneric Receptor properties + */ + private void visitSuperModelAsComponent(final BOMLineHolder aSuperModelComponentBomLine, final Map theSuperModelReceptor) { + // Retrieve the component properties + // May create an eventual receptor in specific reports + Map theSuperModelComponent = visitThisComponent(aSuperModelComponentBomLine); + + // Associate the generic with his RFGeneric + for (BOMLineHolder actualChildOfTopBom : sortBomChildren(aSuperModelComponentBomLine)) { + if (actualChildOfTopBom.getSnecmaObject() == null) { + continue; + } + if (actualChildOfTopBom.getSnecmaObject().isRFGeneric()) { + visitRFGenericAfterGenericComponent(actualChildOfTopBom, theSuperModelReceptor, theSuperModelComponent); + } + } + + // aGenericComponentBomLine may be a Receptor for his own children + if (!aSuperModelComponentBomLine.getBomChilds().isEmpty()) { + visitGenericAsReceptor(aSuperModelComponentBomLine); + } + } + + + /** + * Visit a RFGeneric after a Generic Receptor (link Generic Receptor - RFGeneric Receptor). + * + * @param aRFGenericBomLine BOMLineHolder + * @param theGenericReceptor Map the map with the Generic Receptor properties + */ + private void visitRFGenericAfterGenericReceptor(final BOMLineHolder aRFGenericBomLine, final Map theGenericReceptor) { + mergeReceptorAndRepereReceptor(theGenericReceptor, getRFGenericForReceptor(aRFGenericBomLine)); + } + + /** + * Visit a RFGeneric after a Generic Component (link Generic Component - RFGeneric Component).
    + * A Generic Component is visited after a Generic Receptor and eventually a RFGeneric Receptor. + * + * @param aRFGenericBomLine BOMLineHolder + * @param theGenericReceptor Map the map with the Generic Receptor and RFGeneric Receptor properties + * @param theGenericComponent Map the map with the Generic Component properties + */ + private void visitRFGenericAfterGenericComponent(final BOMLineHolder aRFGenericBomLine, final Map theGenericReceptor, + final Map theGenericComponent) { + // Retrieve the Repere Component properties and merge it with the Component + mergeComponentAndRepereComponent(theGenericComponent, getRFGenericForComponent(aRFGenericBomLine)); + + // Add to report without modify the Receptor + addToReport(theGenericReceptor, theGenericComponent); + } + + /** + * Visit a RFGeneric and a Part number (Part Aero) (link Generic Receptor - RFGeneric - Part number Component).
    + * The RF Generic is before the Part number. + * + * @param aRFGenericBomLine BOMLineHolder + * @param theGenericReceptor Map the map with the Generic Receptor + */ + private void visitRFGenericAndPartNumber(final BOMLineHolder aRFGenericBomLine, final Map theGenericReceptor) { + Map theComponent = getRFGenericForComponent(aRFGenericBomLine); + for (BOMLineHolder actualChild : sortBomChildren(aRFGenericBomLine)) { + if (actualChild.getSnecmaObject() == null) { + continue; + } + if (actualChild.getSnecmaObject().isPart()) { + // Retrieve the Component properties and merge it with the Receptor properties + // Do not modify the Repere Component properties and the Receptor properties + mergeComponentAndRepereComponent(theComponent, visitThisComponent(actualChild)); + + // Add to the report without modify theReceptor + addToReport(theGenericReceptor, theComponent); + } + } + } + + /** + * Visit a RF (RFPart or RFPartAssemb only) before a Part Component (link RF Component - Part Component).
    + * The parameter should not be a RF Generic. + * + * @param aRFBomLine BOMLineHolder + * @param theReceptor Map the map with the Receptor and Repere properties.
    + * If the Receptor is a Generic : link GenericReceptor - RFGeneric Receptor.
    + * If the Receptor is a Part : link RF Receptor - Part Receptor. + */ + private void visitRFBeforePart(final BOMLineHolder aRFBomLine, final Map theReceptor) { + // Retrieve the Repere Component properties + Map theComponent = getTheRepereForComponent(aRFBomLine); + + // Prepare RF when the Part will become a Receptor + Map theFuturRepereReceptorForParts = new HashMap<>(); + if (retrieveRepereReceptor) { + theFuturRepereReceptorForParts = getTheRepereForReceptor(aRFBomLine); + } + + boolean doVisit = this.effectivityBehaviour.shouldVisit(aRFBomLine); + if (doVisit) { + for (BOMLineHolder actualChildOfRF : sortBomChildren(aRFBomLine)) { + if (actualChildOfRF.getSnecmaObject() == null) { + continue; + } + if (actualChildOfRF.getSnecmaObject().isPart()) { + visitPartAsComponent(actualChildOfRF, theReceptor, theComponent, theFuturRepereReceptorForParts); + } + } + } + } + + /** + * Visit a Part as Receptor (link RF Receptor - Part Receptor). + * + * @param aPartBomLine BOMLineHolder + * @param theRepereReceptor Map the map with the RF Receptor properties. + */ + private void visitPartAsReceptor(final BOMLineHolder aPartBomLine, final Map theRepereReceptor) { + // Retrieve the Part Receptor properties and do not modify it + Map thePartReceptor = visitThisReceptor(aPartBomLine); + String partType = aPartBomLine.getSnecmaObject().getType(); + if (SnecmaObjectTypes.isAltOrDet(partType)) { // Specific treatment of Alt or Det Receptor + altOrDetBehaviour.treatAlternateOrDETAsReceptor(thePartReceptor); + if (altOrDetBehaviour.shouldVisitPartsInPseudoFolder()) { + // Visit the pseudo-folder + visitPartsInPseudoFolder(aPartBomLine, thePartReceptor); + } + if (SnecmaObjectTypes.isAlt(partType)) { + visitPartReceptorChilds(aPartBomLine, theRepereReceptor, thePartReceptor, altOrDetBehaviour.shouldVisitPartsBelowAlt()); + } + } + else { + visitPartReceptorChilds(aPartBomLine, theRepereReceptor, thePartReceptor, visitPartBelowPart); + } + } + + private void visitPartReceptorChilds(final BOMLineHolder aPartBomLine, final Map theRepereReceptor, Map thePartReceptor, final boolean doVisitPartAsComponent) { + for (BOMLineHolder actualChildOfPart : sortBomChildren(aPartBomLine)) { + if (actualChildOfPart.getSnecmaObject() == null) { + continue; + } + // Handle Part children + if (actualChildOfPart.getSnecmaObject().isPart()) { + if (doVisitPartAsComponent) { + visitPartAsComponent(actualChildOfPart, thePartReceptor, receptorVisitor.emptyRf(), new HashMap()); + } + continue; + } + // Handle RF children + if (actualChildOfPart.getSnecmaObject().isRFPartOrPartAssemb()) { + // In order to mix Part Receptor and Repere Receptor without modify thePartReceptor + Map thePartReceptorWithRepereReceptor = new HashMap<>(); + thePartReceptorWithRepereReceptor.putAll(thePartReceptor); + mergeReceptorAndRepereReceptor(thePartReceptorWithRepereReceptor, theRepereReceptor); + + // To have the Repere Receptor properties + visitRFBeforePart(actualChildOfPart, thePartReceptorWithRepereReceptor); + } + } + } + + /** + * Visit a Part as Component (link RF Component - Part Component). + * + * @param aPartBomLine BOMLineHolder + * @param theReceptor Map the map with the Receptor and Repere properties.
    + * If the Receptor is a Generic : link GenericReceptor - RFGeneric Receptor.
    + * If the Receptor is a Part : link RF Receptor - Part Receptor. + * @param theRepereComponent Map the map with the RF Component properties + */ + private void visitPartAsComponent(final BOMLineHolder aPartBomLine, final Map theReceptor, final Map theRepereComponent, + final Map aFuturRepereReceptorForParts) { + // Visit this BomLineHolder, as a component + Map thePartComponent = visitThisComponent(aPartBomLine); + + // Retrieve the Component properties and merge it with the Receptor properties + // Do not modify the Repere Component properties and the Receptor properties + mergeComponentAndRepereComponent(thePartComponent, theRepereComponent); + + // Add to the report without modifying theReceptor + addToReport(theReceptor, thePartComponent); + + String fatherType = aPartBomLine.getSnecmaObject().getType(); + if (SnecmaObjectTypes.ALTERNATE_REVISION.equals(fatherType) || SnecmaObjectTypes.DET_REVISION.equals(fatherType)) { + if (altOrDetBehaviour.shouldVisitPartsBelowAlt()) { + visitPartAsReceptor(aPartBomLine, aFuturRepereReceptorForParts); + } + } + else { + // Continue the expansion for browsing Component children + visitPartAsReceptor(aPartBomLine, aFuturRepereReceptorForParts); + } + } + + /** + * Adds a line for each part in the pseudoFolder, including the provided receptor map in each line. + * + * @param fatherAltOrDetBomLine the Alt (or Det) whose pseudo-folder we must visit + */ + private void visitPartsInPseudoFolder(final BOMLineHolder fatherAltOrDetBomLine, final Map fatherAltOrDetAsReceptor) { + AbstractAltOrDetRevision iSnecmaObject = (AbstractAltOrDetRevision) fatherAltOrDetBomLine.getSnecmaObject(); + for (ISnecmaObject obj : iSnecmaObject.getPseudoFolder()) { + Map theLine = obj.accept(componentVisitor); + theLine.putAll(fatherAltOrDetAsReceptor); + altOrDetBehaviour.treatPartsInPseudoFolder(theLine); + theReportTable.add(theLine); + } + } + + /** + * Visit a BOMLineHolder's SnecmaObject using the {@link IReceptorVisitor}. + */ + protected abstract Map visitThisReceptor(final BOMLineHolder aBomLine); + + /** + * Visit a BOMLineHolder's SnecmaObject using the {@link IComponentVisitor}. + */ + protected abstract Map visitThisComponent(final BOMLineHolder aBomLine); + + /** + * Get the properties of a RFGeneric Receptor (link Generic Receptor - RFGeneric Receptor).
    + * Get the Admin properties on children in order to complete the RFGeneric properties. + * + * @param aRFGenericBomLine BOMLineHolder + * @return theRepere Map the RFGeneric Receptor properties + */ + private Map getRFGenericForReceptor(final BOMLineHolder aRFGenericBomLine) { + // Retrieve the Repere properties + Map theRepere = visitThisReceptor(aRFGenericBomLine); + + for (BOMLineHolder actualChildOfRF : sortBomChildren(aRFGenericBomLine)) { + // Sometimes the SnecmaObject in the BomLineholder may be null... + if (actualChildOfRF.getSnecmaObject() == null) { + continue; + } + + String childType = actualChildOfRF.getSnecmaObject().getType(); + // We are only concerned about the Admin children of this RF + if (!actualChildOfRF.getSnecmaObject().isAdmin()) { + continue; + } + + if (SnecmaObjectTypes.RF_ADMIN_REVISION.equals(childType) || SnecmaObjectTypes.RF_ADMIN_AG_REVISION.equals(childType)) { + mergeRepereReceptorandAdmin(theRepere, visitThisReceptor(actualChildOfRF)); + } + } + return theRepere; + } + + /** + * Get the properties of a RFGeneric Component (link Generic Component - RFGeneric Component).
    + * Get the Admin properties on children in order to complete the RFGeneric properties. + * + * @param aRFGenericBomLine BOMLineHolder + * @return theRepere Map the RFGeneric Component properties + */ + private Map getRFGenericForComponent(final BOMLineHolder aRFGenericBomLine) { + // Retrieve the Repere properties + Map theRepere = visitThisComponent(aRFGenericBomLine); + + for (BOMLineHolder actualChildOfRF : sortBomChildren(aRFGenericBomLine)) { + // Sometimes the SnecmaObject in the BomLineholder may be null... + if (actualChildOfRF.getSnecmaObject() == null) { + continue; + } + + String childType = actualChildOfRF.getSnecmaObject().getType(); + // We are only concerned about the Admin children of this RF + if (!actualChildOfRF.getSnecmaObject().isAdmin()) { + continue; + } + + if (SnecmaObjectTypes.RF_ADMIN_REVISION.equals(childType) || SnecmaObjectTypes.RF_ADMIN_AG_REVISION.equals(childType)) { + mergeRepereComponentandAdmin(theRepere, visitThisComponent(actualChildOfRF)); + } + } + return theRepere; + } + + /** + * Get the properties of a RF Receptor (except a RFGeneric) (link RF Receptor - Receptor).
    + * Get the Admin properties on children in order to complete the RF properties. + * + * @param aRFBomLine BOMLineHolder + * @return theRepere Map the RFGeneric Receptor properties + */ + private Map getTheRepereForReceptor(final BOMLineHolder aRFBomLine) { + // Retrieve the Repere properties + Map theRepere = visitThisReceptor(aRFBomLine); + + String parentRfType = aRFBomLine.getSnecmaObject().getType(); + for (BOMLineHolder actualChildOfRF : sortBomChildren(aRFBomLine)) { + // Sometimes the SnecmaObject in the BomLineholder may be null... + if (actualChildOfRF.getSnecmaObject() == null) { + continue; + } + + String childType = actualChildOfRF.getSnecmaObject().getType(); + // We are only concerned about the Admin children of this RF + if (!actualChildOfRF.getSnecmaObject().isAdmin()) { + continue; + } + + if (SnecmaObjectTypes.RF_PART_REVISION.equals(parentRfType)) { + if (SnecmaObjectTypes.RF_ADMIN_REVISION.equals(childType) || SnecmaObjectTypes.RF_ADMIN_AP_REVISION.equals(childType)) { + mergeRepereReceptorandAdmin(theRepere, visitThisReceptor(actualChildOfRF)); + } + } + else if (SnecmaObjectTypes.RF_PART_ASSEMB_REVISION.equals(parentRfType) + && SnecmaObjectTypes.RF_ADMIN_A_REVISION.equals(childType)) { + mergeRepereReceptorandAdmin(theRepere, visitThisReceptor(actualChildOfRF)); + } + } + return theRepere; + } + + /** + * Get the properties of a RF Component (except a RFGeneric) (link RF Component - Component).
    + * Get the Admin properties on children in order to complete the RF properties. + * + * @param aRFBomLine BOMLineHolder + * @return theRepere Map the RFGeneric Component properties + */ + private Map getTheRepereForComponent(final BOMLineHolder aRFBomLine) { + // Retrieve the Repere properties + Map theRepere = visitThisComponent(aRFBomLine); + + String parentRfType = aRFBomLine.getSnecmaObject().getType(); + for (BOMLineHolder actualChildOfRF : sortBomChildren(aRFBomLine)) { + // Sometimes the SnecmaObject in the BomLineholder may be null... + if (actualChildOfRF.getSnecmaObject() == null) { + continue; + } + + String childType = actualChildOfRF.getSnecmaObject().getType(); + // We are only concerned about the Admin children of this RF + if (!actualChildOfRF.getSnecmaObject().isAdmin()) { + continue; + } + + if (SnecmaObjectTypes.RF_PART_REVISION.equals(parentRfType)) { + if (SnecmaObjectTypes.RF_ADMIN_REVISION.equals(childType) || SnecmaObjectTypes.RF_ADMIN_AP_REVISION.equals(childType)) { + mergeRepereComponentandAdmin(theRepere, visitThisComponent(actualChildOfRF)); + } + } + else if (SnecmaObjectTypes.RF_PART_ASSEMB_REVISION.equals(parentRfType) + && SnecmaObjectTypes.RF_ADMIN_A_REVISION.equals(childType)) { + mergeRepereComponentandAdmin(theRepere, visitThisComponent(actualChildOfRF)); + } + } + return theRepere; + } + + /** + * Visit a specific first line if necessary for reports. + * + * @param bomHolder BOMLineHolder + */ + protected abstract void visitSpecificFirstLine(final BOMLineHolder bomHolder); + + /** + * Merge aReceptor and aRepereReceptor in aReceptor.
    + * Modify only aReceptor. + * + * @param aReceptor Map + * @param aRepereReceptor Map + */ + protected abstract void mergeReceptorAndRepereReceptor(final Map aReceptor, final Map aRepereReceptor); + + /** + * Merge aComponent and aRepereComponent and modify only aComponent.
    + * Modify only aComponent. + * + * @param aComponent Map + * @param aRepereComponent Map + */ + protected abstract void mergeComponentAndRepereComponent(final Map aComponent, final Map aRepereComponent); + + /** + * Merge aRepereReceptor and anAdmin and modify only aRepereReceptor. + * + * @param aRepereReceptor Map + * @param anAdmin Map + */ + protected abstract void mergeRepereReceptorandAdmin(final Map aRepereReceptor, final Map anAdmin); + + /** + * Merge aRepereComponent and anAdmin and modify only aRepereComponent. + * + * @param aRepereComponent Map + * @param anAdmin Map + */ + protected abstract void mergeRepereComponentandAdmin(final Map aRepereComponent, final Map anAdmin); + + /** + * Add aReceptor and aComponent to the R21 report.
    + * Do not modify aReceptor. + * + * @param aReceptor Map + */ + protected abstract void addToReport(final Map aReceptor, final Map aComponent); + +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/visitor/BomLineBrowser.java b/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/visitor/BomLineBrowser.java new file mode 100644 index 0000000..bae665d --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/visitor/BomLineBrowser.java @@ -0,0 +1,376 @@ +package com.capgemini.reports.bomlineholder.visitor; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.bomlineholder.BOMLineHolderHelper; +import com.capgemini.reports.bomlineholder.ISnecmaLineProcessor; +import com.capgemini.reports.bomlineholder.flattener.line.SnecmaLine; +import com.capgemini.reports.exceptions.InvalidInputException; +import com.capgemini.reports.exceptions.MalformedNomenclatureException; +import com.capgemini.reports.filter.AllIsGoodFilter; +import com.capgemini.reports.filter.IFilterExplosionNomenclature; +import com.capgemini.reports.releasestatus.EffectivityBehaviourHelper; +import com.capgemini.reports.snecmaobjects.ISnecmaObject; +import com.capgemini.reports.snecmaobjects.part.AbstractAltOrDetRevision; +import com.capgemini.reports.snecmaobjects.part.AbstractPart; +import com.capgemini.reports.snecmaobjects.part.AlternateRevision; +import com.capgemini.reports.snecmaobjects.part.DETRevision; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.Setter; + +import java.util.List; + +/** + * Browse a {@link BOMLineHolder} tree, and presents methods for dealing with a coherent set of objects having a strong relationship in the Bom, like Generic-RfGeneric-PartAero.
    + * The various abstract methods each expose such coherent sets of objects, and are called in the browsing order. + */ +@Getter +@Setter +public class BomLineBrowser { + + // Sub-components that define the behaviour of this Visitor + private final EffectivityBehaviourHelper effectivityBehaviour; + private final boolean doRetrievePartNumberUnderRfGeneric; + private final boolean doVisitPartBelowPart; + private final boolean doVisitPartsInPseudoFolder; + + /** + * This filter can remove whole parts of the bom Tree. + */ + @Setter + private IFilterExplosionNomenclature filterNomenclature; + + /** + * This {@link ISnecmaLineProcessor} is called sequentially on all the {@link SnecmaLine}s of a receptor, BEFORE recursing. + */ + @Setter(value = AccessLevel.PROTECTED) + private ISnecmaLineProcessor preProcessor; + + /** + * This {@link ISnecmaLineProcessor} is eventually called on all the {@link SnecmaLine}s of a receptor, through depth-first recursion. + */ + @Setter(value = AccessLevel.PROTECTED) + private ISnecmaLineProcessor processor; + + /** + * Constructor. + * + * @param effectivityBehaviour : the behaviour regarding Effectivities + * @param visitPartsInPseudoFolder : the behaviour regarding pseudofolders of {@link AlternateRevision} or {@link DETRevision} parts. + * @param retrievePartNumberUnderRfGeneric boolean Take true if we retrieve the Part number under the RF Generic. Take false else. + * @param visitPartBelowPart tells the Visitor weather it should visit a Part that is below another Part + */ + public BomLineBrowser(final EffectivityBehaviourHelper effectivityBehaviour, final boolean visitPartsInPseudoFolder, + final boolean retrievePartNumberUnderRfGeneric, final boolean visitPartBelowPart) { + this.effectivityBehaviour = effectivityBehaviour; + this.doVisitPartsInPseudoFolder = visitPartsInPseudoFolder; + this.doRetrievePartNumberUnderRfGeneric = retrievePartNumberUnderRfGeneric; + this.doVisitPartBelowPart = visitPartBelowPart; + this.processor = new PassiveProcessor(); + this.filterNomenclature = new AllIsGoodFilter(); + } + + private static BOMLineHolder extractRfGeneric(final BOMLineHolder aGeneric) throws MalformedNomenclatureException { + try { + return BOMLineHolderHelper.findRfGenericBL(aGeneric); + } catch (InvalidInputException e) { + throw new MalformedNomenclatureException("No RF Generic found below a null Generic", e); + } + } + + /** + * Visit a Top BOMLineHolder and expand all the children to retrieve the properties. + */ + public void visitTopReceptorBom(final TcSession session, final BOMLineHolder aTopBomLine) throws MalformedNomenclatureException { + ISnecmaObject theSnecmaObject = aTopBomLine.getSnecmaObject(); + if (theSnecmaObject != null) { + processor.visitTopBom(aTopBomLine); + if (theSnecmaObject.isProduct()) { + visitProductAsReceptor(session, aTopBomLine); + } else if (theSnecmaObject.isGeneric()) { + visitGenericAsReceptor(session, aTopBomLine); + } else if (theSnecmaObject.isPart()) { + visitPartAsReceptor(session, aTopBomLine); + } else { + throw new MalformedNomenclatureException("Unupported bom: topLine " + aTopBomLine.getSnecmaObject().getItemId() + + " is not a Generic, a Product, or a Part. It is a " + aTopBomLine.getSnecmaObject().getType()); + } + } else { + throw new MalformedNomenclatureException("Empty top BomLine"); + } + } + + private void visitPartAsReceptor(final TcSession session, final BOMLineHolder aPart) { + if (preProcessor != null) { + for (BOMLineHolder child : aPart.getBomChilds()) { + if (filterNomenclature.isExcluded(session, child)) { + continue; + } + if (doVisitPartBelowPart && child.getSnecmaObject().isPart()) { + preProcessor.visitPartPart(aPart, child); // Non-recursive + } + if (child.getSnecmaObject().isRFPartOrPartAssemb()) { + preProcessor.visitReceptorRepere(session, aPart, child); + visitRfPartNoRec(session, aPart, child); + } + } + if (SnecmaObjectTypes.isAltOrDet(aPart.getSnecmaObject().getType()) && doVisitPartsInPseudoFolder) { // Specific treatment of Alt or Det Receptor + List pseudoFolder1 = ((AbstractAltOrDetRevision) aPart.getSnecmaObject()).getPseudoFolder(); + for (AbstractPart child : pseudoFolder1) { + if (!filterNomenclature.isExcluded(child)) { + // Visit the pseudo-folder + preProcessor.visitPartsInPseudoFolder(aPart, child); + } + } + } + } + + // There may be other children, like some Parts, RF Parts + for (BOMLineHolder child : aPart.getBomChilds()) { + if (filterNomenclature.isExcluded(session, child)) { + continue; + } + if (doVisitPartBelowPart && child.getSnecmaObject().isPart()) { + processor.visitPartPart(aPart, child); + visitPartAsReceptor(session, child); // Recursive + } + if (child.getSnecmaObject().isRFPartOrPartAssemb()) { + visitRfPart(session, aPart, child); + } + } + if (SnecmaObjectTypes.isAltOrDet(aPart.getSnecmaObject().getType()) && doVisitPartsInPseudoFolder) { // Specific treatment of Alt or Det Receptor + List pseudoFolder1 = ((AbstractAltOrDetRevision) aPart.getSnecmaObject()).getPseudoFolder(); + for (AbstractPart child : pseudoFolder1) { + if (!filterNomenclature.isExcluded(child)) { + processor.visitPartsInPseudoFolder(aPart, child); + } + } + } + } + + private void visitRfPartNoRec(final TcSession session, final BOMLineHolder aPart, final BOMLineHolder rfPart) { + boolean doVisit = this.effectivityBehaviour.shouldVisit(rfPart); + if (doVisit) { + boolean partFound = false; + for (BOMLineHolder child : rfPart.getBomChilds()) { + if (child.getSnecmaObject().isPart()) { + partFound = true; + if (filterNomenclature.isExcluded(session, child)) { + continue; + } + if (child.getSnecmaObject().isPart()) { + preProcessor.visitPartAsComponent(aPart, rfPart, child); + } + } + } + if (!partFound) { + preProcessor.visitReceptorWithoutComponent(aPart, rfPart); + } + } + } + + private void visitRfPart(final TcSession session, final BOMLineHolder aPart, final BOMLineHolder rfPart) { + boolean doVisit = this.effectivityBehaviour.shouldVisit(rfPart); + if (doVisit) { + processor.visitReceptorRepere(session, aPart, rfPart); + boolean partFound = false; + for (BOMLineHolder child : rfPart.getBomChilds()) { + if (child.getSnecmaObject().isPart()) { + partFound = true; + if (filterNomenclature.isExcluded(session, child)) { + continue; + } + processor.visitPartAsComponent(aPart, rfPart, child); + visitPartAsReceptor(session, child); + } + } + if (!partFound) { + processor.visitReceptorWithoutComponent(aPart, rfPart); + } + } + } + + private void visitProductAsReceptor(final TcSession session, final BOMLineHolder productReceptors) throws MalformedNomenclatureException { + if (preProcessor != null) { + for (BOMLineHolder child : productReceptors.getBomChilds()) { + if (child.getSnecmaObject().isGeneric() && !filterNomenclature.isExcluded(session, child) + && !filterNomenclature.isExcluded(session, productReceptors)) { + BOMLineHolder rfGenericComponent = extractRfGeneric(child); + preProcessor.visitProductGeneric(productReceptors, child, rfGenericComponent); + preProcessor.visitReceptorRepere(session, productReceptors, rfGenericComponent); // Receptor appears bundled with its component's repere + } + } + } + + // Recursive processing + for (BOMLineHolder child : productReceptors.getBomChilds()) { + if (child.getSnecmaObject().isGeneric() && !filterNomenclature.isExcluded(session, child) && !filterNomenclature.isExcluded(session, productReceptors)) { + // According to the MDD, there is one and only one RF Generic below any Generic. + BOMLineHolder rfGenericComponent = extractRfGeneric(child); + processor.visitProductGeneric(productReceptors, child, rfGenericComponent); + processor.visitReceptorRepere(session, productReceptors, rfGenericComponent); + // Now the component becomes receptor + visitGenericAsReceptor(session, child); + } + } + + } + + private void visitGenericAsReceptor(final TcSession session, final BOMLineHolder genericReceptor) throws MalformedNomenclatureException { + BOMLineHolder rfGeneric = extractRfGeneric(genericReceptor); + if (preProcessor != null) { + // Pre-processing + if (doRetrievePartNumberUnderRfGeneric) { + // Go ahead and extract the generic / Rf Generic / Part + visitRfGeneric(session, genericReceptor, rfGeneric, preProcessor); + } + // There may be other children, like some RF parts + for (BOMLineHolder child : genericReceptor.getBomChilds()) { + if (filterNomenclature.isExcluded(session, child)) { + continue; + } + if (child.getSnecmaObject().isRFPartOrPartAssemb()) { + visitRfPartAsComponentNoRec(session, genericReceptor, rfGeneric, child); + } else if (child.getSnecmaObject().isGeneric()) { + visitGenericAsComponentNoRec(session, genericReceptor, rfGeneric, child); + } + } + } + + // Recursive treatment now + if (doRetrievePartNumberUnderRfGeneric) { + // Go ahead and extract the generic / Rf Generic / Part + visitRfGeneric(session, genericReceptor, rfGeneric, processor); + } + + // There may be other children, like some RF parts + for (BOMLineHolder child : genericReceptor.getBomChilds()) { + if (filterNomenclature.isExcluded(session, child)) { + continue; + } + if (child.getSnecmaObject().isRFPartOrPartAssemb()) { + visitRfPartAsComponentRec(session, genericReceptor, rfGeneric, child); + } else if (child.getSnecmaObject().isGeneric()) { + BOMLineHolder rfGenericComponent = extractRfGeneric(child); + if (!filterNomenclature.isExcluded(session, rfGenericComponent)) { + processor.visitQuad(genericReceptor, rfGeneric, child, rfGenericComponent); + processor.visitReceptorRepere(session, genericReceptor, rfGenericComponent); + visitGenericAsReceptor(session, child); + } + } + } + } + + private void visitGenericAsComponentNoRec(final TcSession session, final BOMLineHolder genericReceptor, final BOMLineHolder rfGenericReceptor, + final BOMLineHolder genericComponent) throws MalformedNomenclatureException { + // According to the MDD, there is one and only one RF Generic below any Generic. + BOMLineHolder rfGenericComponent = extractRfGeneric(genericComponent); + if (!filterNomenclature.isExcluded(session, rfGenericComponent)) { + preProcessor.visitReceptorRepere(session, genericReceptor, rfGenericComponent); + preProcessor.visitQuad(genericReceptor, rfGenericReceptor, genericComponent, rfGenericComponent); + } + } + + private void visitRfPartAsComponentNoRec(final TcSession session, final BOMLineHolder receptor, final BOMLineHolder rfReceptor, final BOMLineHolder rfPart) { + if (effectivityBehaviour.shouldVisit(rfPart)) { + boolean partFound = false; + preProcessor.visitReceptorRepere(session, receptor, rfPart); + for (BOMLineHolder child : rfPart.getBomChilds()) { + if (child.getSnecmaObject().isPart()) { + if (!filterNomenclature.isExcluded(session, child)) { + preProcessor.visitQuad(receptor, rfReceptor, child, rfPart); + } + partFound = true; + } + } + if (!partFound) { + preProcessor.visitReceptorWithoutComponent(receptor, rfPart); + } + } + } + + private void visitRfPartAsComponentRec(final TcSession session, final BOMLineHolder receptor, final BOMLineHolder rfReceptor, final BOMLineHolder rfPart) { + if (effectivityBehaviour.shouldVisit(rfPart)) { + // Recursivity + boolean partFound = false; + processor.visitReceptorRepere(session, receptor, rfPart); + for (BOMLineHolder child : rfPart.getBomChilds()) { + if (child.getSnecmaObject().isPart()) { + if (!filterNomenclature.isExcluded(session, child)) { + processor.visitQuad(receptor, rfReceptor, child, rfPart); + visitPartAsReceptor(session, child); + } + partFound = true; + } + } + if (!partFound) { + processor.visitReceptorWithoutComponent(receptor, rfPart); + } + } + } + + // RF Generics have a single PartAero below them. Also below , RF Admin(s) carry data about this RfGeneric + private void visitRfGeneric(final TcSession session, final BOMLineHolder genericReceptor, final BOMLineHolder rfGeneric, final ISnecmaLineProcessor proc) + throws MalformedNomenclatureException { + for (BOMLineHolder child : rfGeneric.getBomChilds()) { + if (child.getSnecmaObject().isPart() && !filterNomenclature.isExcluded(session, child)) { + proc.visitPartNumber(genericReceptor, rfGeneric, child); + return; + } + } + throw new MalformedNomenclatureException("No part aero found below RfGeneric"); + } + + private static class PassiveProcessor implements ISnecmaLineProcessor { + + @Override + public void visitTopBom(final BOMLineHolder aTopBom) { + // Nothing to do + } + + @Override + public void visitQuad(final BOMLineHolder receptor, final BOMLineHolder rfReceptor, final BOMLineHolder component, + final BOMLineHolder rfComponent) { + // Nothing to do + } + + @Override + public void visitProductGeneric(final BOMLineHolder productReceptor, final BOMLineHolder genericComponent, + final BOMLineHolder rfGenericComponent) { + // Nothing to do + } + + @Override + public void visitPartNumber(final BOMLineHolder genericReceptor, final BOMLineHolder rfGeneric, final BOMLineHolder child) { + // Nothing to do + } + + @Override + public void visitPartAsComponent(final BOMLineHolder part, final BOMLineHolder rfPart, final BOMLineHolder child) { + // Nothing to do + } + + @Override + public void visitPartPart(final BOMLineHolder fatherPart, final BOMLineHolder childPart) { + // Nothing to do + } + + @Override + public void visitPartsInPseudoFolder(final BOMLineHolder aPart, final AbstractPart child) { + // Nothing to do + } + + @Override + public void visitReceptorWithoutComponent(final BOMLineHolder part, final BOMLineHolder rfPart) { + // Nothing to do + } + + @Override + public void visitReceptorRepere(TcSession session, final BOMLineHolder anObject, final BOMLineHolder aRF) { + // Nothing to do + } + } + +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/visitor/IBOMLineHolderExtractor.java b/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/visitor/IBOMLineHolderExtractor.java new file mode 100644 index 0000000..65e225a --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/visitor/IBOMLineHolderExtractor.java @@ -0,0 +1,23 @@ +package com.capgemini.reports.bomlineholder.visitor; + +import com.capgemini.reports.bomlineholder.BOMLineHolder; + +import java.io.Serializable; + +/** + * Extractor of {@link BOMLineHolder} data. Can Extract objects to produce an output.
    + * Produces a custom T object. + * + * @param the output object Type + */ +public interface IBOMLineHolderExtractor extends Serializable { + + /** + * Visit the Top element of the Bom. + * + * @param aBomLineHolder + * @return the produced object (if any) + */ + T visitTopReceptorBom(final BOMLineHolder aBomLineHolder); + +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/visitor/IBOMLineHolderVisitor.java b/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/visitor/IBOMLineHolderVisitor.java new file mode 100644 index 0000000..e8075d1 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/bomlineholder/visitor/IBOMLineHolderVisitor.java @@ -0,0 +1,26 @@ +package com.capgemini.reports.bomlineholder.visitor; + +import com.capgemini.reports.bomlineholder.BOMLineHolder; + +import java.util.List; +import java.util.Map; + +/** + * Visitor of {@link BOMLineHolder}.
    + * Produces a {@link List} of {@link Map}s with specified Key and Value types. + * + * @param the Keys Type + * @param the Values Type + */ +public interface IBOMLineHolderVisitor extends IBOMLineHolderExtractor>> { + + /** + * Visitor which can used the BOMLineHolder properties to make a chosen report. + * + * @param aBomLineHolder BOMLineHolder + * @return ArrayList> + */ + @Override + List> visitTopReceptorBom(final BOMLineHolder aBomLineHolder); + +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/changeobjects/UnitRevision.java b/teamcenter/src/main/java/com/capgemini/reports/changeobjects/UnitRevision.java new file mode 100644 index 0000000..59be60d --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/changeobjects/UnitRevision.java @@ -0,0 +1,343 @@ +package com.capgemini.reports.changeobjects; + +import com.capgemini.framework.common.StringHelper; +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.object.pom.status.StatusEnum; +import com.capgemini.framework.teamcenter.object.pom.status.TcReleaseStatus; +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.capgemini.reports.changeobjects.change.TcChangeRequestRevision; +import com.capgemini.reports.documentationobjects.DocTechnic; +import com.capgemini.reports.snecmaobjects.generic.AbstractGeneric; +import com.capgemini.reports.snecmaobjects.generic.Generic; +import com.capgemini.reports.snecmaobjects.generic.GenericAssemb; +import com.capgemini.reports.snecmaobjects.product.ProductRevision; +import com.capgemini.reports.teamcenter.queries.saved.WorkflowOnUnitQuery; +import com.capgemini.reports.workflows.Task; +import com.teamcenter.soa.client.model.ModelObject; +import com.teamcenter.soa.client.model.strong.*; +import lombok.EqualsAndHashCode; +import lombok.extern.slf4j.Slf4j; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; + +import static com.capgemini.framework.teamcenter.object.SnecmaObjectProperties.*; +import static com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes.*; + +/** + * Class representing a Unit. + */ +@Slf4j +@EqualsAndHashCode +public class UnitRevision implements Serializable { + private static final long serialVersionUID = -1152481045274400434L; + + private static final String REGEX_DOCUMENT_DE_GEL_OR_FREEZE_DOCUMENT = "(.*\\bDocument de gel\\b.*)|(.*\\bFreeze document\\b.*)"; + private static final String TYPE_ITEM_REVISION = "ItemRevision"; + private static final String EMPTY_STRING = StringHelper.EMPTY; + + // Messages + private static final String MSG_NO_RELEASE_STATUS_FOUND = "No ReleaseStatus has been found on the unit revision {}"; + private static final String MSG_NO_GENERIC_FOUND = "No Generic has been found on the Unit revision {}"; + + private final TcSession session; + private final ItemRevision itemRevision; + + private UnitRevision(final TcSession session, final ItemRevision itemRevision) { + this.session = session; + this.itemRevision = itemRevision; + } + + + /** + * Build a UnitRevision.
    + */ + public static UnitRevision build(final TcSession session, final ItemRevision unitTc) { + return new UnitRevision(session, unitTc); + } + + /** + * Choose an appropriate revision of Unit in a list of units ({@link UnitRevision}) from a reference range.
    + * This list may be the list of built {@link UnitRevision} in a built {@link ProductRevision}.
    + * + * @param referenceRange String - the wanted range + * @param unitListinProduct List - the list of {@link UnitRevision} + * @param wantedStatus {@link StatusEnum} - all the wanted status + * @return the selected UnitRevision + */ + public static UnitRevision chooseRevisionOfUnitFromRange(final String referenceRange, final List unitListinProduct, + final StatusEnum... wantedStatus) { + // Obtain the list of all the UnitRevision with same range + List resultUnits = UnitRevision.getUnitRevisionWithSameRange(referenceRange, unitListinProduct); + if (resultUnits.size() == 1) { + return resultUnits.get(0); + } + + // Select A unit + return UnitRevision.getUnitRevisionFromStatusWithMostRecentReleaseDate(resultUnits, null, wantedStatus); + } + + /** + * Return all the {@link UnitRevision} with the same range as the reference parameter. + * + * @param referenceRange String - the reference range + * @param unitList List - the list of unit + * @return the list of UnitRevision with the same range + */ + private static List getUnitRevisionWithSameRange(final String referenceRange, final List unitList) { + List selectedUnits = new ArrayList<>(); + for (UnitRevision unitRev : unitList) { + if (referenceRange.equals(unitRev.getUnitRange())) { + selectedUnits.add(unitRev); + } + } + return selectedUnits; + } + + /** + * Return all the {@link ItemRevision} with the same range as the reference parameter. + * + * @param referenceRange String - the reference range + * @param unitList List - the list of unit + * @return the list of ItemRevision with the same range + */ + public static List getItemRevisionWithSameRange(final TcSession session, final String referenceRange, final List unitList) { + List selectedUnits = new ArrayList<>(); + for (ItemRevision unitRev : unitList) { + if (referenceRange.equals(getRangeOfItemRevision(session, unitRev))) { + selectedUnits.add(unitRev); + } + } + return selectedUnits; + } + + /** + * Get the range of a Unit ({@link ItemRevision}). + * + * @param unit {@link ItemRevision} - the entry unit + * @return unitRange String - the range of the unit. May be null. + */ + public static String getRangeOfItemRevision(final TcSession session, final ItemRevision unit) { + session.loadProperties(unit, "release_status_list"); + ReleaseStatus[] releaseStatuses = unit.get_release_status_list(); + session.loadProperties(releaseStatuses); + for (ReleaseStatus releaseStatus : releaseStatuses) { + if (SnecmaObjectTypes.EFFECTIVITY.equals(releaseStatus.get_name())) { + session.loadProperties(releaseStatus, "effectivities"); + ModelObject[] effectivities = releaseStatus.get_effectivities(); + session.loadProperties(effectivities); + if (effectivities.length == 0) { + log.error("ReleaseStatus named 'TcEffectivity' does not contain Effectivities..."); + } else { + ModelObject objectEffectivity = effectivities[0]; // There should only be one effectivity, we ignore the rest of the list's content + // Cast of the ModelObject to the TcEffectivity of Teamcenter, do not confuse with the TcEffectivity of this application + return ((Effectivity) objectEffectivity).get_unit_range_text(); + } + } + } + return null; + } + + /** + * Returns the {@link UnitRevision} whose {@link TcReleaseStatus} has the most recent release date, amongst the provided UnitRevision.
    + * + * @param unitRevisions the List of candidate {@link UnitRevision}s + * @param userDate the limit user date, only items released before that date will be examined + * @param wantedStatus {@link StatusEnum} - Enumeration of wanted status + * @return the most up-to-date UnitRevision + */ + private static UnitRevision getUnitRevisionFromStatusWithMostRecentReleaseDate(final List unitRevisions, final Calendar userDate, + final StatusEnum... wantedStatus) { + Calendar latestReleaseDate = null; + UnitRevision highestUnitRevision = null; + for (UnitRevision curUnitRevision : unitRevisions) { + // Get the TcReleaseStatus + List listReleaseStatus; + if (wantedStatus == null || wantedStatus.length == 0) { + listReleaseStatus = curUnitRevision.getReleaseStatusContainingMaturity(); + } else { + listReleaseStatus = TcReleaseStatus.filter(curUnitRevision.getReleaseStatusContainingMaturity(), wantedStatus); + } + + // Select the most recent + for (TcReleaseStatus status : listReleaseStatus) { + if (status != null) { + Calendar date = status.dateReleased(); + if (latestReleaseDate == null && safeBefore(userDate, date)) { + highestUnitRevision = curUnitRevision; + latestReleaseDate = date; + } else if (latestReleaseDate != null && latestReleaseDate.compareTo(date) < 0 && safeBefore(userDate, date)) { + highestUnitRevision = curUnitRevision; + latestReleaseDate = date; + } + } + } + } + return highestUnitRevision; + } + + private static boolean safeBefore(final Calendar userDate, final Calendar date) { + return userDate == null || date.before(userDate); + } + + public String getUid() { + return itemRevision.getUid(); + } + + public String getItemId() { + return itemRevision.get_item_id(); + } + + public String getRevision() { + return itemRevision.get_item_revision_id(); + } + + public String getName() { + return itemRevision.get_object_name(); + } + + public String getType() { + return itemRevision.getTypeObject().getName(); + } + + public boolean isExceptionnel() { + String unitExceptionnel = getMasterFormRev().getPropertyObject(PV_UNIT_EXCEPTIONNEL).getStringValue(); + return "Oui / Yes".equalsIgnoreCase(unitExceptionnel); + } + + public DocTechnic getTechnicalDocGel() { + session.loadProperties(itemRevision, PV_DELIVERABLES); + ModelObject[] documents = itemRevision.getPropertyObject(PV_DELIVERABLES).getModelObjectArrayValue(); + session.loadProperties(documents); + Calendar latestMod = null; + DocTechnic technicalDocGel = null; + for (ModelObject currentDoc : documents) { + ItemRevision docAsItemRev = (ItemRevision) currentDoc; + if (DOC_TECHNIC_REVISION.equals(docAsItemRev.getTypeObject().getName())) { + DocTechnic technicalDoc = new DocTechnic(session, docAsItemRev); + if (technicalDoc.getTypeDocTechnic1().matches(REGEX_DOCUMENT_DE_GEL_OR_FREEZE_DOCUMENT)) { + Calendar modDate = docAsItemRev.get_last_mod_date(); + if (latestMod == null || modDate.after(latestMod)) { + latestMod = modDate; + technicalDocGel = technicalDoc; + } + } + } + } + return technicalDocGel; + } + + private Form getMasterFormRev() { + Form masterTag = itemRevision.get_item_master_tag(); + session.loadProperties(masterTag); + return masterTag; + } + + /** + * Returns the Unit Range of a built UnitRevision.
    + * Obtained from the TcReleaseStatus named "TcEffectivity", who owns a (single) TcEffectivity, who owns the requested range. + * + * @return the unit Range + */ + public String getUnitRange() { + TcReleaseStatus tcReleaseStatuses = getReleaseStatusContaininEffectivity(); + if (tcReleaseStatuses == null || tcReleaseStatuses.getEffectivity() == null) { + return EMPTY_STRING; + } else { + return tcReleaseStatuses.getEffectivity().unitRange(); + } + } + + + public List getReleaseStatusContainingMaturity() { + List tcReleaseStatuses = new ArrayList<>(); + session.loadProperties(itemRevision, "release_status_list"); + ReleaseStatus[] releaseStatuses = itemRevision.get_release_status_list(); + session.loadProperties(releaseStatuses); + if (releaseStatuses.length == 0) { + log.debug(MSG_NO_RELEASE_STATUS_FOUND, itemRevision.get_item_id()); + } else { + for (ReleaseStatus status : releaseStatuses) { + TcReleaseStatus statusSnecma = new TcReleaseStatus(session, status); + if (!statusSnecma.isEffectivity()) { + tcReleaseStatuses.add(statusSnecma); + } + } + } + return tcReleaseStatuses; + } + + public TcReleaseStatus getReleaseStatusContaininEffectivity() { + session.loadProperties(itemRevision, "release_status_list"); + ReleaseStatus[] releaseStatuses = itemRevision.get_release_status_list(); + session.loadProperties(releaseStatuses); + if (releaseStatuses.length == 0) { + log.debug(MSG_NO_RELEASE_STATUS_FOUND, itemRevision.get_item_id()); + } else { + for (ReleaseStatus status : releaseStatuses) { + TcReleaseStatus statusSnecma = new TcReleaseStatus(session, status); + if (statusSnecma.isEffectivity()) { + return statusSnecma; + } + } + } + return null; + } + + + public List getGenerics() { + List tcGenerics = new ArrayList<>(); + session.loadProperties(itemRevision, PV_GENERIC); + ModelObject[] generics = itemRevision.getPropertyObject(PV_GENERIC).getModelObjectArrayValue(); + session.loadProperties(generics); + if (generics.length == 0) { + log.debug(MSG_NO_GENERIC_FOUND, itemRevision.get_item_id()); + } else { + for (ModelObject generic : generics) { + String objectType = generic.getTypeObject().getName(); + if (GENERIC.equals(objectType)) { + tcGenerics.add(new Generic(session, (Item) generic)); + } else if (GENERIC_ASSEMB.equals(objectType)) { + tcGenerics.add(new GenericAssemb(session, (Item) generic)); + } else { + log.warn("Obtained an objectType in the pseudofolder Generic of a Unit, which is not a Generic or Generic Assemb"); + } + } + } + + return tcGenerics; + } + + public List getChangeRequestsList() { + List changeRequestRevs = new ArrayList<>(); + session.loadProperties(itemRevision, PV_CHANGE_LIST); + ModelObject[] changes = itemRevision.getPropertyObject(PV_CHANGE_LIST).getModelObjectArrayValue(); + session.loadProperties(changes); + for (ModelObject currentChange : changes) { + ItemRevision changeAsItemRev = (ItemRevision) currentChange; + String changeType = changeAsItemRev.getTypeObject().getName(); + if (changeType != null && changeType.contains("PV4")) { // Filter the changes: we only want the new types of objects, whose names begin with 'PV4' + changeRequestRevs.add(new TcChangeRequestRevision(session, changeAsItemRev)); + } + } + + return changeRequestRevs; + } + + + public List getWorkflowsValidationUnitParSO() { + List tasks = new ArrayList<>(); + List result = WorkflowOnUnitQuery.searchValidationUnitParSO(session, getItemId()).findAll(); + for (EPMTask process : result) { + tasks.add(new Task(session, process)); + } + return tasks; + } + + @Override + public String toString() { + return getType() + " with ID= " + getItemId() + " REV= " + getRevision() + " RANGE= " + getUnitRange(); + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/changeobjects/change/AbstractChangeObject.java b/teamcenter/src/main/java/com/capgemini/reports/changeobjects/change/AbstractChangeObject.java new file mode 100644 index 0000000..fbba810 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/changeobjects/change/AbstractChangeObject.java @@ -0,0 +1,195 @@ +package com.capgemini.reports.changeobjects.change; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.object.pom.status.TcReleaseStatus; +import com.capgemini.reports.exceptions.NotSupportedException; +import com.capgemini.reports.snecmaobjects.SnecmaObjectFactory; +import com.capgemini.reports.snecmaobjects.generic.AbstractGeneric; +import com.capgemini.reports.teamcenter.queries.saved.WorkflowOnChangeQuery; +import com.capgemini.reports.users.SnecmaUser; +import com.capgemini.reports.workflows.Task; +import com.google.common.base.Joiner; +import com.teamcenter.soa.client.model.ModelObject; +import com.teamcenter.soa.client.model.strong.*; +import lombok.extern.slf4j.Slf4j; + +import java.io.Serializable; +import java.util.*; + +import static com.capgemini.framework.teamcenter.TeamcenterObjectProperties.ITEM_ID; +import static com.capgemini.framework.teamcenter.TeamcenterObjectProperties.PROP_LIGNE_PRODUIT; +import static com.capgemini.framework.teamcenter.object.SnecmaObjectProperties.CM_HAS_SOLUTION_ITEM; +import static com.capgemini.framework.teamcenter.object.SnecmaObjectProperties.OBJECT_TYPE; +import static com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes.*; + +/** + * Abstract class representing a ChangeObject. + */ +@Slf4j +public abstract class AbstractChangeObject implements Serializable { + private static final long serialVersionUID = -133060583639527983L; + + protected final TcSession session; + protected final ItemRevision itemRevision; + protected SnecmaUser user; + + protected AbstractChangeObject(final TcSession session, final ItemRevision itemRevision) { + this.session = session; + this.itemRevision = itemRevision; + } + + private static Item obtainItem(final TcSession session, final ModelObject currentObject) throws NotSupportedException { + Item item; + if (currentObject instanceof Item) { + // Normal behavior: master in the pseudo-folder + item = (Item) currentObject; + } else if (currentObject instanceof ItemRevision) { + // There might still be ItemRevisions here! We must try to findAll their Item, and pursue + ItemRevision tempRev = (ItemRevision) currentObject; + session.loadProperties(tempRev, "items_tag"); + item = tempRev.get_items_tag(); + session.loadProperties(item); + } else { + throw new NotSupportedException("Found a {} (with UID = {}) in the pseudo-folder. Not supported object, skipping..."); + } + return item; + + } + + public String getItemId() { + return itemRevision.get_item_id(); + } + + public String getRevisionId() { + return itemRevision.get_item_revision_id(); + } + + public int getSequenceId() { + return itemRevision.get_sequence_id(); + } + + public String getChangeName() { + return itemRevision.get_object_name(); + } + + public Calendar getDateCreation() { + return itemRevision.get_creation_date(); + } + + public String getChangeType() { + return itemRevision.getTypeObject().getName(); + } + + public SnecmaUser getUser() { + session.loadProperties(itemRevision, "owning_user"); + User owningUser = (User) itemRevision.get_owning_user(); + session.loadProperties(owningUser); + return new SnecmaUser(session, owningUser); + } + + public List getLignesProduit() { + List lineList = new ArrayList<>(); + Collections.addAll(lineList, itemRevision.getPropertyObject(PROP_LIGNE_PRODUIT).getStringArrayValue()); + return lineList; + } + + public List getReleaseStatusContainingEffectivity() { + List releaseStatusContainingEffectivity = new ArrayList<>(); + session.loadProperties(itemRevision, "release_status_list"); + ReleaseStatus[] releaseStatuses = itemRevision.get_release_status_list(); + session.loadProperties(releaseStatuses); + for (ReleaseStatus status : releaseStatuses) { + TcReleaseStatus statusSnecma = new TcReleaseStatus(session, status); + if (statusSnecma.isEffectivity()) { + releaseStatusContainingEffectivity.add(statusSnecma); + } + } + return releaseStatusContainingEffectivity; + } + + + public List getReleaseStatusContainingMaturity() { + List releaseStatusContainingMaturity = new ArrayList<>(); + session.loadProperties(itemRevision, "release_status_list"); + ReleaseStatus[] releaseStatuses = itemRevision.get_release_status_list(); + session.loadProperties(releaseStatuses); + for (ReleaseStatus status : releaseStatuses) { + TcReleaseStatus statusSnecma = new TcReleaseStatus(session, status); + if (statusSnecma.isChangeMaturity()) { + releaseStatusContainingMaturity.add(statusSnecma); + } + } + return releaseStatusContainingMaturity; + } + + /** + * Set the list of all Workflows associated to this change. + */ + public List getWkfList() { + List result = new WorkflowOnChangeQuery(session).searchIDAndRevision(this.getItemId(), this.getRevisionId()).searchSequenceId(String.valueOf(getSequenceId())).findAll(); + List taskList = new ArrayList<>(); + for (EPMTask task : result) { + taskList.add(new Task(session, task)); + } + return taskList; + } + + /** + * Get the list of the generic 'with/without rupture of interchangeabiliy' from an ItemRevision representing a ChangeNotice/Request. + */ + AbstractGeneric loadGeneric(final ModelObject genericObject) throws NotSupportedException { + return SnecmaObjectFactory.build(session, obtainItem(session, genericObject)); + } + + @Override + public String toString() { + return this.getChangeType() + " " + this.getItemId() + "/" + this.getRevisionId(); + } + + /** + * Method to get Parts from CR/CN or FPP inside the apres pseudo folder + * If input param is not null it gets the apres pseudo folder of this ModelObject (case of a FPP) + * If it is null it gets the apres pseudo folder of itemRevision attribute of the current instance (Case of CR/CN) + * + * @param object, ModelObject where the apres pseudo folder is + * @return Set + */ + public Set getPartsFromApresPseudoFolder(ModelObject object) { + List apresPseudoFolderContent; + + // sous modification pseudo folder for fpp + if (object != null) { + session.loadProperties(object, CM_HAS_SOLUTION_ITEM); + apresPseudoFolderContent = object.getPropertyObject(CM_HAS_SOLUTION_ITEM).getModelObjectListValue(); + } else { + // for cr/cn + session.loadProperties(itemRevision, CM_HAS_SOLUTION_ITEM); + apresPseudoFolderContent = itemRevision.getPropertyObject(CM_HAS_SOLUTION_ITEM).getModelObjectListValue(); + } + Set result = new HashSet<>(); + for (ModelObject part : apresPseudoFolderContent) { + // get parts type + session.loadProperties(part, OBJECT_TYPE, ITEM_ID); + String part_type = part.getPropertyObject(OBJECT_TYPE).getStringValue(); + if (PART_AERO_REVISION.equals(part_type) || PART_NO_AERO_REVISION.equals(part_type) || STANDARD_REVISION.equals(part_type) || DET_REVISION.equals(part_type) || PART_MAT_REVISION.equals(part_type) || ALTERNATE_REVISION.equals(part_type) || PART_ASSEMB_REVISION.equals(part_type)) { + result.add(part); + } + } + return result; + } + + /** + * Return a String with all itemsID of the modelObjects in the set separated by ; + * + * @param set + * @return String + */ + public static String getItemIdFromModelObjectSetToString(Set set) { + Set result = new HashSet<>(); + for (ModelObject model : set) { + result.add(model.getPropertyObject(ITEM_ID).getStringValue()); + } + return Joiner.on(";").join(result); + } + +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/changeobjects/change/FPPRevision.java b/teamcenter/src/main/java/com/capgemini/reports/changeobjects/change/FPPRevision.java new file mode 100644 index 0000000..e955e33 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/changeobjects/change/FPPRevision.java @@ -0,0 +1,41 @@ +package com.capgemini.reports.changeobjects.change; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.teamcenter.soa.client.model.ModelObject; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import static com.capgemini.framework.teamcenter.object.SnecmaObjectProperties.*; + +/** + * Class representing a TC FPP Revision. + */ +public class FPPRevision extends AbstractChangeObject { + private static final long serialVersionUID = 2601916478580482L; + + public FPPRevision(final TcSession session, final ItemRevision itemRevision) { + super(session, itemRevision); + } + + public String getOrigineDemande() { + return itemRevision.getPropertyObject(PV_ORIGINE_DEMANDE).getStringValue(); + } + + /** + * Method to get Parts inside the apres pseudo folder inside each mod of the sous-modifications pseudo folder + * + * @return List + */ + public Set getPartsOfSubModifications() { + Set result = new HashSet<>(); + session.loadProperties(itemRevision, CM_IMPLEMENTED_BY); + List sousModificationsPseudoFolderContent = itemRevision.getPropertyObject(CM_IMPLEMENTED_BY).getModelObjectListValue(); + for (ModelObject mod : sousModificationsPseudoFolderContent) { + result.addAll(getPartsFromApresPseudoFolder(mod)); + } + return result; + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/changeobjects/change/TcChangeNoticeRevision.java b/teamcenter/src/main/java/com/capgemini/reports/changeobjects/change/TcChangeNoticeRevision.java new file mode 100644 index 0000000..aedba88 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/changeobjects/change/TcChangeNoticeRevision.java @@ -0,0 +1,121 @@ +package com.capgemini.reports.changeobjects.change; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.capgemini.reports.exceptions.NotSupportedException; +import com.capgemini.reports.snecmaobjects.generic.AbstractGeneric; +import com.capgemini.reports.teamcenter.queries.saved.WorkflowOnChangeQuery; +import com.capgemini.reports.workflows.Task; +import com.teamcenter.soa.client.model.ModelObject; +import com.teamcenter.soa.client.model.strong.EPMTask; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Pattern; + +import static com.capgemini.framework.teamcenter.TeamcenterObjectTypes.CHANGE_REQUEST_REVISION; +import static com.capgemini.framework.teamcenter.object.SnecmaObjectProperties.*; + +/** + * Class representing a modification of a Unit. + */ +@Slf4j +public class TcChangeNoticeRevision extends AbstractChangeObject { + private static final long serialVersionUID = -8781834231342513659L; + + private static final Pattern ETUDE_STUDY = Pattern.compile(".*(Etude|Study).*"); + + public TcChangeNoticeRevision(final TcSession session, final ItemRevision itemRevision) { + super(session, itemRevision); + } + + public String getTypeModification() { + return itemRevision.getPropertyObject(PV4_TYPE_MODIFICATION).getDisplayableValue(); + } + + @Override + public List getWkfList() { + List tasks = new ArrayList<>(); + for (EPMTask epmTask : new WorkflowOnChangeQuery(session).searchIDAndRevision(getItemId(), getRevisionId()).searchSequenceId(String.valueOf(getSequenceId())).findAll()) { + if (!Task.TaskState.COMPLETED.equals(Task.TaskState.findState(epmTask.get_state()))) { + tasks.add(new Task(session, epmTask)); + } + } + return tasks; + } + + /** + * Returns true if this generic's type is {@code Etude / Study}. + * + * @return true or false + */ + public boolean isEtude() { + return ETUDE_STUDY.matcher(getTypeModification()).matches(); + } + + public List getImplementsCR() { + List implementsCR = new ArrayList<>(); + session.loadProperties(itemRevision, CM_IMPLEMENTS); + ModelObject[] changes = itemRevision.getPropertyObject(CM_IMPLEMENTS).getModelObjectArrayValue(); + session.loadProperties(changes); + for (ModelObject change : changes) { + if (!SnecmaObjectTypes.isRecursively(CHANGE_REQUEST_REVISION, change.getTypeObject())) { + log.warn("Found a {} object in the '{}' pseudo-folder of ChangeNotice {}, expecting only ChangeRequests. Skipping...", + change.getTypeObject().getName(), CM_IMPLEMENTS, getItemId()); + continue; + } + + implementsCR.add(new TcChangeRequestRevision(session, (ItemRevision) change)); + } + return implementsCR; + } + + public List getListOfGenericRevWithOrWithoutRupture() { + List generics = new ArrayList<>(); + List genericsObjects = new ArrayList<>(); + session.loadProperties(itemRevision, PV_IMP_GENERICS_WITH_INTER, PV_IMP_GENERICS_WITHOUT_INTER); + genericsObjects.addAll(itemRevision.getPropertyObject(PV_IMP_GENERICS_WITH_INTER).getModelObjectListValue()); + genericsObjects.addAll(itemRevision.getPropertyObject(PV_IMP_GENERICS_WITHOUT_INTER).getModelObjectListValue()); + session.loadProperties(genericsObjects.toArray(new ModelObject[genericsObjects.size()])); + for (ModelObject genericsObject : genericsObjects) { + try { + generics.add(loadGeneric(genericsObject)); + } catch (NotSupportedException e) { + log.warn("Unsupported object {} found in pseudo-folder {} or {}", genericsObject.getUid(), PV_IMP_GENERICS_WITH_INTER, PV_IMP_GENERICS_WITHOUT_INTER); + } + } + return generics; + } + + public List getListOfGenericRevWithRupture() { + List generics = new ArrayList<>(); + session.loadProperties(itemRevision, PV_IMP_GENERICS_WITH_INTER); + ModelObject[] genericsObjects = itemRevision.getPropertyObject(PV_IMP_GENERICS_WITH_INTER).getModelObjectArrayValue(); + session.loadProperties(genericsObjects); + for (ModelObject genericsObject : genericsObjects) { + try { + generics.add(loadGeneric(genericsObject)); + } catch (NotSupportedException e) { + log.warn("Unsupported object {} found in pseudo-folder {} or {}", genericsObject.getUid(), PV_IMP_GENERICS_WITH_INTER, PV_IMP_GENERICS_WITHOUT_INTER); + } + } + return generics; + } + + public List getListOfGenericRevWithoutRupture() { + List generics = new ArrayList<>(); + session.loadProperties(itemRevision, PV_IMP_GENERICS_WITHOUT_INTER); + ModelObject[] genericsObjects = itemRevision.getPropertyObject(PV_IMP_GENERICS_WITHOUT_INTER).getModelObjectArrayValue(); + session.loadProperties(genericsObjects); + for (ModelObject genericsObject : genericsObjects) { + try { + generics.add(loadGeneric(genericsObject)); + } catch (NotSupportedException e) { + log.warn("Unsupported object {} found in pseudo-folder {}", genericsObject.getUid(), PV_IMP_GENERICS_WITHOUT_INTER); + } + } + return generics; + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/changeobjects/change/TcChangeRequestRevision.java b/teamcenter/src/main/java/com/capgemini/reports/changeobjects/change/TcChangeRequestRevision.java new file mode 100644 index 0000000..19578d9 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/changeobjects/change/TcChangeRequestRevision.java @@ -0,0 +1,114 @@ +package com.capgemini.reports.changeobjects.change; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.object.pom.status.StatusEnum.AbstractStatusFilter; +import com.capgemini.framework.teamcenter.object.pom.status.TcReleaseStatus; +import com.capgemini.framework.teamcenter.resolution.filtering.TcTypeExclusionFilter; +import com.capgemini.reports.exceptions.NotSupportedException; +import com.capgemini.reports.snecmaobjects.generic.AbstractGeneric; +import com.teamcenter.soa.client.model.ModelObject; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.List; + +import static com.capgemini.framework.teamcenter.object.SnecmaObjectProperties.*; +import static com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes.*; + +/** + * Class representing a modification. + */ +@Slf4j +public class TcChangeRequestRevision extends AbstractChangeObject { + private static final long serialVersionUID = -2682203641880659660L; + + public TcChangeRequestRevision(final TcSession session, final ItemRevision itemRevision) { + super(session, itemRevision); + } + + public List getFppList() { + session.loadProperties(itemRevision, CM_IMPLEMENTS); + ModelObject[] implementsObjects = itemRevision.getPropertyObject(CM_IMPLEMENTS).getModelObjectArrayValue(); + session.loadProperties(implementsObjects); + List fppRevisions = new ArrayList<>(); + for (ModelObject implementsObject : implementsObjects) { + fppRevisions.add(new FPPRevision(session, (ItemRevision) implementsObject)); + } + return fppRevisions; + } + + /** + * Returns true if this CR is a CAD, DCAD, or MACE (actually, {@code PV4_CAD_ACRRevision}, {@code PV4_DCADRevision}, {@code PV4_MACERevision}). + * + * @return true if this CR is a CAD, DCAD, or MACE + */ + public boolean isCadOrDCadOrMace() { + String changeType = getChangeType(); + return PV4_CAD_ACR_REVISION.equals(changeType) || PV4_DCAD_REVISION.equals(changeType) || PV4_MACE_REVISION.equals(changeType); + } + + + public List getChangeNoticesList() { + List changeNotices = new ArrayList<>(); + session.loadProperties(itemRevision, CM_IMPLEMENTED_BY); + ModelObject[] objects = itemRevision.getPropertyObject(CM_IMPLEMENTED_BY).getModelObjectArrayValue(); + session.loadProperties(objects); + for (ModelObject currentObject : objects) { + changeNotices.add(new TcChangeNoticeRevision(session, (ItemRevision) currentObject)); + } + return changeNotices; + } + + public List getChangeNoticesList(final TcTypeExclusionFilter typeExlusionFilter, final AbstractStatusFilter statusExclusionFilter) { + List changeNotices = new ArrayList<>(); + for (TcChangeNoticeRevision changeNotice : getChangeNoticesList()) { + if (typeExlusionFilter.isIncluded(changeNotice.getChangeType()) && !hasExcludeStatuses(statusExclusionFilter, changeNotice)) { + changeNotices.add(changeNotice); + } + } + return changeNotices; + } + + private boolean hasExcludeStatuses(AbstractStatusFilter statusExclusionFilter, TcChangeNoticeRevision changeNotice) { + for (TcReleaseStatus status : changeNotice.getReleaseStatusContainingMaturity()) { + if (statusExclusionFilter.isExcluded(status)) { + return true; + } + } + return false; + } + + public String getTypeModSupportProcess() { + return itemRevision.getPropertyObject(PV4_TYPE_MODIFICATION).getDisplayableValue(); + } + + public List getListOfGenericRevWithOrWithoutRupture() { + List generics = new ArrayList<>(); + List genericsObjects = new ArrayList<>(); + session.loadProperties(itemRevision, PV_IMP_GENERICS_WITH_INTER, PV_IMP_GENERICS_WITHOUT_INTER); + genericsObjects.addAll(itemRevision.getPropertyObject(PV_IMP_GENERICS_WITH_INTER).getModelObjectListValue()); + genericsObjects.addAll(itemRevision.getPropertyObject(PV_IMP_GENERICS_WITHOUT_INTER).getModelObjectListValue()); + session.loadProperties(genericsObjects.toArray(new ModelObject[genericsObjects.size()])); + for (ModelObject genericsObject : genericsObjects) { + try { + generics.add(loadGeneric(genericsObject)); + } catch (NotSupportedException e) { + log.warn("Unsupported object {} found in pseudo-folder {} or {}", genericsObject.getUid(), PV_IMP_GENERICS_WITH_INTER, PV_IMP_GENERICS_WITHOUT_INTER); + } + } + return generics; + } + + public String getApprobationSO() { + session.loadProperties(itemRevision, PV_EXTERNAL_APPROBATION); + ModelObject[] approbationSOarray = itemRevision.getPropertyObject(PV_EXTERNAL_APPROBATION).getModelObjectArrayValue(); + session.loadProperties(approbationSOarray); + for (ModelObject model : approbationSOarray) { + if (APPROBATION_SO.equals(model.getTypeObject().getName())) { + return model.getPropertyObject(PV_NUMERO_APPROBATION).getStringValue(); + } + } + return null; + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/documentationobjects/AbstractDoc.java b/teamcenter/src/main/java/com/capgemini/reports/documentationobjects/AbstractDoc.java new file mode 100644 index 0000000..b9a0065 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/documentationobjects/AbstractDoc.java @@ -0,0 +1,113 @@ +package com.capgemini.reports.documentationobjects; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.object.pom.status.TcReleaseStatus; +import com.teamcenter.soa.client.model.strong.Form; +import com.teamcenter.soa.client.model.strong.Item; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import com.teamcenter.soa.client.model.strong.ReleaseStatus; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; + +import static com.capgemini.framework.teamcenter.object.SnecmaObjectProperties.NIVEAU_SENSIBILITE; + +/** + * Abstract class for all objects of type Document. Contains Id, Revision, Name and Type. + */ +public abstract class AbstractDoc implements Serializable { + private static final long serialVersionUID = -3082137888946282380L; + protected final ItemRevision itemRevision; + protected final TcSession session; + + private List statuses; + private Form masterFormRev; + + public AbstractDoc(final TcSession session, final ItemRevision itemRevision) { + this.session = session; + this.itemRevision = itemRevision; + } + + public String getUid() { + return itemRevision.getUid(); + } + + public String getType() { + return itemRevision.getTypeObject().getName(); + } + + public String getDocId() { + return itemRevision.get_item_id(); + } + + public String getRevision() { + return itemRevision.get_item_revision_id(); + } + + public String getName() { + return itemRevision.get_object_name(); + } + + public Calendar getDateCreation() { + return itemRevision.get_creation_date(); + } + + public Item getItem() { + session.loadProperties(itemRevision, "items_tag"); + Item item = itemRevision.get_items_tag(); + session.loadProperties(item); + return item; + } + + + public Form getMasterForm() { + Item item = getItem(); + session.loadProperties(item, "item_master_tag"); + Form masterTag = item.get_item_master_tag(); + session.loadProperties(masterTag); + return masterTag; + } + + public Form getMasterFormRev() { + if (masterFormRev == null) { + masterFormRev = itemRevision.get_item_master_tag(); + session.loadProperties(masterFormRev); + } + return masterFormRev; + } + + public List getStatus() { + if (statuses == null) { + statuses = new ArrayList<>(); + session.loadProperties(itemRevision, "release_status_list"); + ReleaseStatus[] releaseStatuses = itemRevision.get_release_status_list(); + session.loadProperties(releaseStatuses); + for (ReleaseStatus releaseStatus : releaseStatuses) { + TcReleaseStatus tcReleaseStatus = new TcReleaseStatus(session, releaseStatus); + statuses.add(tcReleaseStatus); + } + } + return statuses; + } + + public String getNiveauSensibilite() { + session.loadProperties(itemRevision, NIVEAU_SENSIBILITE); + return itemRevision.getPropertyObject(NIVEAU_SENSIBILITE).getStringValue(); + } + + @Override + public String toString() { + return this.getType() + " " + this.getDocId() + "/" + this.getRevision(); + } + + /** + * Visitor method. + * + * @param docVisitor a {@link IDocVisitor} + * @param anything you may want to return from your visit + * @return the outcome of the visit + */ + public abstract T accept(final IDocVisitor docVisitor); +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/documentationobjects/DocDrawing.java b/teamcenter/src/main/java/com/capgemini/reports/documentationobjects/DocDrawing.java new file mode 100644 index 0000000..a750b5a --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/documentationobjects/DocDrawing.java @@ -0,0 +1,32 @@ +package com.capgemini.reports.documentationobjects; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +import static com.capgemini.framework.teamcenter.object.SnecmaObjectProperties.PV_DESIGNATION_EN; +import static com.capgemini.framework.teamcenter.object.SnecmaObjectProperties.PV_INDICE_PLAN; + +/** + * Class representing a DocDrawing. + */ +public class DocDrawing extends AbstractDoc { + private static final long serialVersionUID = -7465031832786627181L; + + + public DocDrawing(final TcSession session, final ItemRevision itemRevision) { + super(session, itemRevision); + } + + public String getDesignationEn() { + return getMasterFormRev().getPropertyObject(PV_DESIGNATION_EN).getStringValue(); + } + + public String getIndicePlan() { + return getMasterFormRev().getPropertyObject(PV_INDICE_PLAN).getStringValue(); + } + + @Override + public T accept(final IDocVisitor docVisitor) { + return docVisitor.visit(this); + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/documentationobjects/DocFactory.java b/teamcenter/src/main/java/com/capgemini/reports/documentationobjects/DocFactory.java new file mode 100644 index 0000000..07b796a --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/documentationobjects/DocFactory.java @@ -0,0 +1,56 @@ +package com.capgemini.reports.documentationobjects; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.teamcenter.soa.client.model.strong.Item; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import lombok.extern.slf4j.Slf4j; + +/** + * Factory for all {@link AbstractDoc}s. + */ +@Slf4j +public final class DocFactory { + + private DocFactory() { + // Nothing to do + } + + /** + * Builds an {@link AbstractDoc} from an {@link ItemRevision}.
    + */ + public static AbstractDoc build(final TcSession session, final Item doc) { + String docType = doc.getTypeObject().getName(); + switch (docType) { + case SnecmaObjectTypes.DOC_NORM: + return new DocNorm(session, doc); + case SnecmaObjectTypes.DOC_NORM_STANDARD: + return new DocNormStandard(session, doc); + default: + log.warn("Unable to find the builder for doc: {}", docType); + return null; + } + } + + /** + * Builds an {@link AbstractDoc} from an {@link ItemRevision}.
    + */ + public static AbstractDoc build(final TcSession session, final ItemRevision docRev) { + String docType = docRev.getTypeObject().getName(); + switch (docType) { + case SnecmaObjectTypes.DOC_DRAWING_REVISION: + return new DocDrawing(session, docRev); + case SnecmaObjectTypes.DOC_GEOMETRY_REVISION: + return new DocGeometry(session, docRev); + case SnecmaObjectTypes.DOC_NORM_REVISION: + return new DocNorm(session, docRev); + case SnecmaObjectTypes.DOC_NORM_STANDARD_REVISION: + return new DocNormStandard(session, docRev); + case SnecmaObjectTypes.DOC_TECHNIC_REVISION: + return new DocTechnic(session, docRev); + default: + log.warn("Unable to find the builder for doc: {}", docType); + return null; + } + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/documentationobjects/DocGeometry.java b/teamcenter/src/main/java/com/capgemini/reports/documentationobjects/DocGeometry.java new file mode 100644 index 0000000..f40dbab --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/documentationobjects/DocGeometry.java @@ -0,0 +1,37 @@ +package com.capgemini.reports.documentationobjects; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import lombok.extern.slf4j.Slf4j; + +import static com.capgemini.framework.teamcenter.object.SnecmaObjectProperties.PV_DESIGNATION_EN; +import static com.capgemini.framework.teamcenter.object.SnecmaObjectProperties.PV_INDICE_CARTOUCHE; + +/** + * Class representing a DocGeometry. + */ +@Slf4j +public class DocGeometry extends AbstractDoc { + private static final long serialVersionUID = -7626101075442466263L; + + public DocGeometry(final TcSession session, final ItemRevision itemRevision) { + super(session, itemRevision); + } + + public String getName() { + return itemRevision.get_object_name(); + } + + public String getDesignationEN() { + return getMasterFormRev().getPropertyObject(PV_DESIGNATION_EN).getStringValue(); + } + + public String getIndiceCartouche() { + return getMasterFormRev().getPropertyObject(PV_INDICE_CARTOUCHE).getStringValue(); + } + + @Override + public T accept(final IDocVisitor docVisitor) { + return docVisitor.visit(this); + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/documentationobjects/DocNorm.java b/teamcenter/src/main/java/com/capgemini/reports/documentationobjects/DocNorm.java new file mode 100644 index 0000000..5ca9873 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/documentationobjects/DocNorm.java @@ -0,0 +1,82 @@ +package com.capgemini.reports.documentationobjects; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.teamcenter.soa.client.model.strong.Item; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +import static com.capgemini.framework.teamcenter.object.SnecmaObjectProperties.*; + +/** + * Class representing a DocNorm. + */ +public class DocNorm extends AbstractDoc { + private static final long serialVersionUID = 8380671472697651060L; + private final Item item; + + public DocNorm(final TcSession session, final ItemRevision itemRevision) { + super(session, itemRevision); + this.item = null; + } + + public DocNorm(final TcSession session, final Item item) { + super(session, null); + this.item = item; + } + + public String getItemName() { + if (item == null) { + return getItem().get_object_name(); + } else { + return item.get_object_name(); + } + } + + @Override + public String getType() { + if (item == null) { + return super.getType(); + } else { + return item.getTypeObject().getName(); + } + } + + @Override + public String getDocId() { + if (item == null) { + return super.getDocId(); + } else { + return item.get_item_id(); + } + } + + @Override + public String getRevision() { + if (item == null) { + return super.getRevision(); + } else { + return ""; + } + } + + public String getDesignationEn() { + return getMasterFormRev().getPropertyObject(PV_DESIGNATION_EN).getStringValue(); + } + + public String getTypeDocNorm() { + return getMasterFormRev().getPropertyObject(PV_TYPE_DOC_NORM).getStringValue(); + } + + public String getIdOrigine() { + return getMasterFormRev().getPropertyObject(PV_ID_ORIGINE).getStringValue(); + } + + public String getSensibiliteSecurite() { + return getMasterForm().getPropertyObject(PV_SENSIBILITE_SECURITE).getStringValue(); + } + + @Override + public T accept(final IDocVisitor docVisitor) { + return docVisitor.visit(this); + } + +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/documentationobjects/DocNormStandard.java b/teamcenter/src/main/java/com/capgemini/reports/documentationobjects/DocNormStandard.java new file mode 100644 index 0000000..a24a11b --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/documentationobjects/DocNormStandard.java @@ -0,0 +1,75 @@ +package com.capgemini.reports.documentationobjects; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.teamcenter.soa.client.model.strong.Item; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +import static com.capgemini.framework.teamcenter.object.SnecmaObjectProperties.PV_DESIGNATION_EN; +import static com.capgemini.framework.teamcenter.object.SnecmaObjectProperties.PV_ID_ORIGINE; + +/** + * Class representing a DocNormStandard. + */ +public class DocNormStandard extends AbstractDoc { + private static final long serialVersionUID = 882873890678687030L; + private final Item item; + + public DocNormStandard(final TcSession session, final ItemRevision itemRevision) { + super(session, itemRevision); + this.item = null; + } + + public DocNormStandard(final TcSession session, final Item item) { + super(session, null); + this.item = item; + } + + public String getItemName() { + if (item == null) { + return getItem().get_object_name(); + } else { + return item.get_object_name(); + } + } + + @Override + public String getType() { + if (item == null) { + return super.getType(); + } else { + return item.getTypeObject().getName(); + } + } + + @Override + public String getDocId() { + if (item == null) { + return super.getDocId(); + } else { + return item.get_item_id(); + } + } + + @Override + public String getRevision() { + if (item == null) { + return super.getRevision(); + } else { + return ""; + } + } + + public String getDesignationEn() { + return getMasterFormRev().getPropertyObject(PV_DESIGNATION_EN).getStringValue(); + } + + public String getIdOrigine() { + return getMasterFormRev().getPropertyObject(PV_ID_ORIGINE).getStringValue(); + } + + @Override + public T accept(final IDocVisitor docVisitor) { + return docVisitor.visit(this); + } + +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/documentationobjects/DocTechnic.java b/teamcenter/src/main/java/com/capgemini/reports/documentationobjects/DocTechnic.java new file mode 100644 index 0000000..57b126c --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/documentationobjects/DocTechnic.java @@ -0,0 +1,50 @@ +package com.capgemini.reports.documentationobjects; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +import static com.capgemini.framework.teamcenter.object.SnecmaObjectProperties.*; + +/** + * Represent a document of Gel of Unit. + */ +public class DocTechnic extends AbstractDoc { + private static final long serialVersionUID = -6347639229060368050L; + + public DocTechnic(final TcSession session, final ItemRevision itemRevision) { + super(session, itemRevision); + } + + public String getIndice() { + return getMasterFormRev().getPropertyObject(PV_INDICE_DOCUMENT).getStringValue(); + } + + public String getReference() { + return getDocId(); + } + + public String getTypeDocTechnic1() { + return getMasterFormRev().getPropertyObject(PV_TYPE_DOC_TECHNIC_1).getStringValue(); + } + + public String getTypeDocTechnic2() { + return getMasterFormRev().getPropertyObject(PV_TYPE_DOC_TECHNIC_2).getStringValue(); + } + + public String getIdOrigine() { + return getMasterFormRev().getPropertyObject(PV_ID_ORIGINE).getStringValue(); + } + + public String getDesignationEn() { + return getMasterFormRev().getPropertyObject(PV_DESIGNATION_EN).getStringValue(); + } + + public String getSensibiliteSecurite() { + return getMasterForm().getPropertyObject(PV_SENSIBILITE_SECURITE).getStringValue(); + } + + @Override + public T accept(final IDocVisitor docVisitor) { + return docVisitor.visit(this); + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/documentationobjects/IDocVisitor.java b/teamcenter/src/main/java/com/capgemini/reports/documentationobjects/IDocVisitor.java new file mode 100644 index 0000000..dc92dd5 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/documentationobjects/IDocVisitor.java @@ -0,0 +1,49 @@ +package com.capgemini.reports.documentationobjects; + +/** + * Interface for visitor Pattern, allows someone to visit every Doc type avaialble and implement a dedicated treatent. + * + * @param a produced object during the visit + */ +public interface IDocVisitor { + + /** + * Behaviour when visiting a {@link DocDrawing}. + * + * @param doc + * @return a produced result + */ + T visit(final DocDrawing doc); + + /** + * Behaviour when visiting a {@link DocGeometry}. + * + * @param doc + * @return a produced result + */ + T visit(final DocGeometry doc); + + /** + * Behaviour when visiting a {@link DocNorm}. + * + * @param doc + * @return a produced result + */ + T visit(final DocNorm doc); + + /** + * Behaviour when visiting a {@link DocNormStandard}. + * + * @param doc + * @return a produced result + */ + T visit(final DocNormStandard doc); + + /** + * Behaviour when visiting a {@link DocTechnic}. + * + * @param doc + * @return a produced result + */ + T visit(final DocTechnic doc); +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/exceptions/InvalidInputException.java b/teamcenter/src/main/java/com/capgemini/reports/exceptions/InvalidInputException.java new file mode 100644 index 0000000..4553b90 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/exceptions/InvalidInputException.java @@ -0,0 +1,84 @@ +package com.capgemini.reports.exceptions; + +import com.capgemini.framework.teamcenter.exceptions.KurtException; + +/** KURT functional input value errors ("not a number" etc). */ +public class InvalidInputException extends KurtException { + + private static final long serialVersionUID = -8816332546502998913L; + + protected final UserInputErrorEnum userInputError; + + /** + * Constructs an INTERNAL_ERROR, used when something went wrong while checking the user inputs.
    + * In this case, the user input could not be checked because an internal error occurred first. + * + * @param aMessage a precise Error message for the developer + */ + public InvalidInputException(final String aMessage) { + super(aMessage); + this.userInputError = UserInputErrorEnum.INTERNAL_ERROR; + } + + /** + * Constructs an Exception that may occur if the user provided some wrong inputs.
    + * A preset message will be sent to the user depending on the error.
    + * A preset message will be sent to the Exception log depending on the error.
    + * + * @param aUserInputError {@link UserInputErrorEnum} explaining what went wrong + */ + public InvalidInputException(final UserInputErrorEnum aUserInputError) { + super(aUserInputError.msgEn); + this.userInputError = aUserInputError; + } + + /** + * Constructs an Exception that may occur if the user provided some wrong inputs.
    + * A preset message will be sent to the user depending on the error.
    + * A preset message will be sent to the Exception log depending on the error.
    + * + * @param aUserInputError {@link UserInputErrorEnum} explaining what went wrong + * @param originalException the original exception + */ + public InvalidInputException(final UserInputErrorEnum aUserInputError, final Throwable originalException) { + super(aUserInputError.msgEn, originalException); + this.userInputError = aUserInputError; + } + + /** + * Constructs an Exception that may occur if the user provided some wrong inputs.
    + * A preset message message will be sent to the user depending on the error.
    + * The specified message parameter will be sent to the Exception log and override the default one.
    + * + * @param aMessage a precise Error message for the programmer + * @param aUserInputError {@link UserInputErrorEnum} explaining what went wrong + */ + public InvalidInputException(final String aMessage, final UserInputErrorEnum aUserInputError) { + super(aMessage); + this.userInputError = aUserInputError; + } + + /** + * Constructs an INTERNAL_ERROR, used when something went wrong while checking the user inputs.
    + * In this case, the user input could not be checked because an internal error occurred first.
    + * The original exception is stored for reference. + * + * @param aMessage a precise Error message for the developer + * @param anException the original error + */ + public InvalidInputException(final String aMessage, final Throwable anException) { + super(aMessage, anException); + this.userInputError = UserInputErrorEnum.INTERNAL_ERROR; + } + + /** + * Returns the message to be sent to the user. + * + * @return the message + */ + @Override + public String getErrorMessageForUser() { + return userInputError.msgFr; + } + +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/exceptions/InvalidUserInputException.java b/teamcenter/src/main/java/com/capgemini/reports/exceptions/InvalidUserInputException.java new file mode 100644 index 0000000..de6a8d1 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/exceptions/InvalidUserInputException.java @@ -0,0 +1,90 @@ +package com.capgemini.reports.exceptions; + +import lombok.Getter; + +/** + * KURT functional input value errors ("not a number" etc), specifically coming from the user. + *

    + * Carries a message explaining to the user why the input is wrong.
    + * Also carries contextual information, such as which report has caused this error. + */ +@Getter +public class InvalidUserInputException extends InvalidInputException { + + private static final long serialVersionUID = -8816332546502998913L; + + protected String userInputDynamicError = ""; + + /** + * Builds an Internal Error Exception, with custom message for debugging. + * + * @param anError Error description for devs + */ + public InvalidUserInputException(final String anError) { + super(anError); + } + + /** + * Builds an Internal Error Exception, with custom message for debugging. Includes the Throwable that caused the error. + * + * @param anError Error description for devs + * @param originalError the Original Error that caused all the drama + */ + public InvalidUserInputException(final String anError, final Throwable originalError) { + super(anError, originalError); + } + + /** + * Builds an exception which explains what happened to the user, and to the developer. + * + * @param anError an {@link com.capgemini.reports.exceptions.UserInputErrorEnum} that explains what happened for the user, and for the developper. + */ + public InvalidUserInputException(final UserInputErrorEnum anError) { + super(anError.getMsgEn(), anError); + } + + /** + * Builds an exception which explains what happened to the user, and to the developer. + * + * @param anError an {@link com.capgemini.reports.exceptions.UserInputErrorEnum} that explains what happened for the user, and for the developper. + * @param originalError the original {@link Throwable} Exception that caused the failure. + */ + public InvalidUserInputException(final UserInputErrorEnum anError, final Throwable originalError) { + super(anError, originalError); + } + + + /** + * Builds dynamic exception which explains what happened to the user, and to the developer. + * + * @param anError an {@link com.capgemini.reports.exceptions.UserInputErrorEnum} that explains what happened for the user, and for the developper. + * @param tags String the dynamic parameters to add to the error. + */ + public InvalidUserInputException(final UserInputErrorEnum anError, final String... tags) { + super(replaceTags(anError.getMsgEn(), tags)); + this.userInputDynamicError = replaceTags(anError.getMsgFr(), tags); + } + + private static String replaceTags(final String message, final String[] tags) { + String msg = message; + for (String tag : tags) { + msg = msg.replaceFirst("\\{\\}", tag); + } + return msg; + } + + /** + * Returns the message to be sent to the user. + * + * @return the message + */ + @Override + public String getErrorMessageForUser() { + if (!userInputDynamicError.isEmpty()) { + return userInputDynamicError; + } + else { + return userInputError.msgFr; + } + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/exceptions/MalformedNomenclatureException.java b/teamcenter/src/main/java/com/capgemini/reports/exceptions/MalformedNomenclatureException.java new file mode 100644 index 0000000..5570a11 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/exceptions/MalformedNomenclatureException.java @@ -0,0 +1,31 @@ +package com.capgemini.reports.exceptions; + +import com.capgemini.framework.teamcenter.exceptions.KurtException; + +/** Exception thrown when the nomenclature is not as expected. */ +public class MalformedNomenclatureException extends KurtException { + + + private static final long serialVersionUID = -3794378881986432701L; + + /** + * throw this exception when the nomenclature isn't as axpected (i.e. missing elements like part number below RF Generic, some RF Admins, etc. + * + * @param aMessage a message explaining just how wrong the nomenclature is + */ + public MalformedNomenclatureException(final String aMessage) { + super(aMessage); + } + + /** + * throw this exception when the nomenclature isn't as axpected (i.e. missing elements like part number below RF Generic, some RF Admins, etc. + * + * @param aMessage a message explaining just how wrong the nomenclature is + * @param anException the original exception that can be interpreted as a malformed nomenclature exception. + */ + + public MalformedNomenclatureException(final String aMessage, final Throwable anException) { + super(aMessage, anException); + } + +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/exceptions/NoConfChangesException.java b/teamcenter/src/main/java/com/capgemini/reports/exceptions/NoConfChangesException.java new file mode 100644 index 0000000..c403c6d --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/exceptions/NoConfChangesException.java @@ -0,0 +1,10 @@ +package com.capgemini.reports.exceptions; + +import com.capgemini.framework.teamcenter.exceptions.KurtException; + +public class NoConfChangesException extends KurtException { + + public NoConfChangesException(String aMessage) { + super(aMessage); + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/exceptions/NotFoundException.java b/teamcenter/src/main/java/com/capgemini/reports/exceptions/NotFoundException.java new file mode 100644 index 0000000..2bcfe23 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/exceptions/NotFoundException.java @@ -0,0 +1,29 @@ +package com.capgemini.reports.exceptions; + +import com.capgemini.framework.teamcenter.exceptions.KurtException; + +/** Erreur générée lorsqu'un objet n'a pas été trouvé dans teamcenter. */ +public class NotFoundException extends KurtException { + + private static final long serialVersionUID = -5126739618564266946L; + + /** + * Constructor. + * + * @param aMessage Error message + */ + public NotFoundException(final String aMessage) { + super(aMessage); + } + + /** + * Constructor. + * + * @param aMessage Error message + * @param anException Original exception + */ + public NotFoundException(final String aMessage, final Throwable anException) { + super(aMessage, anException); + } + +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/exceptions/NotSupportedException.java b/teamcenter/src/main/java/com/capgemini/reports/exceptions/NotSupportedException.java new file mode 100644 index 0000000..229131b --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/exceptions/NotSupportedException.java @@ -0,0 +1,30 @@ +package com.capgemini.reports.exceptions; + +import com.capgemini.framework.teamcenter.exceptions.KurtException; + +/** Represents the exception to throw when the operation requested cannot be performed (it is not implemented, or non-sensical. */ +public class NotSupportedException extends KurtException { + + /** Serialization UID. **/ + private static final long serialVersionUID = -7975389522450629095L; + + /** + * Constructor. + * + * @param aMessage Error message + */ + public NotSupportedException(final String aMessage) { + super(aMessage); + } + + /** + * Constructor. + * + * @param aMessage Error message + * @param anException Original exception + */ + public NotSupportedException(final String aMessage, final Throwable anException) { + super(aMessage, anException); + } + +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/exceptions/ServiceException.java b/teamcenter/src/main/java/com/capgemini/reports/exceptions/ServiceException.java new file mode 100644 index 0000000..d190482 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/exceptions/ServiceException.java @@ -0,0 +1,32 @@ +package com.capgemini.reports.exceptions; + +import com.capgemini.framework.teamcenter.exceptions.KurtException; + +/** + * Exception déclenchée lorsqu'un service n'est pas capable de remplir sa tâche. + * + */ +public class ServiceException extends KurtException { + + private static final long serialVersionUID = -5463974860193499398L; + + /** + * Constructor. + * + * @param aMessage Error message + */ + public ServiceException(String aMessage) { + super(aMessage); + } + + /** + * Constructor. + * + * @param aMessage Error message + * @param anException Original exception + */ + public ServiceException(String aMessage, Throwable anException) { + super(aMessage, anException); + } + +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/exceptions/UserInputErrorEnum.java b/teamcenter/src/main/java/com/capgemini/reports/exceptions/UserInputErrorEnum.java new file mode 100644 index 0000000..f7563eb --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/exceptions/UserInputErrorEnum.java @@ -0,0 +1,184 @@ +package com.capgemini.reports.exceptions; + +import lombok.Getter; + +/** + * List of all possible problems the user needs to know about.
    + * WARNING -> Unsupported characters in web browser ie8 : (') and (&) use numeric code. + */ +@Getter +public enum UserInputErrorEnum { + + /** + * Error occurring if the user is requesting a report that has already been asked for, which is still in the queues. + */ + DUPLICATE_REPORT_LAUNCHED_RECENTLY("Previous similar recent launch detected. Prompting user to confirm.", "Une demande identique lancée par {} est déjà en attente de génération. Vous allez être associé au résultat de ce lancement "), + /** + * Error occurring if the user is requesting a report that HE himself has already been asked for, which is still in the queues. + */ + DUPLICATE_REPORT_LAUNCHED_RECENTLY_BY_SELF("Previous similar recent launch detected from the same user. Denying launch.", "Lancement rejeté. Vous avez déjà lancé une demande identique, qui est en attente de génération."), + /** + * Error occurring if the user is requestinga scheduling with a name that already exists. + */ + DUPLICATE_SCHEDULING("Previous scheduling with same name detected. Denying scheduling.", "Lancement rejeté. Une planification du même nom existe déjà."), + + /** + * Error occurring if the user has input a non-numeric Unit. + */ + UNIT_NOT_NUMERIC("Server requested to perform report with non-numeric UNIT argument", "Le Unit fourni n’est pas un nombre."), + /** + * Error occurring if the User has input a product that can not be found in the TC database. + */ + INCORRECT_PRODUCT("Server called with bad arguments: productID is null", "Aucun produit n’a été fourni."), + /** + * Error occurring if the User has input a an invalid Generic under a (possibly valid) Product-Unit. + */ + PRODUCT_UNIT_GENERIC_INVALID("Could not find a correct Product/Unit/Generic combination", "Impossible de trouver le générique fourni sous ce couple produit-unit."), + /** + * Error occurring if the User has input a an invalid Generic Assemb under a (possibly valid) Product-Unit. + */ + PRODUCT_UNIT_GENERIC_ASSEMB_INVALID("Could not find a correct Product/Unit/GenericAssemb combination", "Impossible de trouver le générique assemb fourni sous ce couple produit-unit."), + /** + * Error occurring if the User has input a an invalid Generic for the Product-Unit. + */ + PRODUCT_UNIT_GENERIC_DOES_NOT_EXIST("The requested generic could not be found in the database.", "Le triplet produit-unit-générique n’existe pas."), + /** + * Error occurring When an internal error has occurred. + */ + INTERNAL_ERROR("Internal error", "Une erreur interne s’est produite."), + /** + * Error occurring if the User has input a an invalid Generic. + */ + GENERIC_DOES_NOT_EXIST("Generic does not exist ", "Le Générique est inconnu. Aucune donnée ne peut être affichée"), + /** + * Error occurring if the User has input a an invalid Generic Assemb. + */ + GENERIC_ASSEMB_DOES_NOT_EXIST("Generic Assemb does not exist ", "Générique Montage inconnu."), + /** + * Error occurring if the User has input a an invalid Unit for the Product. + */ + PRODUCT_AND_UNIT_DOES_NOT_EXIST("The unit is not associated to product.", "Le Unit n'est pas associé au Produit."), + /** + * Error occurring if the User has input a an invalid Generic Assemb or Generic under a (possibly valid) Product-Unit. + */ + GENERIC_INPUT("Generic does not exist ", "Saisir un Générique (Générique/Générique Montage) ou cocher ‘Vue Model list’, le ou est exclusif. »"), + /** + * Error occurring if the User has input a an invalid Generic Assemb. + */ + NO_DATA_COULD_BE_EXTRACTED_FOR_GENERIC_PRODUCT_AND_UNIT("No data could be extracted, the triplet product/unit/generic is not consistent", "Aucune donnée n’a pu être extraite, relancer le rapport après avoir vérifié les critères saisis. Pour rappel, le triplet ‘générique / produit / unit’ doit être cohérent."), + /** + * Error occurring if the User has input a an invalid Generic Assemb or Generic under a (possibly valid) Product-Unit. + */ + NO_DATA_COULD_BE_EXTRACTED_FOR_GENERIC_ASSEMB_PRODUCT_AND_UNIT("No data could be extracted, the triplet product/unit/genericAssemb is not consistent", "Aucune donnée n’a pu être extraite, relancer le rapport après avoir vérifié les critères saisis. Pour rappel, le triplet ‘générique montage / produit / unit’ doit être cohérent."), + /** + * Error occurring if the User has input a an invalid type object. + */ + THE_SELECTED_OBJECT_IS_NOT_PERMITTED_ON_THIS_REPORT("The selected object is not permitted on this report.", "L’objet sélectionné n’est pas autorisé sur ce rapport."), + + // Created for R07 + /** + * Error occurring if the User has input an invalid Product-Unit. + */ + THE_UNIT_1_IS_NOT_ASSOCIATED_TO_THE_PRODUCT_1("The unit 1 is not associated to the product 1.", "Le unit 1 n’est pas associé au produit 1."), + /** + * Error occurring if the User has input an invalid Product-Unit. + */ + THE_UNIT_2_IS_NOT_ASSOCIATED_TO_THE_PRODUCT_2("The unit 2 is not associated to the product 2.", "Le unit 2 n’est pas associé au produit 2."), + + // Created for R11 + /** + * Error occurring if the User has input a an invalid Product. + */ + PRODUCT_DOES_NOT_EXIST_NO_DATA_TO_PRINT("Product does not not exist. Unable to print any data.", "Le Produit est inconnu. Aucune donnée ne peut être affichée."), + /** + * Error occurring if the User has input a an invalid type of Generic. + */ + THE_GENERIC_MUST_BELONG_TO_THE_TECHNICAL_VIEW("The generic must be a geric type. Unable to print any data.", "Le générique doit être de type générique. Aucune donnée ne peut être affichée."), + /** + * Error occurring if the User has input a an invalid Generic under a (possibly valid) Product-Unit. + */ + NO_GENERIC_REVISION_IS_ASSOCIATED_TO_THE_PRODUCT_UNIT_NO_DATA_TO_PRINT("No Generic Revision is associated to the product-unit. Unbale to print any data.", "Aucune révision du Générique ne s’applique pour le Produit Unit. Aucune donnée ne peut être affichée."), + + // Created for R16 + /** + * Error occurring if the User has input a an invalid Product or couple of Product-Unit. + */ + WRONG_EFFECTIVITY_THE_PRODUCT_DOES_NOT_EXIST_OR_THE_UNIT_DOES_NOT_EXIST_FOR_THE_PRODUCT("Wrong effectivity, the product does not exist or the unit does not exit for the product.", "Effectivité erronée, produit inconnu ou unit inconnu pour ce produit."), + /** + * Error occurring if the User has input a an invalid Generic or Product-Unit-Generic. + */ + GENERIC_DOES_NOT_EXIST_OR_ENTRY_EFFECTIVITY_IS_NOT_COMPATIBLE_WITH_THE_GENERIC("Generic does not exist - OR - entry effectivity is not compatible with the Generic.", "Générique inconnu – OU - l’effectivité saisie n’est pas compatible avec le générique."), + + // Created for R19 + /** + * Error occurring if the User has selected an invalid object. + */ + TYPE_DOCUMENT_SELECTED_NOT_AUTHORIZED("

    " + "

    The type of item selected is not compatible with the report R19." + "

    The only types compatible are:

    " + "

    - Document "DocDrawing" (revision)

    " + "

    - Document "DocNorm" (master and review)

    " + "

    - Document "DocNormStandard" (master and review)

    " + "

    - Document "DocTechnic" (revision)

    " + "
    ", "
    " + "

    Le type d'article sélectionné n'est pas compatible avec le rapport R19.

    " + "

    Les seuls types compatibles sont les suivants:

    " + "

    - Document "DocDrawing" (révision)

    " + "

    - Document "DocNorm" (master et révision)

    " + "

    - Document "DocNormStandard" (master et révision)

    " + "

    - Document "DocTechnic" (révision)

    " + "
    "), + + // Created for R20 + /** + * Error occurring if the User has input an invalid Product-Unit. + */ + THE_UNIT_AFTER_IS_NOT_ASSOCIATED_TO_THE_PRODUCT_AFTER("The Unit ‘After’ is not associated to the Product ‘After’", "Le Unit ‘Après’ n’est pas associé au Produit ‘Après’."), + /** + * Error occurring if the User has input an invalid Product-Unit. + */ + THE_UNIT_BEFORE_IS_NOT_ASSOCIATED_TO_THE_PRODUCT_BEFORE("The Unit ‘Before’ is not associated to the Product ‘Before’", "Le Unit ‘Avant’ n’est pas associé au Produit ‘Avant’."), + /** + * Error occurring if the User has input an Product-Unit after where th unit's latest maturity status is of the wrong type. + */ + THE_LATEST_UNIT_AFTER_DOES_NOT_HAVE_THE_APPROPRIATE_MATURITY("The latest Unit ‘After’ does not have the proper maturity status", "La révision du Unit ‘Après’ la plus récemment statuée n‘a pas la maturité appropriée pour le gel du unit."), + /** + * Error occurring if the User has input an Product-Unit before where th unit's latest maturity status is of the wrong type. + */ + THE_LATEST_UNIT_BEFORE_DOES_NOT_HAVE_THE_APPROPRIATE_MATURITY("The latest Unit ‘Before’ does not have the proper maturity status", "La révision du Unit ‘Avant’ la plus récemment statuée n‘a pas la maturité appropriée pour le gel du unit."), + /** + * Dynamic error occurring if a ChangeRequest doesn't exist. + */ + UNKNOWN_CHANGE_REQUEST("Unknown ChangeRequest {}", "ChangeRequest {} inconnu"), + /** + * Dynamic error occurring if a ChangeRequest is not compatible with the Unit Before. + */ + REMOVED_CHANGE_REQUEST_IS_NOT_COMPATIBLE_WITH_BEFORE_EFFECTIVITY("Removed ChangeRequest {} is not compatible with ‘Before’ effectivity", "ChangeRequest {} retirée, elle n’est pas compatible avec l’effectivité ‘Avant’ saisie."), + /** + * Dynamic error occurring if a ChangeRequest is deprecated. + */ + REMOVED_CHANGE_REQUEST_IS_DEPRECATED("The LMR Change Request {} is deprecated, which is not authorized for an LMR.", "La modification suivante n’est pas un changeRequest non déprécié : {}."), + /** + * Dynamic error occurring if a ChangeRequest has several revisions under a Unit. + */ + SEVERAL_REVISIONS_OF_RETRIEVED_CHANGE_REQUEST_ARE_COMPATIBLE_WITH_BEFORE_EFFECTIVITY("Several revisions of retrieved ChangeRequest {} are compatible with the ‘Before’ effectivity.", "Plusieurs révisions du ChangeRequest {} retiré sont compatibles avec l’effectivité ‘Avant’ saisie."), + /** + * Error occurring if the User has input an invalid ID or UID. + */ + OBJECT_DOES_NOT_EXIST("The Object does not seem to exist in Tc", "L’objet demandé n’existe pas"), + + NO_DATA_COULD_BE_EXTRACTED_NO_FROZEN_OR_OPEN_UNIT_TO_THE_PRODUCT("No data could be extracted, no open or frozen Unit found for this Product.", "Aucune donnée n’a pu etre extraite, aucun Unit ouvert ou gelé trouvé pour ce Produit."), + NO_DATA_COULD_BE_EXTRACTED_NO_OPEN_UNIT_TO_THE_PRODUCT("No data could be extracted, no open Unit found for this Product.", "Aucune donnée n’a pu etre extraite, aucun Unit ouvert trouvé pour ce Produit."), + + NO_DATA_EXTRACTED_FOR_CRITERIA("No data could be extracted for the criteria.", "Aucune donnée n’a pu etre extraite pour les critères saisis."), + + NO_CONFIGURATION_CHANGES("No configuration changes. Report generation canceled.", "Aucune configuration en évolution. La génération du rapport a été annulée"), + INVALID_FILE("Invalid file. Report generation canceled.", "Fichier non conforme. La génération du rapport a été annulée"), + + // Created for R24 + /** + * Error occurring if no generics exist for the Product-Unit. + */ + NO_GENERIC_FOUND_FOR_THIS_PU("No data could be extracted, no generic found for this Product/Unit or Product.", "Aucune donnée n’a pu etre extraite, aucun générique trouvé pour ce Product/Unit ou Produit."), + + /** + * Error occurring if no data exists to be shown in the User Interface. This is normal behavior. + */ + NOTHING_TO_BE_SHOWN("Nothing to be shown", "Il n'y a rien à afficher"), + + UNABLE_TO_USE_REVISION_RULE("Unable to use the revision rule required for the report. Thank you for renewing your request.", "Impossible d’utiliser la règle de révision nécessaire à l’élaboration du rapport. Merci de renouveler votre demande."); + + protected final String msgEn; + protected final String msgFr; + + UserInputErrorEnum(final String aMsgEn, final String aMsgFr) { + msgEn = aMsgEn; + msgFr = aMsgFr; + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/filter/AllIsGoodFilter.java b/teamcenter/src/main/java/com/capgemini/reports/filter/AllIsGoodFilter.java new file mode 100644 index 0000000..772e3c1 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/filter/AllIsGoodFilter.java @@ -0,0 +1,30 @@ +package com.capgemini.reports.filter; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.snecmaobjects.ISnecmaObject; + +/** Class which implements IFilterExplosionNomenclature, always returns false which means : no part should ever be excluded. */ +public class AllIsGoodFilter implements IFilterExplosionNomenclature { + + @Override + public boolean isExcluded(TcSession session, final BOMLineHolder object) { + return false; + } + + @Override + public boolean isExcluded(final ISnecmaObject object) { + return false; + } + + @Override + public boolean isExcluded(final String type) { + return false; + } + + @Override + public boolean isIncluded(final String type) { + return true; + } + +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/filter/FilterExcludeByType.java b/teamcenter/src/main/java/com/capgemini/reports/filter/FilterExcludeByType.java new file mode 100644 index 0000000..4f44123 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/filter/FilterExcludeByType.java @@ -0,0 +1,29 @@ +package com.capgemini.reports.filter; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.resolution.filtering.TcTypeExclusionFilter; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.snecmaobjects.ISnecmaObject; + +/** Filters objects according to their type. */ +public class FilterExcludeByType extends TcTypeExclusionFilter implements IFilterExplosionNomenclature { + + /** + * Builds a Filter instance, that will ALLOW any object of the provided type. + * + * @param authorizedTypes the object types to be included + */ + public FilterExcludeByType(final String... authorizedTypes) { + super(authorizedTypes); + } + + @Override + public boolean isExcluded(TcSession session, final BOMLineHolder objectToFind) { + return super.isExcluded(objectToFind.getObjectType()); + } + + @Override + public boolean isExcluded(final ISnecmaObject object) { + return super.isExcluded(object.getType()); + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/filter/FilterIncludeByType.java b/teamcenter/src/main/java/com/capgemini/reports/filter/FilterIncludeByType.java new file mode 100644 index 0000000..a5b13e6 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/filter/FilterIncludeByType.java @@ -0,0 +1,30 @@ +package com.capgemini.reports.filter; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.resolution.filtering.TcTypeInclusionFilter; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.snecmaobjects.ISnecmaObject; + + +/** Filters objects according to their type. */ +public class FilterIncludeByType extends TcTypeInclusionFilter implements IFilterExplosionNomenclature { + + /** + * Builds a Filter instance, that will ALLOW any object of the provided type. + * + * @param authorizedTypes the object types to be included + */ + public FilterIncludeByType(final String... authorizedTypes) { + super(authorizedTypes); + } + + @Override + public boolean isExcluded(TcSession session, final BOMLineHolder objectToFind) { + return super.isExcluded(objectToFind.getObjectType()); + } + + @Override + public boolean isExcluded(final ISnecmaObject object) { + return super.isExcluded(object.getType()); + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/filter/IFilterExplosionNomenclature.java b/teamcenter/src/main/java/com/capgemini/reports/filter/IFilterExplosionNomenclature.java new file mode 100644 index 0000000..8e0c065 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/filter/IFilterExplosionNomenclature.java @@ -0,0 +1,28 @@ +package com.capgemini.reports.filter; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.resolution.filtering.ITcTypeFilter; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.snecmaobjects.ISnecmaObject; + +/** Interface for classes that can act as filters on a series of {@link BOMLineHolder}s or {@link ISnecmaObject}s. */ +public interface IFilterExplosionNomenclature extends ITcTypeFilter { + + /** + * Tests the provided object for exclusion. + * + * + * @param session + * @param object the object to be tested + * @return true if the object should be excluded + */ + boolean isExcluded(TcSession session, final BOMLineHolder object); + + /** + * Tests the provided object for exclusion. + * + * @param object the object to be tested + * @return true if the object should be excluded + */ + boolean isExcluded(final ISnecmaObject object); +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/releasestatus/DefaultRevisionSelector.java b/teamcenter/src/main/java/com/capgemini/reports/releasestatus/DefaultRevisionSelector.java new file mode 100644 index 0000000..ed85953 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/releasestatus/DefaultRevisionSelector.java @@ -0,0 +1,69 @@ +package com.capgemini.reports.releasestatus; + +import com.capgemini.framework.common.TeamcenterDateFormatter; +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.object.pom.status.StatusEnum; +import com.capgemini.framework.teamcenter.queries.saved.modelobject.ItemRevisionQuery; +import com.capgemini.reports.teamcenter.ObjectInfoHelper; +import com.google.common.base.Optional; +import com.teamcenter.soa.client.model.strong.Item; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import lombok.extern.slf4j.Slf4j; + +import java.util.Calendar; +import java.util.List; + +/** + * This class is a Default Selector of Revision. Its job is to return the latest {@link ItemRevision} of the {@link Item}.
    + * First looks for the revision which has the TcReleaseStatus with the latest release_date (that is before the embedded deadline).
    + * If no Revision have a TcReleaseStatus, or if none of these statuses have a release date, then returns the Revision with the latest last_mod_date (that is before the provided deadline). + */ +@Slf4j +public class DefaultRevisionSelector implements RevisionSelector { + + private static final long serialVersionUID = 8373335997828920471L; + + private final Calendar deadline; + + private final StatusEnum[] allowedStatuses; + + /** + * Builds a {@link DefaultRevisionSelector} with a {@link Calendar} as a deadline (for release date/mod date) and an (optional) list of allowed TcReleaseStatus. + * + * @param deadline deadline: no status set after this date is allowed / no Revision modified after this date either. If null, all dates are allowed. + * @param allowedStatuses a list of allowed {@link StatusEnum}. If empty, all status are accepted + */ + public DefaultRevisionSelector(final Calendar deadline, final StatusEnum... allowedStatuses) { + this.deadline = deadline; + this.allowedStatuses = allowedStatuses; + } + + /** + * Returns the latest {@link ItemRevision} of the {@link Item}.
    + * First looks for the revision which has the TcReleaseStatus with the latest release_date (that is before the embedded deadline). This TcReleaseStatus must also be in an allowed status (see constructor).
    + * If no Revision have a TcReleaseStatus, or if none of these statuses have a release date, or if no status is allowed, then returns the Revision with the latest last_mod_date (that is before the provided deadline). + * + * @param session an active {@link TcSession} + * @param item the {@link Item} for which we need to find a Revision + * @return ItemRevision the most Up-to-date Revision + */ + @Override + public RevisionStatusAndDate selectRevision(final TcSession session, final Item item) { + String itemID = item.get_item_id(); + String deadLineStr = deadline == null ? "no date" : TeamcenterDateFormatter.formatCalendarToPattern(deadline, "yyyy-MMM-dd"); + log.debug("START findAll correct revision for Item in pseudo-folder of an Alternate or Det {}, with date {}", itemID, deadLineStr); + + List itemsRevision = new ItemRevisionQuery(session).searchID(itemID).findAll(); + Optional bestRevision = ObjectInfoHelper.getRevisionAndStatusWithMostRecentReleaseDate(session, itemsRevision, deadline, allowedStatuses); + if (bestRevision.isPresent()) { + RevisionStatusAndDate rev = bestRevision.get(); + log.debug("The highest revision of the Item {} is {}, it has the latest realease_date", itemID, + rev.getItemRevision().get_item_revision_id()); + return bestRevision.get(); + } else { + RevisionStatusAndDate latestItemRev = ObjectInfoHelper.getRevisionAndStatusWithMostRecentModificationDate(itemsRevision, deadline); + log.debug("The highest revision of the Item {} is {}, it has the latest last_mod_date", itemID, latestItemRev.getItemRevision().get_item_revision_id()); + return latestItemRev; + } + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/releasestatus/EffectivityBehaviourHelper.java b/teamcenter/src/main/java/com/capgemini/reports/releasestatus/EffectivityBehaviourHelper.java new file mode 100644 index 0000000..661f45d --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/releasestatus/EffectivityBehaviourHelper.java @@ -0,0 +1,99 @@ +package com.capgemini.reports.releasestatus; + +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import lombok.EqualsAndHashCode; + +import java.io.Serializable; +import java.util.regex.Pattern; + +/** + * This Helper class presents methods for specifying a visitor's behaviour regarding parts with effectivities. + */ +@EqualsAndHashCode +public final class EffectivityBehaviourHelper implements Serializable { + + private static final long serialVersionUID = 4967460714547927907L; + private static final Pattern UNIT_EFFECTIVITY_PATTERN = Pattern.compile(".*((Configuré en utilisant Numéro d'unité)|(Configured Using Unit Number)).*"); + + private final EffectivityBehaviourEnum behaviour; + + private EffectivityBehaviourHelper(final EffectivityBehaviourEnum behaviour) { + this.behaviour = behaviour; + } + + /** + * Construct an TcEffectivity Behaviour which always visits Parts with any effectivity. + * + * @return the {@link EffectivityBehaviourHelper}. + */ + public static EffectivityBehaviourHelper visitAnyPart() { + return new EffectivityBehaviourHelper(EffectivityBehaviourEnum.ALWAYS_VISIT); + } + + /** + * Construct an TcEffectivity Behaviour which only visits Parts with UNIT effectivity. + * + * @return the {@link EffectivityBehaviourHelper}. + */ + public static EffectivityBehaviourHelper visitOnlyUnitManagedParts() { + return new EffectivityBehaviourHelper(EffectivityBehaviourEnum.ONLY_UNIT_MANAGED); + } + + private static boolean referencesUnit(final String blConfigString) { + return UNIT_EFFECTIVITY_PATTERN.matcher(blConfigString).matches(); + } + + /** + * Returns true if the {@link BOMLineHolder} should be visited based on the behaviour specified and the effectivity list provided.
    + * Mostly used for {@link BOMLineHolder}s holding a RF Part because these objects might have both Unit and Date effectivity.
    + * The available behaviours are the following: + *
      + *
    • ALWAYS_VISIT.
    • + *
    • ONLY_UNIT_MANAGED.
    • + *
    • ONLY_DATE_MANAGED.
    • + *
    + * + * @param aBomLineHolder the {@link BOMLineHolder} to investigate + * @return true if the object should be visited, false otherwise + */ + public boolean shouldVisit(final BOMLineHolder aBomLineHolder) { + final String blConfigString = aBomLineHolder.getBomConfig(); // The reason this bomLine is here, explained by Tc in a String + if (blConfigString == null || blConfigString.isEmpty()) { + return true; // Unknown effectivity, keep the bomLine by default + } + boolean result; + switch (behaviour) { + case ALWAYS_VISIT: + result = true; + break; + case ONLY_DATE_MANAGED: + result = !referencesUnit(blConfigString); + break; + case ONLY_UNIT_MANAGED: + result = referencesUnit(blConfigString); + break; + default: + result = true; + break; + } + return result; + } + + /** + * Desired behaviour regarding effectivities. + */ + private enum EffectivityBehaviourEnum { + /** + * Always visit regardless of effectivities. + */ + ALWAYS_VISIT, + /** + * Only visit if the object is managed in units. + */ + ONLY_UNIT_MANAGED, + /** + * Only visit if the object is managed with date effectivities. + */ + ONLY_DATE_MANAGED + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/releasestatus/RevisionSelector.java b/teamcenter/src/main/java/com/capgemini/reports/releasestatus/RevisionSelector.java new file mode 100644 index 0000000..8835f7f --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/releasestatus/RevisionSelector.java @@ -0,0 +1,23 @@ +package com.capgemini.reports.releasestatus; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.teamcenter.soa.client.model.strong.Item; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +import java.io.Serializable; + +/** + * This interface provides an algorithm which can chose a specific Revision of an Item. + */ +public interface RevisionSelector extends Serializable { + + /** + * Returns the correct {@link ItemRevision} of the {@link Item}.
    + * The exact algorithm for selecting the Revision must be coded inside this method.
    + * + * @param session the Tc session + * @param item the {@link Item} for which we need to find a Revision + * @return ItemRevision the selected Revision + */ + RevisionStatusAndDate selectRevision(final TcSession session, final Item item); +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/releasestatus/RevisionStatusAndDate.java b/teamcenter/src/main/java/com/capgemini/reports/releasestatus/RevisionStatusAndDate.java new file mode 100644 index 0000000..0a681f9 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/releasestatus/RevisionStatusAndDate.java @@ -0,0 +1,20 @@ +package com.capgemini.reports.releasestatus; + +import com.teamcenter.soa.client.model.strong.ItemRevision; +import com.teamcenter.soa.client.model.strong.ReleaseStatus; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Calendar; + +/** + * POJO container for an {@link ItemRevision}, which was elected because of one of its {@link ReleaseStatus} or {@link Calendar}. + */ +@AllArgsConstructor +@Getter +public class RevisionStatusAndDate { + private final Calendar releaseDate; + private final ReleaseStatus releaseStatus; + private final ItemRevision itemRevision; + +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/reports/parameters/DualGenerics.java b/teamcenter/src/main/java/com/capgemini/reports/reports/parameters/DualGenerics.java new file mode 100644 index 0000000..9bd214e --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/reports/parameters/DualGenerics.java @@ -0,0 +1,50 @@ +package com.capgemini.reports.reports.parameters; + +import java.io.Serializable; + +/** + * This class carries a Product and both a Generic and a Generic Assemb below, for comparison.
    + * This class is able to present a design vue or an assembly view. + * + */ +public class DualGenerics implements Serializable { + + private static final long serialVersionUID = -2761749803279516469L; + + private final Generics generic; + private final Generics genericAssemb; + + /** + * Construct object contain generic and genericAssemb and productUnit. + * + * @param productUnit a {@link ProductUnit} + * @param genericID a Generic ID + * @param genericAssembID a Generic Assemb ID + */ + public DualGenerics(final ProductUnit productUnit, final String genericID, final String genericAssembID) { + super(); + this.generic = new Generics(productUnit, genericID, ""); + this.genericAssemb = new Generics(productUnit, "", genericAssembID); + + } + + /** + * Return generic view. + * + * @return generic + */ + public Generics asGeneric() { + return generic; + } + + /** + * Return genericAssemb view. + * + * @return genericAssemb + */ + public Generics asGenericAssemb() { + return genericAssemb; + } + + +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/reports/parameters/EffectivityDate.java b/teamcenter/src/main/java/com/capgemini/reports/reports/parameters/EffectivityDate.java new file mode 100644 index 0000000..91e3e0c --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/reports/parameters/EffectivityDate.java @@ -0,0 +1,102 @@ +package com.capgemini.reports.reports.parameters; + +import com.capgemini.framework.common.StringHelper; +import com.capgemini.framework.common.TeamcenterDateFormatter; +import lombok.EqualsAndHashCode; +import lombok.Getter; + +import java.io.Serializable; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Locale; +import java.util.TimeZone; + +/** + * Represents a date.
    + * Can represent NOW or a specific date in time. Its {@link Calendar} attribute (dateTime ) may be null to represent 'now'. + * + */ +@Getter +@EqualsAndHashCode +public class EffectivityDate implements Serializable { + + private static final long serialVersionUID = -5328049346240627147L; + + /** Is null when {@code isNow == true}. */ + private final Calendar dateTime; + private final boolean now; + + /** + * Creates a date. If the Calendar is null, the date will be the current date. + * + * @param dateTime the Calendar date + */ + public EffectivityDate(final Calendar dateTime) { + super(); + this.now = dateTime == null; + this.dateTime = dateTime; + } + + /** + * Creates a date. If the input String is null or empty, the date will be the current date. + * + * @param date the date with format : dd-MM-yyyy. + */ + public EffectivityDate(final String date) { + this.now = date == null || date.isEmpty(); + this.dateTime = now ? null : TeamcenterDateFormatter.makeTeamcenterCalendar(date); + } + + /** Creates a {@link EffectivityDate} representing the current time. */ + public EffectivityDate() { + super(); + this.dateTime = null; + this.now = true; + } + + /** + * Returns a String representation of this effectivity in a format that Tc can recognize in a query.
    + * Ex {@code 09-Feb-2015} + * + * @return the date as a {@link String}, using {@link Locale#US} + */ + public String getFormattedDateForTcRequest() { + return TeamcenterDateFormatter.translateDateFormatForRequest(dateTime); + } + + /** + * Returns a String representation of this effectivity in a format that a French User can understand.
    + * Uses : {@code dd mmmm yyyy} and {@link TimeZone}: Europe (Paris) and french Locale. Ex: {@code 08 Juillet 2015} + * + * @return the date as a {@link String}, using {@link Locale#US} + */ + public String getFormattedDateForFrenchUser() { + return TeamcenterDateFormatter.formatCalendarToFrench(now ? Calendar.getInstance() : dateTime); + } + + /** + * Format date with the GUI format: dd-MM-yyyy. + * + * @return String value of date + */ + public String formatAsInputCriteria() { + + String theFormatedDate = StringHelper.EMPTY; + + if (dateTime != null) { + SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy", Locale.FRENCH); + sdf.setTimeZone(TeamcenterDateFormatter.getParisTimeZone()); + theFormatedDate = sdf.format(dateTime.getTime()); + } + + return theFormatedDate; + } + + @Override + public String toString() { + return "TcEffectivity date : " + (now ? "now" : dateTime.getTime().toString()); + } + + + +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/reports/parameters/Generics.java b/teamcenter/src/main/java/com/capgemini/reports/reports/parameters/Generics.java new file mode 100644 index 0000000..ad5060b --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/reports/parameters/Generics.java @@ -0,0 +1,197 @@ +package com.capgemini.reports.reports.parameters; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.queries.saved.modelobject.ItemQuery; +import com.capgemini.reports.exceptions.NotFoundException; +import com.teamcenter.soa.client.model.strong.Item; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; + +import java.io.Serializable; +import java.util.List; + +/** + * This class gathers information about a product (+unit), and optionally a generic or a generic assemb.
    + * This class allows either:
    + *
      + *
    • A product and its unit
    • + *
    • A product, its unit, and a Generic that exists under this product
    • + *
    • A product, its unit, and a GenericAssemb that exists under this product
    • + *
    + */ +@Slf4j +@Getter +@EqualsAndHashCode +public class Generics implements Serializable { + + private static final long serialVersionUID = 2362411651537951479L; + private static final String GENERIC_BOM = "GenericBom"; + private static final String ASSEMBLY_BOM = "AssemblyBom"; + private static final String TECHNICAL_BOM = "TechnicalBom"; + private final String generic; + private final String genericAssemb; + private final String revision; + private final ProductUnit productUnit; + private final GenericType type; + + + /** + * Constructs a {@link Generics}. + * + * @param productUnit a {@link ProductUnit} (mandatory) + * @param genericID (may be null) + * @param genericAssembID (may be null) + */ + public Generics(final ProductUnit productUnit, final String genericID, final String genericAssembID) { + super(); + this.productUnit = productUnit; + if (genericID != null && !genericID.isEmpty()) { + this.type = GenericType.GENERIC; + this.generic = genericID; + this.genericAssemb = null; + } else { + if (genericAssembID != null && !genericAssembID.isEmpty()) { + this.type = GenericType.GENERIC_ASSEMB; + this.generic = null; + this.genericAssemb = genericAssembID; + } else { + this.type = GenericType.ONLY_PRODUCT; + this.generic = null; + this.genericAssemb = null; + } + } + // The parameter revision is not used via this constructor. + this.revision = null; + } + + /** + * Constructs a {@link Generics} Revision. + * + * @param productUnit a {@link ProductUnit} (mandatory) + * @param genericID (may be null) + * @param genericAssembID (may be null) + * @param genericRevision (may be null) the revision of the Generic + */ + public Generics(final ProductUnit productUnit, final String genericID, final String genericAssembID, final String genericRevision) { + super(); + this.productUnit = productUnit; + if (genericID != null && !genericID.isEmpty()) { + this.type = GenericType.GENERIC; + this.generic = genericID; + this.genericAssemb = null; + } else { + if (genericAssembID != null && !genericAssembID.isEmpty()) { + this.type = GenericType.GENERIC_ASSEMB; + this.generic = null; + this.genericAssemb = genericAssembID; + } else { + this.type = GenericType.ONLY_PRODUCT; + this.generic = null; + this.genericAssemb = null; + } + } + this.revision = genericRevision; + } + + /** + * Returns the corresponding Teamcenter {@link Item} (a product, Generic or Generic Assemb). + * + * @param session the {@link TcSession} to perform the query. + * @return the {@link Item} representing the item. + * @throws NotFoundException if no reults were found + */ + public Item getItem(final TcSession session) throws NotFoundException { + ItemQuery savedQuery = new ItemQuery(session); + switch (this.type) { + case GENERIC: + savedQuery.searchID(generic); + break; + case GENERIC_ASSEMB: + savedQuery.searchID(genericAssemb); + break; + case ONLY_PRODUCT: + savedQuery.searchID(productUnit.getProductID()); + break; + default: + String msg = "Undefined Generics state: cannot obtain the ItemRevision"; + log.error(msg); + throw new NotFoundException(msg); + } + List results = savedQuery.findAll(); + if (results == null || results.isEmpty()) { + throw new NotFoundException("No Generic found with the provided ID"); + } + return results.get(0); + } + + /** + * Returns the corresponding item ID (of the product, Generic or Generic Assemb). + * + * @return the item ID + */ + public String getID() { + String returnStr; + switch (this.type) { + case GENERIC: + returnStr = generic; + break; + case GENERIC_ASSEMB: + returnStr = genericAssemb; + break; + case ONLY_PRODUCT: + returnStr = productUnit.getProductID(); + break; + default: + log.warn("Undefined Generics state: cannot select an itemID"); + returnStr = ""; + break; + } + return returnStr; + } + + @Override + public String toString() { + String returnStr; + switch (type) { + case GENERIC: + returnStr = "Generic: " + generic; + break; + case GENERIC_ASSEMB: + returnStr = "Generic Assemb: " + genericAssemb; + break; + case ONLY_PRODUCT: + returnStr = "No Generics selected, using father Product: " + productUnit.getProductID(); + break; + default: + returnStr = "Undefined Generics state: defaulting to father Product: " + productUnit.getProductID(); + break; + } + return returnStr; + } + + /** + * Represents a Product-Unit, and some optional Generic or GenericAssemb under it. + */ + @Getter + public enum GenericType { + /** + * Represents only a product-unit. Follows a BomView named "TechnicalBom". + */ + ONLY_PRODUCT(TECHNICAL_BOM), + /** + * Represents a product-unit and a generic under it. Follows a BomView named "GenericBOM". + */ + GENERIC(GENERIC_BOM), + /** + * Represents a product-unit and a genericAssemb under it. Follows a BomView named "AssemblyBOM". + */ + GENERIC_ASSEMB(ASSEMBLY_BOM); + + private final String bomLinkType; + + GenericType(final String bomLinkType) { + this.bomLinkType = bomLinkType; + } + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/reports/parameters/IChecker.java b/teamcenter/src/main/java/com/capgemini/reports/reports/parameters/IChecker.java new file mode 100644 index 0000000..51fbe00 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/reports/parameters/IChecker.java @@ -0,0 +1,20 @@ +package com.capgemini.reports.reports.parameters; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.reports.exceptions.InvalidUserInputException; + +/** + * Represents some required checks for the report parameters.
    + * This interface offers a {@link #check(TcSession)} method which will validate the user inputs. + */ +public interface IChecker { + + /** + * This method performs checks on the validity of the user inputs.
    + * + * @param session the {@link TcSession} to be used to check data from the Teamcenter servers. + * @throws InvalidUserInputException a {@link InvalidUserInputException} must be raised when the check has failed. + */ + void check(final TcSession session) throws InvalidUserInputException; + +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/reports/parameters/MonoMulti.java b/teamcenter/src/main/java/com/capgemini/reports/reports/parameters/MonoMulti.java new file mode 100644 index 0000000..71bf34d --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/reports/parameters/MonoMulti.java @@ -0,0 +1,28 @@ +package com.capgemini.reports.reports.parameters; + +/** + * This class represent the choice of using mono-level or multi-level BOM explosion. + * + */ +public enum MonoMulti { + /** The MONO type of resolution structure. */ + MONO, + /** The MULTI type of resolution structure. */ + MULTI; + + /** + * Constructs a {@link MonoMulti} according to user input. + * + * @param input a String containing the user input. + * @return the {@link MonoMulti} + */ + public static MonoMulti build(final String input) { + // Checking mono-multi + if ("multi".equalsIgnoreCase(input)) { + return MULTI; + } + else { + return MONO; + } + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/reports/parameters/ProductUnit.java b/teamcenter/src/main/java/com/capgemini/reports/reports/parameters/ProductUnit.java new file mode 100644 index 0000000..90274fd --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/reports/parameters/ProductUnit.java @@ -0,0 +1,106 @@ +package com.capgemini.reports.reports.parameters; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.queries.saved.modelobject.ItemQuery; +import com.capgemini.reports.exceptions.InvalidUserInputException; +import com.capgemini.reports.exceptions.UserInputErrorEnum; +import com.teamcenter.soa.client.model.strong.Item; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import lombok.EqualsAndHashCode; +import lombok.extern.slf4j.Slf4j; + +import java.io.Serializable; + +/** + * Represents a Product-unit association.
    + */ +@Slf4j +@EqualsAndHashCode +public class ProductUnit implements Serializable { + private static final long serialVersionUID = -2970983080244741025L; + + private static final String EMPTY = ""; + + private final String productID; + + /** + * This is the raw user input String. + */ + private final String unitStr; + + /** + * This is the validated user input integer. + */ + private int unit; + + public ProductUnit(String productID) { + this(productID, null); + } + + /** + * Basic constructor. + * + * @param productID the ID of the product + * @param unit a unit + */ + public ProductUnit(final String productID, final int unit) { + super(); + this.productID = productID; + this.unit = unit; + this.unitStr = String.valueOf(unit); + } + + /** + * Basic constructor. + * + * @param productID the ID of the product + * @param unitStr a unit (String representation) + */ + public ProductUnit(final String productID, final String unitStr) { + super(); + this.productID = productID == null ? EMPTY : productID; + this.unitStr = unitStr == null ? EMPTY : unitStr; + } + + /** + * Parse the unit String. After the parsing, the integer unit becomes available for further processing. + * + * @throws InvalidUserInputException if the unit could not be understood + */ + public void parseUserUnit() throws InvalidUserInputException { + try { + this.unit = Integer.parseInt(unitStr); + } catch (NumberFormatException e) { + UserInputErrorEnum unitNotNumeric = UserInputErrorEnum.UNIT_NOT_NUMERIC; + log.error(unitNotNumeric.getMsgEn() + ": \"" + unitStr + "\" ", e); + throw new InvalidUserInputException(unitNotNumeric, e); + } + } + + /** + * Returns the corresponding Teamcenter item (a product, Generic or Generic Assemb). + * + * @param session the {@link TcSession} to perform the query. + * @return the {@link ItemRevision} representing the end item. + */ + public Item getProduct(final TcSession session) { + return new ItemQuery(session).searchID(productID).findAll().get(0); + } + + public String getProductID() { + return productID; + } + + public int getUnit() { + return unit; + } + + public String getUnitStr() { + return unitStr; + } + + @Override + public String toString() { + return productID + "-" + unitStr; + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/reports/parameters/SuperModel.java b/teamcenter/src/main/java/com/capgemini/reports/reports/parameters/SuperModel.java new file mode 100644 index 0000000..418f319 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/reports/parameters/SuperModel.java @@ -0,0 +1,116 @@ +package com.capgemini.reports.reports.parameters; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.queries.saved.modelobject.ItemQuery; +import com.capgemini.reports.exceptions.NotFoundException; +import com.teamcenter.soa.client.model.strong.Item; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; + +import java.io.Serializable; +import java.util.List; + +/** + * This class gathers information about a product (+unit), and optionally a generic or a generic assemb.
    + * This class allows either:
    + *
      + *
    • A product and its unit
    • + *
    • A product, its unit, and a Generic that exists under this product
    • + *
    • A product, its unit, and a GenericAssemb that exists under this product
    • + *
    + */ +@Slf4j +@Getter +@EqualsAndHashCode +public class SuperModel implements Serializable { + + private static final long serialVersionUID = 2362411651537951479L; + private static final String GENERIC_BOM = "GenericBom"; + private static final String ASSEMBLY_BOM = "AssemblyBom"; + private static final String TECHNICAL_BOM = "TechnicalBom"; + private final String supermodel; + private final String revision; + private final ProductUnit productUnit; + + + /** + * Constructs a {@link SuperModel}. + * + * @param productUnit a {@link ProductUnit} (mandatory) + * @param supermodel (mandatory) + */ + public SuperModel(final ProductUnit productUnit, final String supermodel) { + super(); + this.productUnit = productUnit; + this.supermodel = supermodel; + // The parameter revision is not used via this constructor. + this.revision = null; + } + + /** + * Constructs a {@link SuperModel} Revision. + * + * @param productUnit a {@link ProductUnit} (mandatory) + * @param supermodel (may be null) + * @param revision (may be null) the revision of the Supermodel + */ + public SuperModel(final ProductUnit productUnit, final String supermodel, final String revision) { + super(); + this.productUnit = productUnit; + this.supermodel = supermodel; + this.revision = revision; + } + + /** + * Returns the corresponding Teamcenter {@link Item} (a product, Generic or Generic Assemb). + * + * @param session the {@link TcSession} to perform the query. + * @return the {@link Item} representing the item. + * @throws NotFoundException if no reults were found + */ + public Item getItem(final TcSession session) throws NotFoundException { + ItemQuery savedQuery = new ItemQuery(session); + savedQuery.searchID(supermodel); + List results = savedQuery.findAll(); + if (results == null || results.isEmpty()) { + throw new NotFoundException("No Super Model found with the provided ID"); + } + return results.get(0); + } + + /** + * Represents a Product-Unit, and some optional Generic or GenericAssemb under it. + */ + @Getter + public enum GenericType { + /** + * Represents only a product-unit. Follows a BomView named "TechnicalBom". + */ + ONLY_PRODUCT(TECHNICAL_BOM), + /** + * Represents a product-unit and a generic under it. Follows a BomView named "GenericBOM". + */ + GENERIC(GENERIC_BOM), + /** + * Represents a product-unit and a genericAssemb under it. Follows a BomView named "AssemblyBOM". + */ + GENERIC_ASSEMB(ASSEMBLY_BOM); + + private final String bomLinkType; + + GenericType(final String bomLinkType) { + this.bomLinkType = bomLinkType; + } + } + + + /** + * Returns the corresponding item ID (of the product, Generic or Generic Assemb). + * + * @return the item ID + */ + public String getID() { + return supermodel; + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/reports/parameters/checker/EffectivityChecker.java b/teamcenter/src/main/java/com/capgemini/reports/reports/parameters/checker/EffectivityChecker.java new file mode 100644 index 0000000..3115cda --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/reports/parameters/checker/EffectivityChecker.java @@ -0,0 +1,37 @@ +package com.capgemini.reports.reports.parameters.checker; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.reports.exceptions.InvalidUserInputException; +import com.capgemini.reports.exceptions.UserInputErrorEnum; +import com.capgemini.reports.reports.parameters.EffectivityDate; +import com.capgemini.reports.reports.parameters.IChecker; +import lombok.extern.slf4j.Slf4j; + +import java.util.Calendar; + +/** + * Checks is a given {@link EffectivityDate} is in a valid state. + */ +@Slf4j +public class EffectivityChecker implements IChecker { + + private final EffectivityDate effectivity; + + /** + * Builds a {@link IChecker} to verify the validity of the provided {@link EffectivityDate}. + */ + public EffectivityChecker(final EffectivityDate effectivity) { + this.effectivity = effectivity; + } + + @Override + public void check(final TcSession session) throws InvalidUserInputException { + if (!effectivity.isNow()) { + Calendar dateTime = effectivity.getDateTime(); + if (dateTime == null) { + log.error("EffectivityDate state is invalid: Calendar is null but TcEffectivity is not NOW."); + throw new InvalidUserInputException(UserInputErrorEnum.INTERNAL_ERROR); + } + } + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/reports/parameters/checker/GenericConditionR21Checker.java b/teamcenter/src/main/java/com/capgemini/reports/reports/parameters/checker/GenericConditionR21Checker.java new file mode 100644 index 0000000..713cd6a --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/reports/parameters/checker/GenericConditionR21Checker.java @@ -0,0 +1,89 @@ +package com.capgemini.reports.reports.parameters.checker; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.reports.exceptions.InvalidUserInputException; +import com.capgemini.reports.exceptions.NotFoundException; +import com.capgemini.reports.exceptions.UserInputErrorEnum; +import com.capgemini.reports.reports.parameters.DualGenerics; +import com.capgemini.reports.reports.parameters.IChecker; +import com.capgemini.reports.reports.parameters.ProductUnit; +import com.capgemini.reports.teamcenter.ObjectInfoHelper; +import com.capgemini.reports.teamcenter.ObjectInfoLoader; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +import java.util.List; + +/** + * Checks some conditions on a Generic for the R21 report. + */ +public class GenericConditionR21Checker implements IChecker { + + private final ProductUnit productUnit; + private final DualGenerics dualGenerics; + + /** + * Define productUnit and dualGenerics configuration. + * + * @param productUnit a {@link ProductUnit} + * @param dualGenerics a {@link DualGenerics} + */ + public GenericConditionR21Checker(final ProductUnit productUnit, final DualGenerics dualGenerics) { + this.productUnit = productUnit; + this.dualGenerics = dualGenerics; + } + + + @Override + public void check(final TcSession session) throws InvalidUserInputException { + checkGenericConditionR21(session); + checkGenericAssembConditionR21(session); + } + + private void checkGenericConditionR21(final TcSession session) throws InvalidUserInputException { + + // Parse user input + productUnit.parseUserUnit(); + int userUnit = productUnit.getUnit(); + + ObjectInfoLoader objectInfoLoader = new ObjectInfoLoader(session); + // Get existing units in Database + try { + List genericsRevision = objectInfoLoader.getGenericUnderProduct(dualGenerics.asGeneric(), productUnit); + if (genericsRevision == null || genericsRevision.isEmpty()) { + throw new InvalidUserInputException(UserInputErrorEnum.GENERIC_DOES_NOT_EXIST); + } + boolean isGenericHasAnUnitRevision = ObjectInfoHelper.getClosestGenerics(session, dualGenerics.asGeneric().getID(), userUnit, genericsRevision); + + if (!isGenericHasAnUnitRevision) { + throw new InvalidUserInputException(UserInputErrorEnum.NO_DATA_COULD_BE_EXTRACTED_FOR_GENERIC_PRODUCT_AND_UNIT); + } + } catch (NotFoundException e) { + throw new InvalidUserInputException(UserInputErrorEnum.NO_DATA_COULD_BE_EXTRACTED_FOR_GENERIC_PRODUCT_AND_UNIT, e); + } + + } + + private void checkGenericAssembConditionR21(final TcSession session) throws InvalidUserInputException { + // Parse user input + productUnit.parseUserUnit(); + int userUnit = productUnit.getUnit(); + + ObjectInfoLoader objectInfoLoader = new ObjectInfoLoader(session); + // Get existing units in Database + try { + List genericsAssembRevision = objectInfoLoader.getGenericAssembUnderProduct(dualGenerics.asGenericAssemb(), productUnit); + if (genericsAssembRevision == null || genericsAssembRevision.isEmpty()) { + throw new InvalidUserInputException(UserInputErrorEnum.GENERIC_ASSEMB_DOES_NOT_EXIST); + } + boolean isGenericHasAnUnitRevision = + ObjectInfoHelper.getClosestGenerics(session, dualGenerics.asGenericAssemb().getID(), userUnit, genericsAssembRevision); + + if (!isGenericHasAnUnitRevision) { + throw new InvalidUserInputException(UserInputErrorEnum.NO_DATA_COULD_BE_EXTRACTED_FOR_GENERIC_PRODUCT_AND_UNIT); + } + } catch (NotFoundException e) { + throw new InvalidUserInputException(UserInputErrorEnum.NO_DATA_COULD_BE_EXTRACTED_FOR_GENERIC_PRODUCT_AND_UNIT, e); + } + } + +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/reports/parameters/checker/GenericExistenceChecker.java b/teamcenter/src/main/java/com/capgemini/reports/reports/parameters/checker/GenericExistenceChecker.java new file mode 100644 index 0000000..aef5785 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/reports/parameters/checker/GenericExistenceChecker.java @@ -0,0 +1,64 @@ +package com.capgemini.reports.reports.parameters.checker; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.queries.saved.modelobject.ItemQuery; +import com.capgemini.reports.exceptions.InvalidUserInputException; +import com.capgemini.reports.exceptions.UserInputErrorEnum; +import com.capgemini.reports.reports.parameters.Generics; +import com.capgemini.reports.reports.parameters.IChecker; +import com.teamcenter.soa.client.model.strong.Item; +import lombok.extern.slf4j.Slf4j; + +import java.util.List; + +/** + * This class checks if a Generics (which represents a Generic and/or GenericAssemb) exists within the TC database. + */ +@Slf4j +public class GenericExistenceChecker implements IChecker { + + protected final Generics generics; + + public GenericExistenceChecker(final Generics generics) { + this.generics = generics; + } + + @Override + public void check(final TcSession session) throws InvalidUserInputException { + switch (generics.getType()) { + case GENERIC: + genericExists(session); + break; + case GENERIC_ASSEMB: + genericAssembExists(session); + break; + case ONLY_PRODUCT: + break; + default: + log.error("Unsupported Enum value"); + break; + } + } + + protected void genericExists(final TcSession session) throws InvalidUserInputException { + List list = new ItemQuery(session).searchID(generics.getGeneric()).searchGeneric().findAll(); + if (list == null || list.isEmpty()) { + throw new InvalidUserInputException(getTechnicalErrorMsg()); + } + } + + protected UserInputErrorEnum getTechnicalErrorMsg() { + return UserInputErrorEnum.GENERIC_DOES_NOT_EXIST; + } + + private void genericAssembExists(final TcSession session) throws InvalidUserInputException { + List list = new ItemQuery(session).searchID(generics.getGenericAssemb()).searchGenericAssemb().findAll(); + if (list == null || list.isEmpty()) { + throw new InvalidUserInputException(getAssemblyErrorMsg()); + } + } + + private UserInputErrorEnum getAssemblyErrorMsg() { + return UserInputErrorEnum.GENERIC_ASSEMB_DOES_NOT_EXIST; + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/reports/parameters/checker/GenericUnderProductUnitChecker.java b/teamcenter/src/main/java/com/capgemini/reports/reports/parameters/checker/GenericUnderProductUnitChecker.java new file mode 100644 index 0000000..a46a5e1 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/reports/parameters/checker/GenericUnderProductUnitChecker.java @@ -0,0 +1,98 @@ +package com.capgemini.reports.reports.parameters.checker; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.reports.exceptions.InvalidUserInputException; +import com.capgemini.reports.exceptions.NotFoundException; +import com.capgemini.reports.exceptions.UserInputErrorEnum; +import com.capgemini.reports.reports.parameters.Generics; +import com.capgemini.reports.reports.parameters.IChecker; +import com.capgemini.reports.reports.parameters.ProductUnit; +import com.capgemini.reports.teamcenter.ObjectInfoLoader; +import lombok.extern.slf4j.Slf4j; + +import java.util.List; + +/** + * This class checks if a {@link Generics}' Generic and/or GenericAssemb exist under the {@link Generics}' Product-Unit. + */ +@Slf4j +public class GenericUnderProductUnitChecker implements IChecker { + + private final Generics generics; + + /** + * Simple Constructor. + * + * @param generic the {@link Generics} + */ + public GenericUnderProductUnitChecker(final Generics generic) { + this.generics = generic; + } + + @Override + public void check(final TcSession session) throws InvalidUserInputException { + switch (generics.getType()) { + case GENERIC: + genericExists(session); + break; + case GENERIC_ASSEMB: + genericAssembExists(session); + break; + case ONLY_PRODUCT: + break; + default: + log.error("Unsupported Enum value, defaulting to ONLY_PRODUCT"); + break; + } + } + + /** + * Checks the generic ID. + */ + private boolean genericExists(final TcSession session) throws InvalidUserInputException { + ProductUnit productUnit = generics.getProductUnit(); + String thisGeneric = generics.getGeneric(); + try { + List genericsFound = new ObjectInfoLoader(session).getGenericsRevisionOfProduct(productUnit); + for (String existingGeneric : genericsFound) { + if (thisGeneric.equals(existingGeneric)) { + return true; + } + } + log.error("No Generic found with ID \"{}\" for productUnit={}", thisGeneric, productUnit); + log.error(" + Existing Generic IDs: {}", genericsFound); + throw new InvalidUserInputException(getTechnicalErrorMessage()); + } catch (NotFoundException e) { + throw new InvalidUserInputException(getTechnicalErrorMessage(), e); + } + } + + private UserInputErrorEnum getTechnicalErrorMessage() { + return UserInputErrorEnum.PRODUCT_UNIT_GENERIC_INVALID; + } + + /** + * Checks the generic Assemb ID. + */ + private boolean genericAssembExists(final TcSession session) throws InvalidUserInputException { + ProductUnit productUnit = generics.getProductUnit(); + String genericAssemb = generics.getGenericAssemb(); + try { + List genericsAssemb = new ObjectInfoLoader(session).getGenericsAssembliesRevisionOfProduct(productUnit); + for (String existingGenericAssemb : genericsAssemb) { + if (genericAssemb.equals(existingGenericAssemb)) { + return true; + } + } + log.error("No Generic Assemb found with ID \"{}\" for productUnit={}", genericAssemb, productUnit); + log.error(" + Existing GenericAssemb IDs: {}", genericsAssemb); + throw new InvalidUserInputException(getAssemblyErrorMessage()); + } catch (NotFoundException e) { + throw new InvalidUserInputException(getAssemblyErrorMessage(), e); + } + } + + private UserInputErrorEnum getAssemblyErrorMessage() { + return UserInputErrorEnum.PRODUCT_UNIT_GENERIC_ASSEMB_INVALID; + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/reports/parameters/checker/ModelObjectChecker.java b/teamcenter/src/main/java/com/capgemini/reports/reports/parameters/checker/ModelObjectChecker.java new file mode 100644 index 0000000..5c82f14 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/reports/parameters/checker/ModelObjectChecker.java @@ -0,0 +1,64 @@ +package com.capgemini.reports.reports.parameters.checker; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.reports.exceptions.InvalidUserInputException; +import com.capgemini.reports.exceptions.NotFoundException; +import com.capgemini.reports.exceptions.UserInputErrorEnum; +import com.capgemini.reports.reports.parameters.IChecker; +import com.capgemini.reports.teamcenter.queries.DirectQuery; +import com.teamcenter.soa.client.model.ModelObject; +import com.teamcenter.soa.client.model.strong.Item; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +import java.util.regex.Pattern; + + +/** This class checks if a ModelObject exists by looking for its uid in Teamcenter. */ +public class ModelObjectChecker implements IChecker { + + private final String[] typePatterns; + private final String objectUID; + + /** + * Constructs a checker that verifies if the type of the ModelObject whose UID is provided matches any of the type filters.
    + * Note: the provided types maybe Item Master or Item Revision Types.
    + * Note2: At least one filter element must be provided. + * + * @param objectUID String UID of the ModelObject + * @param typeFilters the allowed types. Each must be an {@link Item}'s Type or {@link ItemRevision}'s type (i.e. 'DocNorm' or 'DocDrawing Revision')... + */ + public ModelObjectChecker(final String objectUID, final String... typeFilters) { + this.objectUID = objectUID; + this.typePatterns = new String[typeFilters.length]; + + for (int num = 0; num < typeFilters.length; num++) { + this.typePatterns[num] = ".*" + typeFilters[num] + ".*"; + } + } + + @Override + public void check(final TcSession session) throws InvalidUserInputException { + if (typePatterns.length == 0) { + throw new InvalidUserInputException("No Type pattern was specified"); // Should never happen: one must not build a checker without at least one filter element + } + + ModelObject modelObject; + try { + modelObject = new DirectQuery<>(session).searchByUID(objectUID); + } + catch (NotFoundException e) { + throw new InvalidUserInputException(UserInputErrorEnum.OBJECT_DOES_NOT_EXIST, e); + } + + String actualType = modelObject.getTypeObject().getName(); + + for (String type : typePatterns) { + if (Pattern.matches(type, actualType)) { + return; // Type is ok + } + } + // If we findAll here type is not authorised + throw new InvalidUserInputException(UserInputErrorEnum.TYPE_DOCUMENT_SELECTED_NOT_AUTHORIZED); + } + +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/reports/parameters/checker/ObjectTypeChecker.java b/teamcenter/src/main/java/com/capgemini/reports/reports/parameters/checker/ObjectTypeChecker.java new file mode 100644 index 0000000..c6d6a76 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/reports/parameters/checker/ObjectTypeChecker.java @@ -0,0 +1,63 @@ +package com.capgemini.reports.reports.parameters.checker; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.queries.saved.modelobject.ItemQuery; +import com.capgemini.reports.exceptions.InvalidUserInputException; +import com.capgemini.reports.exceptions.UserInputErrorEnum; +import com.capgemini.reports.reports.parameters.IChecker; +import com.teamcenter.soa.client.model.strong.Item; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +import java.util.List; +import java.util.regex.Pattern; + +/** + * Checks if the provided itemId belongs to one of the types provided.
    + * Note: the provided types must be Item Types, not ItemRevision types (i.e. 'PartAero' or 'Standard' are ok, but not 'PartAero Revision'. + */ +public class ObjectTypeChecker implements IChecker { + + private final String itemId; + private final String[] typePatterns; + + /** + * Constructs a checker tht verifies if the type of the Item whose ID is provided matches any of the type filters.
    + * Note: the provided types must be Item Types, not ItemRevision types (i.e. 'PartAero' or 'Standard' are ok, but not 'PartAero Revision'.
    + * Note2: At least one filter element must be provided. + * + * @param itemId the Id of the Item + * @param typeFilters the provided types. Each must be {@link Item} Type, not {@link ItemRevision} type (i.e. 'PartAero' or 'Standard' are ok, but not 'PartAero Revision'. + */ + public ObjectTypeChecker(final String itemId, final String... typeFilters) { + this.itemId = itemId; + this.typePatterns = new String[typeFilters.length]; + for (int num = 0; num < typeFilters.length; num++) { + this.typePatterns[num] = ".*" + typeFilters[num] + ".*"; + } + } + + @Override + public void check(final TcSession session) throws InvalidUserInputException { + if (typePatterns.length == 0) { + throw new InvalidUserInputException("No Type pattern was specified"); // Should never happen: one must not build a checker without at least one filter element + } + List items = new ItemQuery(session).searchID(itemId).findAll(); + if (items == null || items.isEmpty()) { + throw new InvalidUserInputException(getErrorMessage()); + } + for(Item item : items) { + String actualType = item.getTypeObject().getName(); + for (String type : typePatterns) { + if (Pattern.matches(type, actualType)) { + return; // Type is ok + } + } + } + // If we findAll here type is not authorised + throw new InvalidUserInputException(getErrorMessage()); + } + + protected UserInputErrorEnum getErrorMessage() { + return UserInputErrorEnum.THE_SELECTED_OBJECT_IS_NOT_PERMITTED_ON_THIS_REPORT; + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/reports/parameters/checker/ProductChecker.java b/teamcenter/src/main/java/com/capgemini/reports/reports/parameters/checker/ProductChecker.java new file mode 100644 index 0000000..50c4cd6 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/reports/parameters/checker/ProductChecker.java @@ -0,0 +1,47 @@ +package com.capgemini.reports.reports.parameters.checker; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.queries.saved.modelobject.ItemQuery; +import com.capgemini.reports.exceptions.InvalidUserInputException; +import com.capgemini.reports.exceptions.UserInputErrorEnum; +import com.capgemini.reports.reports.parameters.IChecker; +import com.teamcenter.soa.client.model.strong.Item; +import lombok.Getter; + +import java.util.List; + +/** + * This class checks if a product exists by looking for its ID in Teamcenter. + */ +public class ProductChecker implements IChecker { + + private final String productID; + @Getter + private Item product; + + /** + * Simple constructor. + * + * @param aProductID a String + */ + public ProductChecker(final String aProductID) { + productID = aProductID; + } + + @Override + public void check(final TcSession session) throws InvalidUserInputException { + if (productID == null || productID.isEmpty()) { + throw new InvalidUserInputException(getErrorMsg()); + } + List queryObjects = new ItemQuery(session).searchID(productID).searchProduct().findAll(); + if ((queryObjects == null) || (queryObjects.isEmpty())) { + throw new InvalidUserInputException(getErrorMsg()); + } else { + product = queryObjects.get(0); + } + } + + private UserInputErrorEnum getErrorMsg() { + return UserInputErrorEnum.PRODUCT_DOES_NOT_EXIST_NO_DATA_TO_PRINT; + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/reports/parameters/checker/ProductUnitChecker.java b/teamcenter/src/main/java/com/capgemini/reports/reports/parameters/checker/ProductUnitChecker.java new file mode 100644 index 0000000..f2fbf1f --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/reports/parameters/checker/ProductUnitChecker.java @@ -0,0 +1,80 @@ +package com.capgemini.reports.reports.parameters.checker; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.reports.exceptions.InvalidUserInputException; +import com.capgemini.reports.exceptions.NotFoundException; +import com.capgemini.reports.exceptions.UserInputErrorEnum; +import com.capgemini.reports.reports.parameters.IChecker; +import com.capgemini.reports.reports.parameters.ProductUnit; +import com.capgemini.reports.teamcenter.ObjectInfoLoader; +import lombok.extern.slf4j.Slf4j; + +import java.util.List; + +/** + * This class checks if a a given Product-Unit is valid.
    + * It checks weather: + *
      + *
    • The provided unit is parseable to a numeric value
    • + *
    • The product ID provided points to a product
    • + *
    • The product has a matching unit number
    • + *
    + */ +@Slf4j +public class ProductUnitChecker implements IChecker { + + private final ProductUnit productUnit; + + /** + * Simple constructor. + * + * @param productUnit the {@link ProductUnit} to be checked. + */ + public ProductUnitChecker(final ProductUnit productUnit) { + this.productUnit = productUnit; + } + + @Override + public void check(final TcSession session) throws InvalidUserInputException { + String productID = productUnit.getProductID(); + UserInputErrorEnum productAndUnitDoesNotExist = getErrorMessage(); + try { + // Parse user input + productUnit.parseUserUnit(); + int userUnit = productUnit.getUnit(); + + // Get existing units in Database + List units = new ObjectInfoLoader(session).getUnitsOfProduct(productID); + + // check if the user input Unit exists in the list returned by Tc + for (String existingTcUnitStr : units) { + int tcUnit = parseTeamcenterUnit(existingTcUnitStr); + if (userUnit == tcUnit) { + // Found a matching unit, test passed + return; + } + } + // The check has failed if it gets here + log.error(productAndUnitDoesNotExist.getMsgEn()); + log.error("Existing units for this product ({}): {}", productID, units); + throw new InvalidUserInputException(productAndUnitDoesNotExist); + } catch (NotFoundException e) { + throw new InvalidUserInputException(getErrorMessage(), e); + + } + } + + protected UserInputErrorEnum getErrorMessage() { + return UserInputErrorEnum.PRODUCT_AND_UNIT_DOES_NOT_EXIST; + } + + private int parseTeamcenterUnit(final String tcUnitStr) throws InvalidUserInputException { + try { + return Integer.parseInt(tcUnitStr); + } catch (NumberFormatException e) { + log.error("Teamcenter returned a non-parseable unit String : \"" + tcUnitStr + "\"", e); + throw new InvalidUserInputException(UserInputErrorEnum.INTERNAL_ERROR, e); + } + } + +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/reports/parameters/checker/ProductUnitGenericChecker.java b/teamcenter/src/main/java/com/capgemini/reports/reports/parameters/checker/ProductUnitGenericChecker.java new file mode 100644 index 0000000..2ed0c34 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/reports/parameters/checker/ProductUnitGenericChecker.java @@ -0,0 +1,110 @@ +package com.capgemini.reports.reports.parameters.checker; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.queries.saved.modelobject.ItemRevisionQuery; +import com.capgemini.reports.changeobjects.UnitRevision; +import com.capgemini.reports.exceptions.InvalidUserInputException; +import com.capgemini.reports.exceptions.UserInputErrorEnum; +import com.capgemini.reports.reports.parameters.IChecker; +import com.capgemini.reports.reports.parameters.ProductUnit; +import com.capgemini.reports.snecmaobjects.generic.AbstractGenericRevision; +import com.capgemini.reports.teamcenter.ObjectInfoHelper; +import com.teamcenter.soa.client.model.ModelObject; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.List; + +import static com.capgemini.framework.teamcenter.object.SnecmaObjectProperties.PV_UNIT; + +/** + * This class checks if a a given Product-Unit-Generic is valid. + */ +@Slf4j +public class ProductUnitGenericChecker implements IChecker { + + private final String genericId; + private final ProductUnit productUnit; + + /** + * Constructor. + * + * @param genericId String - the generic Id + * @param productUnit {@link ProductUnit} + */ + public ProductUnitGenericChecker(final String genericId, final ProductUnit productUnit) { + this.genericId = genericId; + this.productUnit = productUnit; + } + + private static List transformArray(final ModelObject[] objects) { + List newList = new ArrayList<>(); + for (ModelObject object : objects) { + newList.add((ItemRevision) object); + } + return newList; + } + + @Override + public void check(final TcSession session) throws InvalidUserInputException { + productUnit.parseUserUnit(); + + // Find the product + List productRevisions = new ItemRevisionQuery(session).searchID(productUnit.getProductID()).findAll(); + if (productRevisions == null || productRevisions.isEmpty()) { + throw new InvalidUserInputException( + UserInputErrorEnum.WRONG_EFFECTIVITY_THE_PRODUCT_DOES_NOT_EXIST_OR_THE_UNIT_DOES_NOT_EXIST_FOR_THE_PRODUCT); + } + ItemRevision product = productRevisions.get(0); // Only one revision of Product + + // Find the units of the product + session.loadProperties(product, PV_UNIT); + ModelObject[] objects = product.getPropertyObject(PV_UNIT).getModelObjectArrayValue(); + session.loadProperties(objects); + if (objects == null || objects.length == 0) { + throw new InvalidUserInputException( + UserInputErrorEnum.WRONG_EFFECTIVITY_THE_PRODUCT_DOES_NOT_EXIST_OR_THE_UNIT_DOES_NOT_EXIST_FOR_THE_PRODUCT); + } + + // Find Unit Revision + List result = UnitRevision.getItemRevisionWithSameRange(session, productUnit.getUnitStr(), transformArray(objects)); + if (result.isEmpty()) { + throw new InvalidUserInputException( + UserInputErrorEnum.WRONG_EFFECTIVITY_THE_PRODUCT_DOES_NOT_EXIST_OR_THE_UNIT_DOES_NOT_EXIST_FOR_THE_PRODUCT); + } + + // Find Generic Revision + List generics = getGenericItemRevision(session); + if (generics == null) { + throw new InvalidUserInputException(UserInputErrorEnum.INTERNAL_ERROR); + } + if (generics.isEmpty()) { + throw new InvalidUserInputException(UserInputErrorEnum.GENERIC_DOES_NOT_EXIST_OR_ENTRY_EFFECTIVITY_IS_NOT_COMPATIBLE_WITH_THE_GENERIC); + } + } + + /** + * Get the appropriate Generic Revision. + * + * @param session TcSession + * @return ItemRevision the generic revision + * @throws InvalidUserInputException for the throwable exception + */ + private List getGenericItemRevision(final TcSession session) throws InvalidUserInputException { + if (!AbstractGenericRevision.isGenericRevision(genericId)) { + throw new InvalidUserInputException(UserInputErrorEnum.GENERIC_DOES_NOT_EXIST_OR_ENTRY_EFFECTIVITY_IS_NOT_COMPATIBLE_WITH_THE_GENERIC); + } + + List genericRevisions = new ItemRevisionQuery(session).searchID(genericId).findAll(); + + // Keep only the ItemRevision whose end item is the Product + List checkedGenerics = ObjectInfoHelper.getRevisionWithSameEndItem(session, genericRevisions, productUnit.getProductID()); + genericRevisions.clear(); + + // Compare effectivities + List results = ObjectInfoHelper.getRevisionWithHighestRange(session, checkedGenerics, productUnit.getUnitStr()); + checkedGenerics.clear(); + return results; + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/reports/parameters/checker/UnitRevisionChecker.java b/teamcenter/src/main/java/com/capgemini/reports/reports/parameters/checker/UnitRevisionChecker.java new file mode 100644 index 0000000..c865811 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/reports/parameters/checker/UnitRevisionChecker.java @@ -0,0 +1,131 @@ +package com.capgemini.reports.reports.parameters.checker; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.reports.exceptions.InvalidUserInputException; +import com.capgemini.reports.exceptions.NotFoundException; +import com.capgemini.reports.exceptions.UserInputErrorEnum; +import com.capgemini.reports.reports.parameters.IChecker; +import com.capgemini.reports.reports.parameters.ProductUnit; +import com.capgemini.reports.teamcenter.ObjectInfoLoader; +import com.teamcenter.soa.client.model.ModelObject; +import com.teamcenter.soa.client.model.strong.Effectivity; +import com.teamcenter.soa.client.model.strong.Item; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import com.teamcenter.soa.client.model.strong.ReleaseStatus; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.List; + +import static com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes.EFFECTIVITY; + +/** + * This class checks if a given UnitRevision is valid for a R20 report.
    + * It assumes that the Product and the unit exist (using a {@link ProductUnitChecker}.
    + * It fails if the unit does not have an effectivity matching the product ID. + */ +@Slf4j +public class UnitRevisionChecker implements IChecker { + + @Getter(value = AccessLevel.PROTECTED) + private final ProductUnit productUnit; + + /** + * Simple constructor. + * + * @param productUnit the {@link ProductUnit Product and the Unit} that need to be checked. + */ + public UnitRevisionChecker(final ProductUnit productUnit) { + this.productUnit = productUnit; + } + + @Override + public final void check(final TcSession session) throws InvalidUserInputException { + checkUnits(session); + } + + protected List checkUnits(final TcSession session) throws InvalidUserInputException { + String productID = productUnit.getProductID(); + + // Parse user input + productUnit.parseUserUnit(); + int userUnit = productUnit.getUnit(); + + // Get existing units in Database + List units = checkUnitsOfProduct(session); // Fails if none found + + // Check if the user-input Unit exists in the list returned by Tc + // No TcEffectivity could be found with matching end_item ID and a matching unit range: the check has FAILED, let's throw the correct Exception to explain Why + return checkUnitsOfProductInRange(session, productID, userUnit, units); + } + + private List checkUnitsOfProduct(final TcSession session) throws InvalidUserInputException { + try { + List theUnits = new ObjectInfoLoader(session).getUnitsOfProduct(productUnit); + if (theUnits.isEmpty()) { + throw unitNotAssociatedToProduct(); + } + return theUnits; + } catch (NotFoundException e) { + throw new InvalidUserInputException(UserInputErrorEnum.PRODUCT_AND_UNIT_DOES_NOT_EXIST, e); + } + } + + private List checkUnitsOfProductInRange(final TcSession session, final String productID, final int userUnit, final List existingUnits) + throws InvalidUserInputException { + List unitsInRange = new ArrayList<>(); + for (ItemRevision existingTcUnit : existingUnits) { + session.loadProperties(existingTcUnit, "release_status_list"); + ReleaseStatus[] releaseStatuses = existingTcUnit.get_release_status_list(); + session.loadProperties(releaseStatuses); + if (unitHasEffectivityInRange(session, releaseStatuses, productID, userUnit)) { + unitsInRange.add(existingTcUnit); + } + } + if (unitsInRange.isEmpty()) { + throw unitNotAssociatedToProduct(); + } else { + return unitsInRange; + } + } + + private boolean unitHasEffectivityInRange(final TcSession session, final ReleaseStatus[] releaseStatusList, final String productID, int userUnit) { + for (ReleaseStatus releaseStatus : releaseStatusList) { + if (!EFFECTIVITY.equals(releaseStatus.get_name())) { + continue; // skip + } + session.loadProperties(releaseStatus, "effectivities"); + ModelObject[] effectivities = releaseStatus.get_effectivities(); + session.loadProperties(effectivities); + for (ModelObject effectivityMO : effectivities) { + Effectivity effectivity = (Effectivity) effectivityMO; + session.loadProperties(effectivity, "end_item"); + Item endItem = effectivity.get_end_item(); + session.loadProperties(endItem); + if (endItem.get_item_id().equals(productID) && sameUnit(effectivity.get_unit_range_text(), userUnit)) { + // This Unit Revision has an effectivity with a matching end item and unit range! the test is PASSED + return true; + } + } + } + return false; + } + + protected InvalidUserInputException unitNotAssociatedToProduct() { + UserInputErrorEnum productAndUnitDoesNotExist = UserInputErrorEnum.PRODUCT_AND_UNIT_DOES_NOT_EXIST; + log.error(productAndUnitDoesNotExist.getMsgEn()); + return new InvalidUserInputException(productAndUnitDoesNotExist); + } + + protected InvalidUserInputException errorMessage() { + UserInputErrorEnum productAndUnitDoesNotExist = UserInputErrorEnum.PRODUCT_AND_UNIT_DOES_NOT_EXIST; + log.error(productAndUnitDoesNotExist.getMsgEn()); + return new InvalidUserInputException(productAndUnitDoesNotExist); + } + + private boolean sameUnit(final String tcUnitStr, final int userUnit) { + return Integer.valueOf(tcUnitStr) == userUnit; + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/AbstractSnecmaObject.java b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/AbstractSnecmaObject.java new file mode 100644 index 0000000..ca0363e --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/AbstractSnecmaObject.java @@ -0,0 +1,352 @@ +package com.capgemini.reports.snecmaobjects; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.object.pom.status.StatusEnum; +import com.capgemini.framework.teamcenter.object.pom.status.TcReleaseStatus; +import com.capgemini.framework.teamcenter.resolution.filtering.ITcTypeFilter; +import com.capgemini.reports.documentationobjects.AbstractDoc; +import com.capgemini.reports.documentationobjects.DocFactory; +import com.capgemini.reports.releasestatus.RevisionSelector; +import com.capgemini.reports.releasestatus.RevisionStatusAndDate; +import com.teamcenter.soa.client.model.ModelObject; +import com.teamcenter.soa.client.model.strong.Form; +import com.teamcenter.soa.client.model.strong.Item; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import com.teamcenter.soa.client.model.strong.ReleaseStatus; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import static com.capgemini.framework.teamcenter.TeamcenterObjectProperties.TC_IS_REPRESENTED_BY; +import static com.capgemini.framework.teamcenter.object.SnecmaObjectProperties.*; + +/** + * Abstract class which centralize the methods of all the SnecmaObject. + */ +public abstract class AbstractSnecmaObject implements ISnecmaObject { + private static final long serialVersionUID = -9057538534616767099L; + protected final TcSession session; + protected final ItemRevision itemRevision; + + private Form itemMasterForm; + private List statuses; + private Form itemMasterFormRev; + private static final Logger LOGGER = LoggerFactory.getLogger(AbstractSnecmaObject.class); + + public AbstractSnecmaObject(final TcSession session, final ItemRevision itemRevision) { + this.session = session; + this.itemRevision = itemRevision; + } + + @Override + public String getType() { + return itemRevision.getTypeObject().getName(); + } + + @Override + public String getItemId() { + return itemRevision.get_item_id(); + } + + @Override + public String getRevisionId() { + return itemRevision.get_item_revision_id(); + } + + @Override + public String getName() { + return itemRevision.get_object_name(); + } + + protected Form getMasterForm() { + if (itemMasterForm == null) { + session.loadProperties(itemRevision, "items_tag"); + Item item = itemRevision.get_items_tag(); + session.loadProperties(item, "item_master_tag"); + itemMasterForm = item.get_item_master_tag(); + session.loadProperties(itemMasterForm); + } + return itemMasterForm; + } + + protected Form getMasterFormRev() { + if (itemMasterFormRev == null) { + itemMasterFormRev = itemRevision.get_item_master_tag(); + session.loadProperties(itemMasterFormRev); + } + return itemMasterFormRev; + } + + /** + * Method to get the modelObject representing the 'Spare Part' Form if it existed. + * Else return null + * */ + public ModelObject getSparePartsForm() { + session.loadProperties(itemRevision, "IMAN_specification"); + ModelObject[] formArray = itemRevision.get_IMAN_specification(); + session.loadProperties(formArray); + for (ModelObject form : formArray) { + if (form != null && "Spare Parts".equals(form.getTypeObject().getName())) { + return form; + } + } + return null; + } + + public boolean hasStatus(final StatusEnum... statuses) { + for (TcReleaseStatus releaseStatus : getStatusList()) { + if (releaseStatus.isOneOf(statuses)) { + return true; + } + } + return false; + } + + public List getStatusList() { + if (statuses == null) { + statuses = new ArrayList<>(); + session.loadProperties(itemRevision, "release_status_list"); + ReleaseStatus[] releaseStatuses = itemRevision.get_release_status_list(); + session.loadProperties(releaseStatuses); + for (ReleaseStatus releaseStatus : releaseStatuses) { + TcReleaseStatus tcReleaseStatus = new TcReleaseStatus(session, releaseStatus); + statuses.add(tcReleaseStatus); + } + } + return statuses; + } + + public List getDefinitionDocumentsOfTypes(final ITcTypeFilter typesFilter, final Map docCache) { + List definitionDocuments = new ArrayList<>(); + session.loadProperties(itemRevision, PV_DEFINITION_DOCS); + ModelObject[] definitionDocObjects = itemRevision.getPropertyObject(PV_DEFINITION_DOCS).getModelObjectArrayValue(); + session.loadProperties(definitionDocObjects); + for (ModelObject definitionDocObject : definitionDocObjects) { + String docType = definitionDocObject.getTypeObject().getName(); + if (typesFilter.isIncluded(docType)) { + definitionDocuments.add(getAbstractDoc((ItemRevision) definitionDocObject, docCache)); + } + } + + return definitionDocuments; + } + + public List getRepresentedDocumentsOfTypes(final ITcTypeFilter typesFilter, final Map docCache) { + List representedDocuments = new ArrayList<>(); + session.loadProperties(itemRevision, TC_IS_REPRESENTED_BY); + ModelObject[] representedDocObjects = itemRevision.getPropertyObject(TC_IS_REPRESENTED_BY).getModelObjectArrayValue(); + session.loadProperties(representedDocObjects); + for (ModelObject representedDocObject : representedDocObjects) { + String docType = representedDocObject.getTypeObject().getName(); + if (typesFilter.isIncluded(docType)) { + representedDocuments.add(getAbstractDoc((ItemRevision) representedDocObject, docCache)); + } + } + + return representedDocuments; + } + + /** + * Returns all the ChangeRequests of the CR pseudo-folder as a list of ModelObjects + */ + public List getCRPseudoFolderContent() { + List crRelatedList = new ArrayList<>(); + session.loadProperties(itemRevision, PV4_RUNTIME_CR_RELATED); + ModelObject[] crRelatedArray = itemRevision.getPropertyObject(PV4_RUNTIME_CR_RELATED).getModelObjectArrayValue(); + session.loadProperties(crRelatedArray); + for (ModelObject cr : crRelatedArray) { + crRelatedList.add(cr); + } + return crRelatedList; + } + + /** + * Returns all the ChangeNotices of the CN pseudo-folder as a list of ModelObjects + */ + public List getCNPseudoFolderContent() { + List cnRelatedList = new ArrayList<>(); + session.loadProperties(itemRevision, PV4_RUNTIME_CN_RELATED); + ModelObject[] cnRelatedArray = itemRevision.getPropertyObject(PV4_RUNTIME_CN_RELATED).getModelObjectArrayValue(); + session.loadProperties(cnRelatedArray); + for (ModelObject cr : cnRelatedArray) { + cnRelatedList.add(cr); + } + return cnRelatedList; + } + + /** + * Returns all the Reference documents. + */ + public List getReferenceDocumentsOfTypes(final ITcTypeFilter typesFilter, final RevisionSelector revisionSelector, final Map docCache) { + List referencedDocuments = new ArrayList<>(); + session.loadProperties(itemRevision, PV_REFERENCE_DOCS); + ModelObject[] referencedDocObjects = itemRevision.getPropertyObject(PV_REFERENCE_DOCS).getModelObjectArrayValue(); + session.loadProperties(referencedDocObjects); + for (ModelObject representedDocObject : referencedDocObjects) { + String docType = representedDocObject.getTypeObject().getName(); + if (typesFilter.isIncluded(docType)) { + referencedDocuments.add(getAbstractDoc(revisionSelector, (Item) representedDocObject, docCache)); + } + } + return referencedDocuments; + } + + private AbstractDoc getAbstractDoc(final RevisionSelector revisionSelector, final Item docItem, final Map docCache) { + AbstractDoc cachedDoc = docCache.get(docItem.getUid()); + if (cachedDoc == null) { + RevisionStatusAndDate revisionStatusAndDate = revisionSelector.selectRevision(session, docItem); + AbstractDoc abstractDoc = DocFactory.build(session, revisionStatusAndDate.getItemRevision()); + docCache.put(docItem.getUid(), abstractDoc); + return abstractDoc; + } else { + return cachedDoc; + } + } + + private AbstractDoc getAbstractDoc(final ItemRevision docRev, final Map docCache) { + AbstractDoc cachedDoc = docCache.get(docRev.getUid()); + if (cachedDoc == null) { + AbstractDoc abstractDoc = DocFactory.build(session, docRev); + docCache.put(docRev.getUid(), abstractDoc); + return abstractDoc; + } else { + return cachedDoc; + } + } + + public String getCRPseudoFolderContentAsString() { + StringBuilder stringBuilder = new StringBuilder(); + try { + List CRList = getCRPseudoFolderContent(); + for (ModelObject CR : CRList) { + if (stringBuilder.length() != 0) { + stringBuilder.append(";"); + } + stringBuilder.append(CR.getPropertyObject(ITEM_ID).getStringValue()); + } + } catch (Exception e) { + LOGGER.debug("Error during Searching CR of component Id [{}] Revision [{}] : [{}]", getItemId(), getRevisionId(), e.getMessage()); + } + return stringBuilder.toString(); + } + + public String getCNPseudoFolderContentAsString() { + StringBuilder stringBuilder = new StringBuilder(); + try { + List CNList = getCNPseudoFolderContent(); + for (ModelObject CN : CNList) { + if (stringBuilder.length() != 0) { + stringBuilder.append(";"); + } + stringBuilder.append(CN.getPropertyObject(ITEM_ID).getStringValue()); + } + } catch (Exception e) { + LOGGER.debug("Error during Searching CN of component Id [{}] Revision [{}] : [{}]", getItemId(), getRevisionId(), e.getMessage()); + } + return stringBuilder.toString(); + } + + /** + * Return true if it is a Admin. + * + * @return the boolean + */ + @Override + public boolean isAdmin() { + return false; + } + + /** + * Return true if it is a Generic. + * + * @return the boolean + */ + @Override + public boolean isGeneric() { + return false; + } + + + /** + * Return true if it is a Super Model. + * + * @return the boolean + */ + @Override + public boolean isSuperModel() { + return false; + } + + /** + * Return true if it is a Part. + * + * @return the boolean + */ + @Override + public boolean isPart() { + return false; + } + + /** + * Return true if it is a RF. + * + * @return the boolean + */ + @Override + public boolean isRF() { + return false; + } + + /** + * Return true if it is a RF Generic. + * + * @return the boolean + */ + @Override + public boolean isRFGeneric() { + return false; + } + + /** + * Return true if it is a RF Part or RF Part Assemb. + * + * @return the boolean + */ + @Override + public boolean isRFPartOrPartAssemb() { + return false; + } + + /** + * Return true if it is a MockUp. + * + * @return the boolean + */ + @Override + public boolean isMockup() { + return false; + } + + /** + * Return true if it is a Product. + * + * @return the boolean + */ + @Override + public boolean isProduct() { + return false; + } + + @Override + public boolean isDescriptif() { + return false; + } + + @Override + public String toString() { + return getType() + " with ID= " + getItemId() + " with REVISION= " + getRevisionId(); + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/ISnecmaObject.java b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/ISnecmaObject.java new file mode 100644 index 0000000..7e65fdb --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/ISnecmaObject.java @@ -0,0 +1,121 @@ +package com.capgemini.reports.snecmaobjects; + +import com.capgemini.reports.snecmaobjects.visitor.IComponentVisitor; +import com.capgemini.reports.snecmaobjects.visitor.IReceptorVisitor; + +import java.io.Serializable; + +/** + * Interface representing all the objects. + */ +public interface ISnecmaObject extends Serializable { + + /** + * All the SnecmaObjects must accept the Receptor visitor to make the different reports. + */ + T accept(final IReceptorVisitor aReceptorVisitor); + + /** + * All the SnecmaObjects must accept the Component visitor to make the different reports. + */ + T accept(final IComponentVisitor aComponentVisitor); + + /** + * Getter for the type of the SnecmaObject. + * + * @return the type + */ + String getType(); + + /** + * Getter for the Name of the SnecmaObject. + * + * @return the Name + */ + String getName(); + + /** + * Getter for the Revision of the SnecmaObject. + * + * @return the Revision + */ + String getRevisionId(); + + /** + * Getter for the Id of the SnecmaObject. + * + * @return the Id + */ + String getItemId(); + + /** + * Return true if it is a Admin. + * + * @return the boolean + */ + boolean isAdmin(); + + /** + * Return true if it is a Generic. + * + * @return the boolean + */ + boolean isGeneric(); + + /** + * Return true if it is a SuperModel. + * + * @return the boolean + */ + boolean isSuperModel(); + + /** + * Return true if it is a Part. + * + * @return the boolean + */ + boolean isPart(); + + /** + * Return true if it is a RF. + * + * @return the boolean + */ + boolean isRF(); + + /** + * Return true if it is a RF Generic. + * + * @return the boolean + */ + boolean isRFGeneric(); + + /** + * Return true if it is a RF Part or a RF Part Assemb. + * + * @return the boolean + */ + boolean isRFPartOrPartAssemb(); + + /** + * Return true if it is a Product. + * + * @return the boolean + */ + boolean isProduct(); + + /** + * Return true if it is a Descriptif. + * + * @return the boolean + */ + boolean isDescriptif(); + + /** + * Return true if it is a MockUp. + * + * @return the boolean + */ + boolean isMockup(); + +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/SnecmaObjectFactory.java b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/SnecmaObjectFactory.java new file mode 100644 index 0000000..d28a783 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/SnecmaObjectFactory.java @@ -0,0 +1,96 @@ +package com.capgemini.reports.snecmaobjects; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.reports.exceptions.NotSupportedException; +import com.capgemini.reports.snecmaobjects.admin.RFAdminAGRevision; +import com.capgemini.reports.snecmaobjects.admin.RFAdminAPRevision; +import com.capgemini.reports.snecmaobjects.admin.RFAdminARevision; +import com.capgemini.reports.snecmaobjects.admin.RFAdminRevision; +import com.capgemini.reports.snecmaobjects.descriptif.DescriptifRevision; +import com.capgemini.reports.snecmaobjects.generic.*; +import com.capgemini.reports.snecmaobjects.mockup.MockupRevision; +import com.capgemini.reports.snecmaobjects.part.*; +import com.capgemini.reports.snecmaobjects.product.ProductRevision; +import com.capgemini.reports.snecmaobjects.rf.RFGenericRevision; +import com.capgemini.reports.snecmaobjects.rf.RFPartAssembRevision; +import com.capgemini.reports.snecmaobjects.rf.RFPartRevision; +import com.capgemini.reports.snecmaobjects.supermodel.SuperModelRevision; +import com.teamcenter.soa.client.model.strong.Item; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +import static com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes.*; + +/** + * Factory used for create a structured SnecmaObject (set as null by default). + */ +public class SnecmaObjectFactory { + + protected SnecmaObjectFactory() { + // Nothing to do, just making this private + } + + /** + * Build an object from an {@link Item}. + */ + public static AbstractGeneric build(final TcSession session, final Item item) throws NotSupportedException { + switch (item.getTypeObject().getName()) { + case GENERIC: + return new Generic(session, item); + case GENERIC_ASSEMB: + return new GenericAssemb(session, item); + default: + throw new NotSupportedException("Expected ObjectType was not created, 'type' property was not available!"); + } + } + + /** + * Factory which create the structure of the SnecmaObjects from an {@link ItemRevision}. + */ + public static AbstractSnecmaObject build(final TcSession session, final ItemRevision itemRevision) + throws NotSupportedException { + switch (itemRevision.getTypeObject().getName()) { + case ALTERNATE_REVISION: + return new AlternateRevision(session, itemRevision); + case DESCRIPTIF_REVISION: + return new DescriptifRevision(session, itemRevision); + case DET_REVISION: + return new DETRevision(session, itemRevision); + case GENERIC_ASSEMB_REVISION: + return new GenericAssembRevision(session, itemRevision); + case GENERIC_REVISION: + return new GenericRevision(session, itemRevision); + case SUPERMODEL_REVISION: + return new SuperModelRevision(session, itemRevision); + case MOCKUP_REVISION: + return new MockupRevision(session, itemRevision); + case PART_AERO_REVISION: + return new PartAeroRevision(session, itemRevision); + case PART_ASSEMB_REVISION: + return new PartAssembRevision(session, itemRevision); + case PART_MAT_REVISION: + return new PartMatRevision(session, itemRevision); + case PART_NO_AERO_REVISION: + return new PartNoAeroRevision(session, itemRevision); + case PRODUCT_REVISION: + return new ProductRevision(session, itemRevision); + case RF_ADMIN_AG_REVISION: + return new RFAdminAGRevision(session, itemRevision); + case RF_ADMIN_AP_REVISION: + return new RFAdminAPRevision(session, itemRevision); + case RF_ADMIN_A_REVISION: + return new RFAdminARevision(session, itemRevision); + case RF_ADMIN_REVISION: + return new RFAdminRevision(session, itemRevision); + case RF_GENERIC_REVISION: + return new RFGenericRevision(session, itemRevision); + case RF_PART_ASSEMB_REVISION: + return new RFPartAssembRevision(session, itemRevision); + case RF_PART_REVISION: + return new RFPartRevision(session, itemRevision); + case STANDARD_REVISION: + return new StandardRevision(session, itemRevision); + default: + throw new NotSupportedException("Expected ObjectType was not created, 'type' property was not available!"); + } + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/admin/AbstractAdmin.java b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/admin/AbstractAdmin.java new file mode 100644 index 0000000..5b77bfe --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/admin/AbstractAdmin.java @@ -0,0 +1,22 @@ +package com.capgemini.reports.snecmaobjects.admin; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.reports.snecmaobjects.AbstractSnecmaObject; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +/** + * Abstract class representing all the Admin. + */ +public abstract class AbstractAdmin extends AbstractSnecmaObject { + private static final long serialVersionUID = -2526585943770080825L; + + public AbstractAdmin(final TcSession session, final ItemRevision itemRevision) { + super(session, itemRevision); + } + + @Override + public boolean isAdmin() { + return true; + } + +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/admin/RFAdminAGRevision.java b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/admin/RFAdminAGRevision.java new file mode 100644 index 0000000..75937ec --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/admin/RFAdminAGRevision.java @@ -0,0 +1,49 @@ +package com.capgemini.reports.snecmaobjects.admin; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.reports.snecmaobjects.visitor.IComponentVisitor; +import com.capgemini.reports.snecmaobjects.visitor.IReceptorVisitor; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +import static com.capgemini.framework.teamcenter.object.SnecmaObjectProperties.PV_TRANSFERT_LIEN_LOGISTI; +import static com.capgemini.framework.teamcenter.object.SnecmaObjectProperties.PV_TRANSFERT_LIEN_MONTAGE; +import static com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes.RF_ADMIN_AG_REVISION; + +/** + * Class representing a RFAdminAGRevision. + */ +public class RFAdminAGRevision extends AbstractAdmin { + private static final long serialVersionUID = -5970076629996941060L; + + public RFAdminAGRevision(final TcSession session, final ItemRevision itemRevision) { + super(session, itemRevision); + } + + public String getTransfertLienLogisti() { + return getMasterFormRev().getPropertyObject(PV_TRANSFERT_LIEN_LOGISTI).getStringValue(); + } + + public String getTransfertLienMontage() { + return getMasterFormRev().getPropertyObject(PV_TRANSFERT_LIEN_MONTAGE).getStringValue(); + } + + @Override + public T accept(final IReceptorVisitor aReceptorVisitor) { + return aReceptorVisitor.visitReceptor(this); + } + + @Override + public T accept(final IComponentVisitor aComponentVisitor) { + return aComponentVisitor.visitComponent(this); + } + + @Override + public boolean isSuperModel() { + return false; + } + + @Override + public String toString() { + return RF_ADMIN_AG_REVISION + " " + this.getItemId(); + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/admin/RFAdminAPRevision.java b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/admin/RFAdminAPRevision.java new file mode 100644 index 0000000..ea0cbed --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/admin/RFAdminAPRevision.java @@ -0,0 +1,53 @@ +package com.capgemini.reports.snecmaobjects.admin; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.reports.snecmaobjects.visitor.IComponentVisitor; +import com.capgemini.reports.snecmaobjects.visitor.IReceptorVisitor; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +import static com.capgemini.framework.teamcenter.object.SnecmaObjectProperties.*; +import static com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes.RF_ADMIN_AP_REVISION; + +/** + * Class representing a RFAdminAPRevision. + */ +public class RFAdminAPRevision extends AbstractAdmin { + private static final long serialVersionUID = 3507333355590338363L; + + public RFAdminAPRevision(final TcSession session, final ItemRevision itemRevision) { + super(session, itemRevision); + } + + + public String getSuiviMontage() { + return getMasterFormRev().getPropertyObject(PV_SUIVI_MONTAGE).getStringValue(); + } + + public String getTransfertLienLogisti() { + return getMasterFormRev().getPropertyObject(PV_TRANSFERT_LIEN_LOGISTI).getStringValue(); + } + + public String getTransfertLienMontage() { + return getMasterFormRev().getPropertyObject(PV_TRANSFERT_LIEN_MONTAGE).getStringValue(); + } + + @Override + public T accept(final IReceptorVisitor aReceptorVisitor) { + return aReceptorVisitor.visitReceptor(this); + } + + @Override + public T accept(final IComponentVisitor aComponentVisitor) { + return aComponentVisitor.visitComponent(this); + } + + @Override + public boolean isSuperModel() { + return false; + } + + @Override + public String toString() { + return RF_ADMIN_AP_REVISION + " " + this.getItemId(); + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/admin/RFAdminARevision.java b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/admin/RFAdminARevision.java new file mode 100644 index 0000000..70447f1 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/admin/RFAdminARevision.java @@ -0,0 +1,58 @@ +package com.capgemini.reports.snecmaobjects.admin; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.capgemini.reports.snecmaobjects.visitor.IComponentVisitor; +import com.capgemini.reports.snecmaobjects.visitor.IReceptorVisitor; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +import static com.capgemini.framework.teamcenter.object.SnecmaObjectProperties.*; + +/** Class representing a RFAdminARevision. */ +public class RFAdminARevision extends AbstractAdmin { + private static final long serialVersionUID = 8090505555455825143L; + + public RFAdminARevision(final TcSession session, final ItemRevision itemRevision) { + super(session, itemRevision); + } + + public String getResponsableRepere() { + return getMasterFormRev().getPropertyObject(PV_RESPONSABLE_REPERE).getStringValue(); + } + + public String getSuiviMontage() { + return getMasterFormRev().getPropertyObject(PV_SUIVI_MONTAGE).getStringValue(); + } + + public String getTransfertLienLogisti() { + return getMasterFormRev().getPropertyObject(PV_TRANSFERT_LIEN_LOGISTI).getStringValue(); + } + + public String getTransfertLienMontage() { + return getMasterFormRev().getPropertyObject(PV_TRANSFERT_LIEN_MONTAGE).getStringValue(); + } + + public String getMaqIntExt() { + return getMasterFormRev().getPropertyObject(PV_MAQ_INT_EXT).getStringValue(); + } + + @Override + public T accept(final IReceptorVisitor aReceptorVisitor) { + return aReceptorVisitor.visitReceptor(this); + } + + @Override + public T accept(final IComponentVisitor aComponentVisitor) { + return aComponentVisitor.visitComponent(this); + } + + @Override + public boolean isSuperModel() { + return false; + } + + @Override + public String toString() { + return SnecmaObjectTypes.RF_ADMIN_A_REVISION + " " + this.getItemId(); + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/admin/RFAdminRevision.java b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/admin/RFAdminRevision.java new file mode 100644 index 0000000..a5de2a2 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/admin/RFAdminRevision.java @@ -0,0 +1,93 @@ +package com.capgemini.reports.snecmaobjects.admin; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.capgemini.reports.snecmaobjects.visitor.IComponentVisitor; +import com.capgemini.reports.snecmaobjects.visitor.IReceptorVisitor; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +import static com.capgemini.framework.teamcenter.object.SnecmaObjectProperties.*; + +public class RFAdminRevision extends AbstractAdmin { + private static final long serialVersionUID = 4788588575480262344L; + + public RFAdminRevision(final TcSession session, final ItemRevision itemRevision) { + super(session, itemRevision); + } + + public String getResponsableRepere() { + return getMasterFormRev().getPropertyObject(PV_RESPONSABLE_REPERE).getStringValue(); + } + + public String getFrontiereAvion() { + return getMasterFormRev().getPropertyObject(PV_FRONTIERE_AVION).getStringValue(); + } + + public String getFrontiereCooperant() { + return getMasterFormRev().getPropertyObject(PV_FRONTIERE_COOPERANT).getStringValue(); + } + + public String getMaqIntExt() { + return getMasterFormRev().getPropertyObject(PV_MAQ_INT_EXT).getStringValue(); + } + + public String getGeometriePieceRigide() { + return getMasterFormRev().getPropertyObject(PV_GEOMETRIE_PIECE_RIGIDE).getStringValue(); + } + + public String getGeometrieSimplifiee() { + return getMasterFormRev().getPropertyObject(PV_GEOMETRIE_SIMPLIFIEE).getStringValue(); + } + + public String getTraceAxiale() { + return getMasterFormRev().getPropertyObject(PV_TRACE_AXIALE).getStringValue(); + } + + public String getEnveloppeCinematique() { + return getMasterFormRev().getPropertyObject(PV_ENVELOPPE_CINEMATIQUE).getStringValue(); + } + + public String getEnveloppeMaintenance() { + return getMasterFormRev().getPropertyObject(PV_ENVELOPPE_MAINTENANCE).getStringValue(); + } + + public String getEnveloppeMontage() { + return getMasterFormRev().getPropertyObject(PV_ENVELOPPE_MONTAGE).getStringValue(); + } + + public String getInterfaceRfAdmin() { + return getMasterFormRev().getPropertyObject(PV_INTERFACE_RF_ADMIN).getStringValue(); + } + + public String getProjetMoteur() { + return getMasterFormRev().getPropertyObject(PV_PROJET_MOTEUR).getStringValue(); + } + + public String getMaqEchangeable() { + return getMasterFormRev().getPropertyObject(PV_MAQ_ECHANGEABLE).getStringValue(); + } + + public String getWorkpackage() { + return getMasterFormRev().getPropertyObject(PV_WORKPACKAGE).getStringValue(); + } + + @Override + public T accept(final IReceptorVisitor aReceptorVisitor) { + return aReceptorVisitor.visitReceptor(this); + } + + @Override + public T accept(final IComponentVisitor aComponentVisitor) { + return aComponentVisitor.visitComponent(this); + } + + @Override + public boolean isSuperModel() { + return false; + } + + @Override + public String toString() { + return SnecmaObjectTypes.RF_ADMIN_REVISION + " " + this.getItemId(); + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/descriptif/DescriptifRevision.java b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/descriptif/DescriptifRevision.java new file mode 100644 index 0000000..78bd5fe --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/descriptif/DescriptifRevision.java @@ -0,0 +1,37 @@ +package com.capgemini.reports.snecmaobjects.descriptif; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.reports.snecmaobjects.AbstractSnecmaObject; +import com.capgemini.reports.snecmaobjects.visitor.IComponentVisitor; +import com.capgemini.reports.snecmaobjects.visitor.IReceptorVisitor; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +/** + * Class representing a DescriptifRevision. + */ +public class DescriptifRevision extends AbstractSnecmaObject { + private static final long serialVersionUID = 7170967703658857854L; + + public DescriptifRevision(final TcSession session, final ItemRevision itemRevision) { + super(session, itemRevision); + } + + @Override + public T accept(final IReceptorVisitor aReceptorVisitor) { + return aReceptorVisitor.visitReceptor(this); + } + + public T accept(final IComponentVisitor aComponentVisitor) { + return aComponentVisitor.visitComponent(this); + } + + @Override + public boolean isSuperModel() { + return false; + } + + @Override + public boolean isDescriptif() { + return true; + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/generic/AbstractGeneric.java b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/generic/AbstractGeneric.java new file mode 100644 index 0000000..e18783e --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/generic/AbstractGeneric.java @@ -0,0 +1,42 @@ +package com.capgemini.reports.snecmaobjects.generic; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.teamcenter.soa.client.model.strong.Item; + +public class AbstractGeneric implements Comparable { + private final TcSession session; + private final Item item; + + public AbstractGeneric(final TcSession session, final Item item) { + this.session = session; + this.item = item; + } + + public String getItemId() { + return item.get_item_id(); + } + + + public String getName() { + return item.get_object_name(); + } + + public String getType() { + return item.getTypeObject().getName(); + } + + @Override + public int compareTo(final AbstractGeneric other) { + return this.getItemId().compareTo(other.getItemId()); + } + + @Override + public boolean equals(final Object obj) { + return this == obj || obj instanceof AbstractGeneric && item.equals(((AbstractGeneric) obj).item); + } + + @Override + public int hashCode() { + return item.hashCode(); + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/generic/AbstractGenericRevision.java b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/generic/AbstractGenericRevision.java new file mode 100644 index 0000000..0907276 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/generic/AbstractGenericRevision.java @@ -0,0 +1,59 @@ +package com.capgemini.reports.snecmaobjects.generic; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.reports.snecmaobjects.AbstractSnecmaObject; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import lombok.EqualsAndHashCode; + +import java.util.regex.Pattern; + +import static com.capgemini.framework.teamcenter.object.SnecmaObjectProperties.PV_DESIGNATION_EN; +import static com.capgemini.framework.teamcenter.object.SnecmaObjectProperties.PV_RESPONSABLE_CONCEPTION; + + +/** + * Abstract Class representing a Generic. + */ +@EqualsAndHashCode(callSuper = true) +public abstract class AbstractGenericRevision extends AbstractSnecmaObject implements Comparable { + private static final long serialVersionUID = -190379543546189856L; + + /** + * This pattern identify a {@link GenericRevision} id. + **/ + private static final Pattern REGEX_PATTERN_FOR_GENERIC_REVISION = Pattern.compile("^[A-Z]"); + + public AbstractGenericRevision(final TcSession session, final ItemRevision itemRevision) { + super(session, itemRevision); + } + + /** + * Return true if the id correspond to a {@link GenericRevision} id.
    + */ + public static boolean isGenericRevision(final String genId) { + return REGEX_PATTERN_FOR_GENERIC_REVISION.matcher(genId).find(); + } + + public String getDesignationEN() { + return getMasterFormRev().getPropertyObject(PV_DESIGNATION_EN).getStringValue(); + } + + public String getResponsableConception() { + return getMasterFormRev().getPropertyObject(PV_RESPONSABLE_CONCEPTION).getStringValue(); + } + + @Override + public int compareTo(final AbstractGenericRevision other) { + int compareID = this.getItemId().compareTo(other.getItemId()); + if (compareID != 0) { + return compareID; // Different ID + } else { + return this.getRevisionId().compareTo(other.getRevisionId()); + } + } + + @Override + public boolean isGeneric() { + return true; + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/generic/Generic.java b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/generic/Generic.java new file mode 100644 index 0000000..a982731 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/generic/Generic.java @@ -0,0 +1,11 @@ +package com.capgemini.reports.snecmaobjects.generic; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.teamcenter.soa.client.model.strong.Item; + +public class Generic extends AbstractGeneric { + + public Generic(final TcSession session, final Item item) { + super(session, item); + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/generic/GenericAssemb.java b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/generic/GenericAssemb.java new file mode 100644 index 0000000..f53dc01 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/generic/GenericAssemb.java @@ -0,0 +1,11 @@ +package com.capgemini.reports.snecmaobjects.generic; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.teamcenter.soa.client.model.strong.Item; + +public class GenericAssemb extends AbstractGeneric { + + public GenericAssemb(final TcSession session, final Item item) { + super(session, item); + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/generic/GenericAssembRevision.java b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/generic/GenericAssembRevision.java new file mode 100644 index 0000000..dd2a9b2 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/generic/GenericAssembRevision.java @@ -0,0 +1,39 @@ +package com.capgemini.reports.snecmaobjects.generic; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.capgemini.reports.snecmaobjects.visitor.IComponentVisitor; +import com.capgemini.reports.snecmaobjects.visitor.IReceptorVisitor; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +/** + * Class representing a GenericAssembRevision. + */ +public class GenericAssembRevision extends AbstractGenericRevision { + private static final long serialVersionUID = 74761594141269461L; + + public GenericAssembRevision(final TcSession session, final ItemRevision itemRevision) { + super(session, itemRevision); + } + + @Override + public T accept(final IReceptorVisitor aReceptorVisitor) { + return aReceptorVisitor.visitReceptor(this); + } + + @Override + public T accept(final IComponentVisitor aComponentVisitor) { + return aComponentVisitor.visitComponent(this); + } + + @Override + public boolean isSuperModel() { + return false; + } + + @Override + public String toString() { + return SnecmaObjectTypes.GENERIC_ASSEMB_REVISION + " " + this.getItemId(); + } + +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/generic/GenericRevision.java b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/generic/GenericRevision.java new file mode 100644 index 0000000..1949608 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/generic/GenericRevision.java @@ -0,0 +1,32 @@ +package com.capgemini.reports.snecmaobjects.generic; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.reports.snecmaobjects.visitor.IComponentVisitor; +import com.capgemini.reports.snecmaobjects.visitor.IReceptorVisitor; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +/** + * Class representing a RFAdminAGRevision. + */ +public class GenericRevision extends AbstractGenericRevision { + private static final long serialVersionUID = 4530714427862196578L; + + public GenericRevision(final TcSession session, final ItemRevision itemRevision) { + super(session, itemRevision); + } + + @Override + public T accept(final IReceptorVisitor aReceptorVisitor) { + return aReceptorVisitor.visitReceptor(this); + } + + @Override + public T accept(final IComponentVisitor aComponentVisitor) { + return aComponentVisitor.visitComponent(this); + } + + @Override + public String toString() { + return getType() + " " + this.getItemId(); + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/mockup/MockupRevision.java b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/mockup/MockupRevision.java new file mode 100644 index 0000000..5a21981 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/mockup/MockupRevision.java @@ -0,0 +1,42 @@ +package com.capgemini.reports.snecmaobjects.mockup; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.reports.snecmaobjects.AbstractSnecmaObject; +import com.capgemini.reports.snecmaobjects.visitor.IComponentVisitor; +import com.capgemini.reports.snecmaobjects.visitor.IReceptorVisitor; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +import static com.capgemini.framework.teamcenter.object.SnecmaObjectProperties.PV_COHERENCE_CONTROL; + +/** Class representing a MockupRevision. */ +public class MockupRevision extends AbstractSnecmaObject { + private static final long serialVersionUID = 5130249672177145816L; + + public MockupRevision(final TcSession session, final ItemRevision itemRevision) { + super(session, itemRevision); + } + + public String getCoherenceControl() { + return getMasterFormRev().getPropertyObject(PV_COHERENCE_CONTROL).getStringValue(); + } + + @Override + public T accept(final IReceptorVisitor aReceptorVisitor) { + return aReceptorVisitor.visitReceptor(this); + } + + @Override + public T accept(final IComponentVisitor aComponentVisitor) { + return aComponentVisitor.visitComponent(this); + } + + @Override + public boolean isSuperModel() { + return false; + } + + @Override + public boolean isMockup() { + return true; + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/part/AbstractAltOrDetRevision.java b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/part/AbstractAltOrDetRevision.java new file mode 100644 index 0000000..4526fc2 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/part/AbstractAltOrDetRevision.java @@ -0,0 +1,52 @@ +package com.capgemini.reports.snecmaobjects.part; + + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.reports.snecmaobjects.ISnecmaObject; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +import java.util.ArrayList; +import java.util.List; + +import static com.capgemini.framework.teamcenter.object.SnecmaObjectProperties.PV_FOURNISSEURS; + +/** + * Class representing a AlternateRevision or a DETRevision. + */ +public abstract class AbstractAltOrDetRevision extends AbstractPart { + private static final long serialVersionUID = -1534372886540642285L; + private final List pseudoFolder = new ArrayList<>(); + + public AbstractAltOrDetRevision(final TcSession session, final ItemRevision itemRevision) { + super(session, itemRevision); + } + + public String[] getLstFournisseurs() { + return itemRevision.getPropertyObject(PV_FOURNISSEURS).getStringArrayValue(); + } + + /** + * Adds a {@link ISnecmaObject} to the list of elements found in the pseudo-folder. + */ + public void addInPseudoFolder(final AbstractPart obj) { + pseudoFolder.add(obj); + } + + public void clearPseudoFolder() { + this.pseudoFolder.clear(); + } + + public List getPseudoFolder() { + return pseudoFolder; + } + + @Override + public String toString() { + String superString = super.toString(); + if (pseudoFolder.isEmpty()) { + return superString; + } else { + return superString + ", pseudoFolder with " + pseudoFolder.size() + " elements"; + } + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/part/AbstractPart.java b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/part/AbstractPart.java new file mode 100644 index 0000000..f15b5af --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/part/AbstractPart.java @@ -0,0 +1,320 @@ +package com.capgemini.reports.snecmaobjects.part; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.object.pom.status.StatusEnum; +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.capgemini.reports.releasestatus.RevisionStatusAndDate; +import com.capgemini.reports.snecmaobjects.AbstractSnecmaObject; +import com.capgemini.reports.teamcenter.ObjectInfoHelper; +import com.google.common.base.Joiner; +import com.google.common.base.Optional; +import com.teamcenter.soa.client.model.ModelObject; +import com.teamcenter.soa.client.model.strong.Item; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import lombok.extern.slf4j.Slf4j; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; + +import static com.capgemini.framework.teamcenter.object.SnecmaObjectProperties.*; + +/** + * Abstract Class representing a Part. + */ +@Slf4j +public abstract class AbstractPart extends AbstractSnecmaObject { + private static final long serialVersionUID = 3469538869012990375L; + + private static final Logger LOGGER = LoggerFactory.getLogger(AbstractPart.class); + + public AbstractPart(final TcSession session, final ItemRevision itemRevision) { + super(session, itemRevision); + } + + /** + * Return the list of the definition documents of a Part.
    + * Via the pseudofolder "Documents de définition". + */ + public static List returnDefinitionDocuments(final TcSession session, final ItemRevision partRev) { + List listDefinitionDoc = new ArrayList<>(); + session.loadProperties(partRev, PV_DEFINITION_DOCS); + ModelObject[] definitionDocObjects = partRev.getPropertyObject(PV_DEFINITION_DOCS).getModelObjectArrayValue(); + session.loadProperties(definitionDocObjects); + for (ModelObject definitionDocObject : definitionDocObjects) { + if (definitionDocObject == null) { + log.warn("A Null ModelObject was obtained from the pseudo-folder '_PV_definition_docs' of a Part."); + continue; + } + listDefinitionDoc.add((ItemRevision) definitionDocObject); + } + return listDefinitionDoc; + } + + /** + * Return the list of the reference documents of a Part.
    + * Via the pseudofolder "Documents de référence". + */ + public static List returnReferenceDocuments(final TcSession session, final ItemRevision partRev) { + List listReferenceDoc = new ArrayList<>(); + session.loadProperties(partRev, PV_REFERENCE_DOCS); + ModelObject[] referenceDocObjects = partRev.getPropertyObject(PV_REFERENCE_DOCS).getModelObjectArrayValue(); + session.loadProperties(referenceDocObjects); + for (ModelObject referenceDocObject : referenceDocObjects) { + if (referenceDocObject == null) { + log.warn("A Null ModelObject was obtained from the pseudo-folder '_PV_reference_docs' of a Part."); + continue; + } + listReferenceDoc.add((Item) referenceDocObject); + } + return listReferenceDoc; + } + + /** + * Return the list of the represented documents of a Part.
    + * Via the pseudofolder "Represented by". + */ + public static List returnRepresentedDocuments(final TcSession session, final ItemRevision partRev) { + List listRepresentedDoc = new ArrayList<>(); + session.loadProperties(partRev, TC_IS_REPRESENTED_BY); + ModelObject[] representedDocObjects = partRev.getPropertyObject(TC_IS_REPRESENTED_BY).getModelObjectArrayValue(); + session.loadProperties(representedDocObjects); + for (ModelObject representedDocObject : representedDocObjects) { + if (representedDocObject == null) { + log.warn("A Null ModelObject was obtained from the pseudo-folder 'TC_Is_Represented_By' of a Part."); + continue; + } + listRepresentedDoc.add((ItemRevision) representedDocObject); + } + return listRepresentedDoc; + } + + public String getDesignationEN() { + return getMasterFormRev().getPropertyObject(PV_DESIGNATION_EN).getStringValue(); + } + + public String getRefCompleteConcepteur() { + return getMasterFormRev().getPropertyObject(PV_REF_COMPLETE_CONCEPTEUR).getStringValue(); + } + + public String getRefTransposeeSnecma() { + return getMasterFormRev().getPropertyObject(PV_REF_TRANSPO_SNECMA).getStringValue(); + } + + public String getResponsableConception() { + return getMasterFormRev().getPropertyObject(PV_RESPONSABLE_CONCEPTION).getStringValue(); + } + + public String getClassement() { + return getMasterFormRev().getPropertyObject(PV_CLASSEMENT).getStringValue(); + } + + public String getSuiviUtilisation() { + return getMasterFormRev().getPropertyObject(PV_SUIVI_UTILISATION).getStringValue(); + } + + public String getSuiviDureeVie() { + return getMasterFormRev().getPropertyObject(PV_SUIVI_DUREE_VIE).getStringValue(); + } + + public double getDureeVie() { + return getMasterFormRev().getPropertyObject(PV_DUREE_VIE).getIntValue(); + } + + public String getUniteDureeVie() { + return getMasterFormRev().getPropertyObject(PV_UNITE_DUREE_VIE).getStringValue(); + } + + public Double getMass() { + return getMasterFormRev().getPropertyObject(PV_MASSE_INDICATIVE).getDoubleValue(); + } + + public String getMassUnit() { + return getMasterFormRev().getPropertyObject(PV_UNITE_MASSE).getStringValue(); + } + + public String getDocumentControle() { + return getMasterFormRev().getPropertyObject(PV_DOCUMENT_CONTROLE).getStringValue(); + } + + public String getRefAssociee() { + return getMasterFormRev().getPropertyObject(PV_REF_ASSOCIEE).getStringValue(); + } + + public String getSuiviDeveloppement() { + return getMasterFormRev().getPropertyObject(PV_SUIVI_DEVELOPPEMENT).getStringValue(); + } + + public String getTypeProduit() { + return getMasterFormRev().getPropertyObject(PV_TYPE_PRODUIT).getStringValue(); + } + + public String getExpirationDate() { + session.loadProperties(getMasterFormRev(), PV4_EXPIRATION_DATE); + return getMasterFormRev().getPropertyObject(PV4_EXPIRATION_DATE).getStringValue(); + } + + public String getMotClefEN() { + String value = ""; + if(getSparePartsForm() != null) { + session.loadProperties(getSparePartsForm(), PV_MOT_CLEF_EN); + value = getSparePartsForm().getPropertyObject(PV_MOT_CLEF_EN).getStringValue(); + } + return value; + } + + public String getMotClefFR() { + String value = ""; + if(getSparePartsForm() != null) { + session.loadProperties(getSparePartsForm(), PV_MOT_CLEF_FR); + value = getSparePartsForm().getPropertyObject(PV_MOT_CLEF_FR).getStringValue(); + } + return value; + } + + @Override + public boolean isPart() { + return true; + } + + /** + * This method is specific to R19 report + * It gets DocNorms from "Documents de référence" pseudo-folder of the part. + * It checks the value of pv_type_doc_norm properties and returns the pv_id_origine (or item_id if not found) + * of all DMD type docs separated by a coma + **/ + public String getDMD() { + LOGGER.debug("Entering getDMD method"); + List DMDList = new ArrayList<>(); + // Get content of "Documents de référence" pseudo-folder + List documents = returnReferenceDocuments(session, itemRevision); + LOGGER.debug("Number of reference documents : {}", documents.size()); + if (!documents.isEmpty()) { + for (Item docItem : documents) { + if (docItem == null) { + continue; + } + String docType = docItem.getTypeObject().getName(); + String docId = docItem.get_item_id(); + LOGGER.debug("Processing document : {} of type {}", docId, docType); + if (SnecmaObjectTypes.DOC_NORM.equals(docType)) { + // Get the last revision of the DocNorm and check content of pv_type_doc_norm attribute from his master form rev + ItemRevision docNormRevision = getDocNormLastRevision(session, docItem); + if(docNormRevision != null) { + session.loadProperties(docNormRevision, "IMAN_master_form_rev"); + ModelObject[] masterForm = docNormRevision.getPropertyObject("IMAN_master_form_rev").getModelObjectArrayValue(); + session.loadProperties(masterForm, PV_ID_ORIGINE, PV_TYPE_DOC_NORM); + if (masterForm == null || masterForm.length == 0) { + LOGGER.warn("Error while retrieving master form on document {} this document will be ignored.", docId); + continue; + } + String typeDocNorm = masterForm[0].getPropertyObject(PV_TYPE_DOC_NORM).getStringValue(); + LOGGER.debug("pv_type_doc_norm attribute value of doc {} : {}", docId, typeDocNorm); + if (typeDocNorm.contains(DMD_VALUE_OF_TYPE_DOCNORM)) { + LOGGER.debug("PV_ID_ORIGINE attribute value of doc {} : {}", docId, masterForm[0].getPropertyObject(PV_ID_ORIGINE).getStringValue()); + if (masterForm[0].getPropertyObject(PV_ID_ORIGINE) == null || masterForm[0].getPropertyObject(PV_ID_ORIGINE).getStringValue().isEmpty() || masterForm[0].getPropertyObject(PV_ID_ORIGINE).getStringValue() == "") { + LOGGER.debug("docId added to list"); + DMDList.add(docId); + } else { + LOGGER.debug("PV_ID_ORIGINE added to list"); + DMDList.add(masterForm[0].getPropertyObject(PV_ID_ORIGINE).getStringValue()); + } + } + } + } + } + } + LOGGER.debug("DMDList : {}", DMDList); + return Joiner.on(",").join(DMDList); + } + + /** + * This method is specific to R19 report + * It gets DocNorms from "Documents de référence" pseudo-folder of the part. + * It checks the value of pv_type_doc_norm properties and returns the pv_id_origine (or item_id if not found) + * of all DMF type docs separated by a coma + **/ + public String getDMF() { + LOGGER.debug("Entering getDMF method"); + List DMFList = new ArrayList<>(); + // Get content of "Documents de référence" pseudo-folder + List documents = returnReferenceDocuments(session, itemRevision); + LOGGER.debug("Number of reference documents : {}", documents.size()); + if (!documents.isEmpty()) { + for (Item docItem : documents) { + if (docItem == null) { + continue; + } + String docType = docItem.getTypeObject().getName(); + String docId = docItem.get_item_id(); + LOGGER.debug("Processing document : {} of type {}", docId, docType); + if (SnecmaObjectTypes.DOC_NORM.equals(docType)) { + // Get the last revision of the DocNorm and check content of pv_type_doc_norm attribute from his master form rev + ItemRevision docNormRevision = getDocNormLastRevision(session, docItem); + if(docNormRevision != null) { + session.loadProperties(docNormRevision, "IMAN_master_form_rev"); + ModelObject[] masterForm = docNormRevision.getPropertyObject("IMAN_master_form_rev").getModelObjectArrayValue(); + session.loadProperties(masterForm, PV_ID_ORIGINE, PV_TYPE_DOC_NORM); + if (masterForm == null || masterForm.length == 0) { + LOGGER.warn("Error while retrieving master form on document {} this document will be ignored.", docId); + continue; + } + String typeDocNorm = masterForm[0].getPropertyObject(PV_TYPE_DOC_NORM).getStringValue(); + LOGGER.debug("pv_type_doc_norm attribute value of doc {} : {}", docId, typeDocNorm); + if (typeDocNorm.contains(DMF_VALUE_OF_TYPE_DOCNORM)) { + LOGGER.debug("PV_ID_ORIGINE attribute value of doc {} : {}", docId, masterForm[0].getPropertyObject(PV_ID_ORIGINE).getStringValue()); + if (masterForm[0].getPropertyObject(PV_ID_ORIGINE) == null || masterForm[0].getPropertyObject(PV_ID_ORIGINE).getStringValue().isEmpty() || masterForm[0].getPropertyObject(PV_ID_ORIGINE).getStringValue() == "") { + LOGGER.debug("docId added to list"); + DMFList.add(docId); + } else { + LOGGER.debug("PV_ID_ORIGINE added to list"); + DMFList.add(masterForm[0].getPropertyObject(PV_ID_ORIGINE).getStringValue()); + } + } + } + } + } + } + LOGGER.debug("DMFList : {}", DMFList); + return Joiner.on(",").join(DMFList); + } + + /** + * This method determine the last revision of a docNorm/docNormStandard. + * + * @param session A TcSession instance + * @param docItem The id of the document + * @return ItemRevision object representing the revision of the document + **/ + private ItemRevision getDocNormLastRevision(final TcSession session, final Item docItem) { + // Retrieve the revisions + ModelObject[] revisions = docItem.get_revision_list(); + session.loadProperties(revisions); + LOGGER.debug("Doc {} : number of rev in revision_list attribute = {}", docItem.get_item_id(), revisions.length); + // Convert the List of ModelObject to a List of ItemRevision + List listOfDocNormRev = new ArrayList<>(); + for(ModelObject rev : revisions) { + if(rev != null) { + listOfDocNormRev.add((ItemRevision) rev); + } else { + LOGGER.warn("The revision object returned by TC for Doc {} is null. It will be ignored in DMD and DMF columns.", docItem.get_item_id()); + } + } + + // Try to get the revision with the latest release date + if(listOfDocNormRev.size() > 0) { + Optional selectedDocRev = ObjectInfoHelper.getRevisionFromStatusWithMostRecentReleaseDate(session, listOfDocNormRev, Calendar.getInstance(), StatusEnum.PUBLISHED, StatusEnum.FROZEN); + if (selectedDocRev.isPresent()) { + return selectedDocRev.get(); + } else { + // If no release date found, get the revision with latest modification date + RevisionStatusAndDate revAndStatus = ObjectInfoHelper.getRevisionAndStatusWithMostRecentModificationDate(listOfDocNormRev, Calendar.getInstance()); + return revAndStatus.getItemRevision(); + } + } else { + return null; + } + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/part/AlternateRevision.java b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/part/AlternateRevision.java new file mode 100644 index 0000000..de5b918 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/part/AlternateRevision.java @@ -0,0 +1,52 @@ +package com.capgemini.reports.snecmaobjects.part; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.reports.snecmaobjects.visitor.IComponentVisitor; +import com.capgemini.reports.snecmaobjects.visitor.IReceptorVisitor; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +import static com.capgemini.framework.teamcenter.object.SnecmaObjectProperties.*; +import static com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes.ALTERNATE_REVISION; + +/** + * Class representing a AlternateRevision. + */ +public class AlternateRevision extends AbstractAltOrDetRevision { + private static final long serialVersionUID = 6488368187302297526L; + + public AlternateRevision(final TcSession session, final ItemRevision itemRevision) { + super(session, itemRevision); + } + + public String getTypeAlt1() { + return getMasterFormRev().getPropertyObject(PV_TYPE_ALTERNATIVE_1).getStringValue(); + } + + public String getTypeAlt2() { + return getMasterFormRev().getPropertyObject(PV_TYPE_ALTERNATIVE_2).getStringValue(); + } + + public String getObturation() { + return getMasterFormRev().getPropertyObject(PV_OBTURATION).getStringValue(); + } + + @Override + public T accept(final IReceptorVisitor aReceptorVisitor) { + return aReceptorVisitor.visitReceptor(this); + } + + @Override + public T accept(final IComponentVisitor aComponentVisitor) { + return aComponentVisitor.visitComponent(this); + } + + @Override + public boolean isSuperModel() { + return false; + } + + @Override + public String toString() { + return ALTERNATE_REVISION + " " + this.getItemId(); + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/part/DETRevision.java b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/part/DETRevision.java new file mode 100644 index 0000000..b7b107a --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/part/DETRevision.java @@ -0,0 +1,50 @@ +package com.capgemini.reports.snecmaobjects.part; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.reports.snecmaobjects.visitor.IComponentVisitor; +import com.capgemini.reports.snecmaobjects.visitor.IReceptorVisitor; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +import static com.capgemini.framework.teamcenter.object.SnecmaObjectProperties.*; +import static com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes.DET_REVISION; + +public class DETRevision extends AbstractAltOrDetRevision { + private static final long serialVersionUID = -7225493417867464752L; + + public DETRevision(final TcSession session, final ItemRevision itemRevision) { + super(session, itemRevision); + } + + public String getTypeDet1() { + return getMasterFormRev().getPropertyObject(PV_TYPE_DET_1).getStringValue(); + } + + + public String getTypeDet2() { + return getMasterFormRev().getPropertyObject(PV_TYPE_DET_2).getStringValue(); + } + + public String getObturation() { + return getMasterFormRev().getPropertyObject(PV_OBTURATION).getStringValue(); + } + + @Override + public T accept(final IReceptorVisitor aReceptorVisitor) { + return aReceptorVisitor.visitReceptor(this); + } + + @Override + public T accept(final IComponentVisitor aComponentVisitor) { + return aComponentVisitor.visitComponent(this); + } + + @Override + public boolean isSuperModel() { + return false; + } + + @Override + public String toString() { + return DET_REVISION + " " + this.getItemId(); + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/part/PartAeroRevision.java b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/part/PartAeroRevision.java new file mode 100644 index 0000000..60daaf4 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/part/PartAeroRevision.java @@ -0,0 +1,60 @@ +package com.capgemini.reports.snecmaobjects.part; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.capgemini.reports.snecmaobjects.visitor.IComponentVisitor; +import com.capgemini.reports.snecmaobjects.visitor.IReceptorVisitor; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +import static com.capgemini.framework.teamcenter.object.SnecmaObjectProperties.*; + +/** + * Class representing a PartAeroRevision. + */ +public class PartAeroRevision extends AbstractPart { + private static final long serialVersionUID = -3486163177030124825L; + + public PartAeroRevision(final TcSession session, final ItemRevision itemRevision) { + super(session, itemRevision); + } + + public String getTypeAero1() { + return getMasterFormRev().getPropertyObject(PV_TYPE_PART_AERO_1).getDisplayableValue(); + } + + public String getTypeAero2() { + return getMasterFormRev().getPropertyObject(PV_TYPE_PART_AERO_2).getDisplayableValue(); + } + + public String getTypeAero3() { + return getMasterFormRev().getPropertyObject(PV_TYPE_PART_AERO_3).getDisplayableValue(); + } + + public String getObturation() { + return getMasterFormRev().getPropertyObject(PV_OBTURATION).getStringValue(); + } + + public String[] getLstFournisseurs() { + return itemRevision.getPropertyObject(PV_FOURNISSEURS).getStringArrayValue(); + } + + @Override + public T accept(final IReceptorVisitor aReceptorVisitor) { + return aReceptorVisitor.visitReceptor(this); + } + + @Override + public T accept(final IComponentVisitor aComponentVisitor) { + return aComponentVisitor.visitComponent(this); + } + + @Override + public boolean isSuperModel() { + return false; + } + + @Override + public String toString() { + return SnecmaObjectTypes.PART_AERO_REVISION + " " + this.getItemId(); + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/part/PartAssembRevision.java b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/part/PartAssembRevision.java new file mode 100644 index 0000000..19bfc4e --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/part/PartAssembRevision.java @@ -0,0 +1,49 @@ +package com.capgemini.reports.snecmaobjects.part; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.reports.snecmaobjects.visitor.IComponentVisitor; +import com.capgemini.reports.snecmaobjects.visitor.IReceptorVisitor; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +import static com.capgemini.framework.teamcenter.object.SnecmaObjectProperties.PV_TYPE_PART_MONTAGE_1; +import static com.capgemini.framework.teamcenter.object.SnecmaObjectProperties.PV_TYPE_PART_MONTAGE_2; +import static com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes.PART_ASSEMB_REVISION; + +/** + * Class representing a PartAssembRevision. + */ +public class PartAssembRevision extends AbstractPart { + private static final long serialVersionUID = -296424509222476913L; + + public PartAssembRevision(final TcSession session, final ItemRevision itemRevision) { + super(session, itemRevision); + } + + public String getTypePartMontage1() { + return getMasterFormRev().getPropertyObject(PV_TYPE_PART_MONTAGE_1).getStringValue(); + } + + public String getTypePartMontage2() { + return getMasterFormRev().getPropertyObject(PV_TYPE_PART_MONTAGE_2).getStringValue(); + } + + @Override + public T accept(final IReceptorVisitor aReceptorVisitor) { + return aReceptorVisitor.visitReceptor(this); + } + + @Override + public T accept(final IComponentVisitor aComponentVisitor) { + return aComponentVisitor.visitComponent(this); + } + + @Override + public boolean isSuperModel() { + return false; + } + + @Override + public String toString() { + return PART_ASSEMB_REVISION + " " + this.getItemId(); + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/part/PartMatRevision.java b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/part/PartMatRevision.java new file mode 100644 index 0000000..fd6a3d5 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/part/PartMatRevision.java @@ -0,0 +1,49 @@ +package com.capgemini.reports.snecmaobjects.part; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.capgemini.reports.snecmaobjects.visitor.IComponentVisitor; +import com.capgemini.reports.snecmaobjects.visitor.IReceptorVisitor; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +import static com.capgemini.framework.teamcenter.object.SnecmaObjectProperties.PV_CLASSEMENT_MATIERE; +import static com.capgemini.framework.teamcenter.object.SnecmaObjectProperties.PV_FOURNISSEURS; + +/** + * Class representing a PartMatRevision. + */ +public class PartMatRevision extends AbstractPart { + private static final long serialVersionUID = -3225565405583804909L; + + public PartMatRevision(final TcSession session, final ItemRevision itemRevision) { + super(session, itemRevision); + } + + public String getClassementMat() { + return getMasterFormRev().getPropertyObject(PV_CLASSEMENT_MATIERE).getStringValue(); + } + + public String[] getLstFournisseurs() { + return itemRevision.getPropertyObject(PV_FOURNISSEURS).getStringArrayValue(); + } + + @Override + public T accept(final IReceptorVisitor aReceptorVisitor) { + return aReceptorVisitor.visitReceptor(this); + } + + @Override + public T accept(final IComponentVisitor aComponentVisitor) { + return aComponentVisitor.visitComponent(this); + } + + @Override + public boolean isSuperModel() { + return false; + } + + @Override + public String toString() { + return SnecmaObjectTypes.PART_MAT_REVISION + " " + this.getItemId(); + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/part/PartNoAeroRevision.java b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/part/PartNoAeroRevision.java new file mode 100644 index 0000000..063826e --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/part/PartNoAeroRevision.java @@ -0,0 +1,44 @@ +package com.capgemini.reports.snecmaobjects.part; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.capgemini.reports.snecmaobjects.visitor.IComponentVisitor; +import com.capgemini.reports.snecmaobjects.visitor.IReceptorVisitor; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +import static com.capgemini.framework.teamcenter.object.SnecmaObjectProperties.PV_TYPE_PART_NON_AERO; + +/** + * Class representing a PartNoAeroRevision. + */ +public class PartNoAeroRevision extends AbstractPart { + private static final long serialVersionUID = 6898634008256898679L; + + public PartNoAeroRevision(final TcSession session, final ItemRevision itemRevision) { + super(session, itemRevision); + } + + public String getTypeNoAero() { + return getMasterFormRev().getPropertyObject(PV_TYPE_PART_NON_AERO).getStringValue(); + } + + @Override + public T accept(final IReceptorVisitor aReceptorVisitor) { + return aReceptorVisitor.visitReceptor(this); + } + + @Override + public T accept(final IComponentVisitor aComponentVisitor) { + return aComponentVisitor.visitComponent(this); + } + + @Override + public boolean isSuperModel() { + return false; + } + + @Override + public String toString() { + return SnecmaObjectTypes.PART_NO_AERO_REVISION + " " + this.getItemId(); + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/part/StandardRevision.java b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/part/StandardRevision.java new file mode 100644 index 0000000..96f85fa --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/part/StandardRevision.java @@ -0,0 +1,49 @@ +package com.capgemini.reports.snecmaobjects.part; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.reports.snecmaobjects.visitor.IComponentVisitor; +import com.capgemini.reports.snecmaobjects.visitor.IReceptorVisitor; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +import static com.capgemini.framework.teamcenter.object.SnecmaObjectProperties.PV_FOURNISSEURS; +import static com.capgemini.framework.teamcenter.object.SnecmaObjectProperties.PV_TYPE_STANDARD; +import static com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes.STANDARD_REVISION; + +/** + * Class representing a StandardRevision. + */ +public class StandardRevision extends AbstractPart { + private static final long serialVersionUID = 3254104726494033602L; + + public StandardRevision(final TcSession session, final ItemRevision itemRevision) { + super(session, itemRevision); + } + + public String[] getLstFournisseurs() { + return itemRevision.getPropertyObject(PV_FOURNISSEURS).getStringArrayValue(); + } + + public String getTypeStandard() { + return getMasterFormRev().getPropertyObject(PV_TYPE_STANDARD).getStringValue(); + } + + @Override + public T accept(final IReceptorVisitor aReceptorVisitor) { + return aReceptorVisitor.visitReceptor(this); + } + + @Override + public T accept(final IComponentVisitor aComponentVisitor) { + return aComponentVisitor.visitComponent(this); + } + + @Override + public boolean isSuperModel() { + return false; + } + + @Override + public String toString() { + return STANDARD_REVISION + " " + this.getItemId(); + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/product/ProductRevision.java b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/product/ProductRevision.java new file mode 100644 index 0000000..2489f9e --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/product/ProductRevision.java @@ -0,0 +1,85 @@ +package com.capgemini.reports.snecmaobjects.product; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.reports.changeobjects.UnitRevision; +import com.capgemini.reports.snecmaobjects.AbstractSnecmaObject; +import com.capgemini.reports.snecmaobjects.visitor.IComponentVisitor; +import com.capgemini.reports.snecmaobjects.visitor.IReceptorVisitor; +import com.teamcenter.soa.client.model.ModelObject; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import lombok.EqualsAndHashCode; + +import java.util.ArrayList; +import java.util.List; + +import static com.capgemini.framework.teamcenter.object.SnecmaObjectProperties.*; +import static com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes.PRODUCT_REVISION; +import static com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes.UNIT_REVISION; + +/** + * Class representing a ProductRevision. + */ +@EqualsAndHashCode(callSuper = true) +public class ProductRevision extends AbstractSnecmaObject { + private static final long serialVersionUID = 9116577158989990064L; + + public ProductRevision(final TcSession session, final ItemRevision itemRevision) { + super(session, itemRevision); + } + + public String getDesignationEN() { + return getMasterFormRev().getPropertyObject(PV_DESIGNATION_EN).getStringValue(); + } + + public String getTypeProduit() { + session.loadProperties(getMasterFormRev(),PV_TYPE_PRODUIT); + return getMasterFormRev().getPropertyObject(PV_TYPE_PRODUIT).getStringValue(); + } + + public String getProductLine() { + return getMasterFormRev().getPropertyObject(PV_LIGNE_PRODUIT).getStringValue(); + } + + public String getDomain() { + return getMasterFormRev().getPropertyObject(PV_DOMAINE).getStringValue(); + } + + public List getUnits() { + List units = new ArrayList<>(); + session.loadProperties(itemRevision, PV_UNIT); + ModelObject[] unitsArray = itemRevision.getPropertyObject(PV_UNIT).getModelObjectArrayValue(); + session.loadProperties(unitsArray); + for (ModelObject unit : unitsArray) { + ItemRevision currentItemRev = (ItemRevision) unit; + if (UNIT_REVISION.equals(currentItemRev.getTypeObject().getName())) { + units.add(UnitRevision.build(session, currentItemRev)); + } + } + return units; + } + + @Override + public boolean isProduct() { + return true; + } + + @Override + public T accept(final IReceptorVisitor aReceptorVisitor) { + return aReceptorVisitor.visitReceptor(this); + } + + @Override + public T accept(final IComponentVisitor aComponentVisitor) { + return aComponentVisitor.visitComponent(this); + } + + @Override + public boolean isSuperModel() { + return false; + } + + @Override + public String toString() { + return PRODUCT_REVISION + " " + this.getItemId() + "/" + this.getRevisionId(); + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/rf/AbstractRF.java b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/rf/AbstractRF.java new file mode 100644 index 0000000..4ea9bee --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/rf/AbstractRF.java @@ -0,0 +1,27 @@ +package com.capgemini.reports.snecmaobjects.rf; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.reports.snecmaobjects.AbstractSnecmaObject; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +import static com.capgemini.framework.teamcenter.object.SnecmaObjectProperties.PV_EQUIVALENT_SNS_SIN; + +/** + * Abstract Class representing a RF. + */ +public abstract class AbstractRF extends AbstractSnecmaObject { + private static final long serialVersionUID = 4005615321655255506L; + + public AbstractRF(final TcSession session, final ItemRevision itemRevision) { + super(session, itemRevision); + } + + @Override + public boolean isRF() { + return true; + } + + public String getEquivalentSnsSin() { + return getMasterForm().getPropertyObject(PV_EQUIVALENT_SNS_SIN).getStringValue(); + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/rf/RFGenericRevision.java b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/rf/RFGenericRevision.java new file mode 100644 index 0000000..f7c40ce --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/rf/RFGenericRevision.java @@ -0,0 +1,44 @@ +package com.capgemini.reports.snecmaobjects.rf; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.reports.snecmaobjects.visitor.IComponentVisitor; +import com.capgemini.reports.snecmaobjects.visitor.IReceptorVisitor; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +import static com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes.RF_GENERIC_REVISION; + +/** + * Class representing a RFGenericRevision. + */ +public class RFGenericRevision extends AbstractRF { + private static final long serialVersionUID = 7484003347817912302L; + + public RFGenericRevision(final TcSession session, final ItemRevision itemRevision) { + super(session, itemRevision); + } + + @Override + public T accept(final IReceptorVisitor aReceptorVisitor) { + return aReceptorVisitor.visitReceptor(this); + } + + @Override + public T accept(final IComponentVisitor aComponentVisitor) { + return aComponentVisitor.visitComponent(this); + } + + @Override + public boolean isSuperModel() { + return false; + } + + @Override + public boolean isRFGeneric() { + return true; + } + + @Override + public String toString() { + return RF_GENERIC_REVISION + " " + this.getItemId(); + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/rf/RFPartAssembRevision.java b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/rf/RFPartAssembRevision.java new file mode 100644 index 0000000..bac6e7b --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/rf/RFPartAssembRevision.java @@ -0,0 +1,44 @@ +package com.capgemini.reports.snecmaobjects.rf; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.reports.snecmaobjects.visitor.IComponentVisitor; +import com.capgemini.reports.snecmaobjects.visitor.IReceptorVisitor; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +import static com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes.RF_PART_ASSEMB_REVISION; + +/** + * Class representing a RFPartAssembRevision. + */ +public class RFPartAssembRevision extends AbstractRF { + private static final long serialVersionUID = -7546817776977631474L; + + public RFPartAssembRevision(final TcSession session, final ItemRevision itemRevision) { + super(session, itemRevision); + } + + @Override + public T accept(final IReceptorVisitor aReceptorVisitor) { + return aReceptorVisitor.visitReceptor(this); + } + + @Override + public T accept(final IComponentVisitor aComponentVisitor) { + return aComponentVisitor.visitComponent(this); + } + + @Override + public boolean isSuperModel() { + return false; + } + + @Override + public boolean isRFPartOrPartAssemb() { + return true; + } + + @Override + public String toString() { + return RF_PART_ASSEMB_REVISION + " " + this.getItemId(); + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/rf/RFPartRevision.java b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/rf/RFPartRevision.java new file mode 100644 index 0000000..b42b1d7 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/rf/RFPartRevision.java @@ -0,0 +1,44 @@ +package com.capgemini.reports.snecmaobjects.rf; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.reports.snecmaobjects.visitor.IComponentVisitor; +import com.capgemini.reports.snecmaobjects.visitor.IReceptorVisitor; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +import static com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes.RF_PART_REVISION; + +/** + * Class representing a RFPartRevision. + */ +public class RFPartRevision extends AbstractRF { + private static final long serialVersionUID = -4115692852905919108L; + + public RFPartRevision(final TcSession session, final ItemRevision itemRevision) { + super(session, itemRevision); + } + + @Override + public T accept(final IReceptorVisitor aReceptorVisitor) { + return aReceptorVisitor.visitReceptor(this); + } + + @Override + public T accept(final IComponentVisitor aComponentVisitor) { + return aComponentVisitor.visitComponent(this); + } + + @Override + public boolean isSuperModel() { + return false; + } + + @Override + public String toString() { + return RF_PART_REVISION + " " + this.getItemId(); + } + + @Override + public boolean isRFPartOrPartAssemb() { + return true; + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/supermodel/AbstractSuperModel.java b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/supermodel/AbstractSuperModel.java new file mode 100644 index 0000000..aa4e3fb --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/supermodel/AbstractSuperModel.java @@ -0,0 +1,42 @@ +package com.capgemini.reports.snecmaobjects.supermodel; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.teamcenter.soa.client.model.strong.Item; + +public class AbstractSuperModel implements Comparable { + private final TcSession session; + private final Item item; + + public AbstractSuperModel(final TcSession session, final Item item) { + this.session = session; + this.item = item; + } + + public String getItemId() { + return item.get_item_id(); + } + + + public String getName() { + return item.get_object_name(); + } + + public String getType() { + return item.getTypeObject().getName(); + } + + @Override + public int compareTo(final com.capgemini.reports.snecmaobjects.supermodel.AbstractSuperModel other) { + return this.getItemId().compareTo(other.getItemId()); + } + + @Override + public boolean equals(final Object obj) { + return this == obj || obj instanceof com.capgemini.reports.snecmaobjects.supermodel.AbstractSuperModel && item.equals(((com.capgemini.reports.snecmaobjects.supermodel.AbstractSuperModel) obj).item); + } + + @Override + public int hashCode() { + return item.hashCode(); + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/supermodel/AbstractSuperModelRevision.java b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/supermodel/AbstractSuperModelRevision.java new file mode 100644 index 0000000..7b9490c --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/supermodel/AbstractSuperModelRevision.java @@ -0,0 +1,59 @@ +package com.capgemini.reports.snecmaobjects.supermodel; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.reports.snecmaobjects.AbstractSnecmaObject; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import lombok.EqualsAndHashCode; + +import java.util.regex.Pattern; + +import static com.capgemini.framework.teamcenter.object.SnecmaObjectProperties.PV_DESIGNATION_EN; +import static com.capgemini.framework.teamcenter.object.SnecmaObjectProperties.PV_RESPONSABLE_CONCEPTION; + + +/** + * Abstract Class representing a SuperModel. + */ +@EqualsAndHashCode(callSuper = true) +public abstract class AbstractSuperModelRevision extends AbstractSnecmaObject implements Comparable { + private static final long serialVersionUID = -190379543546189856L; + + /** + * This pattern identify a {@link SuperModelRevision} id. + **/ + private static final Pattern REGEX_PATTERN_FOR_GENERIC_REVISION = Pattern.compile("^[A-Z]"); + + public AbstractSuperModelRevision(final TcSession session, final ItemRevision itemRevision) { + super(session, itemRevision); + } + + /** + * Return true if the id correspond to a {@link SuperModelRevision} id.
    + */ + public static boolean isSuperModelRevision(final String genId) { + return REGEX_PATTERN_FOR_GENERIC_REVISION.matcher(genId).find(); + } + + public String getDesignationEN() { + return getMasterFormRev().getPropertyObject(PV_DESIGNATION_EN).getStringValue(); + } + + public String getResponsableConception() { + return getMasterFormRev().getPropertyObject(PV_RESPONSABLE_CONCEPTION).getStringValue(); + } + + @Override + public int compareTo(final com.capgemini.reports.snecmaobjects.supermodel.AbstractSuperModelRevision other) { + int compareID = this.getItemId().compareTo(other.getItemId()); + if (compareID != 0) { + return compareID; // Different ID + } else { + return this.getRevisionId().compareTo(other.getRevisionId()); + } + } + + @Override + public boolean isSuperModel() { + return true; + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/supermodel/SuperModel.java b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/supermodel/SuperModel.java new file mode 100644 index 0000000..79d8228 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/supermodel/SuperModel.java @@ -0,0 +1,12 @@ +package com.capgemini.reports.snecmaobjects.supermodel; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.reports.snecmaobjects.generic.AbstractGeneric; +import com.teamcenter.soa.client.model.strong.Item; + +public class SuperModel extends AbstractGeneric { + + public SuperModel(final TcSession session, final Item item) { + super(session, item); + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/supermodel/SuperModelRevision.java b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/supermodel/SuperModelRevision.java new file mode 100644 index 0000000..56de49c --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/supermodel/SuperModelRevision.java @@ -0,0 +1,33 @@ +package com.capgemini.reports.snecmaobjects.supermodel; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.reports.snecmaobjects.visitor.IComponentVisitor; +import com.capgemini.reports.snecmaobjects.visitor.IReceptorVisitor; +import com.teamcenter.soa.client.model.strong.ItemRevision; + + +/** + * Class representing a SuperModelRevision. + */ +public class SuperModelRevision extends AbstractSuperModelRevision { + private static final long serialVersionUID = 4530714427862196578L; + + public SuperModelRevision(final TcSession session, final ItemRevision itemRevision) { + super(session, itemRevision); + } + + @Override + public T accept(final IReceptorVisitor aReceptorVisitor) { + return aReceptorVisitor.visitReceptor(this); + } + + @Override + public T accept(final IComponentVisitor aComponentVisitor) { + return aComponentVisitor.visitComponent(this); + } + + @Override + public String toString() { + return getType() + " " + this.getItemId(); + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/visitor/IComponentVisitor.java b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/visitor/IComponentVisitor.java new file mode 100644 index 0000000..61862f4 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/visitor/IComponentVisitor.java @@ -0,0 +1,206 @@ +package com.capgemini.reports.snecmaobjects.visitor; + +import com.capgemini.reports.snecmaobjects.admin.RFAdminAGRevision; +import com.capgemini.reports.snecmaobjects.admin.RFAdminAPRevision; +import com.capgemini.reports.snecmaobjects.admin.RFAdminARevision; +import com.capgemini.reports.snecmaobjects.admin.RFAdminRevision; +import com.capgemini.reports.snecmaobjects.descriptif.DescriptifRevision; +import com.capgemini.reports.snecmaobjects.generic.GenericAssembRevision; +import com.capgemini.reports.snecmaobjects.generic.GenericRevision; +import com.capgemini.reports.snecmaobjects.mockup.MockupRevision; +import com.capgemini.reports.snecmaobjects.part.*; +import com.capgemini.reports.snecmaobjects.product.ProductRevision; +import com.capgemini.reports.snecmaobjects.rf.RFGenericRevision; +import com.capgemini.reports.snecmaobjects.rf.RFPartAssembRevision; +import com.capgemini.reports.snecmaobjects.rf.RFPartRevision; +import com.capgemini.reports.snecmaobjects.supermodel.SuperModelRevision; + +import java.io.Serializable; + +/** + * Interface representing the Component behaviour of a SnecmaObject. + * + * @param produced output type + */ +public interface IComponentVisitor extends Serializable { + + /** + * Visitor which can used the ¨ProductRevision Component properties to make a chosen report. + * + * @param aProductRev ProductRevision + * @return T + * + */ + T visitComponent(final ProductRevision aProductRev); + + /** + * Visitor which can used the GenericRevision Component properties to make a chosen report. + * + * @param aGenericRev GenericRevision + * @return T + * + */ + T visitComponent(final GenericRevision aGenericRev); + + /** + * Visitor which can used the ¨SuperModelRevision Component properties to make a chosen report. + * + * @param aSuperModelRev ProductRevision + * @return T + * + */ + T visitComponent(final SuperModelRevision aSuperModelRev); + + /** + * Visitor which can used the GenericAssembRevision Component properties to make a chosen report. + * + * @param aGenericAssembRev GenericAssembRevision + * @return T + * + */ + T visitComponent(final GenericAssembRevision aGenericAssembRev); + + /** + * Visitor which can used the AlternateRevision Component properties to make a chosen report. + * + * @param aAlternateRev AlternateRevision + * @return T + * + */ + T visitComponent(final AlternateRevision aAlternateRev); + + /** + * Visitor which can used the DETRevision Component properties to make a chosen report. + * + * @param aDetRev DETRevision + * @return T + * + */ + T visitComponent(final DETRevision aDetRev); + + /** + * Visitor which can used the PartAeroRevision Component properties to make a chosen report. + * + * @param aPartAeroRev PartAeroRevision + * @return T + * + */ + T visitComponent(final PartAeroRevision aPartAeroRev); + + /** + * Visitor which can used the PartNoAeroRevision Component properties to make a chosen report. + * + * @param aPartNoAeroRev PartNoAeroRevision + * @return T + * + */ + T visitComponent(final PartNoAeroRevision aPartNoAeroRev); + + /** + * Visitor which can used the PartAssembRevision Component properties to make a chosen report. + * + * @param aPartAssembRev PartAssembRevision + * @return T + * + */ + T visitComponent(final PartAssembRevision aPartAssembRev); + + /** + * Visitor which can used the PartMatRevision Component properties to make a chosen report. + * + * @param aPartMatRev PartMatRevision + * @return T + * + */ + T visitComponent(final PartMatRevision aPartMatRev); + + /** + * Visitor which can used the StandardRevision Component properties to make a chosen report. + * + * @param aStandardRev StandardRevision + * @return T + * + */ + T visitComponent(final StandardRevision aStandardRev); + + /** + * Visitor which can used the RFGenericRevision Component properties to make a chosen report. + * + * @param aRfGenericRev RFGenericRevision + * @return T + * + */ + T visitComponent(final RFGenericRevision aRfGenericRev); + + /** + * Visitor which can used the RFPartAssembRevision Component properties to make a chosen report. + * + * @param aRfPartAssembRev RFPartAssembRevision + * @return T + * + */ + T visitComponent(final RFPartAssembRevision aRfPartAssembRev); + + /** + * Visitor which can used the RFPartRevision Component properties to make a chosen report. + * + * @param aRfPartRev RFPartRevision + * @return T + * + */ + T visitComponent(final RFPartRevision aRfPartRev); + + /** + * Visitor which can used the RFAdminRevision Component properties to make a chosen report. + * + * @param aRfAdminRev RFAdminRevision + * @return T + * + */ + T visitComponent(final RFAdminRevision aRfAdminRev); + + /** + * Visitor which can used the RFAdminARevision Component properties to make a chosen report. + * + * @param aRfAdminARev RFAdminARevision + * @return T + * + */ + T visitComponent(final RFAdminARevision aRfAdminARev); + + /** + * Visitor which can used the RFAdminAPRevision Component properties to make a chosen report. + * + * @param aRfAdminAPRev RFAdminAPRevision + * @return T + * + */ + T visitComponent(final RFAdminAPRevision aRfAdminAPRev); + + /** + * Visitor which can used the RFAdminAGRevision Component properties to make a chosen report. + * + * @param aRfAdminAGRev RFAdminAGRevision + * @return T + * + */ + T visitComponent(final RFAdminAGRevision aRfAdminAGRev); + + /** + * Visitor which can used the MockupRevision Receptor properties to make a chosen report. + * + * @param aMockupRev MockupRevision + * @return T + * + */ + T visitComponent(final MockupRevision aMockupRev); + + /** + * Visitor which can used the DescriptifRevision Receptor properties to make a chosen report. + * + * @param aDescriptifRev DescriptifRevision + * @return T + * + */ + T visitComponent(final DescriptifRevision aDescriptifRev); +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/visitor/IReceptorVisitor.java b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/visitor/IReceptorVisitor.java new file mode 100644 index 0000000..26b58fe --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/snecmaobjects/visitor/IReceptorVisitor.java @@ -0,0 +1,220 @@ +package com.capgemini.reports.snecmaobjects.visitor; + +import com.capgemini.reports.snecmaobjects.admin.RFAdminAGRevision; +import com.capgemini.reports.snecmaobjects.admin.RFAdminAPRevision; +import com.capgemini.reports.snecmaobjects.admin.RFAdminARevision; +import com.capgemini.reports.snecmaobjects.admin.RFAdminRevision; +import com.capgemini.reports.snecmaobjects.descriptif.DescriptifRevision; +import com.capgemini.reports.snecmaobjects.generic.GenericAssembRevision; +import com.capgemini.reports.snecmaobjects.generic.GenericRevision; +import com.capgemini.reports.snecmaobjects.mockup.MockupRevision; +import com.capgemini.reports.snecmaobjects.part.*; +import com.capgemini.reports.snecmaobjects.product.ProductRevision; +import com.capgemini.reports.snecmaobjects.rf.RFGenericRevision; +import com.capgemini.reports.snecmaobjects.rf.RFPartAssembRevision; +import com.capgemini.reports.snecmaobjects.rf.RFPartRevision; +import com.capgemini.reports.snecmaobjects.supermodel.SuperModelRevision; + +import java.io.Serializable; + +/** + * Interface representing the Receptor behaviour of a SnecmaObject. + * + * @param produced output type + */ +public interface IReceptorVisitor extends Serializable { + + /** + * Visitor which can used the ProductRevision Receptor properties to make a chosen report. + * + * @param aProductRev ProductRevision + * @return T + * + */ + T visitReceptor(final ProductRevision aProductRev); + + /** + * Visitor which can used the GenericRevision Receptor properties to make a chosen report. + * + * @param aGenericRev GenericRevision + * @return T + * + */ + T visitReceptor(final GenericRevision aGenericRev); + + /** + * Visitor which can used the GenericAssembRevision Receptor properties to make a chosen report. + * + * @param aGenericAssembRev GenericAssembRevision + * @return T + * + */ + T visitReceptor(final GenericAssembRevision aGenericAssembRev); + + + /** + * Visitor which can used the GenericRevision Receptor properties to make a chosen report. + * + * @param aSuperModelRev GenericRevision + * @return T + * + */ + T visitReceptor(final SuperModelRevision aSuperModelRev); + + /** + * Visitor which can used the AlternateRevision Receptor properties to make a chosen report. + * + * @param aAlternateRev AlternateRevision + * @return T + * + */ + T visitReceptor(final AlternateRevision aAlternateRev); + + /** + * Visitor which can used the SuperModelRevision Receptor properties to make a chosen report. + * + // * @param aSuperModelRev SuperModelRevision + * @return T + * + */ + // T visitReceptor(final SuperModelRevision aSuperModelRev); + + + + /** + * Visitor which can used the DETRevision Receptor properties to make a chosen report. + * + * @param aDetRev DETRevision + * @return T + * + */ + T visitReceptor(final DETRevision aDetRev); + + /** + * Visitor which can used the PartAeroRevision Receptor properties to make a chosen report. + * + * @param aPartAeroRev PartAeroRevision + * @return T + * + */ + T visitReceptor(final PartAeroRevision aPartAeroRev); + + /** + * Visitor which can used the PartNoAeroRevision Receptor properties to make a chosen report. + * + * @param aPartNoAeroRev PartNoAeroRevision + * @return T + * + */ + T visitReceptor(final PartNoAeroRevision aPartNoAeroRev); + + /** + * Visitor which can used the PartAssembRevision Receptor properties to make a chosen report. + * + * @param aPartAssembRev PartAssembRevision + * @return T + * + */ + T visitReceptor(final PartAssembRevision aPartAssembRev); + + /** + * Visitor which can used the PartMatRevision Receptor properties to make a chosen report. + * + * @param aPartMatRev PartMatRevision + * @return T + * + */ + T visitReceptor(final PartMatRevision aPartMatRev); + + /** + * Visitor which can used the StandardRevision Receptor properties to make a chosen report. + * + * @param aStandardRev StandardRevision + * @return T + * + */ + T visitReceptor(final StandardRevision aStandardRev); + + /** + * Visitor which can used the RFGenericRevision Receptor properties to make a chosen report. + * + * @param aRfGenericRev RFGenericRevision + * @return T + * + */ + T visitReceptor(final RFGenericRevision aRfGenericRev); + + /** + * Visitor which can used the RFPartAssembRevision Receptor properties to make a chosen report. + * + * @param aRfPartAssembRev RFPartAssembRevision + * @return T + * + */ + T visitReceptor(final RFPartAssembRevision aRfPartAssembRev); + + /** + * Visitor which can used the RFPartRevision Receptor properties to make a chosen report. + * + * @param aRfPartRev RFPartRevision + * @return T + * + */ + T visitReceptor(final RFPartRevision aRfPartRev); + + /** + * Visitor which can used the RFAdminRevision Receptor properties to make a chosen report. + * + * @param aRfAdminRev RFAdminRevision + * @return T + * + */ + T visitReceptor(final RFAdminRevision aRfAdminRev); + + /** + * Visitor which can used the RFAdminARevision Receptor properties to make a chosen report. + * + * @param aRfAdminARev RFAdminARevision + * @return T + * + */ + T visitReceptor(final RFAdminARevision aRfAdminARev); + + /** + * Visitor which can used the RFAdminAPRevision Receptor properties to make a chosen report. + * + * @param aRfAdminAPRev RFAdminAPRevision + * @return T + * + */ + T visitReceptor(final RFAdminAPRevision aRfAdminAPRev); + + /** + * Visitor which can used the RFAdminAGRevision Receptor properties to make a chosen report. + * + * @param aRfAdminAGRev RFAdminAGRevision + * @return T + * + */ + T visitReceptor(final RFAdminAGRevision aRfAdminAGRev); + + /** + * Visitor which can used the MockupRevision Receptor properties to make a chosen report. + * + * @param aMockupRev MockupRevision + * @return T + * + */ + T visitReceptor(final MockupRevision aMockupRev); + + /** + * Visitor which can used the DescriptifRevision Receptor properties to make a chosen report. + * + * @param aDescriptifRev DescriptifRevision + * @return T + * + */ + T visitReceptor(final DescriptifRevision aDescriptifRev); + + T emptyRf(); +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/teamcenter/ObjectInfoHelper.java b/teamcenter/src/main/java/com/capgemini/reports/teamcenter/ObjectInfoHelper.java new file mode 100644 index 0000000..92b76c7 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/teamcenter/ObjectInfoHelper.java @@ -0,0 +1,687 @@ +package com.capgemini.reports.teamcenter; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.object.SnecmaObjectProperties; +import com.capgemini.framework.teamcenter.object.pom.status.StatusEnum; +import com.capgemini.framework.teamcenter.object.pom.status.StatusEnum.AbstractStatusFilter; +import com.capgemini.framework.teamcenter.object.pom.status.TcReleaseStatus; +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import com.capgemini.reports.ItemRevisionComparator; +import com.capgemini.reports.exceptions.NotFoundException; +import com.capgemini.reports.releasestatus.RevisionStatusAndDate; +import com.google.common.base.Optional; +import com.teamcenter.soa.client.model.ModelObject; +import com.teamcenter.soa.client.model.strong.Effectivity; +import com.teamcenter.soa.client.model.strong.Item; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import com.teamcenter.soa.client.model.strong.ReleaseStatus; +import lombok.extern.slf4j.Slf4j; + +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static com.capgemini.framework.teamcenter.object.SnecmaObjectProperties.PV_ALTERNATIVE; +import static com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes.EFFECTIVITY; + +/** + * This class is able to obtain specific data from some objects in Teamcenter.
    + * To be used when the information is there, it's just buried in layers of TC objects. This helper class will only help retrieve the data reliably.
    + * Typical usage is to find effectivity status of an ItemRevision, obtain the latest maturity status etc. + */ +@Slf4j +public class ObjectInfoHelper { + + private static final String WITH_UNIT = " with Unit "; + + private static final Pattern EFFECTIVITY_RANGE_UP = Pattern.compile("([\\d]{2,})-([Uu][Pp]|[Ss][Oo])"); // Matches an open-ended range like '50-UP' (note: can also be '50-SO') + private static final Pattern EFFECTIVITY_RANGE_NUMBER = Pattern.compile("([\\d]{2,})-[\\d]{2,}"); // Matches a number range like '95-105' + private static final Pattern EFFECTIVITY_RANGE_ALONE = Pattern.compile("([\\d]{2,})"); // Matches a single number (2+ digits) + + + /** + * Returns a {@link List} of {@link ModelObject}s containing Part (Standard or Part Aero) which are inside + * the pseudo folder of a provided {@link ItemRevision} (Alternate Revision or DET Revision).
    + */ + public static List getPartsInPseudoFolderOfAltOrDetRevision(final TcSession session, final ItemRevision itemRevision) { + String objectType = itemRevision.getTypeObject().getName(); + if (SnecmaObjectTypes.isAltOrDet(objectType)) { + List listItem = new ArrayList<>(); + session.loadProperties(itemRevision, PV_ALTERNATIVE); + ModelObject[] alternatives = itemRevision.getPropertyObject(PV_ALTERNATIVE).getModelObjectArrayValue(); + session.loadProperties(alternatives); + for (ModelObject modelObj : alternatives) { + listItem.add((Item) modelObj); + } + return listItem; + } else { + return new ArrayList<>(); + } + } + + /** + * Returns a {@link List} of {@link ModelObject}s containing whatever are inside the pseudo folder.
    + */ + public static List getModelObjectsInPseudoFolderUnderItemRevision(final TcSession session, final ItemRevision itemRevision, final String propertyPseudoFolder) { + session.loadProperties(itemRevision, propertyPseudoFolder); + ModelObject[] folderObjects = itemRevision.getPropertyObject(propertyPseudoFolder).getModelObjectArrayValue(); + session.loadProperties(folderObjects); + return Arrays.asList(folderObjects); + } + + /** + * Check if Generic or GenericAssemb has an unit less than or equal unitTarget. + */ + public static boolean getClosestGenerics(final TcSession session, final String genericID, final int targetUnit, final List genericsRevision) + throws NotFoundException { + boolean isUnitClosest = false; + + if (genericsRevision.isEmpty()) { + throw new NotFoundException("No unitRevision exists for Generic||Generic Assemb " + genericID + WITH_UNIT + targetUnit); + } + for (ItemRevision genericRevision : genericsRevision) { + session.loadProperties(genericRevision, "release_status_list"); + ReleaseStatus[] releaseStatuses = genericRevision.get_release_status_list(); + session.loadProperties(releaseStatuses); + for (ReleaseStatus status : releaseStatuses) { + isUnitClosest = getInferiorUnitFromEffectivities(session, status, targetUnit); + } + } + + return isUnitClosest; + + } + + /** + * Returns the first TcEffectivity whose name is "effectivity" and whose range starts before the provided unit. + */ + private static boolean getInferiorUnitFromEffectivities(final TcSession session, final ReleaseStatus releaseStatus, final int targetUnit) { + session.loadProperties(releaseStatus, "effectivities"); + ModelObject[] effectivities = releaseStatus.get_effectivities(); + session.loadProperties(effectivities); + for (ModelObject objectEffectivity : effectivities) { + String statusName = releaseStatus.get_name(); + if (!EFFECTIVITY.equals(statusName)) { + continue; + } + Effectivity effectivity = (Effectivity) objectEffectivity; + String effectivityRange = effectivity.get_range_text(); + log.debug("Check is current TcEffectivity range : " + effectivityRange + " is <= " + targetUnit); + if (isInRange(targetUnit, effectivityRange)) { + return true; + } + } + return false; + } + + private static boolean isInRange(final int targetUnit, final String effectivityRange) { + boolean found = false; + if (isEffectivityRangeUP(effectivityRange)) { + if (targetUnit <= getFirstRangeValue(effectivityRange, EFFECTIVITY_RANGE_UP)) { + found = true; + } + } else if (isEffectivityRangeNUMBER(effectivityRange)) { + if (targetUnit <= getFirstRangeValue(effectivityRange, EFFECTIVITY_RANGE_NUMBER)) { + found = true; + } + } else if (isEffectivityRangeALONE(effectivityRange) && targetUnit <= getFirstRangeValue(effectivityRange, EFFECTIVITY_RANGE_ALONE)) { + found = true; + } + return found; + } + + private static boolean equalsRangeStart(final int targetUnit, final String effectivityRange) { + boolean found = false; + if (isEffectivityRangeUP(effectivityRange)) { + if (targetUnit == getFirstRangeValue(effectivityRange, EFFECTIVITY_RANGE_UP)) { + found = true; + } + } else if (isEffectivityRangeNUMBER(effectivityRange)) { + if (targetUnit == getFirstRangeValue(effectivityRange, EFFECTIVITY_RANGE_NUMBER)) { + found = true; + } + } else if (isEffectivityRangeALONE(effectivityRange) && targetUnit == getFirstRangeValue(effectivityRange, EFFECTIVITY_RANGE_ALONE)) { + found = true; + } + return found; + } + + /** + * Returns the first match in the unit range, using the provided pattern. + * + * @param range the Unit range (can be a single unit, an pen range, a closed range etc.) + * @param pattern The patter nto decipher the provided range + * @return the unit number which is the start of the provided range + */ + private static int getFirstRangeValue(final String range, final Pattern pattern) { + String data = ""; + Matcher matcher = pattern.matcher(range); + if (matcher.matches() && matcher.groupCount() >= 1) { + data = matcher.group(1); + } + return Integer.parseInt(data); + } + + private static boolean isEffectivityRangeUP(final String input) { + Matcher matcher = EFFECTIVITY_RANGE_UP.matcher(input); + return matcher.matches(); + } + + private static boolean isEffectivityRangeNUMBER(final String input) { + Matcher matcher = EFFECTIVITY_RANGE_NUMBER.matcher(input); + return matcher.matches(); + } + + private static boolean isEffectivityRangeALONE(final String input) { + Matcher matcher = EFFECTIVITY_RANGE_ALONE.matcher(input); + return matcher.matches(); + } + + /** + * Returns the {@link ItemRevision} with the most recent modification date, of an {@link Item}.
    + * This method requires the last_mod_date property on {@link ItemRevision}. + * + * @param itemsRevisions the List of candidate {@link ItemRevision}s + * @param userDate the limit user date, only modifications before that date will be examined + * @return An Optional containing the most up-to-date ItemRevision, TcReleaseStatus and mod date. The Optional may be empty if not Revisions were provided! + */ + public static RevisionStatusAndDate getRevisionAndStatusWithMostRecentModificationDate(final List itemsRevisions, + final Calendar userDate) { + RevisionStatusAndDate bestYet = null; + for (ItemRevision curItemRevision : itemsRevisions) { + Calendar modDateCurrentItem = curItemRevision.get_last_mod_date(); // Requires the last_mod_date property + if (bestYet == null) { // First pass + bestYet = new RevisionStatusAndDate(modDateCurrentItem, null, curItemRevision); + } else { + if (modDateCurrentItem.after(bestYet.getReleaseDate()) + && (userDate == null || modDateCurrentItem.before(userDate) || sameDay(modDateCurrentItem, userDate))) { + bestYet = new RevisionStatusAndDate(modDateCurrentItem, null, curItemRevision); + } + } + } + return bestYet; + } + + /** + * Returns the {@link ItemRevision} with the most recent modification date, of an {@link Item}.
    + * This method requires the last_mod_date property on {@link ItemRevision}. + * + * @param itemsRevision the List of candidate {@link ItemRevision}s + * @return An Optional containing the most up-to-date ItemRevision, TcReleaseStatus and mod date. The Optional may be empty if not Revisions were provided! + */ + public static RevisionStatusAndDate getLastModDate(final ItemRevision itemsRevision) { + RevisionStatusAndDate bestYet = null; + + Calendar modDateCurrentItem = itemsRevision.get_last_mod_date(); // Requires the last_mod_date property + bestYet = new RevisionStatusAndDate(modDateCurrentItem, null, itemsRevision); + + return bestYet; + } + + private static boolean sameDay(final Calendar cal1, final Calendar cal2) { + return cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR) && cal1.get(Calendar.DAY_OF_YEAR) == cal2.get(Calendar.DAY_OF_YEAR); + } + + /** + * Returns the {@link ItemRevision} whose {@link ReleaseStatus} has the most recent release date, amongst the provided ItemRevisions.
    + * This method requires the date_released property on {@link ItemRevision}.
    + * This method requires the date_released property on {@link ReleaseStatus}.
    + * This method requires the release_status_list property on {@link ItemRevision}, with properties. + * + * @param session + * @param itemsRevisions the List of candidate {@link ItemRevision}s + * @param userDate the limit user date, only items released before that date will be examined. If null, all dates are accepted. + * @param statusFilter A filter on the statuses to examine. Statuses rejected by the filter will not be examined at all. + * @return An {@link Optional} containing the most up-to-date ItemRevision, TcReleaseStatus and release date (or empty, if no status matching the date could be found) + */ + public static Optional getRevisionAndStatusWithMostRecentReleaseDate(final TcSession session, final List itemsRevisions, + final Calendar userDate, final AbstractStatusFilter statusFilter) { + Optional bestYet = Optional.absent(); + for (ModelObject curItemRevision : itemsRevisions) { + List listReleaseStatus = statusFilter.filterStatusOf(session, (ItemRevision) curItemRevision); + for (ReleaseStatus status : listReleaseStatus) { + if (status == null) { + continue; + } + Calendar date = status.get_date_released(); + + if ((userDate == null || date.compareTo(userDate) < 0) + && (!bestYet.isPresent() || bestYet.get().getReleaseDate().compareTo(date) < 0)) { + bestYet = Optional.of(new RevisionStatusAndDate(date, status, (ItemRevision) curItemRevision)); + } + } + } + return bestYet; + } + + /** + * Returns the {@link ItemRevision} whose {@link ReleaseStatus} has the most recent release date, amongst the provided ItemRevisions.
    + * This method requires the date_released property on {@link ItemRevision}.
    + * This method requires the date_released property on {@link ReleaseStatus}.
    + * This method requires the release_status_list property on {@link ItemRevision}, with properties. + * + * @param session + * @param itemsRevisions the List of candidate {@link ItemRevision}s + * @param userDate the limit user date, only items released before that date will be examined. If null, all dates are accepted. + * @param allowedStatus if none are given, all status will be used (except TcEffectivity which is not really a maturity status). If not empty, only the provided statuses will be returned. + * @return An {@link Optional} containing the most up-to-date ItemRevision, TcReleaseStatus and release date (or empty, if no status matching the date could be found) + */ + public static Optional getRevisionAndStatusWithMostRecentReleaseDate(final TcSession session, final List itemsRevisions, + final Calendar userDate, final StatusEnum... allowedStatus) { + AbstractStatusFilter filter = + (allowedStatus == null || allowedStatus.length == 0) ? StatusEnum.forbid(StatusEnum.EFFECTIVITY) : StatusEnum.allow(allowedStatus); // By default, forbid TcEffectivity. + return getRevisionAndStatusWithMostRecentReleaseDate(session, itemsRevisions, userDate, filter); + } + + /** + * Returns the {@link ItemRevision} whose {@link ReleaseStatus} has the most recent release date, amongst the provided ItemRevisions.
    + * This method requires the date_released property on {@link ItemRevision}.
    + * This method requires the date_released property on {@link ReleaseStatus}.
    + * This method requires the release_status_list property on {@link ItemRevision}. + * + * @param session + * @param itemsRevision the List of candidate {@link ItemRevision}s + * @param userDate the limit user date, only Statuses released before that date will be examined. May be null if you want to ignore this + * @param wantedStatus Enumeration of wanted status ({@link StatusEnum}). + * @return an {@link Optional} which may contain the ItemRevision with the latest Release Date that still is before the provided deadline, or nothing if no revision meet the constraints + */ + public static Optional getRevisionFromStatusWithMostRecentReleaseDate(final TcSession session, final List itemsRevision, + final Calendar userDate, final StatusEnum... wantedStatus) { + Optional latest = getRevisionAndStatusWithMostRecentReleaseDate(session, itemsRevision, userDate, wantedStatus); + if (latest.isPresent()) { + return Optional.of(latest.get().getItemRevision()); + } else { + return Optional.absent(); + } + } + /** + * Returns the {@link ItemRevision} whose {@link ReleaseStatus} has the most recent release date, amongst the provided ItemRevisions not cancelled.
    + * This method requires the date_released property on {@link ItemRevision}.
    + * This method requires the date_released property on {@link ReleaseStatus}.
    + * This method requires the release_status_list property on {@link ItemRevision}. + * + * @param session + * @param itemsRevision the List of candidate {@link ItemRevision}s + * @param userDate the limit user date, only Statuses released before that date will be examined. May be null if you want to ignore this + * @return an {@link Optional} which may contain the ItemRevision with the latest Release Date that still is before the provided deadline, or nothing if no revision meet the constraints + */ + public static Optional getRevisionFromStatusWithMostRecentReleaseDateNotCancelled(final TcSession session, final List itemsRevision, + final Calendar userDate) { + AbstractStatusFilter filter = StatusEnum.forbid(StatusEnum.EFFECTIVITY,StatusEnum.OLD_EFFECTIVITY); + Optional bestYet = Optional.absent(); + Optional bestYetNoDefApproved= Optional.absent(); + boolean flagDefApproved=false; + for (ItemRevision curItemRevision : itemsRevision) { + List listReleaseStatus = filter.filterStatusOf(session, (ItemRevision) curItemRevision); + boolean flagCancel = false; + boolean flagDefApprovedCurrent = false; + Optional currentBestYet = Optional.absent(); + for (ReleaseStatus status : listReleaseStatus) { + + if (status == null) { + continue; + } + if (status.get_name().equals(StatusEnum.CANCELLED.getIdentifier())) { + flagCancel = true; + //on a trouvé un flag Cancel on à plus besoin de parcourir le rest des status + break; + } + if (status.get_name().equals(StatusEnum.DEF_APPROVED.getIdentifier())){ + flagDefApprovedCurrent =true; + } + Calendar date = status.get_date_released(); + if ((userDate == null || date.compareTo(userDate) < 0) + && (!bestYet.isPresent() || bestYet.get().getReleaseDate().compareTo(date) < 0)) { + currentBestYet = Optional.of(new RevisionStatusAndDate(date, status, (ItemRevision) curItemRevision)); + } + + } + if (!flagCancel) { + // Cas ou pas de status Def Approved + if (listReleaseStatus.size() == 0) { + if ((!bestYetNoDefApproved.isPresent()) + || bestYetNoDefApproved.get().getReleaseDate().compareTo((curItemRevision).get_last_mod_date()) <= 0) { + bestYetNoDefApproved = Optional.of(getLastModDate(curItemRevision)); + } + } else { + //Cas ou on à trouvé un statut def approved + if (currentBestYet.isPresent()) { + bestYet = currentBestYet; + } + flagDefApproved = flagDefApproved || flagDefApprovedCurrent; + } + } + } + RevisionStatusAndDate lastRevStatDate = null; + if (flagDefApproved == true) { + //return Optional.of(latest.get().getItemRevision()); + lastRevStatDate =bestYet.get(); + } else { + + if(bestYetNoDefApproved.isPresent()){ + lastRevStatDate = bestYetNoDefApproved.get(); + }else{ + //all cancel + return Optional.absent(); + + } + } + return Optional.of(lastRevStatDate.getItemRevision()); + } + /** + * Returns the {@link ReleaseStatus} with the most recent release date, amongst the provided {@link ItemRevision}s.
    + * This method requires the date_released property on {@link ReleaseStatus} + * + * @param itemRevision the entry ItemRevision + * @param forbiddenStatus the enumeration of all the forbidden status + * @return ReleaseStatus the appropriate ReleaseStatus with the most recent date released + */ + public static ReleaseStatus getStatusWithMostRecentReleaseDate(final TcSession session, final ItemRevision itemRevision, final StatusEnum... forbiddenStatus) { + // Retrieve all the ReleaseStatus + List releaseStatusPartRev = new ArrayList<>(); + if (forbiddenStatus.length == 0) { + session.loadProperties(itemRevision, "release_status_list"); + ReleaseStatus[] releaseStatuses = itemRevision.get_release_status_list(); + session.loadProperties(releaseStatuses); + Collections.addAll(releaseStatusPartRev, releaseStatuses); + } else { + releaseStatusPartRev = TcReleaseStatus.getAllStatusExceptSome(session, itemRevision, forbiddenStatus); + } + + // Select the most recent ReleaseStatus + ReleaseStatus selectedRS = null; + Calendar selectedDate = null; + for (ReleaseStatus status : releaseStatusPartRev) { + if (status != null) { + Calendar date = status.get_date_released(); + if (selectedDate == null) { // First pass + selectedRS = status; + selectedDate = date; + } else if (selectedDate.compareTo(date) < 0) { + selectedRS = status; + selectedDate = date; + } + } + } + return selectedRS; + } + + + /** + * Get all the {@link ItemRevision}s whose effectivies are the highest (as long as they stay below the provided rangeRefStr parameter). + * + * @param revisionsList List<{@link ItemRevision}> the list of all the {@link ItemRevision} + * @param rangeRefStr String the limit range + * @return the ItemRevisions, in a {@link List} + */ + public static List getRevisionWithHighestRange(final TcSession session, final List revisionsList, final String rangeRefStr) { + int rangeRef = Integer.parseInt(rangeRefStr); + List results = new ArrayList<>(); // The list of all revisions with the highest range + int resultRange = -1; // THe highest Range + + // Browse all revisions + for (ItemRevision itemRev : revisionsList) { + List effectivityList = TcReleaseStatus.getChosenStatus(session, itemRev, StatusEnum.EFFECTIVITY); + if (effectivityList.isEmpty()) { + continue; + } + int selected = selectHighestRange(session, effectivityList, rangeRef); // Is negative if none are found + if (selected > 0) { + if (selected == resultRange) { + results.add(itemRev); // Same range found, add this ItemRev to the list of items found with same range + } else if (selected > resultRange) { // Closer range found, begin a new list with this ItemRev + results.clear(); + results.add(itemRev); + resultRange = selected; + } + } + } + return results; + } + + /** + * Keep the {@link ItemRevision} in the entry list which have the same end Item Id value as the reference value.
    + * Note on the policy: The property {@code end_item} must be set on the TcEffectivity, and {@code withProperties} set to true + * + * @param revisionsList List<{@link ItemRevision}> - the list of revisions + * @param endItemId {@link String} - the wanted value of the end Item Id + * @return the chosen list + */ + public static List getRevisionWithSameEndItem(final TcSession session, final List revisionsList, final String endItemId) { + List results = new ArrayList<>(); + for (ItemRevision itemRev : revisionsList) { + boolean isSuccess = false; + for (ReleaseStatus releaseStatus : TcReleaseStatus.getChosenStatus(session, itemRev, StatusEnum.EFFECTIVITY)) { + session.loadProperties(releaseStatus, "effectivities"); + ModelObject[] effectivities = releaseStatus.get_effectivities(); + session.loadProperties(effectivities); + for (ModelObject effectivityObject : effectivities) { + Effectivity effectivity = (Effectivity) effectivityObject; + session.loadProperties(effectivity, "end_item"); + Item endItem = effectivity.get_end_item(); + session.loadProperties(endItem); + if (endItemId.equals(SnecmaObjectProperties.getItemIdOrNull(endItem))) { + results.add(itemRev); + isSuccess = true; + break; + } + } + if (isSuccess) { + break; + } + } + } + return results; + } + + /** + * Selects the TcEffectivity with the highest range, returns the range.
    + * If no Effectivities are eligible (none exist or those that exist are below the provided rangeRef) returns -1. + */ + private static int selectHighestRange(final TcSession session, final List effectivityList, final int rangeRef) { + int selected = -1; + // This revision seems to be a legitimate candidate, let's look at its effectivities + for (ReleaseStatus releaseStatus : effectivityList) { + if (releaseStatus == null) { + continue; + } + // TcEffectivity encountered + session.loadProperties(releaseStatus, "effectivities"); + ModelObject[] effectivities = releaseStatus.get_effectivities(); + session.loadProperties(effectivities); + for (ModelObject effectivityObject : effectivities) { + Effectivity effectivity = (Effectivity) effectivityObject; + String rangeItemRev = effectivity.get_range_text(); + String[] splitList = rangeItemRev.split("-"); + int candidate = Integer.parseInt(splitList[0]); + if (candidate <= rangeRef && (selected < 0 || selected < candidate)) { + selected = candidate; + } + } + } + return selected; + } + + /** + * Returns a list of object referencer answering to the specification
    + * Has statuts Def Approved And is the the highest sequence between object have the same item_id and revision_id .
    + * You must give a list objects referencing a document, a list object revision authorized and a list status authorized + */ + + public static List filteringObjectsReferencer(final TcSession session, final List objectsReferencer, final List authorizedTypes) { + List results = new ArrayList<>(); + // getAuthorized types + for (ItemRevision object : objectsReferencer) { + if (authorizedTypes.contains(object.getTypeObject().getName())) { + results.add(object); + } else { + log.info("Rejected unauthorized type={} item_id={}", object.getTypeObject().getName(), object.get_item_id()); + } + } + // --findAll parts has status Def Approved + results = checkStatus(session, results); + + // --Group datas by their item_id,and revision_id and return highest sequence + results = groupItemRevisionPerFamily(results); + + // --findAll active sequence and filtering them by their last released date to findAll highest revision + // { part_xx/A.2(-> released_date:15-Jul-2015 11:11), part_xx/B.3 (-> released_date:14-Sept-2015 08:00) } = part_xx/B.3 + + // findAll the active sequence + results = getActiveSequence(results); + // on se retrouve avec ca list {part_1/A.2,part_1/B.2} dans ce cas on garde la B + // Chercher les parts en doublons part_1 et prendre la date_released de l'objet le plus recent + + + return results; + } + + /** + * findAll current item rev if has status Def Approved + * IN : list = {partxA1 DefApproved,partxA2,partyB1} + * OUT : list = {partxA1 DefApproved} + */ + private static List checkStatus(final TcSession session, final List objectsReferencer) { + List listPartsHasStatusDefApproved = new ArrayList<>(); + + for (ItemRevision itemRevision : objectsReferencer) { + session.loadProperties(itemRevision, "release_status_list"); + ReleaseStatus[] releaseStatuses = itemRevision.get_release_status_list(); + session.loadProperties(releaseStatuses); + for (ReleaseStatus releaseStatus : releaseStatuses) { + if (SnecmaObjectProperties.DEF_APPROVED.equals(releaseStatus.get_name())) { + listPartsHasStatusDefApproved.add(itemRevision); + } + } + } + return listPartsHasStatusDefApproved; + } + + /** + * Group datas by their item_id,and revision_id and return highest sequence + * IN : list = {partx/A.1,partx/A.2,party/B.1,partx/B.1} + * OUT : List = {partx/A.2, partx/B.1,party/B.1 } + */ + private static List groupItemRevisionPerFamily(final List objectsReferencerDefApproved) { + List returnList = new ArrayList<>(); + + List temp = new ArrayList<>(); + temp.addAll(objectsReferencerDefApproved); + + for (ItemRevision itemRevision : objectsReferencerDefApproved) { + // create a sub collection + List subCollection = new ArrayList<>(); + int pos = 0; + // Compare current itemRevision_id with an element of the temp collection + // And if ok put the current temp itemRevision in a sub collection + while (pos < temp.size()) { + if (itemRevision.get_item_id().equals(temp.get(pos).get_item_id()) + && itemRevision.get_item_revision_id().equals(temp.get(pos).get_item_revision_id())) { + subCollection.add(temp.get(pos)); + temp.remove(pos); + // re start iteration + pos = 0; + continue; + } + pos++; + } + // can be empty + if (!subCollection.isEmpty()) { + // ordering objects by item_id,rev_id,sequence_id (partx/A.1,partx/A.2,...) + Collections.sort(subCollection, new ItemRevisionComparator()); + ItemRevision latestSequence = subCollection.get(subCollection.size() - 1); + log.info("On group per family -> latest sequence is {}/{}.{}", latestSequence.get_item_id(), latestSequence.get_item_revision_id(), latestSequence.get_sequence_id()); + returnList.add(latestSequence); + } + } + return returnList; + } + + /* Return the latest active sequence check if the highest sequence*/ + private static List getActiveSequence(final List result) { + List results = new ArrayList<>(); + for (ItemRevision curItemRevision : result) { + if (curItemRevision.get_active_seq() != 0) { + results.add(curItemRevision); + } else { + log.info("Rejected {} because is not the last sequence", curItemRevision.getUid()); + } + } + return getHighestSequenceByReleasedDate(results); + } + + /*Compare two Item revision have the same item_id and different revision_id, take the last date released */ + private static List getHighestSequenceByReleasedDate(final List currentList) { + Map map = new HashMap<>(); + for (ItemRevision curItemRevision : currentList) { + if (map.containsKey(defineKey(curItemRevision))) { + ItemRevision existingItemRevision = map.get(defineKey(curItemRevision)); + // findAll good object by date released + ItemRevision candidate = getTheHighestItemRevisionByDate(curItemRevision, existingItemRevision); + map.put(defineKey(candidate), candidate); + } else { + map.put(defineKey(curItemRevision), curItemRevision); + } + } + + return new ArrayList<>(map.values()); + } + + /* Check if current itemRevision have date released superior than existing item revision */ + private static ItemRevision getTheHighestItemRevisionByDate(final ItemRevision curItemRevision, final ItemRevision existingItemRevision) { + Calendar dateReleasedOfCurItemRevision = curItemRevision.get_date_released(); + Calendar dateReleasedOfexistingItemRevision = existingItemRevision.get_date_released(); + if (dateReleasedOfCurItemRevision.after(dateReleasedOfexistingItemRevision)) { + return curItemRevision; + } else { + return existingItemRevision; + } + } + + /* Helper build key for map*/ + private static String defineKey(final ItemRevision itemRevision) { + return itemRevision.get_item_id(); + } + + /** + * Returns true if the {@link ReleaseStatus}'s Effectivities contain one {@link Effectivity} named "effectivity", whose range matches the provided Unit number. + * + * @param releaseStatus the {@link ReleaseStatus} holding all the effectivities + * @param targetUnit the unit to match + * @return true if an {@link Effectivity} is found with a unit value matching the targetUnit, false otherwise + */ + private static boolean getExactUnitInEffectivities(final TcSession session, final ReleaseStatus releaseStatus, final int targetUnit) { + session.loadProperties(releaseStatus, "effectivities"); + ModelObject[] effectivities = releaseStatus.get_effectivities(); + session.loadProperties(effectivities); + for (ModelObject objectEffectivity : effectivities) { + String statusName = releaseStatus.get_name(); + if (EFFECTIVITY.equals(statusName)) { + Effectivity effectivity = (Effectivity) objectEffectivity; + String effectivityRange = effectivity.get_range_text(); + log.debug("Check is current TcEffectivity range : {} is equal to {}", effectivityRange, targetUnit); + if (equalsRangeStart(targetUnit, effectivityRange)) { + return true; + } + } + } + return false; + } + + protected boolean getClosestProductUnit(final TcSession session, final String productID, final int targetUnit, final List unitsRevision) throws NotFoundException { + if (unitsRevision.isEmpty()) { + throw new NotFoundException("No unitRevision exists for Product " + productID + WITH_UNIT + targetUnit); + } + for (ItemRevision unitRevision : unitsRevision) { + session.loadProperties(unitRevision, "release_status_list"); + ReleaseStatus[] releaseStatuses = unitRevision.get_release_status_list(); + session.loadProperties(releaseStatuses); + for (ReleaseStatus status : releaseStatuses) { + if (getExactUnitInEffectivities(session, status, targetUnit)) { + return true; + } + } + } + return false; + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/teamcenter/ObjectInfoLoader.java b/teamcenter/src/main/java/com/capgemini/reports/teamcenter/ObjectInfoLoader.java new file mode 100644 index 0000000..28c4685 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/teamcenter/ObjectInfoLoader.java @@ -0,0 +1,396 @@ +package com.capgemini.reports.teamcenter; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.queries.saved.AbstractReplicatedQuery; +import com.capgemini.framework.teamcenter.queries.saved.modelobject.ItemRevisionQuery; +import com.capgemini.reports.exceptions.InvalidUserInputException; +import com.capgemini.reports.exceptions.NotFoundException; +import com.capgemini.reports.exceptions.UserInputErrorEnum; +import com.capgemini.reports.reports.parameters.EffectivityDate; +import com.capgemini.reports.reports.parameters.Generics; +import com.capgemini.reports.reports.parameters.ProductUnit; +import com.capgemini.reports.teamcenter.queries.DirectQuery; +import com.capgemini.reports.teamcenter.queries.saved.GenericAssembQuery; +import com.capgemini.reports.teamcenter.queries.saved.GenericQuery; +import com.capgemini.reports.teamcenter.queries.saved.ProductTypeQuery; +import com.capgemini.reports.teamcenter.queries.saved.UnitQuery; +import com.teamcenter.soa.client.model.ModelObject; +import com.teamcenter.soa.client.model.strong.*; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.List; + +import static com.capgemini.framework.teamcenter.TeamcenterObjectTypes.ITEM_REVISION; +import static com.capgemini.framework.teamcenter.object.SnecmaObjectProperties.PV_CLAUSE_PROPRIETE; +import static com.capgemini.framework.teamcenter.object.SnecmaObjectProperties.PV_TYPE_PRODUIT; +import static com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes.EFFECTIVITY; + +/** + * This class is able to send requests to the Teamcenter servers to obtain information that hasn't been loaded yet.
    + * Typical functionality is to fetch an object using its UID, load related documents or workflows, etc. + */ +@Slf4j +public class ObjectInfoLoader { + + private static final String TYPE = "Type : "; + private static final String SEARCH_UNIT_OF_PRODUCT_ID = "search unit of product ID: "; + private static final String SAVED_QUERY = "saved query : "; + private static final String UNIT_REVISION_DOES_NOT_CONTAIN_EFFECTIVITIES = "Unit Revision does not contain Effectivities..."; + + protected final TcSession session; + + /** + * Constructs a {@link ObjectInfoLoader} with the {@link TcSession} to be used for the queries. + * + * @param session the {@link TcSession} to be used for the queries. + */ + public ObjectInfoLoader(final TcSession session) { + this.session = session; + } + + /** + * Requests the 'clause de propriete' on a product type. + * + * @param typeProduit the 'type produit' property + * @param session the Tc session to make the query + * @return the clause de propriete + * @throws NotFoundException if unable to find the form + */ + public static String getClausePropriete(final String typeProduit, final TcSession session) throws NotFoundException { + ProductTypeQuery theQuery = new ProductTypeQuery(session); + theQuery.addNomTypeProduit(typeProduit.trim()); + List result = theQuery.findAll(); + for (Form form : result) { + session.loadProperties(form, PV_CLAUSE_PROPRIETE); + return form.getPropertyObject(PV_CLAUSE_PROPRIETE).getStringValue(); + } + throw new NotFoundException("Could not find a Form with the clause de propriete"); + } + + /** + * Returns the Product Type of a given ItemRevision.
    + * + * @param itemRevision the item rev + * @return the product type as a String + */ + public static String getProductType(final TcSession session, final ItemRevision itemRevision) { + // By rule, an itemRevision only owns a single Master Form Revision + Form masterForm = itemRevision.get_item_master_tag(); + session.loadProperties(masterForm); + return masterForm.getPropertyObject(PV_TYPE_PRODUIT).getStringValue(); + } + + private List getUnits(final ReleaseStatus releaseStatus) throws NotFoundException { + session.loadProperties(releaseStatus, "effectivities"); + ModelObject[] effectivities = releaseStatus.get_effectivities(); + session.loadProperties(effectivities); + if (effectivities == null) { + log.error(UNIT_REVISION_DOES_NOT_CONTAIN_EFFECTIVITIES); + throw new NotFoundException(UNIT_REVISION_DOES_NOT_CONTAIN_EFFECTIVITIES); + } + + List listOfUnits = new ArrayList<>(); + for (ModelObject objectEffectivity : effectivities) { + if (EFFECTIVITY.equals(releaseStatus.get_name())) { + Effectivity effectivity = (Effectivity) objectEffectivity; + String unitRange = effectivity.get_unit_range_text(); + log.debug("Unit range : " + unitRange); + listOfUnits.add(unitRange); + } + } + return listOfUnits; + } + + /** + * Renvoie une liste de Generique revision pour le produit dont l'ID est passe en parametre. + * + * @param productUnit le {@link ProductUnit} + * @return List de Generic Ids + * @throws NotFoundException if the Generic, the Product or the Unit could not be found + */ + public List getGenericsRevisionOfProduct(final ProductUnit productUnit) throws NotFoundException { + return getGenericsRevisionOfProduct(productUnit.getProductID(), productUnit.getUnit()); + } + + /** + * Renvoie une liste de Générique Montage revision pour le produit-unit est passé en paramètre. + * + * @param aProductUnit {@link ProductUnit} produit + * @return List de GenericsAssemblies + * @throws NotFoundException if the Generic Assemb, the Product or the Unit could not be found + */ + public List getGenericsAssembliesRevisionOfProduct(final ProductUnit aProductUnit) throws NotFoundException { + return getGenericsAssembliesRevisionOfProduct(aProductUnit.getProductID(), aProductUnit.getUnit()); + } + + /** + * Renvoie une liste de Generique revision pour le produit dont l'ID est passe en parametre. + * + * @param anObjectID Object ID du produit + * @param unit unit du produit + * @return List de Generic IDs + * @throws NotFoundException if the product could not be found + */ + public List getGenericsRevisionOfProduct(final String anObjectID, final int unit) throws NotFoundException { + return getObjectRevisionOfProduct(new GenericQuery(session), anObjectID, unit); + } + + /** + * Renvoie une liste de Générique Montage revision pour le produit dont l'ID et le unitest passé en paramètre. + * + * @param aProductID Id du produit + * @param unit unit du produit + * @return List de GenericsAssemblies + * @throws NotFoundException if the Product could not be found + */ + public List getGenericsAssembliesRevisionOfProduct(final String aProductID, final int unit) + throws NotFoundException { + return getObjectRevisionOfProduct(new GenericAssembQuery(session), aProductID, unit); + } + + /** + * Common sub method for retrieving a list of generic or generic assemb. + * + * @return a {@link List} of revisions + * @throws NotFoundException if the end item could not be found + */ + private List getObjectRevisionOfProduct(final AbstractReplicatedQuery aQuery, final String anEndItemId, final int unit) + throws NotFoundException { + // Setup the query + aQuery.addEndItemID(anEndItemId); + aQuery.addEffectivityUnitIntro(Integer.toString(unit)); + + // Obtain the list of Generics or Generics Assemb + List result = aQuery.findAll(); + if (result.isEmpty()) { + String msg = aQuery.getClass().getName() + " Could not find the request Item Revision..."; + log.error(msg); + throw new NotFoundException(msg); + } + + // Populate return list with the IDs + List listGenOrGenAssemb = new ArrayList<>(); + for (ItemRevision generic : result) { + String itemId = generic.get_item_id(); + log.debug("{} Returned an object with ID : {}", aQuery.getClass().getName(), itemId); + listGenOrGenAssemb.add(itemId); + } + + return listGenOrGenAssemb; + } + + /** + * Renvoie une liste de Unit pour le produit dont l'ID est passé en paramêtre. + * + * @param productID "end_item_id" L'identifiant unique Teamcenter + * @return Liste of Unit as {@link String} + * @throws NotFoundException if no effectivities are found on the ReleaseStatus + */ + public List getUnitsOfProduct(final String productID) throws NotFoundException { + // Setup the query + UnitQuery unitQuery = new UnitQuery(session); + unitQuery.addEndItemID(productID); + + // Perform the query: Obtain the list of all the UNIT Revision of that product + List result = unitQuery.findAll(); + if (result.isEmpty()) { + log.debug("No unit has been found using {} on product {}", unitQuery.getClass().getName(), productID); + return new ArrayList<>(); + } + + // Parse the result to obtain the Units + List listOfUnits = new ArrayList<>(); + for (ItemRevision unitRevision : result) { + session.loadProperties(unitRevision, "release_status_list"); + ReleaseStatus[] releaseStatuses = unitRevision.get_release_status_list(); + session.loadProperties(releaseStatuses); + for (ReleaseStatus status : releaseStatuses) { + listOfUnits.addAll(getUnits(status)); + } + } + return listOfUnits; + } + + /** + * Returns the ID of the object whose UID is provided. + * + * @param objectUID Lthe unique Teamcenter ID + * @return the ID + * @throws NotFoundException if the object does not point a Revision or Item + */ + public String getObjectID(final String objectUID) throws NotFoundException { + // Perform a query of the database + ModelObject modelObject = new DirectQuery<>(session).searchByUID(objectUID); + String itemID; + if (modelObject.getTypeObject().isInstanceOf(ITEM_REVISION)) { + ItemRevision queryItemRevision = (ItemRevision) modelObject; + itemID = queryItemRevision.get_item_id(); + } else if (modelObject.getTypeObject().isInstanceOf("Item")) { + Item queryItem = (Item) modelObject; + itemID = queryItem.get_item_id(); + } else { + String msg = "QueryObject is neither Item nor ItemRevision"; + log.error(msg); + throw new NotFoundException(msg); + } + return itemID; + } + + /** + * Get {@link ItemRevision} of current object by uid. + * + * @param objectUID the (String) unique identifier + * @return the {@link ItemRevision} + * @throws NotFoundException if the object could not be found + * @throws InvalidUserInputException if If the uid does not point to a Tc object at all + */ + public ItemRevision getItemRevisionByUID(final String objectUID) throws NotFoundException, InvalidUserInputException { + // Obtain the Object + ModelObject modelObject; + try { + modelObject = new DirectQuery<>(session).searchByUID(objectUID); + } catch (NotFoundException e) { + throw new NotFoundException("The provided UID could not be found", e); + } + + if (!modelObject.getTypeObject().isInstanceOf(ITEM_REVISION)) { + // The Object is not an ItemRevision! + String msg = "QueryObject is not an ItemRevision"; + log.error(msg); + throw new InvalidUserInputException(UserInputErrorEnum.OBJECT_DOES_NOT_EXIST); + } + return (ItemRevision) modelObject; + } + + /** + * Get generic revision by generic id, product id, effectivity date with saved query. + * + * @param produit the {@link ProductUnit} + * @param generic the {@link Generics} + * @param effectivityDate the {@link EffectivityDate} + * @return listGeneric the list of Generic revisions for the input product/unit + * @throws NotFoundException if the generic is not found + */ + public List getGenericsRevisionOfProductWithDate(final ProductUnit produit, final Generics generic, final EffectivityDate effectivityDate) + throws NotFoundException { + return getObjectRevisionOfProductWithDate(new GenericQuery(session), generic.getID(), produit.getProductID(), + effectivityDate.getFormattedDateForTcRequest()); + } + + /** + * Get generic assemb revision by generic id, product id, effectivity date with saved query. + * + * @param produit the {@link ProductUnit} + * @param generic the {@link Generics} + * @param effectivityDate the {@link EffectivityDate} + * @return listGeneric the list of Generic Assemb revisions for the input product/unit + * @throws NotFoundException if the generic assemb is not found + */ + public List getGenericsAssembRevisionOfProductWithDate(final ProductUnit produit, final Generics generic, + final EffectivityDate effectivityDate) throws NotFoundException { + return getObjectRevisionOfProductWithDate(new GenericAssembQuery(session), generic.getID(), produit.getProductID(), + effectivityDate.getFormattedDateForTcRequest()); + } + + /** + * Returns the Revisions of a Product. + */ + private List getObjectRevisionOfProductWithDate(final AbstractReplicatedQuery aQuery, final String itemID, + final String anEndItemId, final String dateToday) throws NotFoundException { + // Setup the query + aQuery.searchID(itemID); + aQuery.addEndItemID(anEndItemId); + aQuery.addBeforeDate(dateToday); + + // Obtain the list of Generics or Generics Assemb + List result = aQuery.findAll(); + if (result.isEmpty()) { + String msg = aQuery.getClass().getName() + " Could not find the requeste ItemRevision..."; + log.error(msg); + throw new NotFoundException(msg); + } + + // Populate return list with the IDs + List listGenOrGenAssemb = new ArrayList<>(); + for (ItemRevision generic : result) { + log.debug(TYPE + generic.getTypeObject().getName()); + String itemId = generic.get_item_id(); + log.debug("{} found an object with ID : {}", aQuery.getClass().getName(), itemId); + listGenOrGenAssemb.add(itemId); + } + + return listGenOrGenAssemb; + } + + /** + * Retourne une lise d'item revision de type Unit. + * + * @param product the {@link ProductUnit} + * @return list of Units as {@link ItemRevision} + * @throws NotFoundException if no object is found + */ + public List getUnitsOfProduct(final ProductUnit product) throws NotFoundException { + UnitQuery unitQuery = new UnitQuery(session); + log.trace(SAVED_QUERY + unitQuery.getClass().getName()); + log.trace(SEARCH_UNIT_OF_PRODUCT_ID + product.getProductID()); + return getObjectUnderProduct(product.getProductID(), unitQuery); + } + + /** + * Retourne une lise d'item revision de type Generic. + * + * @param generic the {@link Generics} + * @param product the {@link ProductUnit} + * @return liste d'item revision de type Generic + * @throws NotFoundException if no object is found + */ + public List getGenericUnderProduct(final Generics generic, final ProductUnit product) + throws NotFoundException { + GenericQuery genericQuery = new GenericQuery<>(session); + genericQuery.searchID(generic.getID()); + return getObjectUnderProduct(product.getProductID(), genericQuery); + } + + /** + * Retourne une liste d'item revision de type Generic Assemb. + * + * @param generic the {@link Generics} + * @param product the {@link ProductUnit} + * @return liste d'item revision de type Generic Assemb + * @throws NotFoundException if no object is found + */ + public List getGenericAssembUnderProduct(final Generics generic, final ProductUnit product) throws NotFoundException { + GenericAssembQuery genericAssembQuery = new GenericAssembQuery<>(session); + genericAssembQuery.searchID(generic.getID()); + return getObjectUnderProduct(product.getProductID(), genericAssembQuery); + } + + private List getObjectUnderProduct(final String endItem, final AbstractReplicatedQuery aQuery) + throws NotFoundException { + aQuery.addEndItemID(endItem); + log.trace("{} is searching under product {}", aQuery.getClass().getName(), endItem); + List result = aQuery.findAll(); + if (result.isEmpty()) { + String msg = aQuery.getClass().getName() + " did not return any matching Item Revision..."; + log.error(msg); + throw new NotFoundException(msg); + } + return result; + } + + /** + * Search active sequence of a current itemRevision by item_id/rev_id.
    + * And return the active item revision, the item revision may not be the same as that in parameter ex:
    + * INT : part_xx/A.1
    + * OUT : part_xx/A.3 + * + * @param itemRevision the ItemRev whose active sequence we seek + * @return activeItemRevision + */ + public ItemRevision searchActiveSequence(final ItemRevision itemRevision) { + List listItemRevActiveSeq = new ItemRevisionQuery(session) + .searchIDAndRevision(itemRevision.get_item_id(), itemRevision.get_item_revision_id()).findAll(); + return listItemRevActiveSeq.get(0); + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/teamcenter/Platform.java b/teamcenter/src/main/java/com/capgemini/reports/teamcenter/Platform.java new file mode 100644 index 0000000..2c9f2be --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/teamcenter/Platform.java @@ -0,0 +1,19 @@ +package com.capgemini.reports.teamcenter; + +import com.capgemini.framework.teamcenter.authent.FscParameters; +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * Represents a TC platform. + */ +@Getter +@AllArgsConstructor +public enum Platform { + PF36("http://10.24.192.36:80/tc/", new FscParameters("http://10.24.192.36:4544", new String[]{"http://10.24.192.36:4544"}, new String[]{"http://10.24.192.36:4544"}, "C:/Users/Public/kurt/FSCcache")), + AIX("http://10.69.165.176:6666/tcval", new FscParameters("http://10.69.165.201:4544", new String[]{"http://10.69.165.201:4544"}, new String[]{"http://10.69.165.201:4544"}, "C:/Users/Public/kurt/FSCcache")), + MIG("http://10.24.192.23:5555/tcmig/", new FscParameters("http://10.69.165.198:4544", new String[]{"http://10.69.165.198:4544"}, new String[]{"http://10.69.165.198:4544"}, "C:/Users/Public/kurt/FSCcache")); + + private final String connectionAddress; + private final FscParameters fmsParams; +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/DirectQuery.java b/teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/DirectQuery.java new file mode 100644 index 0000000..8ee2f98 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/DirectQuery.java @@ -0,0 +1,33 @@ +package com.capgemini.reports.teamcenter.queries; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.reports.exceptions.NotFoundException; +import com.teamcenter.soa.client.model.ModelObject; +import lombok.extern.slf4j.Slf4j; + +import java.util.List; + +/** + * Request a Teamcenter object directly using its Unique ID (UID). + */ +@Slf4j +public class DirectQuery { + + private final TcSession session; + + public DirectQuery(final TcSession session) { + this.session = session; + } + + /** + * Direct search using a unique ID (UID). + */ + public T searchByUID(final String objectUID) throws NotFoundException { + List modelObjects = session.loadObjects(objectUID); + if (modelObjects.isEmpty()) { + throw new NotFoundException("DirectQuery returned no result for UID=\"" + objectUID + "\""); + } else { + return modelObjects.get(0); + } + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/TypeQuery.java b/teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/TypeQuery.java new file mode 100644 index 0000000..0c6e252 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/TypeQuery.java @@ -0,0 +1,88 @@ +package com.capgemini.reports.teamcenter.queries; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.teamcenter.schemas.soa._2006_03.exceptions.ServiceException; +import com.teamcenter.services.strong.query._2007_06.Finder.FindWorkspaceObjectsResponse; +import com.teamcenter.services.strong.query._2007_06.Finder.WSOFindCriteria; +import com.teamcenter.services.strong.query._2007_06.Finder.WSOFindSet; +import com.teamcenter.soa.client.model.ModelObject; +import com.teamcenter.soa.client.model.strong.*; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.List; + +/** + * Searches for a specific item by its name, with its type specified by the Type Parameter. + * + * @param The type of object to look for. T must extends {@link ModelObject}.
    + * Example: {@link Item}, {@link ItemRevision}, {@link Form}, {@link RevisionRule}. + */ +@Slf4j +public class TypeQuery { + + private final TcSession session; + + private final Class typeParameterClass; + + /** + * Basic constructor. + * + * @param session required to perform the query. + * @param typeParameterClass the Teamcenter {@code class} of the requested object. + */ + private TypeQuery(final TcSession session, final Class typeParameterClass) { + this.session = session; + this.typeParameterClass = typeParameterClass; + } + + /** + * Searches for a specific {@link RevisionRule} by its name. + * + * @param session an active session + * @param objectName the name of the Revision Rule + * @return a {@link List} of results + */ + public static List getRevisionRule(final TcSession session, final String objectName) { + List list = new TypeQuery<>(session, RevisionRule.class).get(objectName); + List output = new ArrayList<>(); + for (ModelObject foundObject : list) { + output.add((RevisionRule) foundObject); + } + return output; + } + + /** + * Perform a {@link TypeQuery} using the specified object name.
    + * Usage: new TypeQuery(getSession(), ItemRevision.class).findAll(itemID); + * + * @param objectName the name of the object + * @return a List containing all matching elements. + */ + private List get(final String objectName) { + WSOFindCriteria criteria = new WSOFindCriteria(); + criteria.objectType = typeParameterClass.getSimpleName(); + criteria.objectName = objectName; + criteria.scope = "WSO_scope_All"; + + WSOFindSet findSet = new WSOFindSet(); + findSet.criterias = new WSOFindCriteria[]{criteria}; + FindWorkspaceObjectsResponse findWorkspaceObjects; + try { + findWorkspaceObjects = session.getFinderService().findWorkspaceObjects(new WSOFindSet[]{findSet}); + } catch (ServiceException e) { + log.warn("finderService failed to deliver WorkspaceObjects", e); + return new ArrayList<>(); + } + if (findWorkspaceObjects.outputList.length > 0) { + // Need to cast each sub-element of the list + List list = new ArrayList<>(); + for (WorkspaceObject workspaceObject : findWorkspaceObjects.outputList[0].foundObjects) { + list.add(typeParameterClass.cast(workspaceObject)); + } + return list; + } + // Nothing found + return new ArrayList<>(); + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/saved/AllSequencesOfItemQuery.java b/teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/saved/AllSequencesOfItemQuery.java new file mode 100644 index 0000000..b20cb47 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/saved/AllSequencesOfItemQuery.java @@ -0,0 +1,43 @@ +package com.capgemini.reports.teamcenter.queries.saved; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.queries.saved.AbstractReplicatedQuery; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +/** + * This class performs requests to obtain all sequences and revisions of an object, given its ID. + */ +public class AllSequencesOfItemQuery extends AbstractReplicatedQuery { + + /** + * Query name of Teamcenter for request in WKF objects. + */ + private static final String QUERY_SUFFIX = "All_Sequences"; + + /** + * Usual constructor with a {@link TcSession} using a proper policy. + * + * @param session an active session + */ + public AllSequencesOfItemQuery(final TcSession session) { + super(session, QUERY_SUFFIX); + } + + /** + * Obtains all sequences fo all revisions of an Item. + * + * @param itemId the item whose sequences we are looking for + * @return the query + */ + + @Override + public AllSequencesOfItemQuery searchID(final String itemId) { + return this.addParam(PARAM_ITEM_ID, itemId); + } + + @Override + protected AllSequencesOfItemQuery selfCast() { + return this; + } + +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/saved/ChangeFromPartQuery.java b/teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/saved/ChangeFromPartQuery.java new file mode 100644 index 0000000..9cad2c1 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/saved/ChangeFromPartQuery.java @@ -0,0 +1,42 @@ +package com.capgemini.reports.teamcenter.queries.saved; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.queries.saved.AbstractReplicatedQuery; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +/** + * This class is able to look for ChangeItem Revision objects in Teamcenter from a Part. + */ +public class ChangeFromPartQuery extends AbstractReplicatedQuery { + /** + * Query name of Teamcenter for request in Unit objects. + */ + private static final String QUERY_SUFFIX_CHANGE_FROM_PART = "Change_from_Part"; + private static final String PARAM_PART_ID = "part_id"; + private static final String PARAM_PART_REVISION = "part_revision"; + + /** + * Constructor to build a Query for ChangeItem objects from a Part. + * + * @param session the session for the connection + */ + public ChangeFromPartQuery(final TcSession session) { + super(session, QUERY_SUFFIX_CHANGE_FROM_PART); + } + + @Override + public ChangeFromPartQuery searchID(final String partId) { + return this.addParam(AbstractReplicatedQuery.REPCOL_PREFIX + PARAM_PART_ID, partId); + } + + + @Override + public ChangeFromPartQuery searchRevision(final String partRevision) { + return this.addParam(AbstractReplicatedQuery.REPCOL_PREFIX + PARAM_PART_REVISION, partRevision); + } + + @Override + protected ChangeFromPartQuery selfCast() { + return this; + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/saved/ChangeNoticeR07Query.java b/teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/saved/ChangeNoticeR07Query.java new file mode 100644 index 0000000..032d4e6 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/saved/ChangeNoticeR07Query.java @@ -0,0 +1,42 @@ +package com.capgemini.reports.teamcenter.queries.saved; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.queries.saved.AbstractReplicatedQuery; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +/** + * Class which allow to findAll change notice which is rely on a part. + */ +public class ChangeNoticeR07Query extends AbstractReplicatedQuery { + /** + * Query name of Teamcenter for request in Unit objects. + */ + private static final String QUERY_SUFFIX_CHANGE_FROM_PART = "ChangeNotice_R07"; + private static final String PARAM_PART_ID = "part_id"; + private static final String PARAM_PART_REVISION = "part_revision"; + + /** + * Constructor to build a Query for ChangeItem objects from a Part. + * + * @param session the session for the connection + */ + public ChangeNoticeR07Query(final TcSession session) { + super(session, QUERY_SUFFIX_CHANGE_FROM_PART); + } + + @Override + public ChangeNoticeR07Query searchID(final String partId) { + return this.addParam(AbstractReplicatedQuery.REPCOL_PREFIX + PARAM_PART_ID, partId); + } + + + @Override + public ChangeNoticeR07Query searchRevision(final String partRevision) { + return this.addParam(AbstractReplicatedQuery.REPCOL_PREFIX + PARAM_PART_REVISION, partRevision); + } + + @Override + protected ChangeNoticeR07Query selfCast() { + return this; + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/saved/ChangeRequestQuery.java b/teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/saved/ChangeRequestQuery.java new file mode 100644 index 0000000..1bda815 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/saved/ChangeRequestQuery.java @@ -0,0 +1,31 @@ +package com.capgemini.reports.teamcenter.queries.saved; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.queries.saved.AbstractReplicatedQuery; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +/** + * This class is able to look for ChangeRequest Revision objects in Teamcenter. + */ +public class ChangeRequestQuery extends AbstractReplicatedQuery { + + /** + * Query name of Teamcenter for request in change objects. + */ + private static final String QUERY_SUFFIX = "ChangeRequest"; + + /** + * Constructor to build a Query for ChangeRequests objects. + * + * @param session {@link TcSession} - the session for the connection + */ + public ChangeRequestQuery(final TcSession session) { + super(session, QUERY_SUFFIX); + } + + @Override + protected ChangeRequestQuery selfCast() { + return this; + } + +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/saved/ChangeRequestR07Query.java b/teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/saved/ChangeRequestR07Query.java new file mode 100644 index 0000000..80f29b9 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/saved/ChangeRequestR07Query.java @@ -0,0 +1,44 @@ +package com.capgemini.reports.teamcenter.queries.saved; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.queries.saved.AbstractReplicatedQuery; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +/** + * Queries all ChangeRevisions attached to an object. + */ +public class ChangeRequestR07Query extends AbstractReplicatedQuery { + + /** + * Query name of Teamcenter request. + */ + private static final String QUERY_SUFFIX_CHANGE_FROM_PART = "ChangeRequest_R07"; + private static final String PARAM_PART_ID = "part_id"; + private static final String PARAM_PART_REVISION = "part_revision"; + + /** + * Constructor to build a Query for ChangeItem objects from a Part. + * + * @param session the session for the connection + */ + public ChangeRequestR07Query(final TcSession session) { + super(session, QUERY_SUFFIX_CHANGE_FROM_PART); + } + + @Override + public ChangeRequestR07Query searchID(final String partId) { + return this.addParam(AbstractReplicatedQuery.REPCOL_PREFIX + PARAM_PART_ID, partId); + } + + + @Override + public ChangeRequestR07Query searchRevision(final String partRevision) { + return this.addParam(AbstractReplicatedQuery.REPCOL_PREFIX + PARAM_PART_REVISION, partRevision); + } + + @Override + protected ChangeRequestR07Query selfCast() { + return this; + } + +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/saved/ChangeRequestWithSeqQuery.java b/teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/saved/ChangeRequestWithSeqQuery.java new file mode 100644 index 0000000..d6d8851 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/saved/ChangeRequestWithSeqQuery.java @@ -0,0 +1,31 @@ +package com.capgemini.reports.teamcenter.queries.saved; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.queries.saved.AbstractReplicatedQuery; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +/** + * This class is able to look for ChangeRequest Revision objects in Teamcenter.
    + * This query contains all the sequences of the revisions. + */ +public class ChangeRequestWithSeqQuery extends AbstractReplicatedQuery { + + /** + * Query name of Teamcenter for request in change objects. + */ + private static final String QUERY_SUFFIX = "ChangeRequest_With_Seq"; + + /** + * Constructor to build a Query for ChangeRequests objects. + * + * @param session {@link TcSession} - the session for the connection + */ + public ChangeRequestWithSeqQuery(final TcSession session) { + super(session, QUERY_SUFFIX); + } + + @Override + protected ChangeRequestWithSeqQuery selfCast() { + return this; + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/saved/FppWithSeqQuery.java b/teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/saved/FppWithSeqQuery.java new file mode 100644 index 0000000..7a3e79f --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/saved/FppWithSeqQuery.java @@ -0,0 +1,31 @@ +package com.capgemini.reports.teamcenter.queries.saved; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.queries.saved.AbstractReplicatedQuery; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +/** + * This class is able to look for FPP Revision objects in Teamcenter.
    + * This query contains all the sequences of the revisions. + */ +public class FppWithSeqQuery extends AbstractReplicatedQuery { + + /** + * Query name of Teamcenter for request in FPP objects. + */ + private static final String QUERY_SUFFIX = "FPP_With_Seq"; + + /** + * Constructor to build a Query for FPP objects. + * + * @param session {@link TcSession}the session for the connection + */ + public FppWithSeqQuery(final TcSession session) { + super(session, QUERY_SUFFIX); + } + + @Override + protected FppWithSeqQuery selfCast() { + return this; + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/saved/GenericAssembQuery.java b/teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/saved/GenericAssembQuery.java new file mode 100644 index 0000000..6ca15bb --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/saved/GenericAssembQuery.java @@ -0,0 +1,37 @@ +package com.capgemini.reports.teamcenter.queries.saved; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.queries.saved.AbstractReplicatedQuery; +import com.teamcenter.soa.client.model.ModelObject; +import com.teamcenter.soa.client.model.strong.Item; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +/** + * This class is able to look for GenericAssemb objects in Teamcenter. + * + * @param the expected type of the Object: either {@link Item} or {@link ItemRevision} + */ +public class GenericAssembQuery extends AbstractReplicatedQuery> { + + /** + * Query name of Teamcenter for requesting a GenericAssemb. + */ + protected static final String QUERY_SUFFIX_GENERIC_ASSEMB = "Generic Assemb"; + + + /** + * Constructor to build a Query for GenericAssemb objects. + * + * @param session the session for the connection + */ + public GenericAssembQuery(final TcSession session) { + super(session, QUERY_SUFFIX_GENERIC_ASSEMB); + } + + + @Override + protected GenericAssembQuery selfCast() { + return this; + } + +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/saved/GenericQuery.java b/teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/saved/GenericQuery.java new file mode 100644 index 0000000..5e8e6eb --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/saved/GenericQuery.java @@ -0,0 +1,29 @@ +package com.capgemini.reports.teamcenter.queries.saved; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.queries.saved.AbstractReplicatedQuery; +import com.teamcenter.soa.client.model.ModelObject; + +/** + * This class is able to look for Generic objects in Teamcenter. + */ +public class GenericQuery extends AbstractReplicatedQuery> { + + /*** Query name of Teamcenter for requesting a Generic. */ + private static final String QUERY_SUFFIX_GENERIC = "Generic"; + + /** + * Constructor to build a Query for Generic objects. + * + * @param session the session for the connection + */ + public GenericQuery(final TcSession session) { + super(session, QUERY_SUFFIX_GENERIC); + } + + @Override + protected GenericQuery selfCast() { + return this; + } + +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/saved/ProductTypeQuery.java b/teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/saved/ProductTypeQuery.java new file mode 100644 index 0000000..c0834b5 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/saved/ProductTypeQuery.java @@ -0,0 +1,39 @@ +package com.capgemini.reports.teamcenter.queries.saved; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.queries.saved.AbstractReplicatedQuery; +import com.teamcenter.soa.client.model.strong.Form; + +/** + * This class is able to look for Product types in Teamcenter. These objects are of type {@link Form}. + */ +public class ProductTypeQuery extends AbstractReplicatedQuery { + + /** + * Query name of Teamcenter for requesting a Product type. + **/ + private static final String QUERY_SUFFIX_PRODUCT_TYPE = "Product Type"; + + /** + * Constructor to build a Query for Product Types. + * + * @param session the session for the connection + */ + public ProductTypeQuery(final TcSession session) { + super(session, QUERY_SUFFIX_PRODUCT_TYPE); + } + + /** + * Request a specific product type name. + * + * @param typeProduit the 'type produit' name + */ + public void addNomTypeProduit(final String typeProduit) { + this.addParam(PARAM_NOM_TYPE_PRODUIT, typeProduit); + } + + @Override + protected ProductTypeQuery selfCast() { + return this; + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/saved/UnitFromChangeRequestQuery.java b/teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/saved/UnitFromChangeRequestQuery.java new file mode 100644 index 0000000..33d76f0 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/saved/UnitFromChangeRequestQuery.java @@ -0,0 +1,38 @@ +package com.capgemini.reports.teamcenter.queries.saved; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.queries.saved.AbstractReplicatedQuery; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +/** + * This class is able to look for Unit Revision objects in Teamcenter from a ChangeRequest. + */ +public class UnitFromChangeRequestQuery extends AbstractReplicatedQuery { + + /** + * Query name of Teamcenter for request in Unit objects. + */ + private static final String QUERY_SUFFIX_UNIT_FROM_CR = "Unit_from_CR"; + private static final String PARAM_CHANGE_ID = "change_id"; + + /** + * Constructor to build a Query for Unit objects from a ChangeRequest. + * + * @param session the session for the connection + */ + public UnitFromChangeRequestQuery(final TcSession session) { + super(session, QUERY_SUFFIX_UNIT_FROM_CR); + } + + @Override + public UnitFromChangeRequestQuery searchID(final String alternateID) { + this.addParam(AbstractReplicatedQuery.REPCOL_PREFIX + PARAM_CHANGE_ID, alternateID); + return this; + } + + @Override + protected UnitFromChangeRequestQuery selfCast() { + return this; + } + +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/saved/UnitQuery.java b/teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/saved/UnitQuery.java new file mode 100644 index 0000000..2f1f134 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/saved/UnitQuery.java @@ -0,0 +1,52 @@ +package com.capgemini.reports.teamcenter.queries.saved; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.queries.saved.AbstractReplicatedQuery; +import com.teamcenter.soa.client.model.strong.ItemRevision; + +/** + * This class is able to look for Unit Revision objects in Teamcenter. + */ +public class UnitQuery extends AbstractReplicatedQuery { + + /** + * Use this String in the Constructor to obtain Units that are going (or have gone) through a Workflow with this name. + */ + static final String UNIT_VALIDATION_UNIT_PAR_SO = "UNIT-Validation UNIT par SO"; + /** + * Query name of Teamcenter for request in Unit objects. + */ + private static final String QUERY_SUFFIX_UNIT = "Unit"; + private static final String QUERY_SUFFIX_UNIT_WITH_WKF = "Unit_With_WKF"; + private static final String TASK_NAME = "task_name"; + + /** + * Constructor to build a Query for Unit objects. + * + * @param session the session for the connection + */ + public UnitQuery(final TcSession session) { + super(session, QUERY_SUFFIX_UNIT); + } + + /** + * Constructor to build a Query for Unit objects. + * + * @param session the session for the connection + * @param wkfName (optional) Provide the name of a Workflow active or done on this unit. Input may be null or empty to deactivate this criteria.
    + * If the input is not empty, then the Unit MUST have a workflow with the provided name.
    + * Exemple value: {@link UnitQuery#UNIT_VALIDATION_UNIT_PAR_SO} + */ + public UnitQuery(final TcSession session, final String wkfName) { + super(session, (wkfName == null || wkfName.isEmpty()) ? QUERY_SUFFIX_UNIT : QUERY_SUFFIX_UNIT_WITH_WKF); + if (wkfName != null && !wkfName.isEmpty()) { + this.addParam(TASK_NAME, wkfName); + } + } + + @Override + protected UnitQuery selfCast() { + return this; + } + +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/saved/WorkflowOnChangeQuery.java b/teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/saved/WorkflowOnChangeQuery.java new file mode 100644 index 0000000..f2906d1 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/saved/WorkflowOnChangeQuery.java @@ -0,0 +1,48 @@ +package com.capgemini.reports.teamcenter.queries.saved; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.queries.saved.AbstractReplicatedQuery; +import com.teamcenter.soa.client.model.strong.EPMTask; + +/** + * This class is able to look for WKF objects in Teamcenter from a Part. + */ +public class WorkflowOnChangeQuery extends AbstractReplicatedQuery { + + /** + * Query name of Teamcenter for request in WKF objects. + */ + private static final String QUERY_SUFFIX = "WKF_on_Change"; + private static final String PARAM_SUFFIX_WKF_NAME = REPCOL_PREFIX + "wkf_name"; + private static final String PARAM_SUFFIX_SEQUENCE_ID = REPCOL_PREFIX + "sequence_id"; + + /** + * Construct a Query to obtain the Workflow(s) acting on a specific ItemRevision. + * + * @param session the Tc session + */ + public WorkflowOnChangeQuery(final TcSession session) { + super(session, QUERY_SUFFIX); + } + + @Override + public WorkflowOnChangeQuery searchName(final String wkfName) { + return this.addParam(PARAM_SUFFIX_WKF_NAME, wkfName); + } + + /** + * Add a search on the sequence_id param. + * + * @param sequenceId the sequence ID + * @return the query + */ + public WorkflowOnChangeQuery searchSequenceId(final String sequenceId) { + return this.addParam(PARAM_SUFFIX_SEQUENCE_ID, sequenceId); + } + + @Override + protected WorkflowOnChangeQuery selfCast() { + return this; + } + +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/saved/WorkflowOnUnitQuery.java b/teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/saved/WorkflowOnUnitQuery.java new file mode 100644 index 0000000..0ae2317 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/teamcenter/queries/saved/WorkflowOnUnitQuery.java @@ -0,0 +1,44 @@ +package com.capgemini.reports.teamcenter.queries.saved; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.queries.saved.AbstractReplicatedQuery; +import com.teamcenter.soa.client.model.strong.EPMTask; + +/** + * Search for a Workflow. + */ +public final class WorkflowOnUnitQuery extends AbstractReplicatedQuery { + + static final String UNIT_VALIDATION_UNIT_PAR_SO = "UNIT-Validation UNIT par SO"; + + /** + * Query name of Teamcenter for requesting a Workflow, by giving the ID of the Unit it was launched upon. + */ + private static final String QUERY_SUFFIX_WKF = "WKF_ValidationUnit_on_Unit"; + private static final String PARAM_SUFFIX_WKF_NAME = REPCOL_PREFIX + "wkf_name"; + private static final String PARAM_SUFFIX_UNIT_ID = REPCOL_PREFIX + "unit_id"; + + private WorkflowOnUnitQuery(final TcSession session, final String wkfSearchName) { + super(session, wkfSearchName); + } + + /** + * Construct a Query that will look for any Workflow named 'UNIT-Validation UNIT par SO' that was launched on the specified Unit. + * + * @param session the session + * @param unitID the ID of the Unit that the Workflow was working on + * @return the Query + */ + public static WorkflowOnUnitQuery searchValidationUnitParSO(final TcSession session, final String unitID) { + WorkflowOnUnitQuery workflowQuery = new WorkflowOnUnitQuery(session, QUERY_SUFFIX_WKF); + workflowQuery.addParam(PARAM_SUFFIX_WKF_NAME, UNIT_VALIDATION_UNIT_PAR_SO); + workflowQuery.addParam(PARAM_SUFFIX_UNIT_ID, unitID); + return workflowQuery; + } + + @Override + protected WorkflowOnUnitQuery selfCast() { + return this; + } + +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/teamcenter/resolution/IBOMLineExplorer.java b/teamcenter/src/main/java/com/capgemini/reports/teamcenter/resolution/IBOMLineExplorer.java new file mode 100644 index 0000000..1f32bf6 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/teamcenter/resolution/IBOMLineExplorer.java @@ -0,0 +1,25 @@ +package com.capgemini.reports.teamcenter.resolution; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.EmptyNomenclatureException; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.bomlineholder.BOMLineHolder.BOMLineHolderState; +import com.capgemini.reports.exceptions.InvalidInputException; +import com.capgemini.reports.exceptions.MalformedNomenclatureException; +import com.capgemini.reports.teamcenter.resolution.structureservice.SingleStructureServiceCaller; +import com.capgemini.reports.teamcenter.resolution.structureservice.SingleStructureServiceCaller.SingleLevelExpander; +import com.teamcenter.soa.client.model.strong.BOMLine; + +/** + * Use this interface to specify how explode a nomenclature, step by step, in a {@link SingleStructureServiceCaller}.
    + * Exemple: Explode a Generic, look for its RFGeneric, explod ONLY this RFGeneric, look for a PArt, return that Part.
    + */ +public interface IBOMLineExplorer { + + /** + * Explore a Top {@link BOMLineHolder}.
    + * The BOMLineHolder should already possess the Teamcenter objects ({@link BOMLine}s) so this BOM must be not built (status Frozen via {@link BOMLineHolderState}). + */ + BOMLineHolder explore(final TcSession session, final SingleLevelExpander expander, final BOMLineHolder bomLineHolder) throws EmptyNomenclatureException, InvalidInputException, + MalformedNomenclatureException; +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/teamcenter/resolution/structureservice/IStructureServiceCaller.java b/teamcenter/src/main/java/com/capgemini/reports/teamcenter/resolution/structureservice/IStructureServiceCaller.java new file mode 100644 index 0000000..32736fd --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/teamcenter/resolution/structureservice/IStructureServiceCaller.java @@ -0,0 +1,27 @@ +package com.capgemini.reports.teamcenter.resolution.structureservice; + +import com.capgemini.framework.teamcenter.exceptions.EmptyNomenclatureException; +import com.capgemini.framework.teamcenter.exceptions.NoSuchBomViewException; +import com.capgemini.framework.teamcenter.resolution.filtering.ITcTypeFilter; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.exceptions.InvalidInputException; +import com.capgemini.reports.exceptions.MalformedNomenclatureException; +import com.capgemini.reports.filter.IFilterExplosionNomenclature; +import com.teamcenter.soa.client.model.strong.BOMLine; + +/** + * Interface for all Services than can perfom an explosion of Nomenclature on a given congiguration. + */ +public interface IStructureServiceCaller { + + /** + * Resolve a nomenclature for a given configuration, while only exposing objects that belong to the provided wanted types. + * + * @param topBomLine the configuration + * @param filter is a {@link ITcTypeFilter}. + * @return a {@link BOMLineHolder} representing the top Line of the nomenclature. + */ + BOMLineHolder resolve(final BOMLine topBomLine, final IFilterExplosionNomenclature filter) + throws EmptyNomenclatureException, NoSuchBomViewException, InvalidInputException, MalformedNomenclatureException; + +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/teamcenter/resolution/structureservice/MultiStructureServiceCaller.java b/teamcenter/src/main/java/com/capgemini/reports/teamcenter/resolution/structureservice/MultiStructureServiceCaller.java new file mode 100644 index 0000000..200e03b --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/teamcenter/resolution/structureservice/MultiStructureServiceCaller.java @@ -0,0 +1,29 @@ +package com.capgemini.reports.teamcenter.resolution.structureservice; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.EmptyNomenclatureException; +import com.capgemini.framework.teamcenter.exceptions.NoSuchBomViewException; +import com.capgemini.framework.teamcenter.resolution.structureservice.MultiStructureServiceCallerRaw; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.filter.IFilterExplosionNomenclature; +import com.teamcenter.soa.client.model.strong.BOMLine; + +/** + * Wrapper dedicated to multi levels resolution of configurations. + **/ +public class MultiStructureServiceCaller implements IStructureServiceCaller { + + private final TcSession session; + + /** + * Constructor for multi levels resolution. + */ + public MultiStructureServiceCaller(final TcSession session) { + this.session = session; + } + + @Override + public BOMLineHolder resolve(final BOMLine topBomLine, final IFilterExplosionNomenclature filter) throws EmptyNomenclatureException, NoSuchBomViewException { + return new MultiStructureServiceCallerRaw(session).resolve(topBomLine, filter); + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/teamcenter/resolution/structureservice/SingleStructureServiceCaller.java b/teamcenter/src/main/java/com/capgemini/reports/teamcenter/resolution/structureservice/SingleStructureServiceCaller.java new file mode 100644 index 0000000..079373c --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/teamcenter/resolution/structureservice/SingleStructureServiceCaller.java @@ -0,0 +1,89 @@ +package com.capgemini.reports.teamcenter.resolution.structureservice; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.EmptyNomenclatureException; +import com.capgemini.framework.teamcenter.exceptions.NoSuchBomViewException; +import com.capgemini.framework.teamcenter.resolution.filtering.ITcTypeFilter; +import com.capgemini.framework.teamcenter.resolution.structureservice.SingleStructureServiceCallerRaw; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.exceptions.InvalidInputException; +import com.capgemini.reports.exceptions.MalformedNomenclatureException; +import com.capgemini.reports.filter.IFilterExplosionNomenclature; +import com.capgemini.reports.teamcenter.resolution.IBOMLineExplorer; +import com.teamcenter.soa.client.model.strong.BOMLine; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.List; + +/** + * Helper dedicated to single level resolution of configurations. + **/ +@Slf4j +public class SingleStructureServiceCaller implements IStructureServiceCaller { + + private final TcSession session; + + /** + * Constructor for single level resolution. + * + * @param session {@link TcSession} - Teamcenter session + */ + public SingleStructureServiceCaller(final TcSession session) { + this.session = session; + } + + @Override + public BOMLineHolder resolve(final BOMLine topBomLine, final IFilterExplosionNomenclature filter) throws EmptyNomenclatureException, NoSuchBomViewException { + return new SingleStructureServiceCallerRaw(session).resolve(topBomLine, filter); + } + + /** + * This method allows the caller to finely explode a nomenclature under a certain configuration.
    + * It allows fine control of which BoLines are opened, through the use of an {@link IBOMLineExplorer} which can open a BomLine one at a time.
    + * All the work will be performed using a single BomWindow. + */ + public BOMLineHolder resolve(final BOMLine topBomLine, final IBOMLineExplorer bomLineExplorer) throws EmptyNomenclatureException, NoSuchBomViewException, InvalidInputException, MalformedNomenclatureException { + SingleStructureServiceCallerRaw impl = new SingleStructureServiceCallerRaw(session); + // Do the exploration while the window is open + return bomLineExplorer.explore(session, new SingleLevelExpander(impl), new BOMLineHolder(topBomLine)); + } + + /** + * This class exists in the context of a bomWindow, and can expand a bom one level below, with a type filter.
    + * It is only able to expand a Bom while said window is open. + */ + @AllArgsConstructor(access = AccessLevel.PRIVATE) + public final class SingleLevelExpander { + + private final SingleStructureServiceCallerRaw impl; + + /** + * Expands a bom one level below the provided {@link BOMLineHolder}. + * + * @param target the parent {@link BOMLineHolder} whose children will be loaded + * @param filter a {@link ITcTypeFilter} to keep only the wanted objects types. + * @throws EmptyNomenclatureException if the nomenclature is empty + */ + public BOMLineHolder expand(final BOMLineHolder target, final ITcTypeFilter filter) throws EmptyNomenclatureException { + return impl.resolve(target.getBomLineObject(), filter); + } + + /** + * Expands a bom one level below the provided {@link BOMLineHolder}. + * + * @param targetBomLineHolders the parent {@link BOMLineHolder} whose children will be loaded + * @param filter a {@link ITcTypeFilter} to keep only the wanted objects types. + * @throws EmptyNomenclatureException if the nomenclature is empty + */ + public List expandEach(final List targetBomLineHolders, final ITcTypeFilter filter) throws EmptyNomenclatureException { + List bomLines = new ArrayList<>(targetBomLineHolders.size()); + for (BOMLineHolder holder : targetBomLineHolders) { + bomLines.add(impl.resolve(holder.getBomLineObject(), filter)); + } + return bomLines; + } + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/teamcenter/resolution/structureservice/TripleStructureServiceCaller.java b/teamcenter/src/main/java/com/capgemini/reports/teamcenter/resolution/structureservice/TripleStructureServiceCaller.java new file mode 100644 index 0000000..24ee17e --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/teamcenter/resolution/structureservice/TripleStructureServiceCaller.java @@ -0,0 +1,187 @@ +package com.capgemini.reports.teamcenter.resolution.structureservice; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.EmptyNomenclatureException; +import com.capgemini.framework.teamcenter.exceptions.NoSuchBomViewException; +import com.capgemini.framework.teamcenter.resolution.filtering.*; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.bomlineholder.BOMLineHolderHelper; +import com.capgemini.reports.exceptions.InvalidInputException; +import com.capgemini.reports.exceptions.MalformedNomenclatureException; +import com.capgemini.reports.filter.IFilterExplosionNomenclature; +import com.capgemini.reports.teamcenter.resolution.IBOMLineExplorer; +import com.capgemini.reports.teamcenter.resolution.structureservice.SingleStructureServiceCaller.SingleLevelExpander; +import com.teamcenter.soa.client.model.strong.BOMLine; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.List; + +import static com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes.*; + +/** + * Helper dedicated to triple levels resolution of configurations. + **/ +@Slf4j +public class TripleStructureServiceCaller implements IStructureServiceCaller { + + private final TcSession session; + + /** + * Constructor for Triple levels resolution. + */ + public TripleStructureServiceCaller(final TcSession session) { + this.session = session; + } + + @Override + public BOMLineHolder resolve(final BOMLine topBomLine, final IFilterExplosionNomenclature filter) throws EmptyNomenclatureException, NoSuchBomViewException, InvalidInputException, MalformedNomenclatureException { + return new SingleStructureServiceCaller(session).resolve(topBomLine, new TripleLevelExplorer(filter)); + } + + private static class TripleLevelExplorer implements IBOMLineExplorer { + private static final ITcTypeFilter RF_GENERIC_FILTER = new TcTypeInclusionFilter(RF_ADMIN_REVISION, RF_ADMIN_AG_REVISION, PART_AERO_REVISION); + private static final ITcTypeFilter COMPONENT_REJECTOR = new TcTypeExclusionFilter(RF_PART_REVISION, RF_PART_ASSEMB_REVISION, GENERIC_REVISION, GENERIC_ASSEMB_REVISION); + + private final ITcTypeFilter componentFilter; + + TripleLevelExplorer(final ITcTypeFilter componentFilter) { + this.componentFilter = componentFilter; + } + + @Override + public BOMLineHolder explore(final TcSession session, final SingleLevelExpander expander, final BOMLineHolder topLine) throws EmptyNomenclatureException, MalformedNomenclatureException { + log.debug("Expand level 1..."); + BOMLineHolder expandedTopLine = expander.expand(topLine, AllFilter.getInstance()); + log.debug("Expand level 1 DONE, size = {}", expandedTopLine.getBomChilds().size()); + + log.debug("Filter the results..."); + // filter out generics & rf generics from the rest (they must receive a special treatment) + List genericsComponents = new ArrayList<>(); + List rfParts = new ArrayList<>(); + BOMLineHolder rfGenericReceptor = filterChildren(expandedTopLine.getBomChilds(), genericsComponents, rfParts); + log.debug("Filtering DONE: {} generics, {} RF Generics and {} RF Part found", genericsComponents.size(), rfGenericReceptor == null ? 0 : 1, rfParts.size()); + + ITcTypeFilter rfGenFilter = new OrFilter(RF_GENERIC_FILTER, componentFilter); + if (rfGenericReceptor != null) { // happens If topline is a Generic / Generic Assemb + for (BOMLineHolder bomChild : expander.expand(rfGenericReceptor, rfGenFilter).getBomChilds()) { + rfGenericReceptor.addChild(bomChild); + } + } + + // Simply expand the lvl 1 RF Parts + log.debug("Expand All RF Parts.."); + List alternates = expandRfPartsExtractAlternates(expander, rfParts); + log.debug("Expand RF Part DONE"); + + // For each Alternate found expand one level further. + log.debug("Expand Alternates..."); + //List expandedAlternates = expander.expandEach(alternates, AllFilter.getInstance()); + for (BOMLineHolder alternate : alternates) { + for (BOMLineHolder bomChild : expander.expand(alternate, AllFilter.getInstance()).getBomChilds()) { + alternate.addChild(bomChild); + } + } + log.debug("Expand Alternates DONE"); + + // The Generics must be expanded. This may also return some RF Generics, which must be added to the existing list. + List rfGenericComponents = expandGenericComponents(expander, genericsComponents); + // RF Generics MUST have their RF Admin loaded because they hold relevant info + // expander.expandEach(rfGenericComponents, rfGenFilter); + for (BOMLineHolder rfGenericComponent : rfGenericComponents) { + for (BOMLineHolder bomChild : expander.expand(rfGenericComponent, rfGenFilter).getBomChilds()) { + rfGenericComponent.addChild(bomChild); + } + } + + log.debug("Mono-level expansion DONE"); + return expandedTopLine; + } + + + /** + * Second level of MONO explosion.
    + * This method expands the provided Generics, but only keeps their RF Generic (Assemb) children.
    + * they will be included into the tree of existing {@link BOMLineHolder}s. + */ + List expandGenericComponents(final SingleLevelExpander expander, final List generics) throws EmptyNomenclatureException, MalformedNomenclatureException { + log.debug("Expand newly found Generics.."); + //expander.expandEach(generics, new AndFilter(COMPONENT_REJECTOR, componentFilter)); // Each Generic now has children, but no further components + for (BOMLineHolder generic : generics) { + for (BOMLineHolder bomChild : expander.expand(generic, new TcTypeInclusionFilter(RF_GENERIC_REVISION)).getBomChilds()) { + generic.addChild(bomChild); + } + } + + // Filter only the RF Generics, add them to the BOMLineholder tree and return them + List rfGenerics = addAndGetRfGenerics(generics); + + log.debug("Expand Generics DONE: {} RF Generics found", rfGenerics.size()); + return rfGenerics; + } + + /** + * Expands one level below the provided RF Generics.
    + * The generated children are all linked to the existing {@link BOMLineHolder}s.
    + * This method also looks for any Alternate and returns them. + */ + List expandRfPartsExtractAlternates(final SingleLevelExpander expander, final List rfParts) throws EmptyNomenclatureException { + // Expand one level + log.debug("Expand RF Generics..."); + //List expandedRfParts = expander.expandEach(rfParts, AllFilter.getInstance());// Each RF Generic now has children + for (BOMLineHolder rfPart : rfParts) { + for (BOMLineHolder bomChild : expander.expand(rfPart, AllFilter.getInstance()).getBomChilds()) { + rfPart.addChild(bomChild); + } + } + + // look for alternates/DET in the children + List alternates = new ArrayList<>(); + for (BOMLineHolder rfPartBom : rfParts) { + for (BOMLineHolder child : rfPartBom.getBomChilds()) { + String objectType = child.getObjectType(); + if (ALTERNATE_REVISION.equals(objectType) || DET_REVISION.equals(objectType)) { + alternates.add(child); + } + } + } + log.debug("Expand RF Parts DONE: {} alternates found", alternates.size()); + return alternates; + } + + /** + * Adds the RG Generics found in the expansion results (with BOMLines) to the {@link BOMLineHolder} map provided. + */ + List addAndGetRfGenerics(final List generics) throws MalformedNomenclatureException { + List rfGenerics = new ArrayList<>(); + log.debug("addAndGetRfGenerics: {} items...", generics.size()); + for (BOMLineHolder gen : generics) { + // Register this BOMLine's children, and create the parent-child link + try { + rfGenerics.add(BOMLineHolderHelper.findRfGenericBL(gen)); + } catch (InvalidInputException e) { + log.error("Null BomLineHolder detected below a Generic", e); + } + } + log.debug("addAndGetRfGenerics: {} RF Generics found", rfGenerics.size()); + return rfGenerics; + } + + BOMLineHolder filterChildren(final List children, final List generics, final List rfPart) { + BOMLineHolder theTopRfGen = null; + for (BOMLineHolder child : children) { + String objectType = child.getObjectType(); + if (GENERIC_REVISION.equals(objectType) || GENERIC_ASSEMB_REVISION.equals(objectType) || SUPERMODEL_REVISION.equals(objectType)) { + generics.add(child); + } else { + if (RF_GENERIC_REVISION.equals(objectType)) { + theTopRfGen = child; + } else { + rfPart.add(child); + } + } + } + return theTopRfGen; + } + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/teamcenter/resolution/structureservice/explorer/PartNumberFinder.java b/teamcenter/src/main/java/com/capgemini/reports/teamcenter/resolution/structureservice/explorer/PartNumberFinder.java new file mode 100644 index 0000000..d3b7770 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/teamcenter/resolution/structureservice/explorer/PartNumberFinder.java @@ -0,0 +1,38 @@ +package com.capgemini.reports.teamcenter.resolution.structureservice.explorer; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.EmptyNomenclatureException; +import com.capgemini.framework.teamcenter.resolution.filtering.TcTypeInclusionFilter; +import com.capgemini.reports.bomlineholder.BOMLineHolder; +import com.capgemini.reports.bomlineholder.BOMLineHolderHelper; +import com.capgemini.reports.exceptions.InvalidInputException; +import com.capgemini.reports.exceptions.MalformedNomenclatureException; +import com.capgemini.reports.exceptions.NotFoundException; +import com.capgemini.reports.teamcenter.resolution.IBOMLineExplorer; +import com.capgemini.reports.teamcenter.resolution.structureservice.SingleStructureServiceCaller.SingleLevelExpander; +import lombok.extern.slf4j.Slf4j; + +import static com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes.PART_AERO_REVISION; +import static com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes.RF_GENERIC_REVISION; + +/** + * This class is an {@link IBOMLineExplorer} using a {@link SingleLevelExpander}.
    + * This class can locate and return the Part Number of a Generic (found below the RF Generic of said Generic). + */ +@Slf4j +public class PartNumberFinder implements IBOMLineExplorer { + + @Override + public BOMLineHolder explore(TcSession session, final SingleLevelExpander expander, final BOMLineHolder genericBom) + throws InvalidInputException, MalformedNomenclatureException, EmptyNomenclatureException { + try { + BOMLineHolder expandedGenericBom = expander.expand(genericBom, new TcTypeInclusionFilter(RF_GENERIC_REVISION)); + BOMLineHolder rfGenericBom = BOMLineHolderHelper.findRfGenericBL(expandedGenericBom); + BOMLineHolder expandedRfGenericBom = expander.expand(rfGenericBom, new TcTypeInclusionFilter(PART_AERO_REVISION)); + return BOMLineHolderHelper.findFirst(expandedRfGenericBom, PART_AERO_REVISION); + } catch (NotFoundException e) { + log.trace("No RF Generic previously loaded in the Generic", e); + return null; + } + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/users/SnecmaPerson.java b/teamcenter/src/main/java/com/capgemini/reports/users/SnecmaPerson.java new file mode 100644 index 0000000..4a69be9 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/users/SnecmaPerson.java @@ -0,0 +1,31 @@ +package com.capgemini.reports.users; + +import com.teamcenter.soa.client.model.strong.Person; + +import java.io.Serializable; + +/** + * Class representing a Person. + */ +public class SnecmaPerson implements Serializable { + private static final long serialVersionUID = 4489416228194869431L; + + private final Person person; + + public SnecmaPerson(final Person person) { + this.person = person; + } + + public String getPersonName() { + return person.get_user_name(); + } + + public String getCodeCourrier() { + return person.get_PA8(); + } + + @Override + public String toString() { + return "Person " + (getPersonName() == null ? "(no name)" : getPersonName()); + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/users/SnecmaUser.java b/teamcenter/src/main/java/com/capgemini/reports/users/SnecmaUser.java new file mode 100644 index 0000000..60e8947 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/users/SnecmaUser.java @@ -0,0 +1,53 @@ +package com.capgemini.reports.users; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.teamcenter.soa.client.model.strong.Person; +import com.teamcenter.soa.client.model.strong.User; + +import java.io.Serializable; + +/** + * Represents a TC User. + */ +public class SnecmaUser implements Serializable { + private static final long serialVersionUID = -4311528092285199052L; + + private static final long ACTIVE_STATUS = 0; // TC code for active status is '0' + private final TcSession session; + private final User user; + + /** + * Builds a TC {@link User}. + */ + public SnecmaUser(final TcSession session, final User user) { + this.session = session; + this.user = user; + } + + public String getName() { + return user.get_user_name(); + } + + public String getUserId() { + return user.get_user_id(); + } + + public SnecmaPerson getPerson() { + session.loadProperties(user, "person"); + Person person = user.get_person(); + session.loadProperties(person); + return new SnecmaPerson(person); + } + + /** + * The values are 1 ("inactif") and 0 ("actif"). + */ + public boolean isActive() { + return user.get_status() == ACTIVE_STATUS; + } + + @Override + public String toString() { + return "User " + getName() + " ID=" + getUserId(); + } +} diff --git a/teamcenter/src/main/java/com/capgemini/reports/workflows/Task.java b/teamcenter/src/main/java/com/capgemini/reports/workflows/Task.java new file mode 100644 index 0000000..65ef493 --- /dev/null +++ b/teamcenter/src/main/java/com/capgemini/reports/workflows/Task.java @@ -0,0 +1,234 @@ +package com.capgemini.reports.workflows; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.reports.changeobjects.change.AbstractChangeObject; +import com.capgemini.reports.users.SnecmaUser; +import com.teamcenter.soa.client.model.ModelObject; +import com.teamcenter.soa.client.model.strong.EPMTask; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import com.teamcenter.soa.client.model.strong.Signoff; +import com.teamcenter.soa.client.model.strong.User; +import lombok.extern.slf4j.Slf4j; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; + +import static com.capgemini.framework.teamcenter.TeamcenterObjectTypes.SIGNOFF; +import static com.capgemini.framework.teamcenter.TeamcenterObjectTypes.USER; + +/** + * Represents a TC EPMTask. + */ +@Slf4j +public class Task implements Serializable { + private static final long serialVersionUID = 2426203736278592266L; + + private static final int VAL_DECISION_PENDING = 0; + private final TcSession session; + private final EPMTask task; + + public Task(final TcSession session, final EPMTask task) { + this.session = session; + this.task = task; + } + + public String getType() { + return task.getTypeObject().getName(); + } + + public String getName() { + return task.get_object_name(); + } + + public SnecmaUser getOwningUser() { + session.loadProperties(task, "owning_user"); + User user = (User) task.get_owning_user(); + session.loadProperties(user); + return new SnecmaUser(session, user); + } + + public SnecmaUser getResponsibleUser() throws KurtException { + try { + session.loadProperties(task, "fnd0Assignee"); + User user = (User) task.get_fnd0Assignee(); + session.loadProperties(user); + return new SnecmaUser(session, user); + } + catch (ClassCastException e) { + throw new KurtException("Erreur lors de la récupération du User responsable.", e); + } + } + + + public SnecmaUser getLastModUser() { + + session.loadProperties(task, "last_mod_user"); + User user = (User) task.get_last_mod_user(); + session.loadProperties(user); + return new SnecmaUser(session, user); + } + + public Calendar getLastModDate() { + return task.get_last_mod_date(); + } + + public Calendar getCreationDate() { + return task.get_creation_date(); + } + + public Calendar getDueDate() { + return task.get_due_date(); + } + + public TaskState getState() { + return TaskState.findState(task.get_state()); + } + + public boolean isInTargetAttachments(final AbstractChangeObject change) { + session.loadProperties(task, "root_target_attachments"); + ModelObject[] rootTargetObjects = task.get_root_target_attachments(); + session.loadProperties(rootTargetObjects); + for (ModelObject object : rootTargetObjects) { + if (object instanceof ItemRevision) { + ItemRevision itemRevision = (ItemRevision) object; + if (itemRevision.get_item_id().equals(change.getItemId()) && itemRevision.get_item_revision_id().equals(change.getRevisionId())) { + return true; + } + } + } + return false; + } + + public List getActiveChildTasks() { + return getChildren(TaskState.STARTED); + } + + public List getCompletedChildTasks() { + return getChildren(TaskState.COMPLETED); + } + + public List getChildren(final TaskState state) { + List children = new ArrayList<>(); + session.loadProperties(task, "child_tasks"); + ModelObject[] childTasks = task.get_child_tasks(); + session.loadProperties(childTasks); + for (ModelObject childTask : childTasks) { + if (childTask instanceof EPMTask) { + if (state.equals(TaskState.findState(((EPMTask) childTask).get_state()))) { + children.add(new Task(session, (EPMTask) childTask)); + } + } + } + + return children; + } + + public List getPendingSignoffsUser() { + List pendingSignoffsUser = new ArrayList<>(); + session.loadProperties(task, "signoff_attachments"); + ModelObject[] signoffAttachments = task.get_signoff_attachments(); + session.loadProperties(signoffAttachments); + for (ModelObject signoff : signoffAttachments) { + if (SIGNOFF.equals(signoff.getTypeObject().getName()) && ((Signoff) signoff).get_decision() == VAL_DECISION_PENDING) { + session.loadProperties(signoff, "owning_user"); + User signoffOwner = (User) ((Signoff) signoff).get_owning_user(); + session.loadProperties(signoffOwner); + if (USER.equals(signoffOwner.getTypeObject().getName())) { + pendingSignoffsUser.add(new SnecmaUser(session, signoffOwner)); + } + } + } + + return pendingSignoffsUser; + } + + public boolean isRunning() { + return getState() == TaskState.STARTED; + } + + @Override + public String toString() { + return getType() + " " + getName(); + } + + + /** + * Represents the state of a Task. + */ + public enum TaskState { + UNASSIGNED, // Unassigned task state. Code 1. + PENDING, // Pending task state. Code 2. + STARTED, // Started task state. Code 4. + COMPLETED, // Completed task state. Code 8. + SKIPPED, // Skipped task state. Code 16. + ABORTED, // Aborted task state. Code 32. + FAILED, // Failed task state. Code 64. + SUSPENDED; // Suspended task state. Code 128. + + private static final int TC_CODE_FOR_SUSPENDED = 128; + private static final int TC_CODE_FOR_FAILED = 64; + private static final int TC_CODE_FOR_ABORTED = 32; + private static final int TC_CODE_FOR_SKIPPED = 16; + private static final int TC_CODE_FOR_COMPLETED = 8; + private static final int TC_CODE_FOR_STARTED = 4; + private static final int TC_CODE_FOR_PENDING = 2; + private static final int TC_CODE_FOR_UNASSIGNED = 1; + + /** + * Return the matching State enum instance form the TC int value, based on the TC convention. + */ + public static TaskState findState(final int intValue) { + switch (intValue) { + case TC_CODE_FOR_UNASSIGNED: + return TaskState.UNASSIGNED; + case TC_CODE_FOR_PENDING: + return TaskState.PENDING; + case TC_CODE_FOR_STARTED: + return TaskState.STARTED; + case TC_CODE_FOR_COMPLETED: + return TaskState.COMPLETED; + case TC_CODE_FOR_SKIPPED: + return TaskState.SKIPPED; + case TC_CODE_FOR_ABORTED: + return TaskState.ABORTED; + case TC_CODE_FOR_FAILED: + return TaskState.FAILED; + case TC_CODE_FOR_SUSPENDED: + return TaskState.SUSPENDED; + default: + log.error("Task State unknown: {}", intValue); + return null; + } + } + + /** + * Returns true if this {@link TaskState} and the provided Task code are a match. + */ + public boolean matches(final int intValue) { + switch (intValue) { + case TC_CODE_FOR_UNASSIGNED: + return this == TaskState.UNASSIGNED; + case TC_CODE_FOR_PENDING: + return this == TaskState.PENDING; + case TC_CODE_FOR_STARTED: + return this == TaskState.STARTED; + case TC_CODE_FOR_COMPLETED: + return this == TaskState.COMPLETED; + case TC_CODE_FOR_SKIPPED: + return this == TaskState.SKIPPED; + case TC_CODE_FOR_ABORTED: + return this == TaskState.ABORTED; + case TC_CODE_FOR_FAILED: + return this == TaskState.FAILED; + case TC_CODE_FOR_SUSPENDED: + return this == TaskState.SUSPENDED; + default: + log.error("Task Code unknown: {}", intValue); + return false; + } + } + } +} diff --git a/teamcenter/src/main/java/com/teamcenter/soa/exceptions/NotLoadedException.java b/teamcenter/src/main/java/com/teamcenter/soa/exceptions/NotLoadedException.java new file mode 100644 index 0000000..47e8906 --- /dev/null +++ b/teamcenter/src/main/java/com/teamcenter/soa/exceptions/NotLoadedException.java @@ -0,0 +1,14 @@ +package com.teamcenter.soa.exceptions; + +import com.capgemini.framework.teamcenter.exceptions.runtime.KurtRuntimeException; + +public class NotLoadedException extends KurtRuntimeException { + private static final long serialVersionUID = 6774158621504788960L; + + public NotLoadedException() { + } + + public NotLoadedException(String message) { + super(message); + } +} diff --git a/teamcenter/src/test/java/com/capgemini/framework/common/DummyBean.java b/teamcenter/src/test/java/com/capgemini/framework/common/DummyBean.java new file mode 100644 index 0000000..06bb2f5 --- /dev/null +++ b/teamcenter/src/test/java/com/capgemini/framework/common/DummyBean.java @@ -0,0 +1,52 @@ +package com.capgemini.framework.common; + +/** + * Dummy test class.
    + * Required by: ReflectionHelperTest + **/ +public class DummyBean { + + private String fooString; + private int fooInt; + + /** Default constructor. **/ + public DummyBean() { + // Nothing to do but must be keep for reflection + } + + /** + * String getter. + * + * @return String value + **/ + public String getFooString() { + return fooString; + } + + /** + * String setter. + * + * @param aFooString String value + **/ + public void setFooString(String aFooString) { + fooString = aFooString; + } + + /** + * Integer getter. + * + * @return Integer value + **/ + public int getFooInt() { + return fooInt; + } + + /** + * Integer setter. + * + * @param aFooInt Integer value + **/ + public void setFooInt(int aFooInt) { + fooInt = aFooInt; + } +} diff --git a/teamcenter/src/test/java/com/capgemini/framework/common/ReflectionHelperTest.java b/teamcenter/src/test/java/com/capgemini/framework/common/ReflectionHelperTest.java new file mode 100644 index 0000000..d2331d1 --- /dev/null +++ b/teamcenter/src/test/java/com/capgemini/framework/common/ReflectionHelperTest.java @@ -0,0 +1,28 @@ +package com.capgemini.framework.common; + +import junit.framework.Assert; +import org.junit.Test; + +public class ReflectionHelperTest { + private static final String DUMMY_BEAN_CLASSNAME = "com.capgemini.framework.common.DummyBean"; + private static final String WRONG_CLASSNAME = "com.capgemini.framework.common.WrongBean"; + + @Test + public void testGetClassForName() { + Class theClass = ReflectionHelper.getClassForName(DUMMY_BEAN_CLASSNAME); + Assert.assertEquals("Compare classes", DummyBean.class, theClass); + + Class theNullClass = ReflectionHelper.getClassForName(WRONG_CLASSNAME); + Assert.assertNull("Unknown class", theNullClass); + } + + @Test + public void testNewFromClassForName() { + Object theObj = ReflectionHelper.newFromClassForName(DUMMY_BEAN_CLASSNAME); + boolean isInstance = theObj instanceof DummyBean; + Assert.assertTrue("Compare classes", isInstance); + + Object theNullObj = ReflectionHelper.newFromClassForName(WRONG_CLASSNAME); + Assert.assertNull("Unknown class name for newInstance", theNullObj); + } +} diff --git a/teamcenter/src/test/java/com/capgemini/framework/common/StringHelperTest.java b/teamcenter/src/test/java/com/capgemini/framework/common/StringHelperTest.java new file mode 100644 index 0000000..36c00d6 --- /dev/null +++ b/teamcenter/src/test/java/com/capgemini/framework/common/StringHelperTest.java @@ -0,0 +1,25 @@ +package com.capgemini.framework.common; + +import junit.framework.Assert; +import org.junit.Test; + +public class StringHelperTest { + + @Test + public void testTruncate() { + Assert.assertEquals("Truncated value", "12345", StringHelper.truncate("1234567890", 5)); + Assert.assertEquals("Equals to length value", "12345", StringHelper.truncate("12345", 5)); + Assert.assertEquals("Too small value", "1", StringHelper.truncate("1", 5)); + Assert.assertEquals("Null value", null, StringHelper.truncate(null, 5)); + } + + @Test + public void testSplitWithoutDelim() { + String value = "2015-11"; + String expected = "2015"; + + String delimiter = StringHelper.DASH; + String[] tokens = StringHelper.splitWithoutDelim(delimiter, value); + Assert.assertEquals("Expected the first range [" + expected + "] of value:" + value + " with delimiter [" + delimiter + "]", expected, tokens[0]); + } +} diff --git a/teamcenter/src/test/java/com/capgemini/framework/common/TeamcenterDateFormatterTest.java b/teamcenter/src/test/java/com/capgemini/framework/common/TeamcenterDateFormatterTest.java new file mode 100644 index 0000000..3e7ada3 --- /dev/null +++ b/teamcenter/src/test/java/com/capgemini/framework/common/TeamcenterDateFormatterTest.java @@ -0,0 +1,30 @@ +package com.capgemini.framework.common; + +import junit.framework.Assert; +import lombok.extern.slf4j.Slf4j; +import org.junit.Test; + +import java.text.ParseException; +import java.util.Calendar; + + +@Slf4j +public class TeamcenterDateFormatterTest { + + /** + * JUNIT TEST. + * + * @throws ParseException should not happen + */ + @Test + public void testFormatCalendarToFrench() throws ParseException { + log.info("testCalendarWithTimeZoneFR ...."); + Calendar date = Calendar.getInstance(); + date.set(2015, 1, 2); // Feb 4th, 2015 + String dateFr = TeamcenterDateFormatter.formatCalendarToFrench(date); + log.info("Date FR : " + dateFr); + + log.info("With date to compare : " + date); + Assert.assertEquals("WRONG FORMAT DATE EXPECTED [DD MMMM YYYY], LOCALE FR", "02 février 2015", dateFr); + } +} diff --git a/teamcenter/src/test/java/com/capgemini/framework/teamcenter/files/DatasetPreparatorTest.java b/teamcenter/src/test/java/com/capgemini/framework/teamcenter/files/DatasetPreparatorTest.java new file mode 100644 index 0000000..dd2f1a2 --- /dev/null +++ b/teamcenter/src/test/java/com/capgemini/framework/teamcenter/files/DatasetPreparatorTest.java @@ -0,0 +1,99 @@ +package com.capgemini.framework.teamcenter.files; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.InvalidConfigurationException; +import com.capgemini.framework.teamcenter.exceptions.MalformedDataSetException; +import com.capgemini.framework.teamcenter.exceptions.NoTeamcenterConnectionException; +import com.capgemini.framework.teamcenter.files.FileManagement.FileType; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.teamcenter.schemas.soa._2006_03.exceptions.InvalidCredentialsException; +import com.teamcenter.schemas.soa._2006_03.exceptions.ServiceException; +import com.teamcenter.services.loose.core._2006_03.FileManagement.GetDatasetWriteTicketsInputData; +import com.teamcenter.soa.client.model.ModelObject; +import junit.framework.Assert; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.File; +import java.util.NoSuchElementException; + +public class DatasetPreparatorTest { + private static final String DESCRIPTION = "A nice description"; + private static final String DATASET_NAME = "aDatasetName"; + private static final String FILE_NAME = "jasperPdfPrinterTest.pdf"; + private static final String FOLDER = "src/test/resources/"; + private static final PolicyLocation XML_POLICY = PolicyLocation.make("test_policy", "/test_policy.xml"); + private static final TcSession session = new TcSession(); + + @BeforeClass + public static void login() throws NoTeamcenterConnectionException, InvalidConfigurationException { + session.login(); + session.setObjectPropPolicy(XML_POLICY); + } + + @AfterClass + public static void logout() { + session.close(); + } + + @Test + public void testAddFile() throws MalformedDataSetException, InvalidCredentialsException, ServiceException, NoTeamcenterConnectionException { + DatasetPreparator datapreparator = new DatasetPreparator(session, DATASET_NAME, DESCRIPTION); + addValidfile(datapreparator); + } + + @Test(expected = MalformedDataSetException.class) + public void testDatasetPreparatorNoName() throws MalformedDataSetException { + DatasetPreparator datasetPreparator = new DatasetPreparator(session, "", DESCRIPTION); + Assert.fail("'" + datasetPreparator.getDatasetName() + "' should not be accepted as a dataset name"); + } + + @Test(expected = MalformedDataSetException.class) + public void testDatasetPreparatorNullName() throws MalformedDataSetException { + DatasetPreparator datasetPreparator = new DatasetPreparator(session, null, DESCRIPTION); + datasetPreparator.isEmpty(); + Assert.fail("NULL should not be accepted as a dataset name"); + } + + @Test(expected = MalformedDataSetException.class) + public void testDatasetPreparatorNoFile() + throws MalformedDataSetException, InvalidCredentialsException, ServiceException, NoTeamcenterConnectionException { + DatasetPreparator datapreparator = new DatasetPreparator(session, DATASET_NAME, ""); + datapreparator.prepare(); // Fails here + } + + @Test + public void testPrepare() throws MalformedDataSetException, InvalidCredentialsException, ServiceException, NoTeamcenterConnectionException { + DatasetPreparator datapreparator = new DatasetPreparator(session, DATASET_NAME, DESCRIPTION); + addValidfile(datapreparator); + GetDatasetWriteTicketsInputData createdDataset = datapreparator.prepare(); + + // Cleanup + ModelObject asModelObject = createdDataset.dataset; + session.deleteObjects(asModelObject); + } + + @Test + public void testIsCreated() throws MalformedDataSetException, InvalidCredentialsException, ServiceException, NoTeamcenterConnectionException { + DatasetPreparator datapreparator = new DatasetPreparator(session, DATASET_NAME, DESCRIPTION); + Assert.assertFalse(datapreparator.isCreated()); + addValidfile(datapreparator); + Assert.assertFalse(datapreparator.isCreated()); + GetDatasetWriteTicketsInputData createdDataset = datapreparator.prepare(); + Assert.assertTrue(datapreparator.isCreated()); + + // Cleanup + ModelObject asModelObject = createdDataset.dataset; + session.deleteObjects(asModelObject); + } + + // Helper function + private void addValidfile(DatasetPreparator datapreparator) throws MalformedDataSetException { + File theFile = new File(FOLDER + FILE_NAME); + if (!theFile.exists() || theFile.isDirectory()) { + throw new NoSuchElementException("Missing test file " + FOLDER + FILE_NAME); // This is the failure of the test-class, not of the class being tested + } + datapreparator.addFile(theFile, FileType.FICHE_ARTICLE); + } +} diff --git a/teamcenter/src/test/java/com/capgemini/framework/teamcenter/files/FileManagementTest.java b/teamcenter/src/test/java/com/capgemini/framework/teamcenter/files/FileManagementTest.java new file mode 100644 index 0000000..46be90b --- /dev/null +++ b/teamcenter/src/test/java/com/capgemini/framework/teamcenter/files/FileManagementTest.java @@ -0,0 +1,104 @@ +package com.capgemini.framework.teamcenter.files; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.ConnectionMisconguredException; +import com.capgemini.framework.teamcenter.exceptions.MalformedDataSetException; +import com.capgemini.framework.teamcenter.exceptions.NoTeamcenterConnectionException; +import com.capgemini.framework.teamcenter.files.FileManagement.FileType; +import com.teamcenter.schemas.soa._2006_03.exceptions.InvalidCredentialsException; +import com.teamcenter.schemas.soa._2006_03.exceptions.ServiceException; +import com.teamcenter.services.loose.core._2006_03.FileManagement.GetDatasetWriteTicketsInputData; +import com.teamcenter.soa.client.model.ModelObject; +import junit.framework.Assert; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; +import java.util.List; + +public class FileManagementTest { + + private static final String DESCRIPTION = "A nice description"; + private static final String DATASET_NAME = "aDatasetName"; + private static final String TEXT_FILE_NAME = "TextFile.txt"; + private static final String PDF_FILE_NAME = "jasperPdfPrinterTest.pdf"; + private static final String FOLDER = "src/test/resources/"; + + @Test + public void testFileManagementText() + throws MalformedDataSetException, IOException, ConnectionMisconguredException, NoTeamcenterConnectionException { + try (TcSession session = new TcSession()) { + session.login(); + + // Prepare dataset + DatasetPreparator dataset = new DatasetPreparator(session, DATASET_NAME, DESCRIPTION); + File targetFile = new File(FOLDER + TEXT_FILE_NAME); + dataset.addFile(targetFile, FileType.TEXT_FILE); + + // Upload file (dataset will be uploaded too) + FileManagement fileManager = new FileManagement(session); + fileManager.addDataSet(dataset); + fileManager.upload(); + + List createdDatasets = fileManager.getDataSets(); + // Verify creation + Assert.assertFalse(createdDatasets.isEmpty()); + + // Delete all objects created + ModelObject[] datasets = new ModelObject[createdDatasets.size()]; + int num = 0; + for (GetDatasetWriteTicketsInputData data : createdDatasets) { + datasets[num++] = data.dataset; + } + session.deleteObjects(datasets); + } + } + + @Test + public void testFileManagementPDF() + throws MalformedDataSetException, IOException, ConnectionMisconguredException, NoTeamcenterConnectionException { + try (TcSession session = new TcSession()) { + session.login(); + + // Prepare dataset + DatasetPreparator dataset = new DatasetPreparator(session, DATASET_NAME, DESCRIPTION); + File targetFile = new File(FOLDER + PDF_FILE_NAME); + dataset.addFile(targetFile, FileType.PDF); + + // Upload file (dataset will be uploaded too) + FileManagement fileManager = new FileManagement(session); + fileManager.addDataSet(dataset); + try { + // Perform the file upload + fileManager.upload(); + + // Verify creation + List createdDatasets = fileManager.getDataSets(); + Assert.assertFalse(createdDatasets.isEmpty()); + } finally { + if (dataset.isCreated()) { + // Delete The dataset + session.deleteObjects(dataset.getCreatedDataset().dataset); + } + } + } + } + + @Test(expected = MalformedDataSetException.class) + public void testFileManagementNoDataset() + throws InvalidCredentialsException, ServiceException, MalformedDataSetException, ConnectionMisconguredException { + try (TcSession session = new TcSession()) { + FileManagement fileManager = new FileManagement(session); + fileManager.upload(); // Should fail because no datasets were provided + } + } + + @Test(expected = MalformedDataSetException.class) + public void testFileManagementFailedDataset() + throws InvalidCredentialsException, ServiceException, MalformedDataSetException, ConnectionMisconguredException { + try (TcSession session = new TcSession()) { + FileManagement fileManager = new FileManagement(session); + fileManager.addDataSetWithSingleFile(DATASET_NAME, DESCRIPTION, null, FileType.FICHE_ARTICLE); + } + } +} diff --git a/teamcenter/src/test/java/com/capgemini/framework/teamcenter/queries/saved/modelobject/ItemQueryTest.java b/teamcenter/src/test/java/com/capgemini/framework/teamcenter/queries/saved/modelobject/ItemQueryTest.java new file mode 100644 index 0000000..f8f81f0 --- /dev/null +++ b/teamcenter/src/test/java/com/capgemini/framework/teamcenter/queries/saved/modelobject/ItemQueryTest.java @@ -0,0 +1,69 @@ +package com.capgemini.framework.teamcenter.queries.saved.modelobject; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.InvalidConfigurationException; +import com.capgemini.framework.teamcenter.exceptions.NoTeamcenterConnectionException; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.teamcenter.soa.client.model.strong.Item; +import lombok.extern.slf4j.Slf4j; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.util.List; + +@Slf4j +public class ItemQueryTest { + private static final TcSession session = new TcSession(); + private static final String expectedItemID = "22U"; + private static final PolicyLocation XML_POLICY = PolicyLocation.make("test_policy", "/test_policy.xml"); + + + @BeforeClass + public static void login() throws NoTeamcenterConnectionException, InvalidConfigurationException { + session.login(); + session.setObjectPropPolicy(XML_POLICY); + } + + @AfterClass + public static void logout() { + session.close(); + } + + @Test + public void testSearchID() { + log.info("testSearchID--------------------------"); + + // Create a query + ItemQuery query = new ItemQuery(session); + query.searchID(expectedItemID); + + // Execute the query + List result = query.findAll(); + Assert.assertNotNull(result); + Assert.assertFalse(result.isEmpty()); + + // Parse the results + log.info("Matching Items: "); + for (Item item : result) { + Assert.assertNotNull(item); + log.info("ID = {}\t\tName = {}", item.get_item_id(), item.get_object_name()); + Assert.assertEquals(expectedItemID, item.get_item_id()); + } + } + + @Test + public void testSearchFakeID() { + log.info("testSearchID--------------------------"); + + // Create a query + ItemQuery query = new ItemQuery(session); + query.searchID("babar"); + + // Execute the query + List result = query.findAll(); + Assert.assertNotNull(result); + Assert.assertTrue(result.isEmpty()); + } +} diff --git a/teamcenter/src/test/java/com/capgemini/framework/teamcenter/queries/saved/modelobject/ItemRevisionQueryTest.java b/teamcenter/src/test/java/com/capgemini/framework/teamcenter/queries/saved/modelobject/ItemRevisionQueryTest.java new file mode 100644 index 0000000..6c53c58 --- /dev/null +++ b/teamcenter/src/test/java/com/capgemini/framework/teamcenter/queries/saved/modelobject/ItemRevisionQueryTest.java @@ -0,0 +1,140 @@ +package com.capgemini.framework.teamcenter.queries.saved.modelobject; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.InvalidConfigurationException; +import com.capgemini.framework.teamcenter.exceptions.NoTeamcenterConnectionException; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import lombok.extern.slf4j.Slf4j; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.util.List; + +@Slf4j +public class ItemRevisionQueryTest { + private static final TcSession session = new TcSession(); + private static final String expectedItemID = "22U"; + private static final String expectedObjectName = "GE90 M10 MOTEUR ASSEMBLE"; + private static final String expectedItemRevision = "C"; // <-- revision B also exists + private static final PolicyLocation XML_POLICY = PolicyLocation.make("test_policy", "/test_policy.xml"); + + @BeforeClass + public static void login() throws NoTeamcenterConnectionException, InvalidConfigurationException { + session.login(); + session.setObjectPropPolicy(XML_POLICY); + } + + @AfterClass + public static void logout() { + session.close(); + } + + @Test + public void testSearchID() { + log.info("testSearchID--------------------------"); + // Create a query + ItemRevisionQuery query = new ItemRevisionQuery(session); + query.searchID(expectedItemID); + + // Execute the query + List result = query.findAll(); + Assert.assertNotNull(result); + Assert.assertFalse(result.isEmpty()); + + // Parse the results + log.info("Matching ItemRevisions: "); + for (ItemRevision itemRev : result) { + log.info("ID = {}\tRev={}\tName = {}", itemRev.get_item_id(), itemRev.get_item_revision_id(), itemRev.get_object_name()); + Assert.assertEquals(expectedItemID, itemRev.get_item_id()); + } + } + + @Test + public void testSearchFakeID() { + log.info("testSearchFakeID----------------------"); + // Create a query + ItemRevisionQuery query = new ItemRevisionQuery(session); + query.searchID("some ID that does not exist"); + + // Execute the query + List result = query.findAll(); + Assert.assertNotNull(result); + Assert.assertTrue(result.isEmpty()); + } + + @Test + public void testSearchIDAndRevision() { + log.info("testSearchIDAndRevision---------------"); + // Create a query + ItemRevisionQuery query = new ItemRevisionQuery(session); + query.searchIDAndRevision(expectedItemID, expectedItemRevision); + + // Execute the query + List result = query.findAll(); + Assert.assertNotNull(result); + Assert.assertTrue(result.size() == 1); + + // Parse the results + ItemRevision theItemRev = result.get(0); + Assert.assertNotNull(theItemRev); + Assert.assertEquals(expectedItemID, theItemRev.get_item_id()); + Assert.assertEquals(expectedItemRevision, theItemRev.get_item_revision_id()); + log.info("Matching ItemRevision: "); + log.info("ID = {}\tRev={}\tName = {}", theItemRev.get_item_id(), theItemRev.get_item_revision_id(), theItemRev.get_object_name()); + } + + /** + * JUnit test. + */ + @Test + public void testSearchIdAndFakeRevision() { + log.info("testSearchIdAndFakeRevision-----------"); + // Create a query + ItemRevisionQuery query = new ItemRevisionQuery(session); + query.searchIDAndRevision(expectedItemID, "pouet pouet truc"); + + // Execute the query + List result = query.searchID(expectedItemID).findAll(); + Assert.assertNotNull(result); + Assert.assertTrue(result.isEmpty()); + } + + @Test + public void testSearchName() { + log.info("testSearchName------------------------"); + // Create a query + ItemRevisionQuery query = new ItemRevisionQuery(session); + query.searchName(expectedObjectName); + + // Execute the query + List result = query.findAll(); + Assert.assertNotNull(result); + Assert.assertTrue(!result.isEmpty()); + + // Parse the results + log.info("Matching ItemRevisions: "); + for (ItemRevision itemRev : result) { + log.info("ID = {}\tRev={}", itemRev.get_item_id(), itemRev.get_item_revision_id()); + Assert.assertEquals(expectedObjectName, itemRev.get_object_name()); + } + } + + /** + * JUnit test. + */ + @Test + public void testSearchFakeName() { + log.info("testSearchFakeName--------------------"); + // Create a query + ItemRevisionQuery query = new ItemRevisionQuery(session); + query.searchName("pouet pouet truc"); + + // Execute the query + List result = query.searchID(expectedItemID).findAll(); + Assert.assertNotNull(result); + Assert.assertTrue(result.isEmpty()); + } +} diff --git a/teamcenter/src/test/java/com/capgemini/framework/teamcenter/relations/RelationshipManagerTest.java b/teamcenter/src/test/java/com/capgemini/framework/teamcenter/relations/RelationshipManagerTest.java new file mode 100644 index 0000000..a2775fa --- /dev/null +++ b/teamcenter/src/test/java/com/capgemini/framework/teamcenter/relations/RelationshipManagerTest.java @@ -0,0 +1,63 @@ +package com.capgemini.framework.teamcenter.relations; + +import com.capgemini.framework.teamcenter.TeamcenterObjectTypes; +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.FailedRelationshipActionException; +import com.capgemini.framework.teamcenter.exceptions.MalformedDataSetException; +import com.capgemini.framework.teamcenter.exceptions.NoTeamcenterConnectionException; +import com.capgemini.framework.teamcenter.files.DatasetPreparator; +import com.capgemini.framework.teamcenter.files.FileManagement.FileType; +import com.capgemini.framework.teamcenter.queries.saved.modelobject.ItemQuery; +import com.teamcenter.schemas.soa._2006_03.exceptions.InvalidCredentialsException; +import com.teamcenter.services.loose.core._2006_03.FileManagement.GetDatasetWriteTicketsInputData; +import com.teamcenter.soa.client.model.ModelObject; +import com.teamcenter.soa.client.model.strong.Item; +import junit.framework.Assert; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.io.File; +import java.util.NoSuchElementException; + +public class RelationshipManagerTest { + + private static final String DATASET_NAME = "TestDataset"; + private static final String PART_ID = "002711"; + private static final String FILE_NAME = "jasperPdfPrinterTest.pdf"; + private static final String FOLDER = "src/test/resources/"; + + private final TcSession session = new TcSession(); + private ModelObject dataset; + + @Before + public void makeDataset() throws MalformedDataSetException, InvalidCredentialsException, NoTeamcenterConnectionException { + session.login(); + DatasetPreparator datapreparator = new DatasetPreparator(session, DATASET_NAME, "For Kurt Unit testing"); + File theFile = new File(FOLDER + FILE_NAME); + if (!theFile.exists() || theFile.isDirectory()) { + throw new NoSuchElementException("Missing test file " + FOLDER + FILE_NAME); // This is the failure of the test-class, not of the class being tested + } + datapreparator.addFile(theFile, FileType.FICHE_ARTICLE); + GetDatasetWriteTicketsInputData datasetTicket = datapreparator.prepare(); + dataset = datasetTicket.dataset; + } + + @Test + public void createDeleteTest() throws InvalidCredentialsException, FailedRelationshipActionException, NoTeamcenterConnectionException { + Item part = new ItemQuery(session).searchID(PART_ID).findAll().get(0); + + // Create the link + Assert.assertNotNull(session.createRelation(part, dataset, TeamcenterObjectTypes.IMAN_REFERENCE)); + session.deleteRelations(part, dataset, TeamcenterObjectTypes.IMAN_REFERENCE); + } + + /** + * Destroy the dataset. + */ + @After + public void cleanup() { + session.deleteObjects(dataset); + session.close(); + } +} diff --git a/teamcenter/src/test/java/com/capgemini/framework/teamcenter/statuating/StatusSetterTest.java b/teamcenter/src/test/java/com/capgemini/framework/teamcenter/statuating/StatusSetterTest.java new file mode 100644 index 0000000..a72d572 --- /dev/null +++ b/teamcenter/src/test/java/com/capgemini/framework/teamcenter/statuating/StatusSetterTest.java @@ -0,0 +1,58 @@ +package com.capgemini.framework.teamcenter.statuating; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.InvalidConfigurationException; +import com.capgemini.framework.teamcenter.exceptions.MalformedDataSetException; +import com.capgemini.framework.teamcenter.exceptions.NoTeamcenterConnectionException; +import com.capgemini.framework.teamcenter.exceptions.UnableToCreateStatusException; +import com.capgemini.framework.teamcenter.files.DatasetPreparator; +import com.capgemini.framework.teamcenter.files.FileManagement.FileType; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.teamcenter.services.loose.core._2006_03.FileManagement.GetDatasetWriteTicketsInputData; +import com.teamcenter.soa.client.model.strong.ReleaseStatus; +import com.teamcenter.soa.client.model.strong.WorkspaceObject; +import junit.framework.Assert; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.File; + +public class StatusSetterTest { + private static final TcSession session = new TcSession(); + private static final String DESCRIPTION = "to perform a test, will be destroyed"; + private static final String DATASET_NAME = "aDatasetName"; + private static final String FILE_NAME = "jasperPdfPrinterTest.pdf"; + private static final String FOLDER = "src/test/resources/"; + private static final String TEST_STATUS_NAME = "J3B"; + private static final PolicyLocation XML_POLICY = PolicyLocation.make("test_policy", "/test_policy.xml"); + + @BeforeClass + public static void login() throws NoTeamcenterConnectionException, InvalidConfigurationException { + session.login(); + session.setObjectPropPolicy(XML_POLICY); + } + + @AfterClass + public static void logout() { + session.close(); + } + + + @Test + public void poseAndDeleteStatus() throws MalformedDataSetException, UnableToCreateStatusException { + // Create the target Dataset + DatasetPreparator datasetPreparator = new DatasetPreparator(session, DATASET_NAME, DESCRIPTION); + datasetPreparator.addFile(new File(FOLDER + FILE_NAME), FileType.PDF); + GetDatasetWriteTicketsInputData datasetTicket = datasetPreparator.prepare(); + + // Perform the test: put a status on the brand new dataset + StatusSetter setter = new StatusSetter(session); + ReleaseStatus createdStatus = setter.putStatus((WorkspaceObject) datasetTicket.dataset, TEST_STATUS_NAME); + Assert.assertNotNull(createdStatus); + Assert.assertEquals(TEST_STATUS_NAME, createdStatus.get_name()); + + // Status passed! now delete the dataset, with the and with it + session.deleteObjects(datasetTicket.dataset); + } +} diff --git a/teamcenter/src/test/java/com/capgemini/reports/AbstractTeamcenterTest.java b/teamcenter/src/test/java/com/capgemini/reports/AbstractTeamcenterTest.java new file mode 100644 index 0000000..e4fe254 --- /dev/null +++ b/teamcenter/src/test/java/com/capgemini/reports/AbstractTeamcenterTest.java @@ -0,0 +1,233 @@ +package com.capgemini.reports; + +import com.capgemini.framework.teamcenter.authent.TcSession; +import com.capgemini.framework.teamcenter.exceptions.InvalidConfigurationException; +import com.capgemini.framework.teamcenter.exceptions.NoTeamcenterConnectionException; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.reports.teamcenter.Platform; +import com.teamcenter.schemas.soa._2006_03.exceptions.ServiceException; +import lombok.extern.slf4j.Slf4j; +import org.junit.AfterClass; + +/** + * Helper class to initialize a Teamcenter connection.
    + * Provides daughter classes a transparent way to access a Teamcenter connection.
    + * The session will have its Property Policies set to the default testing policies found in "/src/test/resources/test_policy.xml". + *

    + * Access the connection through the static {@link AbstractTeamcenterTest#getSession()} method. + */ +@Slf4j +public abstract class AbstractTeamcenterTest { + + /** + * Minimum delay between each login (by milliseconds). + **/ + private static final long LOGIN_DELAY = 30000; + + /** + * Time by milliseconds of the last login. + **/ + private static long lastLogInTimeMs = 0L; + + /** + * Plateform A36 for Tests. + */ + public static final Platform A36_URL = Platform.PF36; + /** + * Plateform AIX for Tests. + */ + public static final Platform AIX_URL = Platform.AIX; + /** + * Plateform MIG. + */ + public static final Platform MIG_URL = Platform.MIG; + + /** + * The file location of the default policy. (test_policy). + **/ + public static final PolicyLocation DEFAULT_POLICY = PolicyLocation.make("test_policy", "/xml/policies/test_policy.xml"); + /** + * The file location of the policy with full access to all attributes. + **/ + public static final PolicyLocation POLICY_FULL = PolicyLocation.make("policy_full", "/xml/policies/policy_full.xml"); + /** + * The file location of the policy with full access to all attributes. + **/ + public static final PolicyLocation POLICY_LIGHT = PolicyLocation.make("policy_light", "/xml/policies/policy_light.xml"); + /** + * The file location of the policy with minimal content, that still performs nomenclature resolution tests. + **/ + public static final PolicyLocation BOM_POLICY = PolicyLocation.make("bom_policy", "/xml/policies/bom_policy.xml"); + /** + * The file location of the full policy for a R01 report. + **/ + public static final PolicyLocation R01_POLICY_FULL = PolicyLocation.make("R01_policy_full", "/xml/policies/r01report/R01_policy_full.xml"); + /** + * The file location of the light policy for a R01 report. + **/ + public static final PolicyLocation R01_POLICY_LIGHT = PolicyLocation.make("R01_policy_light", "/xml/policies/r01report/R01_policy_light.xml"); + /** + * The file location of the full policy for a R03 report. + **/ + public static final PolicyLocation R03_POLICY_FULL = PolicyLocation.make("R03_policy_full", "/xml/policies/r03report/R03_policy_full.xml"); + /** + * The file location of the light policy for a R03 report. + **/ + public static final PolicyLocation R03_POLICY_LIGHT = PolicyLocation.make("R03_policy_light", "/xml/policies/r03report/R03_policy_light.xml"); + /** + * The file location of the full policy for a R03 report. + **/ + public static final PolicyLocation R07_POLICY_FULL = PolicyLocation.make("R07_policy_full", "/xml/policies/r07report/R07_policy_full.xml"); + /** + * The file location of the light policy for a R03 report. + **/ + public static final PolicyLocation R07_POLICY_LIGHT = PolicyLocation.make("R07_policy_light", "/xml/policies/r07report/R07_policy_light.xml"); + /** + * The file location of the full policy for a R10 report. + **/ + public static final PolicyLocation R10_POLICY_FULL = PolicyLocation.make("R10_policy_full", "/xml/policies/r10report/R10_policy_full.xml"); + /** + * The file location of the light policy for a R10 report. + **/ + public static final PolicyLocation R10_POLICY_LIGHT = PolicyLocation.make("R10_policy_light", "/xml/policies/r10report/R10_policy_light.xml"); + /** + * The file location of the full policy for a R11 report. + **/ + public static final PolicyLocation R11_POLICY_FULL = PolicyLocation.make("R11_policy_full", "/xml/policies/r11report/R11_policy_full.xml"); + /** + * The file location of the light policy for a R11 report. + **/ + public static final PolicyLocation R11_POLICY_LIGHT = PolicyLocation.make("R11_policy_light", "/xml/policies/r11report/R11_policy_light.xml"); + /** + * The file location of the full policy for a R13 report. + **/ + public static final PolicyLocation R13_POLICY_FULL = PolicyLocation.make("R13_policy_full", "/xml/policies/r13report/R13_policy_full.xml"); + /** + * The file location of the light policy for a R13 report. + **/ + public static final PolicyLocation R13_POLICY_LIGHT = PolicyLocation.make("R13_policy_light", "/xml/policies/r13report/R13_policy_light.xml"); + /** + * The file location of the full policy for a R15 report. + **/ + public static final PolicyLocation R15_POLICY_FULL = PolicyLocation.make("R15_policy_full", "/xml/policies/r15report/R15_policy_full.xml"); + /** + * The file location of the light policy for a R15 report. + **/ + public static final PolicyLocation R15_POLICY_LIGHT = PolicyLocation.make("R15_policy_light", "/xml/policies/r15report/R15_policy_light.xml"); + /** + * The file location of the full policy for a R16 report. + **/ + public static final PolicyLocation R16_POLICY_FULL = PolicyLocation.make("R16_policy_full", "/xml/policies/r16report/R16_policy_full.xml"); + /** + * The file location of the light policy for a R16 report. + **/ + public static final PolicyLocation R16_POLICY_LIGHT = PolicyLocation.make("R16_policy_light", "/xml/policies/r16report/R16_policy_light.xml"); + /** + * The file location of the full policy for a R17 report. + **/ + public static final PolicyLocation R17_POLICY_FULL = PolicyLocation.make("R17_policy_full", "/xml/policies/r17report/R17_policy_full.xml"); + /** + * The file location of the light policy for a R17 report. + **/ + public static final PolicyLocation R17_POLICY_LIGHT = PolicyLocation.make("R17_policy_light", "/xml/policies/r17report/R17_policy_light.xml"); + /** + * The file location of the full policy for a R19 report. + **/ + public static final PolicyLocation R19_POLICY_FULL = PolicyLocation.make("R19_policy_full", "/xml/policies/r19report/R19_policy_full.xml"); + /** + * The file location of the light policy for a R19 report. + **/ + public static final PolicyLocation R19_POLICY_LIGHT = PolicyLocation.make("R19_policy_light", "/xml/policies/r19report/R19_policy_light.xml"); + /** + * The file location of the full policy for a R20 report. + **/ + public static final PolicyLocation R20_POLICY_FULL = PolicyLocation.make("R20_policy_full", "/xml/policies/r20report/R20_policy_full.xml"); + /** + * The file location of the light policy for a R20 report. + **/ + public static final PolicyLocation R20_POLICY_LIGHT = PolicyLocation.make("R20_policy_light", "/xml/policies/r20report/R20_policy_light.xml"); + /** + * The file location of the full policy for a R21 report. + **/ + public static final PolicyLocation R21_POLICY_FULL = PolicyLocation.make("R21_policy_full", "/xml/policies/r21report/R21_policy_full.xml"); + /** + * The file location of the light policy for a R21 report. + **/ + public static final PolicyLocation R21_POLICY_LIGHT = PolicyLocation.make("R21_policy_light", "/xml/policies/r21report/R21_policy_light.xml"); + /** + * The file location of the full policy for a R22 report. + **/ + public static final PolicyLocation R22_POLICY_FULL = PolicyLocation.make("R22_policy_full", "/xml/policies/r22report/R22_policy_full.xml"); + /** + * The file location of the light policy for a R22 report. + **/ + public static final PolicyLocation R22_POLICY_LIGHT = PolicyLocation.make("R22_policy_light", "/xml/policies/r22report/R22_policy_light.xml"); + + /** + * Flag to only build the objects once. + **/ + private static boolean isPolicySetup; + + private static boolean isChangeSession; + + private static TcSession session; + + /** + * Opens a connection. May fail if the default policy (policy_full.xml) does not exist on the TC server + * + * @return the session + * @throws NoTeamcenterConnectionException Should not happen + */ + public static TcSession getSession() throws NoTeamcenterConnectionException { + if (session == null) { + // Check the duration between current login and the previous one + long theCurrentTimestamp = System.currentTimeMillis(); + if (theCurrentTimestamp < lastLogInTimeMs + LOGIN_DELAY) { + long theWaitDuration = lastLogInTimeMs + LOGIN_DELAY - theCurrentTimestamp; + log.info("Waiting for next login retry in order to wait during the TCServer initialization: " + theWaitDuration + "ms"); + try { + Thread.sleep(theWaitDuration); + } catch (InterruptedException e) { + log.error("Sleep interrupted", e); + } + } + + // Save the current login time + lastLogInTimeMs = System.currentTimeMillis(); + + // Create the session (login is performed) + session = new TcSession(); + session.login(); + try { + session.setObjectPropPolicy(POLICY_FULL); + } catch (InvalidConfigurationException e) { + throw new RuntimeException("Unable to load properties", e); + } + } + return session; + } + + /** + * Cleanly close the connection. + * + * @throws ServiceException Should not happen + */ + @AfterClass + public static void logoutTeamcenter() throws ServiceException { + // Try to log out the current session + if (session == null) { + log.error("No session handle found to close the session. The session may not have been closed."); + } else { + session.close(); + } + } + + /** + * Declares the location of the property policy to be used throughout the daughter class's unit Tests.
    + * A default policy file location is provided by this class in the static constant DEFAULT_POLICY. + * + * @return the relative location of the property policy file. + */ + public abstract PolicyLocation getPropertyPolicyIdentifier(); + +} diff --git a/teamcenter/src/test/java/com/capgemini/reports/ScenarioForTests.java b/teamcenter/src/test/java/com/capgemini/reports/ScenarioForTests.java new file mode 100644 index 0000000..0900356 --- /dev/null +++ b/teamcenter/src/test/java/com/capgemini/reports/ScenarioForTests.java @@ -0,0 +1,101 @@ +package com.capgemini.reports; + +/** + * Enumeration of different scenarios.
    + * Used for tests. + **/ +public enum ScenarioForTests { + /** + * Normal test. + */ + TEST_N24( + "N24", + "24N", + "35R0", + "60", + "/serialization/n24-24n/serialN24etudeMono.ser", + "/serialization/n24-24n/serialN24etudeMulti.ser", + "/serialization/n24-24n/serial24NassembMono.ser", + "/serialization/n24-24n/serial24NassembMulti.ser"), + /** + * Large test. + */ + TEST_U22( + "U22", + "22U", + "97R0", + "550", + "/serialization/u22-22u/serialU22etudeMono.ser", + "/serialization/u22-22u/serialU22etudeMulti.ser", + "/serialization/u22-22u/serial22UassembMono.ser", + "/serialization/u22-22u/serial22UassembMulti.ser"), + /** + * Tiny test. + */ + TEST_E24( + "E24", + "24E", + "30E0", + "20", + "/serialization/e24-24e/serialE24etudeMono.ser", + "/serialization/e24-24e/serialE24etudeMulti.ser", + "/serialization/e24-24e/serial24EassembMono.ser", + "/serialization/e24-24e/serial24EassembMulti.ser"), + /** + * Small test. + */ + TEST_U24( + "U24", + "24U", + "35R0", + "60", + "/serialization/u24-24u/serialU24etudeMono.ser", + "/serialization/u24-24u/serialU24etudeMulti.ser", + "/serialization/u24-24u/serial24UassembMono.ser", + "/serialization/u24-24u/serial24UassembMulti.ser"); + + /** + * The id of the Generic. + */ + public final String generic; + /** + * The id of the Generic Assemb. + */ + public final String genericAssemb; + /** + * The id of the Product. + */ + public final String product; + /** + * The unit. + */ + public final String unit; + /** + * The file of Technical view for deserialization in Mono. + */ + public final String fileTechnicalMono; + /** + * The file of Technical view for deserialization in Multi. + */ + public final String fileTechnicalMulti; + /** + * The file of Assembly view for deserialization in Mono. + */ + public final String fileAssembMono; + /** + * The file of Assembly view for deserialization in Multi. + */ + public final String fileAssembMulti; + + ScenarioForTests(final String generic, final String genericAssemb, final String product, final String unit, + final String fileTechnicalMono, final String fileTechnicalMulti, final String fileAssembMono, final String fileAssembMulti) { + this.product = product; + this.generic = generic; + this.genericAssemb = genericAssemb; + this.unit = unit; + this.fileTechnicalMono = fileTechnicalMono; + this.fileTechnicalMulti = fileTechnicalMulti; + this.fileAssembMono = fileAssembMono; + this.fileAssembMulti = fileAssembMulti; + } +} diff --git a/teamcenter/src/test/java/com/capgemini/reports/TeamcenterTypeObjectsTest.java b/teamcenter/src/test/java/com/capgemini/reports/TeamcenterTypeObjectsTest.java new file mode 100644 index 0000000..4b71229 --- /dev/null +++ b/teamcenter/src/test/java/com/capgemini/reports/TeamcenterTypeObjectsTest.java @@ -0,0 +1,78 @@ +package com.capgemini.reports; + +import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes; +import lombok.extern.slf4j.Slf4j; +import org.junit.Assert; +import org.junit.Test; + + +@Slf4j +public class TeamcenterTypeObjectsTest { + + + @Test + public void testIsPart() { + log.info("Testing pattern: '{}'", SnecmaObjectTypes.PART_REVISION_PATTERN.pattern()); + + // Success + Assert.assertTrue(SnecmaObjectTypes.isPartRevision("Alternate Revision")); + Assert.assertTrue(SnecmaObjectTypes.isPartRevision("DET Revision")); + Assert.assertTrue(SnecmaObjectTypes.isPartRevision("Part Aero Revision")); + Assert.assertTrue(SnecmaObjectTypes.isPartRevision("Part Assemb Revision")); + Assert.assertTrue(SnecmaObjectTypes.isPartRevision("Part Mat Revision")); + Assert.assertTrue(SnecmaObjectTypes.isPartRevision("Part No Aero Revision")); + Assert.assertTrue(SnecmaObjectTypes.isPartRevision("Standard Revision")); + + // Fails + Assert.assertFalse(SnecmaObjectTypes.isPartRevision(SnecmaObjectTypes.GENERIC_REVISION)); + Assert.assertFalse(SnecmaObjectTypes.isPartRevision("Altrnate Revision")); // misspelled on purpose + Assert.assertFalse(SnecmaObjectTypes.isPartRevision("Alternate")); // Item + Assert.assertFalse(SnecmaObjectTypes.isPartRevision("Alternate Revision Master")); // Master + } + + + @Test + public void testIsAltOrDet() { + log.info("Testing pattern: '{}'", SnecmaObjectTypes.ALT_OR_DET_PATTERN.pattern()); + + // Success + Assert.assertTrue(SnecmaObjectTypes.isAltOrDet("Alternate Revision")); + Assert.assertTrue(SnecmaObjectTypes.isAltOrDet("DET Revision")); + + // Fails + Assert.assertFalse(SnecmaObjectTypes.isAltOrDet("Part Aero Revision")); + Assert.assertFalse(SnecmaObjectTypes.isAltOrDet("Part Assemb Revision")); + Assert.assertFalse(SnecmaObjectTypes.isAltOrDet("Part Mat Revision")); + Assert.assertFalse(SnecmaObjectTypes.isAltOrDet("Part No Aero Revision")); + Assert.assertFalse(SnecmaObjectTypes.isAltOrDet("Standard Revision")); + Assert.assertFalse(SnecmaObjectTypes.isAltOrDet(SnecmaObjectTypes.GENERIC_REVISION)); + Assert.assertFalse(SnecmaObjectTypes.isAltOrDet("Altrnate Revision")); // misspelled on purpose + Assert.assertFalse(SnecmaObjectTypes.isAltOrDet("Alternate")); // Item + Assert.assertFalse(SnecmaObjectTypes.isAltOrDet("Alternate Revision Master")); // Master + } + + + @Test + public void testIsA() { + log.info("Testing pattern: '{}'", SnecmaObjectTypes.PART_REVISION_PATTERN.pattern()); + + // Success + Assert.assertTrue(SnecmaObjectTypes.isA("Alternate Revision", SnecmaObjectTypes.ALTERNATE_REVISION)); + Assert.assertTrue(SnecmaObjectTypes.isA("Alternate Revision", SnecmaObjectTypes.ALTERNATE_REVISION, + SnecmaObjectTypes.PART_AERO_REVISION, SnecmaObjectTypes.PART_NO_AERO_REVISION, SnecmaObjectTypes.PART_ASSEMB_REVISION, + SnecmaObjectTypes.PART_MAT_REVISION, SnecmaObjectTypes.DET_REVISION, SnecmaObjectTypes.STANDARD_REVISION)); + Assert.assertTrue(SnecmaObjectTypes.isA("Part Aero Revision", SnecmaObjectTypes.ALTERNATE_REVISION, + SnecmaObjectTypes.PART_AERO_REVISION, SnecmaObjectTypes.PART_NO_AERO_REVISION, SnecmaObjectTypes.PART_ASSEMB_REVISION, + SnecmaObjectTypes.PART_MAT_REVISION, SnecmaObjectTypes.DET_REVISION, SnecmaObjectTypes.STANDARD_REVISION)); + + // Fails + Assert.assertFalse(SnecmaObjectTypes.isA("Altrnate Revision", SnecmaObjectTypes.ALTERNATE_REVISION)); // misspelled on purpose + Assert.assertFalse(SnecmaObjectTypes.isA("Alternate Revision Master", SnecmaObjectTypes.ALTERNATE_REVISION)); // master + Assert.assertFalse(SnecmaObjectTypes.isA("Alternate Master", SnecmaObjectTypes.ALTERNATE_REVISION)); // master + Assert.assertFalse(SnecmaObjectTypes.isA("Alternate", SnecmaObjectTypes.ALTERNATE_REVISION)); // item + Assert.assertFalse(SnecmaObjectTypes.isA("Alternate Revision", SnecmaObjectTypes.PART_AERO_REVISION, + SnecmaObjectTypes.PART_NO_AERO_REVISION, SnecmaObjectTypes.PART_ASSEMB_REVISION, SnecmaObjectTypes.PART_MAT_REVISION, + SnecmaObjectTypes.DET_REVISION, SnecmaObjectTypes.STANDARD_REVISION)); // alt is not there + } + +} diff --git a/teamcenter/src/test/java/com/capgemini/reports/changeobjects/AbstractChangeObjectTest.java b/teamcenter/src/test/java/com/capgemini/reports/changeobjects/AbstractChangeObjectTest.java new file mode 100644 index 0000000..2649a2f --- /dev/null +++ b/teamcenter/src/test/java/com/capgemini/reports/changeobjects/AbstractChangeObjectTest.java @@ -0,0 +1,103 @@ +package com.capgemini.reports.changeobjects; + +import com.capgemini.framework.teamcenter.exceptions.NoTeamcenterConnectionException; +import com.capgemini.framework.teamcenter.object.pom.status.TcReleaseStatus; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.framework.teamcenter.queries.saved.modelobject.ItemRevisionQuery; +import com.capgemini.reports.AbstractTeamcenterTest; +import com.capgemini.reports.changeobjects.change.TcChangeNoticeRevision; +import com.capgemini.reports.changeobjects.change.TcChangeRequestRevision; +import com.capgemini.reports.snecmaobjects.generic.AbstractGeneric; +import com.capgemini.reports.teamcenter.queries.saved.ChangeRequestQuery; +import com.capgemini.reports.workflows.Task; +import com.teamcenter.schemas.soa._2006_03.exceptions.ServiceException; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import junit.framework.Assert; +import org.junit.Test; + +import java.util.List; + + +public class AbstractChangeObjectTest extends AbstractTeamcenterTest { + + @Test + public void testLigneProduit() throws ServiceException, NoTeamcenterConnectionException { + ItemRevisionQuery query = new ItemRevisionQuery(getSession()); + query.searchID("MOD200281"); + query.searchType("PV4_ETU_ANTICIPRevision"); // Making sure we don't obtain the (deprecated) EngChange with the same name + ItemRevision MOD200281 = query.findAll().get(0); + TcChangeNoticeRevision changeRequest = new TcChangeNoticeRevision(getSession(), MOD200281); + Assert.assertNotNull("pv4_ligne_produit was not loaded on the Change!", changeRequest.getLignesProduit()); + Assert.assertFalse("pv4_ligne_poduit was empty", changeRequest.getLignesProduit().isEmpty()); + Assert.assertEquals("pv4_ligne_poduit did not contain the expected element", "ATAR 08K50 ETAT", changeRequest.getLignesProduit().get(0)); + } + + @Test + public void testActorStatusOnTask() throws ServiceException, NoTeamcenterConnectionException { + ChangeRequestQuery query = new ChangeRequestQuery(getSession()); + query.searchID("MOD200411"); + ItemRevision crMOD20411_AA = query.findAll().get(0); + TcChangeRequestRevision changeRequest = new TcChangeRequestRevision(getSession(), crMOD20411_AA); + Assert.assertNotNull(changeRequest.getWkfList()); + Assert.assertFalse(changeRequest.getWkfList().isEmpty()); // Should be 1 workflow with 1 active task + Task wkf = changeRequest.getWkfList().get(0); + Assert.assertNotNull(wkf); + Assert.assertFalse(wkf.getActiveChildTasks().isEmpty()); + } + + @Test + public void testChangeWithOrWithoutRupture() throws ServiceException, NoTeamcenterConnectionException { + ItemRevisionQuery query = new ItemRevisionQuery(getSession()).searchID("Change952"); + ItemRevision r201_051 = query.findAll().get(0); + TcChangeRequestRevision changeRequest = new TcChangeRequestRevision(getSession(), r201_051); + List without = changeRequest.getListOfGenericRevWithOrWithoutRupture(); + Assert.assertNotNull(without); + Assert.assertFalse(without.isEmpty()); + Assert.assertNotNull(without.get(0)); + } + + @Test + public void testReleaseStatusWithMaturity() throws ServiceException, NoTeamcenterConnectionException { + ChangeRequestQuery query = new ChangeRequestQuery(getSession()); + query.searchID("MOD200497"); + ItemRevision crMOD200497 = query.findAll().get(0); + TcChangeRequestRevision changeRequest = new TcChangeRequestRevision(getSession(), crMOD200497); + Assert.assertFalse(changeRequest.getReleaseStatusContainingEffectivity().isEmpty()); + for (TcReleaseStatus status : changeRequest.getReleaseStatusContainingEffectivity()) { + Assert.assertNotNull(status); + Assert.assertTrue(status.isEffectivity()); + Assert.assertFalse(status.isChangeMaturity()); + } + Assert.assertFalse(changeRequest.getReleaseStatusContainingMaturity().isEmpty()); + for (TcReleaseStatus status : changeRequest.getReleaseStatusContainingMaturity()) { + Assert.assertNotNull(status); + Assert.assertTrue(status.isChangeMaturity()); + Assert.assertFalse(status.isEffectivity()); + } + } + + @Test + public void testReleaseStatusWithInterfaceTODO() throws ServiceException, NoTeamcenterConnectionException { + ChangeRequestQuery query = new ChangeRequestQuery(getSession()); + query.searchID("MOD200330"); + ItemRevision crMOD200497 = query.findAll().get(0); + TcChangeRequestRevision changeRequest = new TcChangeRequestRevision(getSession(), crMOD200497); + Assert.assertFalse(changeRequest.getReleaseStatusContainingEffectivity().isEmpty()); + for (TcReleaseStatus status : changeRequest.getReleaseStatusContainingEffectivity()) { + Assert.assertNotNull(status); + Assert.assertTrue(status.isEffectivity()); + Assert.assertFalse(status.isChangeMaturity()); + } + Assert.assertFalse(changeRequest.getReleaseStatusContainingMaturity().isEmpty()); + for (TcReleaseStatus status : changeRequest.getReleaseStatusContainingMaturity()) { + Assert.assertNotNull(status); + Assert.assertTrue(status.isChangeMaturity()); + Assert.assertFalse(status.isEffectivity()); + } + } + + @Override + public PolicyLocation getPropertyPolicyIdentifier() { + return R13_POLICY_FULL; + } +} diff --git a/teamcenter/src/test/java/com/capgemini/reports/changeobjects/UnitRevisionTest.java b/teamcenter/src/test/java/com/capgemini/reports/changeobjects/UnitRevisionTest.java new file mode 100644 index 0000000..d95ee81 --- /dev/null +++ b/teamcenter/src/test/java/com/capgemini/reports/changeobjects/UnitRevisionTest.java @@ -0,0 +1,215 @@ +package com.capgemini.reports.changeobjects; + +import com.capgemini.framework.common.TeamcenterDateFormatter; +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.exceptions.NoTeamcenterConnectionException; +import com.capgemini.framework.teamcenter.object.pom.status.StatusEnum; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.framework.teamcenter.queries.saved.modelobject.ItemRevisionQuery; +import com.capgemini.reports.AbstractTeamcenterTest; +import com.capgemini.reports.changeobjects.change.TcChangeRequestRevision; +import com.capgemini.reports.snecmaobjects.product.ProductRevision; +import com.capgemini.reports.teamcenter.queries.saved.UnitQuery; +import com.capgemini.reports.workflows.Task; +import com.teamcenter.schemas.soa._2006_03.exceptions.ServiceException; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import lombok.extern.slf4j.Slf4j; +import org.junit.Assert; +import org.junit.Test; + +import java.util.List; + + +@Slf4j +public class UnitRevisionTest extends AbstractTeamcenterTest { + + private static final String UNIT_REV = "C"; + private static final String UNIT_ID = "MOD163427"; + private static final String UNIT_ID_WITH_GEL = "MOD120174";// "MOD143898"; // This one has a Workflow attached which is a 'Gel de Unit' + private static final String UNIT_ID_WITH_SO_CURRENT = "00041717"; // This one is currently going through a 'Unit-Validation UNIT par Services officiels' Workflow + private static final String UNIT_ID_WITH_SO_FINISHED = "00041694"; // This one has fully gone through a 'Unit-Validation UNIT par Services officiels' Workflow + + /** + * JUnit test. + * + * @throws NoTeamcenterConnectionException should not happen + */ + @Test + public void unitRevisionTest() throws NoTeamcenterConnectionException { + // Obtain the itemRev + List results = new ItemRevisionQuery(getSession()).searchIDAndRevision(UNIT_ID, UNIT_REV).findAll(); + Assert.assertFalse(results.isEmpty()); + ItemRevision tcUnit = results.get(0); + // Build It + UnitRevision unit = UnitRevision.build(getSession(), tcUnit); + + // Test it + Assert.assertNotNull(unit.getItemId()); + log.info("getItemId= " + unit.getItemId()); + Assert.assertEquals(UNIT_ID, unit.getItemId()); + + Assert.assertNotNull(unit.getName()); + log.info("getName= " + unit.getName()); + Assert.assertFalse(unit.getName().isEmpty()); + + Assert.assertNotNull(unit.getRevision()); + log.info("getRevision= " + unit.getRevision()); + Assert.assertEquals(UNIT_REV, unit.getRevision()); + + Assert.assertNotNull(unit.getType()); + log.info("getType= " + unit.getType()); + Assert.assertFalse(unit.getType().isEmpty()); + + Assert.assertNotNull(unit.getUid()); + log.info("getUid= " + unit.getUid()); + Assert.assertFalse(unit.getUid().isEmpty()); + + Assert.assertNotNull(unit.getUnitRange()); + log.info("unitRange= " + unit.getUnitRange()); + Assert.assertFalse(unit.getUnitRange().isEmpty()); + + log.info("isExceptionnel= " + unit.isExceptionnel()); + Assert.assertTrue(unit.isExceptionnel()); + + // Change request + Assert.assertNotNull(unit.getChangeRequestsList()); + log.info("getChangeRequestsList= " + unit.getChangeRequestsList()); + Assert.assertFalse(unit.getChangeRequestsList().isEmpty()); + for (TcChangeRequestRevision request : unit.getChangeRequestsList()) { + log.info(" + TcChangeRequestRevision ID = {}, Rev={}", request.getItemId(), request.getRevisionId()); + } + + // Generics + Assert.assertNotNull(unit.getGenerics()); + log.info("getGenerics= " + unit.getGenerics()); + Assert.assertFalse(unit.getGenerics().isEmpty()); + // Release status + Assert.assertNotNull(unit.getReleaseStatusContainingMaturity()); + log.info("getReleaseStatusContainingMaturity = " + unit.getReleaseStatusContainingMaturity()); + Assert.assertFalse(unit.getReleaseStatusContainingMaturity().isEmpty()); // there should be some maturity status + Assert.assertNotNull(unit.getTechnicalDocGel()); + log.info("getTechnicalDocGel = " + unit.getTechnicalDocGel()); + } + + /** + * JUnit test for max query size. + * + * @throws ServiceException should not happen + * @throws KurtException should not happen + */ + @Test + public void testUnitExceptionnel() throws ServiceException, KurtException { + getSession().setObjectPropPolicy(R20_POLICY_LIGHT); + // Fetch an EXCEPTIONAL Unit + List result = new UnitQuery(getSession()).searchID("00065685").findAll(); + ItemRevision unit = result.get(0); + // Build it + UnitRevision builtUnit = UnitRevision.build(getSession(), unit); + // Now test it + Assert.assertTrue(builtUnit.isExceptionnel()); + } + + /** + * JUnit test for max query size. + * + * @throws ServiceException should not happen + * @throws KurtException should not happen + */ + @Test + public void testUnit87() throws ServiceException, KurtException { + List result = new UnitQuery(getSession()).addEndItemID("35R0").findAll(); + Assert.assertTrue(result.size() > 50); + } + + /** + * JUnit test. + * + * @throws NoTeamcenterConnectionException should not happen + */ + @Test + public void loadWorkflowsValidationUnitParSOTest() throws NoTeamcenterConnectionException { + List results = new ItemRevisionQuery(getSession()).searchIDAndRevision(UNIT_ID_WITH_SO_FINISHED, "A").findAll(); + Assert.assertFalse(results.isEmpty()); + ItemRevision tcUnit = results.get(0); + UnitRevision unit = UnitRevision.build(getSession(), tcUnit); + + log.info("Building workflows..."); + Assert.assertFalse(unit.getWorkflowsValidationUnitParSO().isEmpty()); + + log.info("Browsing {} workflows", unit.getWorkflowsValidationUnitParSO().size()); + for (Task task : unit.getWorkflowsValidationUnitParSO()) { + Assert.assertNotNull(task); + String lastModDate = TeamcenterDateFormatter.formatCalendarToFrench(task.getLastModDate()); + String creationDate = TeamcenterDateFormatter.formatCalendarToFrench(task.getCreationDate()); + String owner = task.getOwningUser() == null ? null : task.getOwningUser().getName(); + String validator = task.getLastModUser() == null ? null : task.getLastModUser().getName(); + } + } + + /** + * JUnit test. + * + * @throws NoTeamcenterConnectionException should not happen + */ + @Test + public void loadWorkflowsValidationUnitParSOTestCURRENT() throws NoTeamcenterConnectionException { + List results = new ItemRevisionQuery(getSession()).searchIDAndRevision(UNIT_ID_WITH_SO_CURRENT, "A").findAll(); + Assert.assertFalse(results.isEmpty()); + ItemRevision tcUnit = results.get(0); + UnitRevision unit = UnitRevision.build(getSession(), tcUnit); + + log.info("Building workflows..."); + Assert.assertFalse(unit.getWorkflowsValidationUnitParSO().isEmpty()); + + log.info("Browsing {} workflows", unit.getWorkflowsValidationUnitParSO().size()); + for (Task task : unit.getWorkflowsValidationUnitParSO()) { + Assert.assertNotNull(task); + String lastModDate = TeamcenterDateFormatter.formatCalendarToFrench(task.getLastModDate()); + String creationDate = TeamcenterDateFormatter.formatCalendarToFrench(task.getCreationDate()); + String owner = task.getOwningUser() == null ? null : task.getOwningUser().getName(); + String validator = task.getLastModUser() == null ? null : task.getLastModUser().getName(); + } + } + + @Test + public void unitRevisionTestGel() throws NoTeamcenterConnectionException { + List results = new ItemRevisionQuery(getSession()).searchIDAndRevision(UNIT_ID_WITH_GEL, "D").findAll(); + Assert.assertFalse(results.isEmpty()); + ItemRevision tcUnit = results.get(0); + UnitRevision unit = UnitRevision.build(getSession(), tcUnit); + log.info("getItemId= " + unit.getItemId()); + Assert.assertNotNull(unit.getItemId()); + Assert.assertEquals(UNIT_ID_WITH_GEL, unit.getItemId()); + + Assert.assertNotNull(unit.getTechnicalDocGel()); + } + + @Test + public void testChooseRevisionOfUnitFromRange() throws NoTeamcenterConnectionException { + // Configuration + String productId = "29R0"; + String productRevisionId = "B"; + String range = "240"; + + // Query + List productRevisions = + new ItemRevisionQuery(getSession()).searchIDAndRevision(productId, productRevisionId).findAll(); + + // Build objects + ProductRevision product = new ProductRevision(getSession(), productRevisions.get(0)); + + // Method to test + UnitRevision result = UnitRevision.chooseRevisionOfUnitFromRange(range, product.getUnits(), StatusEnum.J3B); + + // Checks + Assert.assertNotNull(result); + Assert.assertEquals("Id is not equals to the expected value.", "MOD113586", result.getItemId()); + Assert.assertEquals("RevisionId is not equals to the expected value.", "E", result.getRevision()); + } + + @Override + public PolicyLocation getPropertyPolicyIdentifier() { + return R20_POLICY_FULL; + } + +} diff --git a/teamcenter/src/test/java/com/capgemini/reports/documentationobjects/DocDrawingTest.java b/teamcenter/src/test/java/com/capgemini/reports/documentationobjects/DocDrawingTest.java new file mode 100644 index 0000000..e661ae5 --- /dev/null +++ b/teamcenter/src/test/java/com/capgemini/reports/documentationobjects/DocDrawingTest.java @@ -0,0 +1,36 @@ +package com.capgemini.reports.documentationobjects; + +import com.capgemini.framework.teamcenter.exceptions.NoTeamcenterConnectionException; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.framework.teamcenter.queries.saved.modelobject.ItemRevisionQuery; +import com.capgemini.reports.AbstractTeamcenterTest; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import org.junit.Assert; +import org.junit.Test; + +import java.util.List; + +public class DocDrawingTest extends AbstractTeamcenterTest { + private final String id = "00037481"; + private final String revision = "--A"; + private final String name = "00037481"; + private final String designationEN = "FAN CASE"; + private final String indicePlan = "-A"; + + @Test + public void testBuild() throws NoTeamcenterConnectionException { + List results = new ItemRevisionQuery(getSession()).searchIDAndRevision(id, revision).findAll(); + DocDrawing test = new DocDrawing(getSession(), results.get(0)); + Assert.assertNotNull(test); + Assert.assertEquals(id, test.getDocId()); + Assert.assertEquals(revision, test.getRevision()); + Assert.assertEquals(name, test.getName()); + Assert.assertEquals(designationEN, test.getDesignationEn()); + Assert.assertEquals(indicePlan, test.getIndicePlan()); + } + + @Override + public PolicyLocation getPropertyPolicyIdentifier() { + return R15_POLICY_FULL; + } +} diff --git a/teamcenter/src/test/java/com/capgemini/reports/documentationobjects/DocGeometryTest.java b/teamcenter/src/test/java/com/capgemini/reports/documentationobjects/DocGeometryTest.java new file mode 100644 index 0000000..65aba07 --- /dev/null +++ b/teamcenter/src/test/java/com/capgemini/reports/documentationobjects/DocGeometryTest.java @@ -0,0 +1,37 @@ +package com.capgemini.reports.documentationobjects; + +import com.capgemini.framework.teamcenter.exceptions.NoTeamcenterConnectionException; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.framework.teamcenter.queries.saved.modelobject.ItemRevisionQuery; +import com.capgemini.reports.AbstractTeamcenterTest; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import org.junit.Assert; +import org.junit.Test; + +import java.util.List; + +public class DocGeometryTest extends AbstractTeamcenterTest { + + private final String id = "DOC-00237937"; + private final String revision = "--A"; + private final String name = "DOC-00237937"; + private final String designationEN = "WASHERS"; + private final String indiceCartouche = ""; + + @Test + public void testBuild() throws NoTeamcenterConnectionException { + List results = new ItemRevisionQuery(getSession()).searchIDAndRevision(id, revision).findAll(); + DocGeometry test = new DocGeometry(getSession(), results.get(0)); + Assert.assertNotNull(test); + Assert.assertEquals(id, test.getDocId()); + Assert.assertEquals(revision, test.getRevision()); + Assert.assertEquals(name, test.getName()); + Assert.assertEquals(designationEN, test.getDesignationEN()); + Assert.assertEquals(indiceCartouche, test.getIndiceCartouche()); + } + + @Override + public PolicyLocation getPropertyPolicyIdentifier() { + return R15_POLICY_FULL; + } +} diff --git a/teamcenter/src/test/java/com/capgemini/reports/documentationobjects/DocNormStandardTest.java b/teamcenter/src/test/java/com/capgemini/reports/documentationobjects/DocNormStandardTest.java new file mode 100644 index 0000000..6f74402 --- /dev/null +++ b/teamcenter/src/test/java/com/capgemini/reports/documentationobjects/DocNormStandardTest.java @@ -0,0 +1,37 @@ +package com.capgemini.reports.documentationobjects; + +import com.capgemini.framework.teamcenter.exceptions.NoTeamcenterConnectionException; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.framework.teamcenter.queries.saved.modelobject.ItemRevisionQuery; +import com.capgemini.reports.AbstractTeamcenterTest; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import org.junit.Assert; +import org.junit.Test; + +import java.util.List; + +public class DocNormStandardTest extends AbstractTeamcenterTest { + + private final String id = "000155"; + private final String revision = "A"; + private final String name = "RACCORD A BRIDE A SOUDER"; + private final String designationEN = "-"; + private final String idOrigine = "649-491-010/032-0"; + + @Test + public void testBuild() throws NoTeamcenterConnectionException { + List results = new ItemRevisionQuery(getSession()).searchIDAndRevision(id, revision).findAll(); + DocNormStandard test = new DocNormStandard(getSession(), results.get(0)); + Assert.assertNotNull(test); + Assert.assertEquals(id, test.getDocId()); + Assert.assertEquals(revision, test.getRevision()); + Assert.assertEquals(name, test.getName()); + Assert.assertEquals(designationEN, test.getDesignationEn()); + Assert.assertEquals(idOrigine, test.getIdOrigine()); + } + + @Override + public PolicyLocation getPropertyPolicyIdentifier() { + return R15_POLICY_FULL; + } +} diff --git a/teamcenter/src/test/java/com/capgemini/reports/documentationobjects/DocNormTest.java b/teamcenter/src/test/java/com/capgemini/reports/documentationobjects/DocNormTest.java new file mode 100644 index 0000000..e4d7df6 --- /dev/null +++ b/teamcenter/src/test/java/com/capgemini/reports/documentationobjects/DocNormTest.java @@ -0,0 +1,40 @@ +package com.capgemini.reports.documentationobjects; + +import com.capgemini.framework.teamcenter.exceptions.NoTeamcenterConnectionException; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.framework.teamcenter.queries.saved.modelobject.ItemRevisionQuery; +import com.capgemini.reports.AbstractTeamcenterTest; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import org.junit.Assert; +import org.junit.Test; + +import java.util.List; + +public class DocNormTest extends AbstractTeamcenterTest { + + private final String id = "000189"; + private final String revision = "A"; + private final String name = "PLAN SUPPORT"; + private final String designationEN = "-"; + private final String idOrigine = "PLAN-888-370-100-104"; + private final String securite = ""; + + @Test + public void testBuild() throws NoTeamcenterConnectionException { + List results = new ItemRevisionQuery(getSession()).searchIDAndRevision(id, revision).findAll(); + Assert.assertFalse(results.isEmpty()); + DocNorm test = new DocNorm(getSession(), results.get(0)); + Assert.assertNotNull(test); + Assert.assertEquals(id, test.getDocId()); + Assert.assertEquals(revision, test.getRevision()); + Assert.assertEquals(name, test.getName()); + Assert.assertEquals(designationEN, test.getDesignationEn()); + Assert.assertEquals(idOrigine, test.getIdOrigine()); + Assert.assertEquals(securite, test.getSensibiliteSecurite()); + } + + @Override + public PolicyLocation getPropertyPolicyIdentifier() { + return R15_POLICY_FULL; + } +} diff --git a/teamcenter/src/test/java/com/capgemini/reports/documentationobjects/DocTechnicTest.java b/teamcenter/src/test/java/com/capgemini/reports/documentationobjects/DocTechnicTest.java new file mode 100644 index 0000000..bd9197f --- /dev/null +++ b/teamcenter/src/test/java/com/capgemini/reports/documentationobjects/DocTechnicTest.java @@ -0,0 +1,51 @@ +package com.capgemini.reports.documentationobjects; + +import com.capgemini.framework.teamcenter.exceptions.NoTeamcenterConnectionException; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.framework.teamcenter.queries.saved.modelobject.ItemRevisionQuery; +import com.capgemini.reports.AbstractTeamcenterTest; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import lombok.extern.slf4j.Slf4j; +import org.junit.Assert; +import org.junit.Test; + +import java.util.List; + +@Slf4j +public class DocTechnicTest extends AbstractTeamcenterTest { + + private static final String DOC_REV = "B"; + private static final String DOC_ID = "DOC-00264940"; + + @Test + public void testBuild() throws NoTeamcenterConnectionException { + List results = new ItemRevisionQuery(getSession()).searchIDAndRevision(DOC_ID, DOC_REV).findAll(); + Assert.assertFalse(results.isEmpty()); + ItemRevision techItemRev = results.get(0); + DocTechnic docTechnic = new DocTechnic(getSession(), techItemRev); + log.info("Name = " + docTechnic.getName()); + Assert.assertNotNull(docTechnic.getName()); + Assert.assertFalse(docTechnic.getName().isEmpty()); + log.info("Revision = " + docTechnic.getRevision()); + Assert.assertNotNull(docTechnic.getRevision()); + Assert.assertEquals(DOC_REV, docTechnic.getRevision()); + log.info("Indice = " + docTechnic.getIndice()); + Assert.assertNotNull(docTechnic.getIndice()); + Assert.assertFalse(docTechnic.getIndice().isEmpty()); + log.info("Reference = " + docTechnic.getReference()); + Assert.assertNotNull(docTechnic.getReference()); + Assert.assertFalse(docTechnic.getReference().isEmpty()); + log.info("Type = " + docTechnic.getType()); + Assert.assertNotNull(docTechnic.getType()); + Assert.assertFalse(docTechnic.getType().isEmpty()); + log.info("Typedoctechnic = " + docTechnic.getTypeDocTechnic1()); + Assert.assertNotNull(docTechnic.getTypeDocTechnic1()); + Assert.assertTrue(docTechnic.getTypeDocTechnic1().contains("Freeze document")); + } + + @Override + public PolicyLocation getPropertyPolicyIdentifier() { + return R20_POLICY_FULL; + } + +} diff --git a/teamcenter/src/test/java/com/capgemini/reports/releasestatus/TcReleaseStatusTest.java b/teamcenter/src/test/java/com/capgemini/reports/releasestatus/TcReleaseStatusTest.java new file mode 100644 index 0000000..10bb680 --- /dev/null +++ b/teamcenter/src/test/java/com/capgemini/reports/releasestatus/TcReleaseStatusTest.java @@ -0,0 +1,58 @@ +package com.capgemini.reports.releasestatus; + +import com.capgemini.framework.teamcenter.exceptions.NoTeamcenterConnectionException; +import com.capgemini.framework.teamcenter.object.pom.status.StatusEnum; +import com.capgemini.framework.teamcenter.object.pom.status.TcReleaseStatus; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.framework.teamcenter.queries.saved.modelobject.ItemRevisionQuery; +import com.capgemini.reports.AbstractTeamcenterTest; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import com.teamcenter.soa.client.model.strong.ReleaseStatus; +import org.junit.Assert; +import org.junit.Test; + +import java.util.List; + + +public class TcReleaseStatusTest extends AbstractTeamcenterTest { + + private static final String DET_ID = "620-037-104-0"; + + @Test + public void testGetChosenStatus() throws NoTeamcenterConnectionException { + // GET ALTERNATE REVISION LIST + List detRevisionList = new ItemRevisionQuery(getSession()).searchIDAndRevision(DET_ID, "A").findAll(); + Assert.assertNotNull(detRevisionList); + Assert.assertFalse(detRevisionList.isEmpty()); + + List releaseStatusList = TcReleaseStatus.getChosenStatus(getSession(), detRevisionList.get(0), StatusEnum.J3A); + if (!releaseStatusList.isEmpty()) { + for (ReleaseStatus status : releaseStatusList) { + Assert.assertEquals(StatusEnum.J3A.getIdentifier(), status.get_name()); + } + } + } + + @Test + public void testGetAllStatusExceptSome() throws NoTeamcenterConnectionException { + // GET ALTERNATE REVISION LIST + List detRevisionList = new ItemRevisionQuery(getSession()).searchIDAndRevision(DET_ID, "A").findAll(); + Assert.assertNotNull(detRevisionList); + Assert.assertFalse(detRevisionList.isEmpty()); + + List releaseStatusList = + TcReleaseStatus.getAllStatusExceptSome(getSession(), detRevisionList.get(0), StatusEnum.J3A, StatusEnum.J3B, StatusEnum.EFFECTIVITY); + if (!releaseStatusList.isEmpty()) { + for (ReleaseStatus status : releaseStatusList) { + Assert.assertNotSame(StatusEnum.J3A.getIdentifier(), status.get_name()); + Assert.assertNotSame(StatusEnum.J3B.getIdentifier(), status.get_name()); + Assert.assertNotSame(StatusEnum.EFFECTIVITY.getIdentifier(), status.get_name()); + } + } + } + + @Override + public PolicyLocation getPropertyPolicyIdentifier() { + return DEFAULT_POLICY; + } +} diff --git a/teamcenter/src/test/java/com/capgemini/reports/reports/parameters/DualsGenericsTest.java b/teamcenter/src/test/java/com/capgemini/reports/reports/parameters/DualsGenericsTest.java new file mode 100644 index 0000000..d0e81bd --- /dev/null +++ b/teamcenter/src/test/java/com/capgemini/reports/reports/parameters/DualsGenericsTest.java @@ -0,0 +1,47 @@ +package com.capgemini.reports.reports.parameters; + +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import lombok.extern.slf4j.Slf4j; +import org.junit.Test; + +/** + * @author JMONTOUT + * + */ +@Slf4j +public class DualsGenericsTest { + + private static final String PRODUCT_97R0 = "97R0"; + private static final String GENERIC_U22 = "U22"; + private static final String GENERIC_ASSEMB_22U = "22U"; + private static final int UNIT_520 = 520; + + + private ProductUnit getProductUnit() { + return new ProductUnit(PRODUCT_97R0, UNIT_520); + } + + /** + * JUNIT Test + * + * @throws KurtException should not happen + */ + @Test + public void testCreateDualGenerics() throws KurtException { + log.info("testCreateDualGenerics ...."); + + DualGenerics dualGenerics = new DualGenerics(getProductUnit(), GENERIC_U22, GENERIC_ASSEMB_22U); + log.info("###############################"); + log.info("Type : " + dualGenerics.asGeneric().getType()); + log.info("ID : " + dualGenerics.asGeneric().getID()); + log.info("toString : " + dualGenerics.asGeneric().toString()); + log.info("BOMLine : " + dualGenerics.asGeneric().getType().getBomLinkType()); + log.info("###############################"); + log.info("Type : " + dualGenerics.asGenericAssemb().getType()); + log.info("ID : " + dualGenerics.asGenericAssemb().getID()); + log.info("toString : " + dualGenerics.asGenericAssemb().toString()); + log.info("BOMLine : " + dualGenerics.asGenericAssemb().getType().getBomLinkType()); + } + + +} diff --git a/teamcenter/src/test/java/com/capgemini/reports/reports/parameters/GenericsTest.java b/teamcenter/src/test/java/com/capgemini/reports/reports/parameters/GenericsTest.java new file mode 100644 index 0000000..87cd566 --- /dev/null +++ b/teamcenter/src/test/java/com/capgemini/reports/reports/parameters/GenericsTest.java @@ -0,0 +1,58 @@ +package com.capgemini.reports.reports.parameters; + +import com.capgemini.framework.teamcenter.exceptions.NoTeamcenterConnectionException; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.reports.AbstractTeamcenterTest; +import com.capgemini.reports.exceptions.NotFoundException; +import lombok.extern.slf4j.Slf4j; +import org.junit.Test; + +/** + * @author JMONTOUT + */ +@Slf4j +public class GenericsTest extends AbstractTeamcenterTest { + + private static final String PRODUCT_97R0 = "97R0"; + private static final String GENERIC_U22 = "U22"; + private static final String GENERIC_EMPTY = ""; + private static final String GENERIC_ASSEMB_22U = "22U"; + private static final String GENERIC_ASSEMB_EMPTY = ""; + private static final int UNIT_520 = 520; + + @Override + public PolicyLocation getPropertyPolicyIdentifier() { + return DEFAULT_POLICY; + } + + @Test + public void testGeneric() throws NotFoundException, NoTeamcenterConnectionException { + log.info("testGeneric ...."); + log.info("GENERIC ID {" + GENERIC_U22 + "} AND GENERIC_ASSEMB {" + GENERIC_ASSEMB_EMPTY + "} EMPTY "); + Generics generic = new Generics(getProductUnit(), GENERIC_U22, GENERIC_ASSEMB_EMPTY); + + log.info("EXPECTED type {" + generic.getType() + "}"); + log.info("EXPECTED ID {" + generic.getID() + "}"); + log.info("EXPECTED BOM line type {" + generic.getType().getBomLinkType() + "}"); + log.info("EXPECTED getItemID {" + generic.getItem(getSession()).get_item_id() + "}"); + + } + + @Test + public void testGenericAssemb() throws NotFoundException, NoTeamcenterConnectionException { + log.info("testGenericAssemb ...."); + log.info("GENERIC ID {" + GENERIC_EMPTY + "} EMPTY AND GENERIC_ASSEMB {" + GENERIC_ASSEMB_22U + "}"); + Generics genericAssemb = new Generics(getProductUnit(), GENERIC_EMPTY, GENERIC_ASSEMB_22U); + + log.info("EXPECTED type {" + genericAssemb.getType() + "}"); + log.info("EXPECTED ID {" + genericAssemb.getID() + "}"); + log.info("EXPECTED BOM line type {" + genericAssemb.getType().getBomLinkType() + "}"); + log.info("EXPECTED getItemID {" + genericAssemb.getItem(getSession()).get_item_id() + "}"); + } + + + private ProductUnit getProductUnit() { + return new ProductUnit(PRODUCT_97R0, UNIT_520); + } + +} diff --git a/teamcenter/src/test/java/com/capgemini/reports/reports/parameters/ProductUnitTest.java b/teamcenter/src/test/java/com/capgemini/reports/reports/parameters/ProductUnitTest.java new file mode 100644 index 0000000..373d4da --- /dev/null +++ b/teamcenter/src/test/java/com/capgemini/reports/reports/parameters/ProductUnitTest.java @@ -0,0 +1,56 @@ +package com.capgemini.reports.reports.parameters; + +import com.capgemini.framework.teamcenter.exceptions.NoTeamcenterConnectionException; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.reports.AbstractTeamcenterTest; +import com.capgemini.reports.exceptions.InvalidUserInputException; +import com.capgemini.reports.exceptions.NotFoundException; +import com.teamcenter.soa.client.model.strong.Item; +import org.junit.Assert; +import org.junit.Test; + + +public class ProductUnitTest extends AbstractTeamcenterTest { + + private static final String PRODUCT_ID = "97R0"; + + private static final int GOOD_UNIT = 520; + private static final String GOOD_UNIT_STR = "520"; + private static final String BAD_UNIT_STR = "520adf"; + + @Override + public PolicyLocation getPropertyPolicyIdentifier() { + return DEFAULT_POLICY; + } + + /** + * JUnit test. + * + * @throws InvalidUserInputException should not happen + */ + @Test + public void parseUserUnitTest() throws InvalidUserInputException { + ProductUnit productUnit = new ProductUnit(PRODUCT_ID, GOOD_UNIT_STR); + productUnit.parseUserUnit(); + Assert.assertEquals(GOOD_UNIT, productUnit.getUnit()); + } + + /** + * JUnit test. + * + * @throws InvalidUserInputException should not happen + */ + @Test(expected = InvalidUserInputException.class) + public void parseUserUnitTestFail() throws InvalidUserInputException { + ProductUnit productUnit = new ProductUnit(PRODUCT_ID, BAD_UNIT_STR); + productUnit.parseUserUnit(); + } + + @Test + public void getProductTest() throws NotFoundException, NoTeamcenterConnectionException { + ProductUnit productUnit = new ProductUnit(PRODUCT_ID, BAD_UNIT_STR); + Item item = productUnit.getProduct(getSession()); + Assert.assertEquals(PRODUCT_ID, item.get_item_id()); + } + +} diff --git a/teamcenter/src/test/java/com/capgemini/reports/reports/parameters/TcEffectivityDateTest.java b/teamcenter/src/test/java/com/capgemini/reports/reports/parameters/TcEffectivityDateTest.java new file mode 100644 index 0000000..a2dff25 --- /dev/null +++ b/teamcenter/src/test/java/com/capgemini/reports/reports/parameters/TcEffectivityDateTest.java @@ -0,0 +1,76 @@ +package com.capgemini.reports.reports.parameters; + +import com.capgemini.framework.common.TeamcenterDateFormatter; +import lombok.extern.slf4j.Slf4j; +import org.junit.Assert; +import org.junit.Test; + +import java.util.Calendar; + + +@Slf4j +public class TcEffectivityDateTest { + + + private static final String DATE_USER_INPUT = "08-12-2014"; + private static final String DATE_USER_INPUT_EMPTY = ""; + + + @Test + public void testEffectivityDateWithUserInput() { + log.info("testEffectivityDateWithUserInputNotEmpty..."); + log.info("User Input: " + DATE_USER_INPUT); + String formattedDate = TeamcenterDateFormatter.translateDateFormatForRequest(DATE_USER_INPUT); + Calendar userInputDate = TeamcenterDateFormatter.makeTeamcenterCalendar(DATE_USER_INPUT); + + EffectivityDate effectivityDate = new EffectivityDate(userInputDate); + + Assert.assertFalse(effectivityDate.isNow()); + Assert.assertNotNull(effectivityDate.getDateTime()); + + log.info("Expected object Calendar = {}", effectivityDate.getDateTime()); + log.info("Expected isNow = {}", effectivityDate.isNow()); + Assert.assertEquals(formattedDate, effectivityDate.getFormattedDateForTcRequest()); + + } + + + @Test + public void testEffectivityDateWithoutUserInput() { + log.info("testEffectivityDateWithUserInputNotEmpty..."); + log.info("User Input: " + DATE_USER_INPUT); + + EffectivityDate effectivityDate = new EffectivityDate(); + + Assert.assertTrue(effectivityDate.isNow()); + Assert.assertNull(effectivityDate.getDateTime()); + + log.info("Expected object Calendar = {}", effectivityDate.getDateTime()); + log.info("Expected isNow = {}", effectivityDate.isNow()); + } + + + @Test + public void testEffectivityDateWithEmptyUserInput() { + log.info("testEffectivityDateWITHOUTUserInputNotEmpty..."); + log.info("USER INPUT {" + DATE_USER_INPUT_EMPTY + "} EMPTY"); + + EffectivityDate effectivityDate = new EffectivityDate(DATE_USER_INPUT_EMPTY); + + Assert.assertTrue(effectivityDate.isNow()); + Assert.assertNull(effectivityDate.getDateTime()); + + log.info("Expected object Calendar TODAY = {}", effectivityDate.getDateTime()); + log.info("Expected isNow = {}", effectivityDate.isNow()); + } + + + @Test + public void testIsNowTRUE() { + log.info("testIsNowTRUE ...."); + EffectivityDate effectivityDate = new EffectivityDate(); + Assert.assertTrue(effectivityDate.isNow()); + log.info("Expected isNow = {}", effectivityDate.isNow()); + } + +} diff --git a/teamcenter/src/test/java/com/capgemini/reports/reports/parameters/checker/GenericExistenceCheckTest.java b/teamcenter/src/test/java/com/capgemini/reports/reports/parameters/checker/GenericExistenceCheckTest.java new file mode 100644 index 0000000..26aa5db --- /dev/null +++ b/teamcenter/src/test/java/com/capgemini/reports/reports/parameters/checker/GenericExistenceCheckTest.java @@ -0,0 +1,55 @@ +package com.capgemini.reports.reports.parameters.checker; + +import com.capgemini.framework.teamcenter.exceptions.NoTeamcenterConnectionException; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.reports.AbstractTeamcenterTest; +import com.capgemini.reports.exceptions.InvalidUserInputException; +import com.capgemini.reports.reports.parameters.Generics; +import com.capgemini.reports.reports.parameters.ProductUnit; +import lombok.extern.slf4j.Slf4j; +import org.junit.Test; + + +@Slf4j +public class GenericExistenceCheckTest extends AbstractTeamcenterTest { + + private static final String PRODUCT_ID_FOR_GENERIC_ASSEMB = "97R0"; + private static final String UNIT_FOR_GENERIC_ASSEMB = "520"; + private static final String GENERIC_ASSEMB_ID = "22U"; + + private static final String PRODUCT_ID_FOR_GENERIC = "65A1"; + private static final String GENERIC_ID = "A29"; + private static final String UNIT_FOR_GENERIC = "20"; + + @Override + public PolicyLocation getPropertyPolicyIdentifier() { + return DEFAULT_POLICY; + } + + /** + * JUnit Test. + * + * @throws InvalidUserInputException should not happen + * @throws NoTeamcenterConnectionException should not happen + */ + @Test + public void checkTest() throws InvalidUserInputException, NoTeamcenterConnectionException { + log.info("Checking Product-Unit Alone..."); + ProductUnit productUnitAlone = new ProductUnit(PRODUCT_ID_FOR_GENERIC, UNIT_FOR_GENERIC); + Generics productAlone = new Generics(productUnitAlone, null, null); + new GenericExistenceChecker(productAlone).check(getSession()); + log.info(" Product-Unit Alone OK"); + + log.info("Checking Generic Assemb..."); + ProductUnit productUnitForGenericAssemb = new ProductUnit(PRODUCT_ID_FOR_GENERIC_ASSEMB, UNIT_FOR_GENERIC_ASSEMB); + Generics genericAssemb = new Generics(productUnitForGenericAssemb, null, GENERIC_ASSEMB_ID); + new GenericExistenceChecker(genericAssemb).check(getSession()); + log.info(" Generic Assemb OK"); + + log.info("Checking Generic..."); + ProductUnit productUnitForGeneric = new ProductUnit(PRODUCT_ID_FOR_GENERIC, UNIT_FOR_GENERIC); + Generics generic = new Generics(productUnitForGeneric, GENERIC_ID, null); + new GenericExistenceChecker(generic).check(getSession()); + log.info(" Generic OK"); + } +} diff --git a/teamcenter/src/test/java/com/capgemini/reports/reports/parameters/checker/ObjectTypeCheckerTest.java b/teamcenter/src/test/java/com/capgemini/reports/reports/parameters/checker/ObjectTypeCheckerTest.java new file mode 100644 index 0000000..ea06064 --- /dev/null +++ b/teamcenter/src/test/java/com/capgemini/reports/reports/parameters/checker/ObjectTypeCheckerTest.java @@ -0,0 +1,86 @@ +package com.capgemini.reports.reports.parameters.checker; + +import com.capgemini.framework.teamcenter.exceptions.NoTeamcenterConnectionException; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.reports.AbstractTeamcenterTest; +import com.capgemini.reports.exceptions.InvalidUserInputException; +import org.junit.Test; + + +public class ObjectTypeCheckerTest extends AbstractTeamcenterTest { + + private static final String PART_ID = "350-290-601-0"; + + /** + * JUnit test. + * + * @throws InvalidUserInputException should not happen + * @throws NoTeamcenterConnectionException should not happen + */ + @Test + public void testCheckPartPass() throws InvalidUserInputException, NoTeamcenterConnectionException { + new ObjectTypeChecker(PART_ID, "Part").check(getSession()); + } + + /** + * JUnit test. + * + * @throws InvalidUserInputException should not happen + * @throws NoTeamcenterConnectionException should not happen + */ + @Test + public void testCheckPartAeroPass() throws InvalidUserInputException, NoTeamcenterConnectionException { + new ObjectTypeChecker(PART_ID, "Part Aero").check(getSession()); + } + + /** + * JUnit test. + * + * @throws InvalidUserInputException should not happen + * @throws NoTeamcenterConnectionException should not happen + */ + @Test + public void testCheckMultiPass() throws InvalidUserInputException, NoTeamcenterConnectionException { + new ObjectTypeChecker(PART_ID, "Truc", "Machin", "Part Aero").check(getSession()); + } + + /** + * JUnit test. + * + * @throws InvalidUserInputException SHOULD HAPPEN! + * @throws NoTeamcenterConnectionException should not happen + */ + @Test(expected = InvalidUserInputException.class) + public void testCheckPartAeroRevisionFail() throws InvalidUserInputException, NoTeamcenterConnectionException { + new ObjectTypeChecker(PART_ID, "Part Aero Revision").check(getSession()); + } + + + /** + * JUnit test. + * + * @throws InvalidUserInputException SHOULD HAPPEN! + * @throws NoTeamcenterConnectionException should not happen + */ + @Test(expected = InvalidUserInputException.class) + public void testCheckPartFailNofilter() throws InvalidUserInputException, NoTeamcenterConnectionException { + new ObjectTypeChecker(PART_ID).check(getSession()); + } + + /** + * JUnit test. + * + * @throws InvalidUserInputException SHOULD HAPPEN! + * @throws NoTeamcenterConnectionException should not happen + */ + @Test(expected = InvalidUserInputException.class) + public void testCheckPartFail() throws InvalidUserInputException, NoTeamcenterConnectionException { + new ObjectTypeChecker(PART_ID, "Truc", "Bidule").check(getSession()); + } + + @Override + public PolicyLocation getPropertyPolicyIdentifier() { + return DEFAULT_POLICY; + } + +} diff --git a/teamcenter/src/test/java/com/capgemini/reports/reports/parameters/checker/ProductCheckTest.java b/teamcenter/src/test/java/com/capgemini/reports/reports/parameters/checker/ProductCheckTest.java new file mode 100644 index 0000000..7d5eb1e --- /dev/null +++ b/teamcenter/src/test/java/com/capgemini/reports/reports/parameters/checker/ProductCheckTest.java @@ -0,0 +1,31 @@ +package com.capgemini.reports.reports.parameters.checker; + +import com.capgemini.framework.teamcenter.exceptions.NoTeamcenterConnectionException; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.reports.AbstractTeamcenterTest; +import com.capgemini.reports.exceptions.InvalidUserInputException; +import org.junit.Test; + +/** + * JUnit test class. + */ +public class ProductCheckTest extends AbstractTeamcenterTest { + + private static final String PRODUCT_ID_FOR_GENERIC_ASSEMB = "97R0"; + + @Override + public PolicyLocation getPropertyPolicyIdentifier() { + return DEFAULT_POLICY; + } + + /** + * JUnit test. + * + * @throws InvalidUserInputException should not happen + * @throws NoTeamcenterConnectionException should not happen + */ + @Test + public void checkTest() throws InvalidUserInputException, NoTeamcenterConnectionException { + new ProductChecker(PRODUCT_ID_FOR_GENERIC_ASSEMB).check(getSession()); + } +} diff --git a/teamcenter/src/test/java/com/capgemini/reports/reports/parameters/checker/ProductUnitCheckTest.java b/teamcenter/src/test/java/com/capgemini/reports/reports/parameters/checker/ProductUnitCheckTest.java new file mode 100644 index 0000000..2913708 --- /dev/null +++ b/teamcenter/src/test/java/com/capgemini/reports/reports/parameters/checker/ProductUnitCheckTest.java @@ -0,0 +1,40 @@ +package com.capgemini.reports.reports.parameters.checker; + +import com.capgemini.framework.teamcenter.exceptions.NoTeamcenterConnectionException; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.reports.AbstractTeamcenterTest; +import com.capgemini.reports.exceptions.InvalidUserInputException; +import com.capgemini.reports.reports.parameters.ProductUnit; +import lombok.extern.slf4j.Slf4j; +import org.junit.Assert; +import org.junit.Test; + +/** + * JUnit test class. + */ +@Slf4j +public class ProductUnitCheckTest extends AbstractTeamcenterTest { + + private static final String PRODUCT_ID_FOR_GENERIC_ASSEMB = "97R0"; + private static final String UNIT_FOR_GENERIC_ASSEMB_STR = "520"; + private static final int UNIT_FOR_GENERIC_ASSEMB = 520; + + @Override + public PolicyLocation getPropertyPolicyIdentifier() { + return DEFAULT_POLICY; + } + + /** + * JUnit test. + * + * @throws InvalidUserInputException should not happen + * @throws NoTeamcenterConnectionException should not happen + */ + @Test + public void checkTest() throws InvalidUserInputException, NoTeamcenterConnectionException { + log.info("Checking existence of product Id=" + PRODUCT_ID_FOR_GENERIC_ASSEMB); + ProductUnit productUnit = new ProductUnit(PRODUCT_ID_FOR_GENERIC_ASSEMB, UNIT_FOR_GENERIC_ASSEMB_STR); + new ProductUnitChecker(productUnit).check(getSession()); + Assert.assertEquals(UNIT_FOR_GENERIC_ASSEMB, productUnit.getUnit()); + } +} diff --git a/teamcenter/src/test/java/com/capgemini/reports/reports/parameters/checker/TcEffectivityCheckerTest.java b/teamcenter/src/test/java/com/capgemini/reports/reports/parameters/checker/TcEffectivityCheckerTest.java new file mode 100644 index 0000000..43e67c2 --- /dev/null +++ b/teamcenter/src/test/java/com/capgemini/reports/reports/parameters/checker/TcEffectivityCheckerTest.java @@ -0,0 +1,41 @@ +package com.capgemini.reports.reports.parameters.checker; + +import com.capgemini.reports.exceptions.InvalidUserInputException; +import com.capgemini.reports.reports.parameters.EffectivityDate; +import org.junit.Test; + +import java.util.Calendar; + + +public class TcEffectivityCheckerTest { + + /** + * JUnit test. + * + * @throws InvalidUserInputException should not happen + */ + @Test + public void checkSuccess() throws InvalidUserInputException { + // Check for 'now' : should not throw an exception + EffectivityDate now = new EffectivityDate(); + new EffectivityChecker(now).check(null); // no need for a session + + // Check for a date in the past: should not throw an exception + Calendar fiveDaysAgo = Calendar.getInstance(); + fiveDaysAgo.add(Calendar.DAY_OF_MONTH, -5); + new EffectivityChecker(new EffectivityDate(fiveDaysAgo)).check(null); + } + + /** + * JUnit test. + * + * @throws InvalidUserInputException should not happen + */ + public void checkNullDateNotNow() throws InvalidUserInputException { + // Give no or null input, still obtain a valid date representing the current date + new EffectivityChecker(new EffectivityDate()).check(null); + new EffectivityChecker(new EffectivityDate((String) null)).check(null); + new EffectivityChecker(new EffectivityDate((Calendar) null)).check(null); + } + +} diff --git a/teamcenter/src/test/java/com/capgemini/reports/teamcenter/ObjectInfoHelperTest.java b/teamcenter/src/test/java/com/capgemini/reports/teamcenter/ObjectInfoHelperTest.java new file mode 100644 index 0000000..c99a3a7 --- /dev/null +++ b/teamcenter/src/test/java/com/capgemini/reports/teamcenter/ObjectInfoHelperTest.java @@ -0,0 +1,217 @@ +package com.capgemini.reports.teamcenter; + +import com.capgemini.framework.teamcenter.exceptions.KurtException; +import com.capgemini.framework.teamcenter.exceptions.NoTeamcenterConnectionException; +import com.capgemini.framework.teamcenter.object.pom.status.StatusEnum; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.framework.teamcenter.queries.saved.modelobject.ItemRevisionQuery; +import com.capgemini.reports.AbstractTeamcenterTest; +import com.capgemini.reports.exceptions.InvalidUserInputException; +import com.capgemini.reports.exceptions.NotFoundException; +import com.capgemini.reports.releasestatus.RevisionStatusAndDate; +import com.capgemini.reports.reports.parameters.Generics; +import com.capgemini.reports.reports.parameters.ProductUnit; +import com.google.common.base.Optional; +import com.teamcenter.soa.client.model.ModelObject; +import com.teamcenter.soa.client.model.strong.Item; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import com.teamcenter.soa.client.model.strong.ReleaseStatus; +import lombok.extern.slf4j.Slf4j; +import org.junit.Assert; +import org.junit.Test; + +import java.util.Arrays; +import java.util.Calendar; +import java.util.List; + +@Slf4j +public class ObjectInfoHelperTest extends AbstractTeamcenterTest { + + private static final String PRODUCT_35R0 = "35R0"; + private static final String GENERIC_N24 = "N24"; + private static final String GENERIC_ASSEMB_24N = "24N"; + private static final int UNIT_60 = 60; + + // ************ For Alternate and DET tests ************** + private static final String[] EXPECTED_PARTS_ID_OF_ALTERNATE = {"1688M69P01", "1688M69P07"}; + private static final String[] EXPECTED_PARTS_ID_OF_DET = {"327-701-088-0", "327-701-105-0"}; + private static final String ALTERNATE_ID = "ART00010127"; + private static final String DET_ID = "620-037-104-0"; + + @Override + public PolicyLocation getPropertyPolicyIdentifier() { + return DEFAULT_POLICY; + } + + @Test + public void testGetPartsInPseudoFolderOfAlternateRevision() throws KurtException { + log.info("testGetPartsOfAlternateRevision() with Alternate Revision : " + ALTERNATE_ID); + + // GET ALTERNATE REVISION + List alternateRevisionList = new ItemRevisionQuery(getSession()).searchIDAndRevision(ALTERNATE_ID, "A").findAll(); + Assert.assertNotNull(alternateRevisionList); + Assert.assertFalse(alternateRevisionList.isEmpty()); + + // GET ALTERNATE REVISION + ItemRevision itemRevision = alternateRevisionList.get(0); + Assert.assertNotNull(itemRevision); + + List listPartsOfAlternate = ObjectInfoHelper.getPartsInPseudoFolderOfAltOrDetRevision(getSession(), itemRevision); + + Assert.assertEquals(EXPECTED_PARTS_ID_OF_ALTERNATE.length, listPartsOfAlternate.size()); + + String parts = "[ "; + for (ModelObject modelObject : listPartsOfAlternate) { + parts += modelObject.getPropertyDisplayableValue("item_id") + " "; + } + parts += "]"; + log.info("Found IDs = {}", parts); + log.info("Expected IDs = {}", Arrays.toString(EXPECTED_PARTS_ID_OF_ALTERNATE)); + } + + @Test + public void testGetClosestGenerics() + throws NotFoundException, InvalidUserInputException, NoTeamcenterConnectionException { + log.info("testGetClosestGenerics "); + ObjectInfoLoader infoLoader = new ObjectInfoLoader(getSession()); + ProductUnit product = new ProductUnit(PRODUCT_35R0, UNIT_60); + + // Test on a generic + Generics generic = new Generics(product, GENERIC_N24, ""); + log.info("check Generic " + generic.getID() + "with unit " + product.getUnit()); + List listGenericRevision = infoLoader.getGenericUnderProduct(generic, product); + boolean isGenericHasAnUnitRevision = ObjectInfoHelper.getClosestGenerics(getSession(), generic.getID(), product.getUnit(), listGenericRevision); + Assert.assertTrue("FAILED : Check Generic is " + GENERIC_N24 + " hasn't an Unit Revision " + UNIT_60, isGenericHasAnUnitRevision); + log.info("SUCCESS : Generic " + GENERIC_N24 + " has an Unit Revision with " + UNIT_60 + " result " + isGenericHasAnUnitRevision); + + // Test on a generic assemb + Generics genericAssemb = new Generics(product, "", GENERIC_ASSEMB_24N); + log.info("check Generic Assemb " + generic.getID() + "with unit " + product.getUnit()); + List listGenericAssembRevision = infoLoader.getGenericUnderProduct(generic, product); + boolean isGenericAssembHasAnUnitRevision = + ObjectInfoHelper.getClosestGenerics(getSession(), genericAssemb.getID(), product.getUnit(), listGenericAssembRevision); + Assert.assertTrue("FAILED : Check Generic is " + GENERIC_N24 + " hasn't an Unit Revision " + UNIT_60, isGenericAssembHasAnUnitRevision); + log.info("SUCCESS : Generic " + GENERIC_N24 + " has an Unit Revision with " + UNIT_60 + " result " + isGenericAssembHasAnUnitRevision); + } + + @Test + public void testGetPartsInPseudoFolderOfAltOrDetRevision() throws KurtException { + log.info("testGetPartsInPseudoFolderOfAltOrDetRevision()"); + + ItemRevision alt = new ItemRevisionQuery(getSession()).searchIDAndRevision("351-403-051-0", "A").findAll().get(0); + Assert.assertNotNull(alt); + List list = ObjectInfoHelper.getPartsInPseudoFolderOfAltOrDetRevision(getSession(), alt); + Assert.assertNotNull(list); + Assert.assertTrue(!list.isEmpty()); + + for (Item item : list) { + log.info("Parts in the psudo-folder : {}\t{}", item.getUid(), item.get_item_id()); + } + } + + @Test + public void testGetPartsOfDETRevision() throws KurtException { + log.info("testGetPartsOfDETRevision() with DET Revision : " + DET_ID); + + // GET ALTERNATE REVISION LIST + List alternateRevisionList = new ItemRevisionQuery(getSession()).searchIDAndRevision(DET_ID, "A").findAll(); + Assert.assertNotNull(alternateRevisionList); + Assert.assertFalse(alternateRevisionList.isEmpty()); + + // GET ALTERNATE REVISION + ItemRevision itemRevision = alternateRevisionList.get(0); + Assert.assertNotNull(itemRevision); + + List listPartsOfDET = ObjectInfoHelper.getPartsInPseudoFolderOfAltOrDetRevision(getSession(), itemRevision); + Assert.assertNotNull(listPartsOfDET); + Assert.assertEquals(EXPECTED_PARTS_ID_OF_DET.length, listPartsOfDET.size()); + + String parts = "[ "; + for (Item item : listPartsOfDET) { + parts += item.get_item_id() + " "; + } + parts += "]"; + log.info("Found IDs = {}", parts); + log.info("Expected IDs = {}", Arrays.toString(EXPECTED_PARTS_ID_OF_DET)); + } + + @Test + public void testGetRevisionWithHighestRange() throws NoTeamcenterConnectionException { + List genericRevisions = new ItemRevisionQuery(getSession()).searchID("U24").findAll(); + List genericRevFiltered = ObjectInfoHelper.getRevisionWithHighestRange(getSession(), genericRevisions, "60"); + Assert.assertNotNull(genericRevFiltered); + Assert.assertFalse(genericRevFiltered.isEmpty()); + + // Verifying contents: 3 revisions have a unit range 10-UP: c, I, and K. no other revision have unit range between 10 and 60 (the limit) + Assert.assertEquals(3, genericRevFiltered.size()); + boolean foundRevisionC = false; + boolean foundRevisionI = false; + boolean foundRevisionK = false; + for (ItemRevision item : genericRevFiltered) { + foundRevisionC = foundRevisionC || "C".equals(item.get_item_revision_id()); + foundRevisionI = foundRevisionI || "I".equals(item.get_item_revision_id()); + foundRevisionK = foundRevisionK || "K".equals(item.get_item_revision_id()); + } + Assert.assertTrue(foundRevisionI && foundRevisionK); + } + + @Test + public void testGetModelObjectsInPseudoFolderUnderItemRevision() throws KurtException { + List rfGenericRevisions = new ItemRevisionQuery(getSession()).searchIDAndRevision("00014868", "I").findAll(); + ItemRevision rfGeneric = rfGenericRevisions.get(0); + Assert.assertNotNull(rfGeneric); + + List resultsPseudoFolder = ObjectInfoHelper.getModelObjectsInPseudoFolderUnderItemRevision(getSession(), rfGeneric, "RFGenericBom"); + Assert.assertNotNull(resultsPseudoFolder); + Assert.assertFalse(resultsPseudoFolder.isEmpty()); + } + + @Test + public void testGetRevisionAndStatusWithMostRecentReleaseDate() + throws NoTeamcenterConnectionException { + // There are 13 revisions of this object! + List revisions = new ItemRevisionQuery(getSession()).searchID("00014868").findAll(); + Optional selectStatus = ObjectInfoHelper.getRevisionAndStatusWithMostRecentReleaseDate(getSession(), revisions, null); + Assert.assertNotNull(selectStatus); + Assert.assertTrue(selectStatus.isPresent()); + Assert.assertNotNull(selectStatus.get()); + Assert.assertNotNull(selectStatus.get().getItemRevision()); + Assert.assertNotNull(selectStatus.get().getReleaseDate()); + Assert.assertNotNull(selectStatus.get().getReleaseStatus()); + Assert.assertEquals(selectStatus.get().getItemRevision().get_item_id(), "00014868"); + Assert.assertEquals(selectStatus.get().getItemRevision().get_item_revision_id(), "B"); + Assert.assertEquals(selectStatus.get().getReleaseStatus().get_name(), "J3B"); + } + + @Test + public void testGetRevisionAndStatusWithMostRecentReleaseDateNotFound() throws NoTeamcenterConnectionException { + List revisions = new ItemRevisionQuery(getSession()).searchID("00065682").findAll(); + Optional selectStatus = + ObjectInfoHelper.getRevisionAndStatusWithMostRecentReleaseDate(getSession(), revisions, Calendar.getInstance()); + Assert.assertNotNull(selectStatus); + Assert.assertFalse(selectStatus.isPresent()); + } + + @Test + public void testGetRevisionWithMostRecentModificationDate() throws NoTeamcenterConnectionException { + List revisions = new ItemRevisionQuery(getSession()).searchIDAndRevision("00014868", "I").findAll(); + Assert.assertNotNull(revisions); + Assert.assertFalse(revisions.isEmpty()); + + RevisionStatusAndDate selectedRevision = + ObjectInfoHelper.getRevisionAndStatusWithMostRecentModificationDate(revisions, Calendar.getInstance()); + Assert.assertNotNull(selectedRevision); + for (ItemRevision itemRev : revisions) { + Assert.assertFalse(itemRev.get_last_mod_date().getTime().after(selectedRevision.getItemRevision().get_last_mod_date().getTime())); + } + } + + @Test + public void testGetStatusWithMostRecentReleaseDate() throws NoTeamcenterConnectionException { + List revisions = new ItemRevisionQuery(getSession()).searchIDAndRevision("309-162-004-0", "D").findAll(); + ItemRevision itemRev = revisions.get(0); + ReleaseStatus selectStatus = ObjectInfoHelper.getStatusWithMostRecentReleaseDate(getSession(), itemRev, StatusEnum.EFFECTIVITY); + Assert.assertNotNull(selectStatus); + Assert.assertFalse(StatusEnum.EFFECTIVITY.getIdentifier().equals(selectStatus.get_name())); + } +} diff --git a/teamcenter/src/test/java/com/capgemini/reports/teamcenter/TeamcenterConnectionTest.java b/teamcenter/src/test/java/com/capgemini/reports/teamcenter/TeamcenterConnectionTest.java new file mode 100644 index 0000000..0bf9d4b --- /dev/null +++ b/teamcenter/src/test/java/com/capgemini/reports/teamcenter/TeamcenterConnectionTest.java @@ -0,0 +1,27 @@ +package com.capgemini.reports.teamcenter; + +import com.capgemini.framework.teamcenter.exceptions.NoTeamcenterConnectionException; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.reports.AbstractTeamcenterTest; +import org.junit.Assert; +import org.junit.Test; + + +public class TeamcenterConnectionTest extends AbstractTeamcenterTest { + + /** + * JUnit test. + * + * @throws NoTeamcenterConnectionException should not happen + **/ + @Test + public void testLoginLogout() throws NoTeamcenterConnectionException { + // The inheritance of AbstractTeamcenterTest is sufficient to test the login() and logout() of TcSession . + Assert.assertNotNull(getSession()); + } + + @Override + public PolicyLocation getPropertyPolicyIdentifier() { + return DEFAULT_POLICY; + } +} diff --git a/teamcenter/src/test/java/com/capgemini/reports/teamcenter/queries/TypeQueryTest.java b/teamcenter/src/test/java/com/capgemini/reports/teamcenter/queries/TypeQueryTest.java new file mode 100644 index 0000000..076ed03 --- /dev/null +++ b/teamcenter/src/test/java/com/capgemini/reports/teamcenter/queries/TypeQueryTest.java @@ -0,0 +1,44 @@ +package com.capgemini.reports.teamcenter.queries; + +import com.capgemini.framework.teamcenter.exceptions.NoTeamcenterConnectionException; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.reports.AbstractTeamcenterTest; +import com.teamcenter.soa.client.model.strong.RevisionRule; +import lombok.extern.slf4j.Slf4j; +import org.junit.Assert; +import org.junit.Test; + +import java.util.List; + +@Slf4j +public class TypeQueryTest extends AbstractTeamcenterTest { + + private static final String REVISION_RULE_NAME = " DMA Configuration Interface"; + + @Override + public PolicyLocation getPropertyPolicyIdentifier() { + return DEFAULT_POLICY; + } + + @Test + public void testGetRevisionRule() throws NoTeamcenterConnectionException { + // Execute the query + List list = TypeQuery.getRevisionRule(getSession(), REVISION_RULE_NAME); + Assert.assertNotNull(list); + Assert.assertTrue(!list.isEmpty()); + + // Parse the content + for (RevisionRule rule : list) { + log.info("Revision rule name: \"{}\"", rule.get_object_name()); + Assert.assertEquals(REVISION_RULE_NAME, rule.get_object_name()); + } + } + + @Test + public void testGetRevisionRuleWrongName() throws NoTeamcenterConnectionException { + // Execute the query + List list = TypeQuery.getRevisionRule(getSession(), "babar"); + Assert.assertNotNull(list); + Assert.assertTrue(list.isEmpty()); + } +} diff --git a/teamcenter/src/test/java/com/capgemini/reports/teamcenter/queries/saved/AllSequencesQueryTest.java b/teamcenter/src/test/java/com/capgemini/reports/teamcenter/queries/saved/AllSequencesQueryTest.java new file mode 100644 index 0000000..91ff208 --- /dev/null +++ b/teamcenter/src/test/java/com/capgemini/reports/teamcenter/queries/saved/AllSequencesQueryTest.java @@ -0,0 +1,35 @@ +package com.capgemini.reports.teamcenter.queries.saved; + +import com.capgemini.framework.teamcenter.exceptions.NoTeamcenterConnectionException; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.reports.AbstractTeamcenterTest; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import lombok.extern.slf4j.Slf4j; +import org.junit.Assert; +import org.junit.Test; + +import java.util.List; + +@Slf4j +public class AllSequencesQueryTest extends AbstractTeamcenterTest { + + @Test + public void testSearchAllSequancesOfItem() throws NoTeamcenterConnectionException { + AllSequencesOfItemQuery query = new AllSequencesOfItemQuery(getSession()); + query.searchID("002603"); + List result = query.findAll(); + + Assert.assertEquals("Check itemRevision existence", result.isEmpty(), false); + log.info("Query has found {} itemRevision(s)", result.size()); + + for (ItemRevision itemRevision : result) { + log.info("--> found " + itemRevision.get_item_id() + "/" + itemRevision.get_item_revision_id() + "." + itemRevision.get_sequence_id()); + } + } + + @Override + public PolicyLocation getPropertyPolicyIdentifier() { + return DEFAULT_POLICY; + } + +} diff --git a/teamcenter/src/test/java/com/capgemini/reports/teamcenter/queries/saved/ChangeRequestQueryTest.java b/teamcenter/src/test/java/com/capgemini/reports/teamcenter/queries/saved/ChangeRequestQueryTest.java new file mode 100644 index 0000000..df4915e --- /dev/null +++ b/teamcenter/src/test/java/com/capgemini/reports/teamcenter/queries/saved/ChangeRequestQueryTest.java @@ -0,0 +1,49 @@ +package com.capgemini.reports.teamcenter.queries.saved; + +import com.capgemini.framework.teamcenter.exceptions.NoTeamcenterConnectionException; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.reports.AbstractTeamcenterTest; +import com.teamcenter.schemas.soa._2006_03.exceptions.ServiceException; +import com.teamcenter.soa.client.model.Property; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import lombok.extern.slf4j.Slf4j; +import org.junit.Assert; +import org.junit.Test; + +import java.util.List; + +@Slf4j +public class ChangeRequestQueryTest extends AbstractTeamcenterTest { + private static final String CHANGE_ID = "R201-012"; + + @Test + public void changeRequestQueryTest() throws NoTeamcenterConnectionException { + List list = new ChangeRequestQuery(getSession()).searchID(CHANGE_ID).findAll(); + Assert.assertNotNull(list); + Assert.assertFalse(list.isEmpty()); + log.info("{} ChangeRequest found with matching ID ({})", list.size(), CHANGE_ID); + for (ItemRevision itemRev : list) { + log.info(" + UID={}\tID={}\tRev={}", itemRev.getUid(), itemRev.get_item_id(), itemRev.get_item_revision_id()); + } + } + + @Test + public void changeRequestTypeModification() throws ServiceException, NoTeamcenterConnectionException { + List list = new ChangeRequestQuery(getSession()).searchID(CHANGE_ID).findAll(); + Assert.assertNotNull(list); + Assert.assertFalse(list.isEmpty()); + log.info("{} ChangeRequest found with matching ID ({})", list.size(), CHANGE_ID); + for (ItemRevision itemRev : list) { + Property prop = itemRev.getPropertyObject("pv4_type_modification"); + log.info(" + UID={}\tID={}\tRev={}", itemRev.getUid(), itemRev.get_item_id(), itemRev.get_item_revision_id()); + log.info(" -> ALL = {}", prop.getStringValue()); + log.info(" -> FR = {}", prop.getDisplayableValue()); + } + } + + @Override + public PolicyLocation getPropertyPolicyIdentifier() { + return R07_POLICY_FULL; + } + +} diff --git a/teamcenter/src/test/java/com/capgemini/reports/teamcenter/queries/saved/UnitFromCRTest.java b/teamcenter/src/test/java/com/capgemini/reports/teamcenter/queries/saved/UnitFromCRTest.java new file mode 100644 index 0000000..754faf8 --- /dev/null +++ b/teamcenter/src/test/java/com/capgemini/reports/teamcenter/queries/saved/UnitFromCRTest.java @@ -0,0 +1,41 @@ +package com.capgemini.reports.teamcenter.queries.saved; + +import com.capgemini.framework.teamcenter.exceptions.NoTeamcenterConnectionException; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.reports.AbstractTeamcenterTest; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import lombok.extern.slf4j.Slf4j; +import org.junit.Assert; +import org.junit.Test; + +import java.util.List; + +@Slf4j +public class UnitFromCRTest extends AbstractTeamcenterTest { + + private static final String CHANGE_ID = "report_change_id"; + private static final String MOD119895 = "MOD119895"; + private static final String UNIT_REVISION = "Unit Revision"; + + @Test + public void testSearchUnitFromCR() throws NoTeamcenterConnectionException { + UnitFromChangeRequestQuery query = new UnitFromChangeRequestQuery(getSession()); + query.addParam(CHANGE_ID, MOD119895); + + List result = query.findAll(); + Assert.assertEquals("Check unit existence", result.isEmpty(), false); + + log.info("Query has found {} item(s)", result.size()); + for (ItemRevision item : result) { + if (UNIT_REVISION.equals(item.get_object_type())) { + log.info(" + " + item.get_object_type() + " " + item.get_item_id()); + } + Assert.assertEquals(UNIT_REVISION, item.get_object_type()); + } + } + + @Override + public PolicyLocation getPropertyPolicyIdentifier() { + return DEFAULT_POLICY; + } +} diff --git a/teamcenter/src/test/java/com/capgemini/reports/teamcenter/queries/saved/UnitQueryTest.java b/teamcenter/src/test/java/com/capgemini/reports/teamcenter/queries/saved/UnitQueryTest.java new file mode 100644 index 0000000..9b4136f --- /dev/null +++ b/teamcenter/src/test/java/com/capgemini/reports/teamcenter/queries/saved/UnitQueryTest.java @@ -0,0 +1,44 @@ +package com.capgemini.reports.teamcenter.queries.saved; + +import com.capgemini.framework.teamcenter.exceptions.NoTeamcenterConnectionException; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.reports.AbstractTeamcenterTest; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import lombok.extern.slf4j.Slf4j; +import org.junit.Assert; +import org.junit.Test; + +import java.util.List; + +@Slf4j +public class UnitQueryTest extends AbstractTeamcenterTest { + + @Test + public void testSearchUnit() throws NoTeamcenterConnectionException { + UnitQuery query = new UnitQuery(getSession()); + query.addEndItemID("65A1"); + + List result = query.findAll(); + Assert.assertEquals("Check unit existence", result.isEmpty(), false); + } + + @Test + public void testSearchUnitWithWorkflow() throws NoTeamcenterConnectionException { + UnitQuery query = new UnitQuery(getSession(), UnitQuery.UNIT_VALIDATION_UNIT_PAR_SO); + query.addEndItemID("*"); // Search any unit with this workflow + + List result = query.findAll(); + Assert.assertEquals("Check unit existence", result.isEmpty(), false); + + log.info("Query has found {} item(s)", result.size()); + for (ItemRevision item : result) { + log.info(" + " + item.get_item_id()); + } + } + + @Override + public PolicyLocation getPropertyPolicyIdentifier() { + return DEFAULT_POLICY; + } + +} diff --git a/teamcenter/src/test/java/com/capgemini/reports/teamcenter/queries/saved/WorkflowOnChangeQueryTest.java b/teamcenter/src/test/java/com/capgemini/reports/teamcenter/queries/saved/WorkflowOnChangeQueryTest.java new file mode 100644 index 0000000..8b218ad --- /dev/null +++ b/teamcenter/src/test/java/com/capgemini/reports/teamcenter/queries/saved/WorkflowOnChangeQueryTest.java @@ -0,0 +1,33 @@ +package com.capgemini.reports.teamcenter.queries.saved; + +import com.capgemini.framework.teamcenter.exceptions.NoTeamcenterConnectionException; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.reports.AbstractTeamcenterTest; +import com.teamcenter.schemas.soa._2006_03.exceptions.ServiceException; +import com.teamcenter.soa.client.model.strong.EPMTask; +import org.junit.Assert; +import org.junit.Test; + +import java.util.List; + +public class WorkflowOnChangeQueryTest extends AbstractTeamcenterTest { + + @Test + public void testSearchWorkflow() throws ServiceException, NoTeamcenterConnectionException { + List result = new WorkflowOnChangeQuery(getSession()).searchIDAndRevision("MOD200381", "A").searchSequenceId("1").findAll(); + Assert.assertNotNull(result); + Assert.assertFalse(result.isEmpty()); + } + + @Test + public void testSearchWorkflow2() throws ServiceException, NoTeamcenterConnectionException { + List result = new WorkflowOnChangeQuery(getSession()).searchIDAndRevision("FPP0020016", "AA").searchSequenceId("1").findAll(); + Assert.assertNotNull(result); + Assert.assertFalse(result.isEmpty()); + } + + @Override + public PolicyLocation getPropertyPolicyIdentifier() { + return R13_POLICY_FULL; + } +} diff --git a/teamcenter/src/test/java/com/capgemini/reports/teamcenter/queries/saved/WorkflowQueryTest.java b/teamcenter/src/test/java/com/capgemini/reports/teamcenter/queries/saved/WorkflowQueryTest.java new file mode 100644 index 0000000..8305f06 --- /dev/null +++ b/teamcenter/src/test/java/com/capgemini/reports/teamcenter/queries/saved/WorkflowQueryTest.java @@ -0,0 +1,34 @@ +package com.capgemini.reports.teamcenter.queries.saved; + +import com.capgemini.framework.teamcenter.exceptions.NoTeamcenterConnectionException; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.reports.AbstractTeamcenterTest; +import com.teamcenter.soa.client.model.strong.EPMTask; +import lombok.extern.slf4j.Slf4j; +import org.junit.Assert; +import org.junit.Test; + +import java.util.List; + +@Slf4j +public class WorkflowQueryTest extends AbstractTeamcenterTest { + + @Test + public void testSearchValidationUnitParSO() throws NoTeamcenterConnectionException { + WorkflowOnUnitQuery query = WorkflowOnUnitQuery.searchValidationUnitParSO(getSession(), "00041717"); + List result = query.findAll(); + Assert.assertEquals("Check unit existence", result.isEmpty(), false); + + log.info("Query has found {} item(s)", result.size()); + for (EPMTask task : result) { + log.info(" + " + task.get_object_name()); + Assert.assertEquals("Task is not Validation Unit", WorkflowOnUnitQuery.UNIT_VALIDATION_UNIT_PAR_SO, task.get_object_name()); + } + } + + @Override + public PolicyLocation getPropertyPolicyIdentifier() { + return DEFAULT_POLICY; + } + +} diff --git a/teamcenter/src/test/java/com/capgemini/reports/users/SnecmaPersonTest.java b/teamcenter/src/test/java/com/capgemini/reports/users/SnecmaPersonTest.java new file mode 100644 index 0000000..ae10cf8 --- /dev/null +++ b/teamcenter/src/test/java/com/capgemini/reports/users/SnecmaPersonTest.java @@ -0,0 +1,41 @@ +package com.capgemini.reports.users; + +import com.capgemini.framework.teamcenter.exceptions.NoTeamcenterConnectionException; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.framework.teamcenter.queries.saved.modelobject.ItemRevisionQuery; +import com.capgemini.reports.AbstractTeamcenterTest; +import com.teamcenter.soa.client.model.ModelObject; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import com.teamcenter.soa.client.model.strong.Person; +import com.teamcenter.soa.client.model.strong.User; +import org.junit.Assert; +import org.junit.Test; + + +public class SnecmaPersonTest extends AbstractTeamcenterTest { + + /** + * JUnit test. + * @throws NoTeamcenterConnectionException Should not happen + */ + @Test + public void testBuild() throws NoTeamcenterConnectionException { + ItemRevision result = new ItemRevisionQuery(getSession()).searchIDAndRevision("INITB0204", "A").findAll().get(0); + Assert.assertNotNull(result); + + User user = (User) result.get_owning_user(); + Assert.assertNotNull(user); + + ModelObject personObject = user.get_person(); + Assert.assertNotNull(personObject); + + SnecmaPerson person = new SnecmaPerson((Person) personObject); + Assert.assertNotNull(person); + Assert.assertEquals("sp0mig11", person.getPersonName()); + } + + @Override + public PolicyLocation getPropertyPolicyIdentifier() { + return R13_POLICY_FULL; + } +} diff --git a/teamcenter/src/test/java/com/capgemini/reports/users/SnecmaUserTest.java b/teamcenter/src/test/java/com/capgemini/reports/users/SnecmaUserTest.java new file mode 100644 index 0000000..9de7d3d --- /dev/null +++ b/teamcenter/src/test/java/com/capgemini/reports/users/SnecmaUserTest.java @@ -0,0 +1,38 @@ +package com.capgemini.reports.users; + +import com.capgemini.framework.teamcenter.exceptions.NoTeamcenterConnectionException; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.framework.teamcenter.queries.saved.modelobject.ItemRevisionQuery; +import com.capgemini.reports.AbstractTeamcenterTest; +import com.teamcenter.soa.client.model.strong.ItemRevision; +import com.teamcenter.soa.client.model.strong.User; +import org.junit.Assert; +import org.junit.Test; + + +public class SnecmaUserTest extends AbstractTeamcenterTest { + + /** + * JUnit test. + * @throws NoTeamcenterConnectionException Should not happen + */ + @Test + public void testBuild() throws NoTeamcenterConnectionException { + ItemRevision result = new ItemRevisionQuery(getSession()).searchIDAndRevision("INITB0204", "A").findAll().get(0); + Assert.assertNotNull(result); + + User userObject = (User) result.get_owning_user(); + Assert.assertNotNull(userObject); + + SnecmaUser user = new SnecmaUser(getSession(), userObject); + Assert.assertNotNull(user); + Assert.assertEquals("sp0mig11", user.getUserId()); + Assert.assertEquals("sp0mig11", user.getName()); + Assert.assertNotNull(user.getPerson()); + } + + @Override + public PolicyLocation getPropertyPolicyIdentifier() { + return R13_POLICY_FULL; + } +} diff --git a/teamcenter/src/test/java/com/capgemini/reports/workflows/TaskTest.java b/teamcenter/src/test/java/com/capgemini/reports/workflows/TaskTest.java new file mode 100644 index 0000000..03b0005 --- /dev/null +++ b/teamcenter/src/test/java/com/capgemini/reports/workflows/TaskTest.java @@ -0,0 +1,87 @@ +package com.capgemini.reports.workflows; + +import com.capgemini.framework.teamcenter.exceptions.NoTeamcenterConnectionException; +import com.capgemini.framework.teamcenter.policies.PolicyLocation; +import com.capgemini.reports.AbstractTeamcenterTest; +import com.capgemini.reports.exceptions.NotFoundException; +import com.capgemini.reports.teamcenter.queries.DirectQuery; +import com.capgemini.reports.teamcenter.queries.saved.WorkflowOnChangeQuery; +import com.capgemini.reports.users.SnecmaUser; +import com.capgemini.reports.workflows.Task.TaskState; +import com.teamcenter.soa.client.model.strong.EPMTask; +import org.junit.Assert; +import org.junit.Test; + +import java.util.List; + +public class TaskTest extends AbstractTeamcenterTest { + + @Test + public void testBuildDaughterTask() throws NoTeamcenterConnectionException, NotFoundException { + DirectQuery taskQuery = new DirectQuery<>(getSession()); + EPMTask task = taskQuery.searchByUID("iOeZxqYwhLofXA"); // iOeZxqYwhLofXA <-- Add TcReleaseStatus Task + getSession().loadProperties(task,"state","creation_date","last_mod_date"); + Assert.assertNotNull(task); + Task motherTask = new Task(getSession(), task); + // State + Assert.assertEquals(TaskState.COMPLETED, motherTask.getState()); + // No active Tasks in this simple task + List activeTasks = motherTask.getActiveChildTasks(); + Assert.assertNotNull(activeTasks); + Assert.assertTrue(activeTasks.isEmpty()); + // Dates duly created + Assert.assertNotNull(motherTask.getCreationDate()); + Assert.assertNotNull(motherTask.getLastModDate()); + Assert.assertNotNull(motherTask.getLastModUser()); + // No Signoff users + Assert.assertNotNull(motherTask.getPendingSignoffsUser()); + Assert.assertTrue(motherTask.getPendingSignoffsUser().isEmpty()); + } + + @Test + public void testBuildTaskWithValidAndInvalidSignoffs() throws NoTeamcenterConnectionException, NotFoundException { + DirectQuery taskQuery = new DirectQuery<>(getSession()); + EPMTask task = taskQuery.searchByUID("jQXZxqYwhLofXA"); // jQXZxqYwhLofXA <-- EPMSelectSignoffTask select-signoff-team + Assert.assertNotNull(task); + getSession().loadProperties(task,"state","creation_date","last_mod_date"); + Task motherTask = new Task(getSession(), task); + // State + Assert.assertEquals(TaskState.COMPLETED, motherTask.getState()); + // No active Tasks in this simple task + List activeTasks = motherTask.getActiveChildTasks(); + Assert.assertNotNull(activeTasks); + Assert.assertTrue(activeTasks.isEmpty()); + // Mother task is its own parent + // Dates duly created + Assert.assertNotNull(motherTask.getCreationDate()); + Assert.assertNotNull(motherTask.getLastModDate()); + Assert.assertNotNull(motherTask.getLastModUser()); + // Signoff users: invalid + Assert.assertNotNull(motherTask.getPendingSignoffsUser()); + Assert.assertEquals(1, motherTask.getPendingSignoffsUser().size()); + for (SnecmaUser user : motherTask.getPendingSignoffsUser()) { + Assert.assertNotNull(user); + Assert.assertEquals("mbo", user.getUserId()); + } + } + + + @Test + public void testBuild() throws NoTeamcenterConnectionException { + WorkflowOnChangeQuery query = new WorkflowOnChangeQuery(getSession()); + query.searchIDAndRevision("MOD200478", "AA"); + List tasksList = query.findAll(); + EPMTask theMotherTask = null; + for (EPMTask epmTask : tasksList) { + if ("TEXZxqYwhLofXA".equals(epmTask.getUid())) { + theMotherTask = epmTask; + } + } + Assert.assertNotNull(theMotherTask); + } + + @Override + public PolicyLocation getPropertyPolicyIdentifier() { + return R13_POLICY_FULL; + } +} diff --git a/teamcenter/src/test/resources/TextFile.txt b/teamcenter/src/test/resources/TextFile.txt new file mode 100644 index 0000000..c57eff5 --- /dev/null +++ b/teamcenter/src/test/resources/TextFile.txt @@ -0,0 +1 @@ +Hello World! \ No newline at end of file diff --git a/teamcenter/src/test/resources/jasperPdfPrinterTest.pdf b/teamcenter/src/test/resources/jasperPdfPrinterTest.pdf new file mode 100644 index 0000000000000000000000000000000000000000..42a49af9a4aa3ccff1dd3bd65bb0386e3e53c132 GIT binary patch literal 2219 zcmaJ@dsGu=7MJ=ujfj1~QdVlGo}xTXn3<5tV+*k%4@3dO5FTp;9g+_W4VgF@5JE(c zIZ|3IIeU)ubg4&y9<7Sm>TWSTl}PE9_Q=Wt+tL>mL_~sGt4m5jW!Y~6HP-Ig@1JkJ zJKz1?dw;(>H;K|H)qFf&$cwr<+WQ4B0l^Tuu!NVGh^7H^F}o9yN=2yJXkr0_s!bFN zlt51#fJ|m(89JY9+zZyPXyvlhEt-43Pkjvk&r+0jd+ud_gK@7qZcloADpufzSleY@u8HW=E1lWirAnvCJBHX|@;C2! z^}MD&T;D%g(=v`{7G(RLt2^Qj^IX)d-S?9{?)Ztf=+UML_qI;=*{ms@{B*4%a*=03 zqo(aQ_7&XndAmaT>bl(PzMI-Q)A#NDQj_x=`pxjh(WNSM-JbqB{<>2Gp&n0;>?LbQ zL(u8#I;m>FzM7a7eR-!;!@(U?D19wFPp$WCkY}HFX_)QletlKPo9w66ueNLIb3blL zscA`hJDLph>{B@}&E_mSbA;{+&7O39?HkPNbT{YvK^!T*c3#pd?|}kmfj7uA(ez61 zVq4R(RfW4boW4jj+SWV}?&*`a99Kvys$BM+JseacJr+9f@6wHp)$f!{i(>D)kett6 ze9@MApdi_|KL{qJ3bQ@gzhbI-^>pp*R~5~X@7JoFD^*TB^K^_2qU`V&HLk;9QJWj9 z2XpT5S9Mp%)i&%xluoVp>88&eYm(MLx|&{bE=ubA*YeEBIn?L63#DxG?s^Zk9dzuC z5Bbk{g}i?;-_>kb)H;)sk;xzat0Z!G=3MKDZkH^?uilkdM|NxQXW7eE=R_QA4bE{1 zp399eZ3EYkH%8}@R|E&UEkC2F{c;bbi>qV>DLJTl@Mv;LiH+(4-qbshpNOTe>>uI0l=J zi4L_log9N2w%Ipdwb;i8oA=YHhn)_3=~+R@huz3Pti#eEugP9E66?^m27i*hEFw2T zT6=YRZ!>I)?z<(;-pntLXWgD(KTry53$}N6!WA?yY{A2h4_r z&mBH-;{gwhi4=w|v%qnot+W8te?S#ks1lSL^?*!CMzc^YLz%4>iUDSQrA&ruxF;47 zLI@I7&}J5%tOz%F$axSARSZxqRcM92B(TzDj2>8F1Pw#$vjB_eP&l&?R0}Ft1Whf4 zx04rk#loJN4}ncIlVzdw0D3-}5X?XggF>qsM+96{8C+;OFc_(1xximYc1{hv%%aLYAYG;}j2s<|tdhP1WXUqXqGJyf`L6niW=E2C2o- z%|?TDKEeEeyC~qEL6rilE_xHWT_aCXZI@>#Hf|xeW83iw*O}jb=7WPnkFZF!|?SOwmt^+2ZMP3_f{ay z3Roi#LvW0TJzR*0AQA|q2wAY81AEyVoLmLP)a{@RAYj2^e)LIQTzukYar0?5u| zHsXKy5~APU6JfBAAM+JskL1EKl+gqj?jHe3(=5X2O`@qvM3;yW59?Xpjmi zj1VUPOezo-5fmoCFj*qN5`+dI6(l4S3J8N#B*Y0I72`z|VUSP~kwlh{rkaargj1J9 cvy3(Xse^1 + + + + + + + + + + + + + + + + + + diff --git a/teamcenter/src/test/resources/xml/policies/PoliciesDomParserTest.xml b/teamcenter/src/test/resources/xml/policies/PoliciesDomParserTest.xml new file mode 100644 index 0000000..735c1ee --- /dev/null +++ b/teamcenter/src/test/resources/xml/policies/PoliciesDomParserTest.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/teamcenter/src/test/resources/xml/policies/bom_policy.xml b/teamcenter/src/test/resources/xml/policies/bom_policy.xml new file mode 100644 index 0000000..761b32a --- /dev/null +++ b/teamcenter/src/test/resources/xml/policies/bom_policy.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/teamcenter/src/test/resources/xml/policies/policy_full.xml b/teamcenter/src/test/resources/xml/policies/policy_full.xml new file mode 100644 index 0000000..ba90d89 --- /dev/null +++ b/teamcenter/src/test/resources/xml/policies/policy_full.xml @@ -0,0 +1,167 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/teamcenter/src/test/resources/xml/policies/policy_light.xml b/teamcenter/src/test/resources/xml/policies/policy_light.xml new file mode 100644 index 0000000..1354d8a --- /dev/null +++ b/teamcenter/src/test/resources/xml/policies/policy_light.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/teamcenter/src/test/resources/xml/policies/test_policy.xml b/teamcenter/src/test/resources/xml/policies/test_policy.xml new file mode 100644 index 0000000..6c3eadd --- /dev/null +++ b/teamcenter/src/test/resources/xml/policies/test_policy.xml @@ -0,0 +1,159 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/teamcenter/src/test/resources/xml/ref/MultiStructureServiceCallerTest_item.xml b/teamcenter/src/test/resources/xml/ref/MultiStructureServiceCallerTest_item.xml new file mode 100644 index 0000000..330a174 --- /dev/null +++ b/teamcenter/src/test/resources/xml/ref/MultiStructureServiceCallerTest_item.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/teamcenter/src/test/resources/xml/ref/MultiStructureServiceCallerTest_item_revision.xml b/teamcenter/src/test/resources/xml/ref/MultiStructureServiceCallerTest_item_revision.xml new file mode 100644 index 0000000..7f03594 --- /dev/null +++ b/teamcenter/src/test/resources/xml/ref/MultiStructureServiceCallerTest_item_revision.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/teamcenter/src/test/resources/xml/ref/StructureServiceCallerTest_mono.xml b/teamcenter/src/test/resources/xml/ref/StructureServiceCallerTest_mono.xml new file mode 100644 index 0000000..173cb9c --- /dev/null +++ b/teamcenter/src/test/resources/xml/ref/StructureServiceCallerTest_mono.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + diff --git a/teamcenter/src/test/resources/xml/ref/StructureServiceCallerTest_multi.xml b/teamcenter/src/test/resources/xml/ref/StructureServiceCallerTest_multi.xml new file mode 100644 index 0000000..76289d3 --- /dev/null +++ b/teamcenter/src/test/resources/xml/ref/StructureServiceCallerTest_multi.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + diff --git a/teamcenter/src/test/resources/xml/ref/TripleStructureServiceCallerTest_item.xml b/teamcenter/src/test/resources/xml/ref/TripleStructureServiceCallerTest_item.xml new file mode 100644 index 0000000..7db0976 --- /dev/null +++ b/teamcenter/src/test/resources/xml/ref/TripleStructureServiceCallerTest_item.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + diff --git a/teamcenter/src/test/resources/xml/ref/TripleStructureServiceCallerTest_item_revision.xml b/teamcenter/src/test/resources/xml/ref/TripleStructureServiceCallerTest_item_revision.xml new file mode 100644 index 0000000..e69de29

  • " + "Lien de relance : " + relaunchURL + ""; + } + +} diff --git a/kurt-utility/src/main/java/com/capgemini/reports/emailing/templates/FailedWorkflowEmailTemplateAdmin.java b/kurt-utility/src/main/java/com/capgemini/reports/emailing/templates/FailedWorkflowEmailTemplateAdmin.java new file mode 100644 index 0000000..2684f27 --- /dev/null +++ b/kurt-utility/src/main/java/com/capgemini/reports/emailing/templates/FailedWorkflowEmailTemplateAdmin.java @@ -0,0 +1,26 @@ +package com.capgemini.reports.emailing.templates; + +/** + * In case report triggered by a workflow fails, this email is sent to the administrators. + */ +public class FailedWorkflowEmailTemplateAdmin extends FailedEmailTemplateAdmin { + + /** + * Constructor. + * + * @param completeReportName the complete report name (like 'R22 - BOM Par Date') + * @param postingTime the time at which the report has been posted + * @param startTime the time at which the report has started to execute + * @param failureTime the he time at which the report has failed + * @param errorMessage the error message + * @param relaunchURL a URL that the admins may use to re-launch this report with the same parameters + */ + public FailedWorkflowEmailTemplateAdmin(final String completeReportName, final String postingTime, final String startTime, + final String failureTime, final String errorMessage, final String relaunchURL) { + super(completeReportName, postingTime, startTime, failureTime, makeErrorMessageFromFailure(errorMessage, relaunchURL)); + } + + private static String makeErrorMessageFromFailure(final String errorMessage, final String relaunchURL) { + return "Description de l'erreur : " + errorMessage + "

  • >mR~!+N+%U*IfjeGQ`n_Qyh-?(UVNwRvL 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ⅈ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