@Test @RunWithCustomExecutor public void givenSipWhenUnitsLinkedToOneDataObjectGroupThenDipContainOneDataObjectGroupElement() throws Exception { HandlerIO handlerIO = mock(HandlerIO.class); MetaDataClient metaDataClient = mock(MetaDataClient.class); given(metaDataClientFactory.getClient()).willReturn(metaDataClient); VitamThreadUtils.getVitamSession().setTenantId(TENANT_ID); AccessContractModel accessContractModel = new AccessContractModel(); accessContractModel.setEveryDataObjectVersion(false); accessContractModel.setDataObjectVersion(new HashSet<>(Arrays.asList("PhysicalMaster", "BinaryMaster_1"))); accessContractModel.setEveryOriginatingAgency(true); VitamThreadUtils.getVitamSession().setContract(accessContractModel); JsonNode queryUnit = JsonHandler.getFromInputStream(getClass().getResourceAsStream("/CreateManifest/querybug5160.json")); JsonNode queryUnitWithTree = JsonHandler.getFromInputStream( getClass().getResourceAsStream("/CreateManifest/queryWithTreeProjectionbug5160.json")); JsonNode queryObjectGroup = JsonHandler .getFromInputStream(getClass().getResourceAsStream("/CreateManifest/queryObjectGroupbug5160.json")); given(handlerIO.getJsonFromWorkspace("query.json")).willReturn(queryUnit); given(metaDataClient.selectUnits(queryUnit.deepCopy())).willReturn( JsonHandler .getFromInputStream(getClass().getResourceAsStream("/CreateManifest/resultMetadatabug5160.json"))); given(metaDataClient.selectUnits(queryUnitWithTree)).willReturn( JsonHandler .getFromInputStream(getClass().getResourceAsStream("/CreateManifest/resultMetadatabug5160.json"))); given(metaDataClient.selectObjectGroups(queryObjectGroup)).willReturn( JsonHandler .getFromInputStream(getClass().getResourceAsStream("/CreateManifest/resultObjectGroup5160.json"))); File manifestFile = tempFolder.newFile(); given(handlerIO.getOutput(MANIFEST_XML_RANK)) .willReturn(new ProcessingUri(UriPrefix.WORKSPACE, manifestFile.getPath())); given(handlerIO.getNewLocalFile(manifestFile.getPath())).willReturn(manifestFile); File reportFile = tempFolder.newFile(); given(handlerIO.getOutput(REPORT)).willReturn(new ProcessingUri(UriPrefix.WORKSPACE, reportFile.getPath())); given(handlerIO.getNewLocalFile(reportFile.getPath())).willReturn(reportFile); File guidToPathFile = tempFolder.newFile(); given(handlerIO.getOutput(GUID_TO_INFO_RANK)) .willReturn(new ProcessingUri(UriPrefix.WORKSPACE, guidToPathFile.getPath())); given(handlerIO.getNewLocalFile(guidToPathFile.getPath())).willReturn(guidToPathFile); File binaryFile = tempFolder.newFile(); given(handlerIO.getOutput(BINARIES_RANK)) .willReturn(new ProcessingUri(UriPrefix.WORKSPACE, binaryFile.getPath())); given(handlerIO.getNewLocalFile(binaryFile.getPath())).willReturn(binaryFile); ExportRequest exportRequest = new ExportRequest(); exportRequest.setExportWithLogBookLFC(true); exportRequest.setDslRequest(queryUnit); given(handlerIO.getJsonFromWorkspace("export_query.json")).willReturn(JsonHandler.toJsonNode(exportRequest)); ItemStatus itemStatus = createManifest.execute(WorkerParametersFactory.newWorkerParameters(), handlerIO); assertThat(itemStatus.getGlobalStatus()).isEqualTo(StatusCode.OK); Assert.assertThat(StringUtils.countMatches(Files.readAllLines(Paths.get(manifestFile.getPath()), Charset.defaultCharset()).get(0), "<DataObjectGroup id=\"aebaaaaaaefjz7wkabvpoalnfgzdwfyaaaaq\">"), equalTo(1)); }
@Override public ItemStatus execute(WorkerParameters param, HandlerIO handlerIO) throws ProcessingException { final ItemStatus itemStatus = new ItemStatus(CREATE_MANIFEST); File manifestFile = handlerIO.getNewLocalFile(handlerIO.getOutput(MANIFEST_XML_RANK).getPath()); File report = handlerIO.getNewLocalFile(handlerIO.getOutput(REPORT).getPath()); try (MetaDataClient client = metaDataClientFactory.getClient(); OutputStream outputStream = new FileOutputStream(manifestFile); FileOutputStream fileOutputStream = new FileOutputStream(report); FileInputStream reportFile = new FileInputStream(report); BufferedOutputStream buffOut = new BufferedOutputStream(fileOutputStream); ManifestBuilder manifestBuilder = new ManifestBuilder(outputStream)) { ExportRequest exportRequest = JsonHandler .getFromJsonNode(handlerIO.getJsonFromWorkspace(EXPORT_QUERY_FILE_NAME), ExportRequest.class); TransferReportHeader reportHeader = new TransferReportHeader(exportRequest.getDslRequest()); if (ArchiveTransfer.equals(exportRequest.getExportType())) { buffOut.write(unprettyPrint(JsonHandler.createObjectNode()).getBytes(UTF_8)); buffOut.write(System.lineSeparator().getBytes(StandardCharsets.UTF_8)); buffOut.write(unprettyPrint(reportHeader).getBytes(StandardCharsets.UTF_8)); buffOut.write(System.lineSeparator().getBytes(StandardCharsets.UTF_8)); } switch (exportRequest.getExportType()) { case ArchiveDeliveryRequestReply: case ArchiveTransfer: manifestBuilder.validate(exportRequest.getExportType(), exportRequest.getExportRequestParameters()); break; default: break; } manifestBuilder.startDocument(param.getContainerName(), exportRequest.getExportType(), exportRequest.getExportRequestParameters()); ListMultimap<String, String> multimap = ArrayListMultimap.create(); Set<String> originatingAgencies = new HashSet<>(); String originatingAgency = VitamConfiguration.getDefaultOriginatingAgencyForExport( ParameterHelper.getTenantParameter()); Map<String, String> ogs = new HashMap<>(); SelectParserMultiple parser = new SelectParserMultiple(); parser.parse(exportRequest.getDslRequest()); SelectMultiQuery request = parser.getRequest(); request.setProjection(projection); ScrollSpliterator<JsonNode> scrollRequest = ScrollSpliteratorHelper .createUnitScrollSplitIterator(client, request); StreamSupport.stream(scrollRequest, false) .forEach(item -> createGraph(multimap, originatingAgencies, ogs, item)); if (checkNumberOfUnit(itemStatus, scrollRequest.estimateSize())) { return new ItemStatus(CREATE_MANIFEST).setItemsStatus(CREATE_MANIFEST, itemStatus); } if (originatingAgencies.size() == 1) { originatingAgency = Iterables.getOnlyElement(originatingAgencies); } manifestBuilder.startDataObjectPackage(); Select select = new Select(); Map<String, JsonNode> idBinaryWithFileName = new HashMap<>(); boolean exportWithLogBookLFC = exportRequest.isExportWithLogBookLFC(); Set<String> dataObjectVersions = Objects.nonNull(exportRequest.getDataObjectVersionToExport()) ? exportRequest.getDataObjectVersionToExport().getDataObjectVersions() : Collections.emptySet(); Iterable<List<Entry<String, String>>> partitions = partition(ogs.entrySet(), MAX_ELEMENT_IN_QUERY); for (List<Entry<String, String>> partition : partitions) { ListMultimap<String, String> unitsForObjectGroupId = partition.stream() .collect( ArrayListMultimap::create, (map, entry) -> map.put(entry.getValue(), entry.getKey()), (list1, list2) -> list1.putAll(list2) ); InQuery in = QueryHelper.in(id(), partition.stream().map(Entry::getValue).toArray(String[]::new)); select.setQuery(in); JsonNode response = client.selectObjectGroups(select.getFinalSelect()); ArrayNode objects = (ArrayNode) response.get("$results"); for (JsonNode object : objects) { List<String> linkedUnits = unitsForObjectGroupId.get( object.get(ParserTokens.PROJECTIONARGS.ID.exactToken()).textValue()); idBinaryWithFileName.putAll(manifestBuilder .writeGOT(object, linkedUnits.get(linkedUnits.size() - 1), dataObjectVersions, exportWithLogBookLFC)); } } storeBinaryInformationOnWorkspace(handlerIO, idBinaryWithFileName); SelectParserMultiple initialQueryParser = new SelectParserMultiple(); initialQueryParser.parse(exportRequest.getDslRequest()); scrollRequest = new ScrollSpliterator<>(initialQueryParser.getRequest(), query -> { try { JsonNode node = client.selectUnits(query.getFinalSelect()); return RequestResponseOK.getFromJsonNode(node); } catch (MetaDataExecutionException | MetaDataDocumentSizeException | MetaDataClientServerException | InvalidParseOperationException e) { throw new IllegalStateException(e); } }, VitamConfiguration.getElasticSearchScrollTimeoutInMilliseconds(), VitamConfiguration.getElasticSearchScrollLimit()); manifestBuilder.startDescriptiveMetadata(); StreamSupport.stream(scrollRequest, false) .forEach(result -> { try { ArchiveUnitModel unit = manifestBuilder.writeArchiveUnit(result, multimap, ogs, exportWithLogBookLFC); if (ArchiveTransfer.equals(exportRequest.getExportType())) { List<String> opts = ListUtils.defaultIfNull(unit.getOpts(), new ArrayList<>()); TransferStatus status = opts.isEmpty()? TransferStatus.OK: TransferStatus.ALREADY_IN_TRANSFER; opts.add(param.getContainerName()); ObjectNode updateMultiQuery = getUpdateQuery(opts); if (TransferStatus.ALREADY_IN_TRANSFER.equals(status)) { itemStatus.increment(StatusCode.WARNING); ObjectNode infoNode = JsonHandler.createObjectNode(); infoNode.put(REASON_FIELD, String.format("unit %s already in transfer", unit.getId())); String evDetData = JsonHandler.unprettyPrint(infoNode); itemStatus.setEvDetailData(evDetData); } client.updateUnitById(updateMultiQuery, unit.getId()); TransferReportLine reportLine = new TransferReportLine(unit.getId(), status); buffOut.write(unprettyPrint(reportLine).getBytes(StandardCharsets.UTF_8)); buffOut.write(System.lineSeparator().getBytes(StandardCharsets.UTF_8)); } } catch (JAXBException | DatatypeConfigurationException | IOException | ProcessingException | InvalidParseOperationException | InvalidCreateOperationException | MetaDataNotFoundException | MetaDataExecutionException | MetaDataDocumentSizeException | MetaDataClientServerException e) { throw new IllegalArgumentException(e); } }); buffOut.flush(); manifestBuilder.endDescriptiveMetadata(); switch (exportRequest.getExportType()) { case ArchiveTransfer: originatingAgency = exportRequest.getExportRequestParameters().getOriginatingAgencyIdentifier(); break; case ArchiveDeliveryRequestReply: if (Strings.isNullOrEmpty(originatingAgency)) { originatingAgency = exportRequest.getExportRequestParameters().getOriginatingAgencyIdentifier(); } break; default: break; } String submissionAgencyIdentifier = exportRequest.getExportRequestParameters() != null ? exportRequest.getExportRequestParameters().getSubmissionAgencyIdentifier() : null; manifestBuilder .writeManagementMetadata(originatingAgency, submissionAgencyIdentifier); manifestBuilder.endDataObjectPackage(); switch (exportRequest.getExportType()) { case ArchiveDeliveryRequestReply: case ArchiveTransfer: if (Strings.isNullOrEmpty(exportRequest.getExportRequestParameters().getTransferringAgency())) { exportRequest.getExportRequestParameters() .setTransferringAgency(VitamConfiguration.getVitamDefaultTransferringAgency()); } manifestBuilder .writeFooter(exportRequest.getExportType(), exportRequest.getExportRequestParameters()); break; default: break; } manifestBuilder.closeManifest(); handlerIO.addOutputResult(MANIFEST_XML_RANK, manifestFile, true, false); itemStatus.increment(StatusCode.OK); if (ArchiveTransfer.equals(exportRequest.getExportType())) { handlerIO.transferInputStreamToWorkspace(handlerIO.getContainerName() + JSONL_EXTENSION, reportFile, null, false); } } catch (ExportException e) { itemStatus.increment(StatusCode.KO); ObjectNode infoNode = JsonHandler.createObjectNode(); infoNode.put(REASON_FIELD, e.getMessage()); String evDetData = JsonHandler.unprettyPrint(infoNode); itemStatus.setEvDetailData(evDetData); } catch (IOException | MetaDataExecutionException | InvalidCreateOperationException | MetaDataClientServerException | XMLStreamException | JAXBException | MetaDataDocumentSizeException | InvalidParseOperationException e) { throw new ProcessingException(e); } return new ItemStatus(CREATE_MANIFEST).setItemsStatus(CREATE_MANIFEST, itemStatus); }
CreateManifest extends ActionHandler { @Override public ItemStatus execute(WorkerParameters param, HandlerIO handlerIO) throws ProcessingException { final ItemStatus itemStatus = new ItemStatus(CREATE_MANIFEST); File manifestFile = handlerIO.getNewLocalFile(handlerIO.getOutput(MANIFEST_XML_RANK).getPath()); File report = handlerIO.getNewLocalFile(handlerIO.getOutput(REPORT).getPath()); try (MetaDataClient client = metaDataClientFactory.getClient(); OutputStream outputStream = new FileOutputStream(manifestFile); FileOutputStream fileOutputStream = new FileOutputStream(report); FileInputStream reportFile = new FileInputStream(report); BufferedOutputStream buffOut = new BufferedOutputStream(fileOutputStream); ManifestBuilder manifestBuilder = new ManifestBuilder(outputStream)) { ExportRequest exportRequest = JsonHandler .getFromJsonNode(handlerIO.getJsonFromWorkspace(EXPORT_QUERY_FILE_NAME), ExportRequest.class); TransferReportHeader reportHeader = new TransferReportHeader(exportRequest.getDslRequest()); if (ArchiveTransfer.equals(exportRequest.getExportType())) { buffOut.write(unprettyPrint(JsonHandler.createObjectNode()).getBytes(UTF_8)); buffOut.write(System.lineSeparator().getBytes(StandardCharsets.UTF_8)); buffOut.write(unprettyPrint(reportHeader).getBytes(StandardCharsets.UTF_8)); buffOut.write(System.lineSeparator().getBytes(StandardCharsets.UTF_8)); } switch (exportRequest.getExportType()) { case ArchiveDeliveryRequestReply: case ArchiveTransfer: manifestBuilder.validate(exportRequest.getExportType(), exportRequest.getExportRequestParameters()); break; default: break; } manifestBuilder.startDocument(param.getContainerName(), exportRequest.getExportType(), exportRequest.getExportRequestParameters()); ListMultimap<String, String> multimap = ArrayListMultimap.create(); Set<String> originatingAgencies = new HashSet<>(); String originatingAgency = VitamConfiguration.getDefaultOriginatingAgencyForExport( ParameterHelper.getTenantParameter()); Map<String, String> ogs = new HashMap<>(); SelectParserMultiple parser = new SelectParserMultiple(); parser.parse(exportRequest.getDslRequest()); SelectMultiQuery request = parser.getRequest(); request.setProjection(projection); ScrollSpliterator<JsonNode> scrollRequest = ScrollSpliteratorHelper .createUnitScrollSplitIterator(client, request); StreamSupport.stream(scrollRequest, false) .forEach(item -> createGraph(multimap, originatingAgencies, ogs, item)); if (checkNumberOfUnit(itemStatus, scrollRequest.estimateSize())) { return new ItemStatus(CREATE_MANIFEST).setItemsStatus(CREATE_MANIFEST, itemStatus); } if (originatingAgencies.size() == 1) { originatingAgency = Iterables.getOnlyElement(originatingAgencies); } manifestBuilder.startDataObjectPackage(); Select select = new Select(); Map<String, JsonNode> idBinaryWithFileName = new HashMap<>(); boolean exportWithLogBookLFC = exportRequest.isExportWithLogBookLFC(); Set<String> dataObjectVersions = Objects.nonNull(exportRequest.getDataObjectVersionToExport()) ? exportRequest.getDataObjectVersionToExport().getDataObjectVersions() : Collections.emptySet(); Iterable<List<Entry<String, String>>> partitions = partition(ogs.entrySet(), MAX_ELEMENT_IN_QUERY); for (List<Entry<String, String>> partition : partitions) { ListMultimap<String, String> unitsForObjectGroupId = partition.stream() .collect( ArrayListMultimap::create, (map, entry) -> map.put(entry.getValue(), entry.getKey()), (list1, list2) -> list1.putAll(list2) ); InQuery in = QueryHelper.in(id(), partition.stream().map(Entry::getValue).toArray(String[]::new)); select.setQuery(in); JsonNode response = client.selectObjectGroups(select.getFinalSelect()); ArrayNode objects = (ArrayNode) response.get("$results"); for (JsonNode object : objects) { List<String> linkedUnits = unitsForObjectGroupId.get( object.get(ParserTokens.PROJECTIONARGS.ID.exactToken()).textValue()); idBinaryWithFileName.putAll(manifestBuilder .writeGOT(object, linkedUnits.get(linkedUnits.size() - 1), dataObjectVersions, exportWithLogBookLFC)); } } storeBinaryInformationOnWorkspace(handlerIO, idBinaryWithFileName); SelectParserMultiple initialQueryParser = new SelectParserMultiple(); initialQueryParser.parse(exportRequest.getDslRequest()); scrollRequest = new ScrollSpliterator<>(initialQueryParser.getRequest(), query -> { try { JsonNode node = client.selectUnits(query.getFinalSelect()); return RequestResponseOK.getFromJsonNode(node); } catch (MetaDataExecutionException | MetaDataDocumentSizeException | MetaDataClientServerException | InvalidParseOperationException e) { throw new IllegalStateException(e); } }, VitamConfiguration.getElasticSearchScrollTimeoutInMilliseconds(), VitamConfiguration.getElasticSearchScrollLimit()); manifestBuilder.startDescriptiveMetadata(); StreamSupport.stream(scrollRequest, false) .forEach(result -> { try { ArchiveUnitModel unit = manifestBuilder.writeArchiveUnit(result, multimap, ogs, exportWithLogBookLFC); if (ArchiveTransfer.equals(exportRequest.getExportType())) { List<String> opts = ListUtils.defaultIfNull(unit.getOpts(), new ArrayList<>()); TransferStatus status = opts.isEmpty()? TransferStatus.OK: TransferStatus.ALREADY_IN_TRANSFER; opts.add(param.getContainerName()); ObjectNode updateMultiQuery = getUpdateQuery(opts); if (TransferStatus.ALREADY_IN_TRANSFER.equals(status)) { itemStatus.increment(StatusCode.WARNING); ObjectNode infoNode = JsonHandler.createObjectNode(); infoNode.put(REASON_FIELD, String.format("unit %s already in transfer", unit.getId())); String evDetData = JsonHandler.unprettyPrint(infoNode); itemStatus.setEvDetailData(evDetData); } client.updateUnitById(updateMultiQuery, unit.getId()); TransferReportLine reportLine = new TransferReportLine(unit.getId(), status); buffOut.write(unprettyPrint(reportLine).getBytes(StandardCharsets.UTF_8)); buffOut.write(System.lineSeparator().getBytes(StandardCharsets.UTF_8)); } } catch (JAXBException | DatatypeConfigurationException | IOException | ProcessingException | InvalidParseOperationException | InvalidCreateOperationException | MetaDataNotFoundException | MetaDataExecutionException | MetaDataDocumentSizeException | MetaDataClientServerException e) { throw new IllegalArgumentException(e); } }); buffOut.flush(); manifestBuilder.endDescriptiveMetadata(); switch (exportRequest.getExportType()) { case ArchiveTransfer: originatingAgency = exportRequest.getExportRequestParameters().getOriginatingAgencyIdentifier(); break; case ArchiveDeliveryRequestReply: if (Strings.isNullOrEmpty(originatingAgency)) { originatingAgency = exportRequest.getExportRequestParameters().getOriginatingAgencyIdentifier(); } break; default: break; } String submissionAgencyIdentifier = exportRequest.getExportRequestParameters() != null ? exportRequest.getExportRequestParameters().getSubmissionAgencyIdentifier() : null; manifestBuilder .writeManagementMetadata(originatingAgency, submissionAgencyIdentifier); manifestBuilder.endDataObjectPackage(); switch (exportRequest.getExportType()) { case ArchiveDeliveryRequestReply: case ArchiveTransfer: if (Strings.isNullOrEmpty(exportRequest.getExportRequestParameters().getTransferringAgency())) { exportRequest.getExportRequestParameters() .setTransferringAgency(VitamConfiguration.getVitamDefaultTransferringAgency()); } manifestBuilder .writeFooter(exportRequest.getExportType(), exportRequest.getExportRequestParameters()); break; default: break; } manifestBuilder.closeManifest(); handlerIO.addOutputResult(MANIFEST_XML_RANK, manifestFile, true, false); itemStatus.increment(StatusCode.OK); if (ArchiveTransfer.equals(exportRequest.getExportType())) { handlerIO.transferInputStreamToWorkspace(handlerIO.getContainerName() + JSONL_EXTENSION, reportFile, null, false); } } catch (ExportException e) { itemStatus.increment(StatusCode.KO); ObjectNode infoNode = JsonHandler.createObjectNode(); infoNode.put(REASON_FIELD, e.getMessage()); String evDetData = JsonHandler.unprettyPrint(infoNode); itemStatus.setEvDetailData(evDetData); } catch (IOException | MetaDataExecutionException | InvalidCreateOperationException | MetaDataClientServerException | XMLStreamException | JAXBException | MetaDataDocumentSizeException | InvalidParseOperationException e) { throw new ProcessingException(e); } return new ItemStatus(CREATE_MANIFEST).setItemsStatus(CREATE_MANIFEST, itemStatus); } }
CreateManifest extends ActionHandler { @Override public ItemStatus execute(WorkerParameters param, HandlerIO handlerIO) throws ProcessingException { final ItemStatus itemStatus = new ItemStatus(CREATE_MANIFEST); File manifestFile = handlerIO.getNewLocalFile(handlerIO.getOutput(MANIFEST_XML_RANK).getPath()); File report = handlerIO.getNewLocalFile(handlerIO.getOutput(REPORT).getPath()); try (MetaDataClient client = metaDataClientFactory.getClient(); OutputStream outputStream = new FileOutputStream(manifestFile); FileOutputStream fileOutputStream = new FileOutputStream(report); FileInputStream reportFile = new FileInputStream(report); BufferedOutputStream buffOut = new BufferedOutputStream(fileOutputStream); ManifestBuilder manifestBuilder = new ManifestBuilder(outputStream)) { ExportRequest exportRequest = JsonHandler .getFromJsonNode(handlerIO.getJsonFromWorkspace(EXPORT_QUERY_FILE_NAME), ExportRequest.class); TransferReportHeader reportHeader = new TransferReportHeader(exportRequest.getDslRequest()); if (ArchiveTransfer.equals(exportRequest.getExportType())) { buffOut.write(unprettyPrint(JsonHandler.createObjectNode()).getBytes(UTF_8)); buffOut.write(System.lineSeparator().getBytes(StandardCharsets.UTF_8)); buffOut.write(unprettyPrint(reportHeader).getBytes(StandardCharsets.UTF_8)); buffOut.write(System.lineSeparator().getBytes(StandardCharsets.UTF_8)); } switch (exportRequest.getExportType()) { case ArchiveDeliveryRequestReply: case ArchiveTransfer: manifestBuilder.validate(exportRequest.getExportType(), exportRequest.getExportRequestParameters()); break; default: break; } manifestBuilder.startDocument(param.getContainerName(), exportRequest.getExportType(), exportRequest.getExportRequestParameters()); ListMultimap<String, String> multimap = ArrayListMultimap.create(); Set<String> originatingAgencies = new HashSet<>(); String originatingAgency = VitamConfiguration.getDefaultOriginatingAgencyForExport( ParameterHelper.getTenantParameter()); Map<String, String> ogs = new HashMap<>(); SelectParserMultiple parser = new SelectParserMultiple(); parser.parse(exportRequest.getDslRequest()); SelectMultiQuery request = parser.getRequest(); request.setProjection(projection); ScrollSpliterator<JsonNode> scrollRequest = ScrollSpliteratorHelper .createUnitScrollSplitIterator(client, request); StreamSupport.stream(scrollRequest, false) .forEach(item -> createGraph(multimap, originatingAgencies, ogs, item)); if (checkNumberOfUnit(itemStatus, scrollRequest.estimateSize())) { return new ItemStatus(CREATE_MANIFEST).setItemsStatus(CREATE_MANIFEST, itemStatus); } if (originatingAgencies.size() == 1) { originatingAgency = Iterables.getOnlyElement(originatingAgencies); } manifestBuilder.startDataObjectPackage(); Select select = new Select(); Map<String, JsonNode> idBinaryWithFileName = new HashMap<>(); boolean exportWithLogBookLFC = exportRequest.isExportWithLogBookLFC(); Set<String> dataObjectVersions = Objects.nonNull(exportRequest.getDataObjectVersionToExport()) ? exportRequest.getDataObjectVersionToExport().getDataObjectVersions() : Collections.emptySet(); Iterable<List<Entry<String, String>>> partitions = partition(ogs.entrySet(), MAX_ELEMENT_IN_QUERY); for (List<Entry<String, String>> partition : partitions) { ListMultimap<String, String> unitsForObjectGroupId = partition.stream() .collect( ArrayListMultimap::create, (map, entry) -> map.put(entry.getValue(), entry.getKey()), (list1, list2) -> list1.putAll(list2) ); InQuery in = QueryHelper.in(id(), partition.stream().map(Entry::getValue).toArray(String[]::new)); select.setQuery(in); JsonNode response = client.selectObjectGroups(select.getFinalSelect()); ArrayNode objects = (ArrayNode) response.get("$results"); for (JsonNode object : objects) { List<String> linkedUnits = unitsForObjectGroupId.get( object.get(ParserTokens.PROJECTIONARGS.ID.exactToken()).textValue()); idBinaryWithFileName.putAll(manifestBuilder .writeGOT(object, linkedUnits.get(linkedUnits.size() - 1), dataObjectVersions, exportWithLogBookLFC)); } } storeBinaryInformationOnWorkspace(handlerIO, idBinaryWithFileName); SelectParserMultiple initialQueryParser = new SelectParserMultiple(); initialQueryParser.parse(exportRequest.getDslRequest()); scrollRequest = new ScrollSpliterator<>(initialQueryParser.getRequest(), query -> { try { JsonNode node = client.selectUnits(query.getFinalSelect()); return RequestResponseOK.getFromJsonNode(node); } catch (MetaDataExecutionException | MetaDataDocumentSizeException | MetaDataClientServerException | InvalidParseOperationException e) { throw new IllegalStateException(e); } }, VitamConfiguration.getElasticSearchScrollTimeoutInMilliseconds(), VitamConfiguration.getElasticSearchScrollLimit()); manifestBuilder.startDescriptiveMetadata(); StreamSupport.stream(scrollRequest, false) .forEach(result -> { try { ArchiveUnitModel unit = manifestBuilder.writeArchiveUnit(result, multimap, ogs, exportWithLogBookLFC); if (ArchiveTransfer.equals(exportRequest.getExportType())) { List<String> opts = ListUtils.defaultIfNull(unit.getOpts(), new ArrayList<>()); TransferStatus status = opts.isEmpty()? TransferStatus.OK: TransferStatus.ALREADY_IN_TRANSFER; opts.add(param.getContainerName()); ObjectNode updateMultiQuery = getUpdateQuery(opts); if (TransferStatus.ALREADY_IN_TRANSFER.equals(status)) { itemStatus.increment(StatusCode.WARNING); ObjectNode infoNode = JsonHandler.createObjectNode(); infoNode.put(REASON_FIELD, String.format("unit %s already in transfer", unit.getId())); String evDetData = JsonHandler.unprettyPrint(infoNode); itemStatus.setEvDetailData(evDetData); } client.updateUnitById(updateMultiQuery, unit.getId()); TransferReportLine reportLine = new TransferReportLine(unit.getId(), status); buffOut.write(unprettyPrint(reportLine).getBytes(StandardCharsets.UTF_8)); buffOut.write(System.lineSeparator().getBytes(StandardCharsets.UTF_8)); } } catch (JAXBException | DatatypeConfigurationException | IOException | ProcessingException | InvalidParseOperationException | InvalidCreateOperationException | MetaDataNotFoundException | MetaDataExecutionException | MetaDataDocumentSizeException | MetaDataClientServerException e) { throw new IllegalArgumentException(e); } }); buffOut.flush(); manifestBuilder.endDescriptiveMetadata(); switch (exportRequest.getExportType()) { case ArchiveTransfer: originatingAgency = exportRequest.getExportRequestParameters().getOriginatingAgencyIdentifier(); break; case ArchiveDeliveryRequestReply: if (Strings.isNullOrEmpty(originatingAgency)) { originatingAgency = exportRequest.getExportRequestParameters().getOriginatingAgencyIdentifier(); } break; default: break; } String submissionAgencyIdentifier = exportRequest.getExportRequestParameters() != null ? exportRequest.getExportRequestParameters().getSubmissionAgencyIdentifier() : null; manifestBuilder .writeManagementMetadata(originatingAgency, submissionAgencyIdentifier); manifestBuilder.endDataObjectPackage(); switch (exportRequest.getExportType()) { case ArchiveDeliveryRequestReply: case ArchiveTransfer: if (Strings.isNullOrEmpty(exportRequest.getExportRequestParameters().getTransferringAgency())) { exportRequest.getExportRequestParameters() .setTransferringAgency(VitamConfiguration.getVitamDefaultTransferringAgency()); } manifestBuilder .writeFooter(exportRequest.getExportType(), exportRequest.getExportRequestParameters()); break; default: break; } manifestBuilder.closeManifest(); handlerIO.addOutputResult(MANIFEST_XML_RANK, manifestFile, true, false); itemStatus.increment(StatusCode.OK); if (ArchiveTransfer.equals(exportRequest.getExportType())) { handlerIO.transferInputStreamToWorkspace(handlerIO.getContainerName() + JSONL_EXTENSION, reportFile, null, false); } } catch (ExportException e) { itemStatus.increment(StatusCode.KO); ObjectNode infoNode = JsonHandler.createObjectNode(); infoNode.put(REASON_FIELD, e.getMessage()); String evDetData = JsonHandler.unprettyPrint(infoNode); itemStatus.setEvDetailData(evDetData); } catch (IOException | MetaDataExecutionException | InvalidCreateOperationException | MetaDataClientServerException | XMLStreamException | JAXBException | MetaDataDocumentSizeException | InvalidParseOperationException e) { throw new ProcessingException(e); } return new ItemStatus(CREATE_MANIFEST).setItemsStatus(CREATE_MANIFEST, itemStatus); } CreateManifest(); @VisibleForTesting  CreateManifest(MetaDataClientFactory metaDataClientFactory); }
CreateManifest extends ActionHandler { @Override public ItemStatus execute(WorkerParameters param, HandlerIO handlerIO) throws ProcessingException { final ItemStatus itemStatus = new ItemStatus(CREATE_MANIFEST); File manifestFile = handlerIO.getNewLocalFile(handlerIO.getOutput(MANIFEST_XML_RANK).getPath()); File report = handlerIO.getNewLocalFile(handlerIO.getOutput(REPORT).getPath()); try (MetaDataClient client = metaDataClientFactory.getClient(); OutputStream outputStream = new FileOutputStream(manifestFile); FileOutputStream fileOutputStream = new FileOutputStream(report); FileInputStream reportFile = new FileInputStream(report); BufferedOutputStream buffOut = new BufferedOutputStream(fileOutputStream); ManifestBuilder manifestBuilder = new ManifestBuilder(outputStream)) { ExportRequest exportRequest = JsonHandler .getFromJsonNode(handlerIO.getJsonFromWorkspace(EXPORT_QUERY_FILE_NAME), ExportRequest.class); TransferReportHeader reportHeader = new TransferReportHeader(exportRequest.getDslRequest()); if (ArchiveTransfer.equals(exportRequest.getExportType())) { buffOut.write(unprettyPrint(JsonHandler.createObjectNode()).getBytes(UTF_8)); buffOut.write(System.lineSeparator().getBytes(StandardCharsets.UTF_8)); buffOut.write(unprettyPrint(reportHeader).getBytes(StandardCharsets.UTF_8)); buffOut.write(System.lineSeparator().getBytes(StandardCharsets.UTF_8)); } switch (exportRequest.getExportType()) { case ArchiveDeliveryRequestReply: case ArchiveTransfer: manifestBuilder.validate(exportRequest.getExportType(), exportRequest.getExportRequestParameters()); break; default: break; } manifestBuilder.startDocument(param.getContainerName(), exportRequest.getExportType(), exportRequest.getExportRequestParameters()); ListMultimap<String, String> multimap = ArrayListMultimap.create(); Set<String> originatingAgencies = new HashSet<>(); String originatingAgency = VitamConfiguration.getDefaultOriginatingAgencyForExport( ParameterHelper.getTenantParameter()); Map<String, String> ogs = new HashMap<>(); SelectParserMultiple parser = new SelectParserMultiple(); parser.parse(exportRequest.getDslRequest()); SelectMultiQuery request = parser.getRequest(); request.setProjection(projection); ScrollSpliterator<JsonNode> scrollRequest = ScrollSpliteratorHelper .createUnitScrollSplitIterator(client, request); StreamSupport.stream(scrollRequest, false) .forEach(item -> createGraph(multimap, originatingAgencies, ogs, item)); if (checkNumberOfUnit(itemStatus, scrollRequest.estimateSize())) { return new ItemStatus(CREATE_MANIFEST).setItemsStatus(CREATE_MANIFEST, itemStatus); } if (originatingAgencies.size() == 1) { originatingAgency = Iterables.getOnlyElement(originatingAgencies); } manifestBuilder.startDataObjectPackage(); Select select = new Select(); Map<String, JsonNode> idBinaryWithFileName = new HashMap<>(); boolean exportWithLogBookLFC = exportRequest.isExportWithLogBookLFC(); Set<String> dataObjectVersions = Objects.nonNull(exportRequest.getDataObjectVersionToExport()) ? exportRequest.getDataObjectVersionToExport().getDataObjectVersions() : Collections.emptySet(); Iterable<List<Entry<String, String>>> partitions = partition(ogs.entrySet(), MAX_ELEMENT_IN_QUERY); for (List<Entry<String, String>> partition : partitions) { ListMultimap<String, String> unitsForObjectGroupId = partition.stream() .collect( ArrayListMultimap::create, (map, entry) -> map.put(entry.getValue(), entry.getKey()), (list1, list2) -> list1.putAll(list2) ); InQuery in = QueryHelper.in(id(), partition.stream().map(Entry::getValue).toArray(String[]::new)); select.setQuery(in); JsonNode response = client.selectObjectGroups(select.getFinalSelect()); ArrayNode objects = (ArrayNode) response.get("$results"); for (JsonNode object : objects) { List<String> linkedUnits = unitsForObjectGroupId.get( object.get(ParserTokens.PROJECTIONARGS.ID.exactToken()).textValue()); idBinaryWithFileName.putAll(manifestBuilder .writeGOT(object, linkedUnits.get(linkedUnits.size() - 1), dataObjectVersions, exportWithLogBookLFC)); } } storeBinaryInformationOnWorkspace(handlerIO, idBinaryWithFileName); SelectParserMultiple initialQueryParser = new SelectParserMultiple(); initialQueryParser.parse(exportRequest.getDslRequest()); scrollRequest = new ScrollSpliterator<>(initialQueryParser.getRequest(), query -> { try { JsonNode node = client.selectUnits(query.getFinalSelect()); return RequestResponseOK.getFromJsonNode(node); } catch (MetaDataExecutionException | MetaDataDocumentSizeException | MetaDataClientServerException | InvalidParseOperationException e) { throw new IllegalStateException(e); } }, VitamConfiguration.getElasticSearchScrollTimeoutInMilliseconds(), VitamConfiguration.getElasticSearchScrollLimit()); manifestBuilder.startDescriptiveMetadata(); StreamSupport.stream(scrollRequest, false) .forEach(result -> { try { ArchiveUnitModel unit = manifestBuilder.writeArchiveUnit(result, multimap, ogs, exportWithLogBookLFC); if (ArchiveTransfer.equals(exportRequest.getExportType())) { List<String> opts = ListUtils.defaultIfNull(unit.getOpts(), new ArrayList<>()); TransferStatus status = opts.isEmpty()? TransferStatus.OK: TransferStatus.ALREADY_IN_TRANSFER; opts.add(param.getContainerName()); ObjectNode updateMultiQuery = getUpdateQuery(opts); if (TransferStatus.ALREADY_IN_TRANSFER.equals(status)) { itemStatus.increment(StatusCode.WARNING); ObjectNode infoNode = JsonHandler.createObjectNode(); infoNode.put(REASON_FIELD, String.format("unit %s already in transfer", unit.getId())); String evDetData = JsonHandler.unprettyPrint(infoNode); itemStatus.setEvDetailData(evDetData); } client.updateUnitById(updateMultiQuery, unit.getId()); TransferReportLine reportLine = new TransferReportLine(unit.getId(), status); buffOut.write(unprettyPrint(reportLine).getBytes(StandardCharsets.UTF_8)); buffOut.write(System.lineSeparator().getBytes(StandardCharsets.UTF_8)); } } catch (JAXBException | DatatypeConfigurationException | IOException | ProcessingException | InvalidParseOperationException | InvalidCreateOperationException | MetaDataNotFoundException | MetaDataExecutionException | MetaDataDocumentSizeException | MetaDataClientServerException e) { throw new IllegalArgumentException(e); } }); buffOut.flush(); manifestBuilder.endDescriptiveMetadata(); switch (exportRequest.getExportType()) { case ArchiveTransfer: originatingAgency = exportRequest.getExportRequestParameters().getOriginatingAgencyIdentifier(); break; case ArchiveDeliveryRequestReply: if (Strings.isNullOrEmpty(originatingAgency)) { originatingAgency = exportRequest.getExportRequestParameters().getOriginatingAgencyIdentifier(); } break; default: break; } String submissionAgencyIdentifier = exportRequest.getExportRequestParameters() != null ? exportRequest.getExportRequestParameters().getSubmissionAgencyIdentifier() : null; manifestBuilder .writeManagementMetadata(originatingAgency, submissionAgencyIdentifier); manifestBuilder.endDataObjectPackage(); switch (exportRequest.getExportType()) { case ArchiveDeliveryRequestReply: case ArchiveTransfer: if (Strings.isNullOrEmpty(exportRequest.getExportRequestParameters().getTransferringAgency())) { exportRequest.getExportRequestParameters() .setTransferringAgency(VitamConfiguration.getVitamDefaultTransferringAgency()); } manifestBuilder .writeFooter(exportRequest.getExportType(), exportRequest.getExportRequestParameters()); break; default: break; } manifestBuilder.closeManifest(); handlerIO.addOutputResult(MANIFEST_XML_RANK, manifestFile, true, false); itemStatus.increment(StatusCode.OK); if (ArchiveTransfer.equals(exportRequest.getExportType())) { handlerIO.transferInputStreamToWorkspace(handlerIO.getContainerName() + JSONL_EXTENSION, reportFile, null, false); } } catch (ExportException e) { itemStatus.increment(StatusCode.KO); ObjectNode infoNode = JsonHandler.createObjectNode(); infoNode.put(REASON_FIELD, e.getMessage()); String evDetData = JsonHandler.unprettyPrint(infoNode); itemStatus.setEvDetailData(evDetData); } catch (IOException | MetaDataExecutionException | InvalidCreateOperationException | MetaDataClientServerException | XMLStreamException | JAXBException | MetaDataDocumentSizeException | InvalidParseOperationException e) { throw new ProcessingException(e); } return new ItemStatus(CREATE_MANIFEST).setItemsStatus(CREATE_MANIFEST, itemStatus); } CreateManifest(); @VisibleForTesting  CreateManifest(MetaDataClientFactory metaDataClientFactory); @Override ItemStatus execute(WorkerParameters param, HandlerIO handlerIO); @Override void checkMandatoryIOParameter(HandlerIO handler); }
CreateManifest extends ActionHandler { @Override public ItemStatus execute(WorkerParameters param, HandlerIO handlerIO) throws ProcessingException { final ItemStatus itemStatus = new ItemStatus(CREATE_MANIFEST); File manifestFile = handlerIO.getNewLocalFile(handlerIO.getOutput(MANIFEST_XML_RANK).getPath()); File report = handlerIO.getNewLocalFile(handlerIO.getOutput(REPORT).getPath()); try (MetaDataClient client = metaDataClientFactory.getClient(); OutputStream outputStream = new FileOutputStream(manifestFile); FileOutputStream fileOutputStream = new FileOutputStream(report); FileInputStream reportFile = new FileInputStream(report); BufferedOutputStream buffOut = new BufferedOutputStream(fileOutputStream); ManifestBuilder manifestBuilder = new ManifestBuilder(outputStream)) { ExportRequest exportRequest = JsonHandler .getFromJsonNode(handlerIO.getJsonFromWorkspace(EXPORT_QUERY_FILE_NAME), ExportRequest.class); TransferReportHeader reportHeader = new TransferReportHeader(exportRequest.getDslRequest()); if (ArchiveTransfer.equals(exportRequest.getExportType())) { buffOut.write(unprettyPrint(JsonHandler.createObjectNode()).getBytes(UTF_8)); buffOut.write(System.lineSeparator().getBytes(StandardCharsets.UTF_8)); buffOut.write(unprettyPrint(reportHeader).getBytes(StandardCharsets.UTF_8)); buffOut.write(System.lineSeparator().getBytes(StandardCharsets.UTF_8)); } switch (exportRequest.getExportType()) { case ArchiveDeliveryRequestReply: case ArchiveTransfer: manifestBuilder.validate(exportRequest.getExportType(), exportRequest.getExportRequestParameters()); break; default: break; } manifestBuilder.startDocument(param.getContainerName(), exportRequest.getExportType(), exportRequest.getExportRequestParameters()); ListMultimap<String, String> multimap = ArrayListMultimap.create(); Set<String> originatingAgencies = new HashSet<>(); String originatingAgency = VitamConfiguration.getDefaultOriginatingAgencyForExport( ParameterHelper.getTenantParameter()); Map<String, String> ogs = new HashMap<>(); SelectParserMultiple parser = new SelectParserMultiple(); parser.parse(exportRequest.getDslRequest()); SelectMultiQuery request = parser.getRequest(); request.setProjection(projection); ScrollSpliterator<JsonNode> scrollRequest = ScrollSpliteratorHelper .createUnitScrollSplitIterator(client, request); StreamSupport.stream(scrollRequest, false) .forEach(item -> createGraph(multimap, originatingAgencies, ogs, item)); if (checkNumberOfUnit(itemStatus, scrollRequest.estimateSize())) { return new ItemStatus(CREATE_MANIFEST).setItemsStatus(CREATE_MANIFEST, itemStatus); } if (originatingAgencies.size() == 1) { originatingAgency = Iterables.getOnlyElement(originatingAgencies); } manifestBuilder.startDataObjectPackage(); Select select = new Select(); Map<String, JsonNode> idBinaryWithFileName = new HashMap<>(); boolean exportWithLogBookLFC = exportRequest.isExportWithLogBookLFC(); Set<String> dataObjectVersions = Objects.nonNull(exportRequest.getDataObjectVersionToExport()) ? exportRequest.getDataObjectVersionToExport().getDataObjectVersions() : Collections.emptySet(); Iterable<List<Entry<String, String>>> partitions = partition(ogs.entrySet(), MAX_ELEMENT_IN_QUERY); for (List<Entry<String, String>> partition : partitions) { ListMultimap<String, String> unitsForObjectGroupId = partition.stream() .collect( ArrayListMultimap::create, (map, entry) -> map.put(entry.getValue(), entry.getKey()), (list1, list2) -> list1.putAll(list2) ); InQuery in = QueryHelper.in(id(), partition.stream().map(Entry::getValue).toArray(String[]::new)); select.setQuery(in); JsonNode response = client.selectObjectGroups(select.getFinalSelect()); ArrayNode objects = (ArrayNode) response.get("$results"); for (JsonNode object : objects) { List<String> linkedUnits = unitsForObjectGroupId.get( object.get(ParserTokens.PROJECTIONARGS.ID.exactToken()).textValue()); idBinaryWithFileName.putAll(manifestBuilder .writeGOT(object, linkedUnits.get(linkedUnits.size() - 1), dataObjectVersions, exportWithLogBookLFC)); } } storeBinaryInformationOnWorkspace(handlerIO, idBinaryWithFileName); SelectParserMultiple initialQueryParser = new SelectParserMultiple(); initialQueryParser.parse(exportRequest.getDslRequest()); scrollRequest = new ScrollSpliterator<>(initialQueryParser.getRequest(), query -> { try { JsonNode node = client.selectUnits(query.getFinalSelect()); return RequestResponseOK.getFromJsonNode(node); } catch (MetaDataExecutionException | MetaDataDocumentSizeException | MetaDataClientServerException | InvalidParseOperationException e) { throw new IllegalStateException(e); } }, VitamConfiguration.getElasticSearchScrollTimeoutInMilliseconds(), VitamConfiguration.getElasticSearchScrollLimit()); manifestBuilder.startDescriptiveMetadata(); StreamSupport.stream(scrollRequest, false) .forEach(result -> { try { ArchiveUnitModel unit = manifestBuilder.writeArchiveUnit(result, multimap, ogs, exportWithLogBookLFC); if (ArchiveTransfer.equals(exportRequest.getExportType())) { List<String> opts = ListUtils.defaultIfNull(unit.getOpts(), new ArrayList<>()); TransferStatus status = opts.isEmpty()? TransferStatus.OK: TransferStatus.ALREADY_IN_TRANSFER; opts.add(param.getContainerName()); ObjectNode updateMultiQuery = getUpdateQuery(opts); if (TransferStatus.ALREADY_IN_TRANSFER.equals(status)) { itemStatus.increment(StatusCode.WARNING); ObjectNode infoNode = JsonHandler.createObjectNode(); infoNode.put(REASON_FIELD, String.format("unit %s already in transfer", unit.getId())); String evDetData = JsonHandler.unprettyPrint(infoNode); itemStatus.setEvDetailData(evDetData); } client.updateUnitById(updateMultiQuery, unit.getId()); TransferReportLine reportLine = new TransferReportLine(unit.getId(), status); buffOut.write(unprettyPrint(reportLine).getBytes(StandardCharsets.UTF_8)); buffOut.write(System.lineSeparator().getBytes(StandardCharsets.UTF_8)); } } catch (JAXBException | DatatypeConfigurationException | IOException | ProcessingException | InvalidParseOperationException | InvalidCreateOperationException | MetaDataNotFoundException | MetaDataExecutionException | MetaDataDocumentSizeException | MetaDataClientServerException e) { throw new IllegalArgumentException(e); } }); buffOut.flush(); manifestBuilder.endDescriptiveMetadata(); switch (exportRequest.getExportType()) { case ArchiveTransfer: originatingAgency = exportRequest.getExportRequestParameters().getOriginatingAgencyIdentifier(); break; case ArchiveDeliveryRequestReply: if (Strings.isNullOrEmpty(originatingAgency)) { originatingAgency = exportRequest.getExportRequestParameters().getOriginatingAgencyIdentifier(); } break; default: break; } String submissionAgencyIdentifier = exportRequest.getExportRequestParameters() != null ? exportRequest.getExportRequestParameters().getSubmissionAgencyIdentifier() : null; manifestBuilder .writeManagementMetadata(originatingAgency, submissionAgencyIdentifier); manifestBuilder.endDataObjectPackage(); switch (exportRequest.getExportType()) { case ArchiveDeliveryRequestReply: case ArchiveTransfer: if (Strings.isNullOrEmpty(exportRequest.getExportRequestParameters().getTransferringAgency())) { exportRequest.getExportRequestParameters() .setTransferringAgency(VitamConfiguration.getVitamDefaultTransferringAgency()); } manifestBuilder .writeFooter(exportRequest.getExportType(), exportRequest.getExportRequestParameters()); break; default: break; } manifestBuilder.closeManifest(); handlerIO.addOutputResult(MANIFEST_XML_RANK, manifestFile, true, false); itemStatus.increment(StatusCode.OK); if (ArchiveTransfer.equals(exportRequest.getExportType())) { handlerIO.transferInputStreamToWorkspace(handlerIO.getContainerName() + JSONL_EXTENSION, reportFile, null, false); } } catch (ExportException e) { itemStatus.increment(StatusCode.KO); ObjectNode infoNode = JsonHandler.createObjectNode(); infoNode.put(REASON_FIELD, e.getMessage()); String evDetData = JsonHandler.unprettyPrint(infoNode); itemStatus.setEvDetailData(evDetData); } catch (IOException | MetaDataExecutionException | InvalidCreateOperationException | MetaDataClientServerException | XMLStreamException | JAXBException | MetaDataDocumentSizeException | InvalidParseOperationException e) { throw new ProcessingException(e); } return new ItemStatus(CREATE_MANIFEST).setItemsStatus(CREATE_MANIFEST, itemStatus); } CreateManifest(); @VisibleForTesting  CreateManifest(MetaDataClientFactory metaDataClientFactory); @Override ItemStatus execute(WorkerParameters param, HandlerIO handlerIO); @Override void checkMandatoryIOParameter(HandlerIO handler);  }