001/* 002 * Copyright 2020 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.ametys.plugins.contentio.archive; 017 018import java.nio.file.Path; 019import java.util.Optional; 020 021import org.slf4j.Logger; 022import org.w3c.dom.Document; 023 024import org.ametys.plugins.contentio.archive.Archivers.AmetysObjectNotImportedException; 025import org.ametys.plugins.contentio.archive.ImportReport.ImportError; 026import org.ametys.plugins.contentio.archive.Merger.AfterMerge; 027 028/** 029 * Unitary importer of an abstract object into Ametys. 030 * @param <O> The type of object to import 031 */ 032public interface UnitaryImporter<O> 033{ 034 /** 035 * The name for the object to import in error logs 036 * @return The name for the object to import in error logs 037 */ 038 String objectNameForLogs(); 039 040 /** 041 * Gets the properties XML file from its ZIP path 042 * @param zipEntryPath The ZIP entry path of the XML file 043 * @return The properties XML file 044 * @throws Exception if an error occurs 045 */ 046 Document getPropertiesXml(Path zipEntryPath) throws Exception; 047 048 /** 049 * Retrieves the id of the object to import from the XML file 050 * @param propertiesXml The properties XML file 051 * @return The id of the object to import 052 * @throws Exception if an error occurs 053 */ 054 String retrieveId(Document propertiesXml) throws Exception; 055 056 /** 057 * Creates the object with the given id and XML properties file. 058 * <br>Note that the implementation must create the object with the given id, but it can also create sub-objects for this unitary object (for instance a Resource as an attachment for a Content, etc.). 059 * @param zipEntryPath The ZIP entry path of the XML file 060 * @param id The id of the object to import 061 * @param propertiesXml The properties XML file 062 * @return The created object 063 * @throws AmetysObjectNotImportedException If the object was not imported due to an exception (for instance an attribute is missing in the XML file). Then the object is ignored and the import will continue to the next object. 064 * @throws ImportGlobalFailException If the global import process must stop due to any fatal exception. 065 * @throws Exception if another unexpected error occurs 066 */ 067 O create(Path zipEntryPath, String id, Document propertiesXml) throws AmetysObjectNotImportedException, ImportGlobalFailException, Exception; 068 069 /** 070 * The {@link ImportReport} 071 * @return The {@link ImportReport} 072 */ 073 ImportReport getReport(); 074 075 /** 076 * The optional process to do in a `finally` block in {@link #unitaryImport} 077 */ 078 default void unitaryImportFinalize() 079 { 080 // Do nothing by default 081 } 082 083 /** 084 * Does the unitary import. 085 * <br>Do not override the default behavior. 086 * @param zipArchivePath The ZIP file 087 * @param zipEntryPath The ZIP entry path of the XML file 088 * @param merger The {@link Merger} 089 * @param logger The logger 090 * @return The optionally created object 091 * @throws ImportGlobalFailException If the global import process must stop due to any fatal exception. 092 */ 093 default Optional<O> unitaryImport(Path zipArchivePath, Path zipEntryPath, Merger merger, Logger logger) throws ImportGlobalFailException 094 { 095 try 096 { 097 Document propertiesXml = getPropertiesXml(zipEntryPath); 098 099 String id = retrieveId(propertiesXml); 100 if (merger.needsMerge(id)) 101 { 102 AfterMerge afterMerge = merger.merge(id); 103 switch (afterMerge) 104 { 105 case STOP_PROCESS: 106 // stop the object creation, process next object id 107 return Optional.empty(); 108 case CONTINUE_PROCESS: 109 default: 110 // continue the object creation 111 break; 112 } 113 } 114 115 O created = create(zipEntryPath, id, propertiesXml); 116 return Optional.of(created); 117 } 118 catch (ImportGlobalFailException e) 119 { 120 getReport().addError(new ImportError(e)); 121 throw e; 122 } 123 catch (AmetysObjectNotImportedException e) 124 { 125 logger.error("{} for '{}!{}' could not be imported.", objectNameForLogs(), zipArchivePath, zipEntryPath, e); 126 getReport().addError(new ImportError(e)); 127 return Optional.empty(); 128 } 129 catch (Exception e) 130 { 131 logger.error("An unexpected exception occured when trying to import {} for '{}!{}'.", objectNameForLogs(), zipArchivePath, zipEntryPath, e); 132 getReport().addError(new ImportError(e)); 133 return Optional.empty(); 134 } 135 finally 136 { 137 unitaryImportFinalize(); 138 } 139 } 140} 141