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.io.IOException;
019import java.io.InputStream;
020import java.nio.file.DirectoryStream;
021import java.nio.file.Files;
022import java.nio.file.Path;
023import java.util.HashMap;
024import java.util.Iterator;
025import java.util.Map;
026import java.util.Optional;
027
028import org.ametys.cms.data.type.ModelItemTypeConstants;
029import org.ametys.plugins.repository.data.extractor.xml.XMLValuesExtractorAdditionalDataGetter;
030import org.ametys.runtime.model.type.ElementType;
031
032/**
033 * Retrieves the additional data of resources types (files, binaries, rich texts) 
034 */
035public class ResourcesAdditionalDataGetter implements XMLValuesExtractorAdditionalDataGetter
036{
037    private final Path _archivePath;
038    private final Path _path;
039
040    /**
041     * Creates an additional data getter
042     * @param archivePath The path to the zip archive
043     * @param path The path to the object being imported
044     */
045    public ResourcesAdditionalDataGetter(Path archivePath, Path path)
046    {
047        _archivePath = archivePath;
048        _path = path;
049    }
050    
051    @Override
052    public Optional<Object> getAdditionalData(String dataPath, ElementType type)
053    {
054        try
055        {
056            return _getExtractorAdditionalData(dataPath, type);
057        }
058        catch (Exception e)
059        {
060            throw new RuntimeException("An unexpected error occured", e);
061        }
062    }
063    
064    private Optional<Object> _getExtractorAdditionalData(String dataPath, ElementType type) throws Exception
065    {
066        switch (type.getId())
067        {
068            case ModelItemTypeConstants.FILE_ELEMENT_TYPE_ID:
069                return Optional.of(_getFileAdditionalData(Archivers.__FILE_ATTRIBUTES_FOLDER_NAME, dataPath));
070            case ModelItemTypeConstants.BINARY_ELEMENT_TYPE_ID:
071                return Optional.of(_getFileAdditionalData(Archivers.__BINARY_ATTRIBUTES_FOLDER_NAME, dataPath));
072            case ModelItemTypeConstants.RICH_TEXT_ELEMENT_TYPE_ID:
073                return Optional.of(_getFileAdditionalData(Archivers.__RICH_TEXT_ATTACHMENTS_FOLDER_NAME, dataPath));
074            default:
075                return Optional.empty();
076        }
077    }
078    
079    private Map<String, InputStream> _getFileAdditionalData(String folderName, String dataPath) throws IOException
080    {
081        Path zipEntryFileParentFolderPath = _path.resolve(folderName)
082                .resolve(Archivers.getFolderPathFromDataPath(dataPath));
083        
084        String folderPath = zipEntryFileParentFolderPath.toString();
085        if (ZipEntryHelper.zipEntryFolderExists(_archivePath, folderPath))
086        {
087            return _getFileNameAndInputStream(folderPath);
088        }
089        
090        return Map.of();
091    }
092    
093    private Map<String, InputStream> _getFileNameAndInputStream(String folderPath) throws IOException
094    {
095        DirectoryStream<Path> fileChildren = ZipEntryHelper.children(
096            _archivePath, 
097            Optional.of(folderPath), 
098            p -> !Files.isDirectory(p));
099        
100        try (fileChildren)
101        {
102            Map<String, InputStream> files = new HashMap<>();
103            
104            Iterator<Path> fileIt = fileChildren.iterator();
105            while (fileIt.hasNext())
106            {
107                Path file = fileIt.next();
108                String fileName = file.getFileName().toString();
109                InputStream is = ZipEntryHelper.zipEntryFileInputStream(_archivePath, file.toString());
110                files.put(fileName, is);
111            }
112            
113            return files;
114        }
115    }
116}