001/*
002 *  Copyright 2014 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.flipbook;
017
018import java.io.InputStream;
019import java.util.Arrays;
020import java.util.Iterator;
021import java.util.List;
022
023import org.apache.commons.codec.digest.DigestUtils;
024
025import org.ametys.cms.data.Binary;
026import org.ametys.cms.repository.Content;
027import org.ametys.core.util.FilenameUtils;
028import org.ametys.plugins.repository.data.holder.ModelAwareDataHolder;
029import org.ametys.plugins.repository.data.holder.group.ModelAwareRepeater;
030import org.ametys.plugins.repository.data.type.ModelItemTypeConstants;
031import org.ametys.runtime.model.ModelItem;
032
033/**
034 * Implementation of a {@link AbstractConvertDocument2ImagesComponent} for a binary metadata
035 */
036public class ConvertMetadata2ImagesComponent extends AbstractConvertDocument2ImagesComponent
037{
038    /** Avalon ROLE. */
039    public static final String ROLE = ConvertMetadata2ImagesComponent.class.getName();
040    
041    /**
042     * Put the file in cache
043     * @param content the content
044     * @param metadataPath the path of the metadata
045     * @param siteName the name of the site
046     * @return The absolute cache path
047     * @throws Exception if an error occurs while caching the file
048     */
049    public String doCache(Content content, String metadataPath, String siteName) throws Exception
050    {
051        Binary binary = _getBinary(metadataPath, content);
052
053        String cachePath = _getCacheDirectory(metadataPath, binary.getFilename(), content.getName(), siteName);
054        try (InputStream is = binary.getInputStream(); InputStream is2 = binary.getInputStream())
055        {
056            String md5sum = DigestUtils.md5Hex(is);
057            return cache(cachePath, md5sum, is2, content.getName(), content.getId(), binary.getMimeType());
058        }
059    }
060    
061    private Binary _getBinary(String dataPath, Content content)
062    {
063        if (dataPath.contains("["))
064        {
065            // The path contains a repeater entry with the new syntax ("repeater[1]/myBinaryData"), the getValue method can be used
066            return content.getValue(dataPath);
067        }
068        else
069        {
070            // FILPBOOK-63: The path could contain a repeater with the old syntax ("repeater/1/myBinaryData"), look over each path segment to get the binary data
071            // TODO NEWATTRIBUTEAPI: When all generators have been migrated to the new API, this code is unnecessary
072            List<String> pathSegments = Arrays.asList(dataPath.split(ModelItem.ITEM_PATH_SEPARATOR));
073            Iterator<String> pathSegmentsIt = pathSegments.iterator();
074            
075            ModelAwareDataHolder dataHolder = content;
076            Binary binary = null;
077            while (pathSegmentsIt.hasNext())
078            {
079                String pathSegment = pathSegmentsIt.next();
080                
081                if (pathSegmentsIt.hasNext())
082                {
083                    // Not the last segment: it is a repeater or a composite
084                    if (dataHolder.getType(pathSegment).getId().equals(ModelItemTypeConstants.REPEATER_TYPE_ID))
085                    {
086                        ModelAwareRepeater repeater = dataHolder.getRepeater(pathSegment);
087                        int repeaterPosition = Integer.valueOf(pathSegmentsIt.next());
088                        dataHolder = repeater.getEntry(repeaterPosition);
089                    }
090                    else
091                    {
092                        dataHolder = dataHolder.getComposite(pathSegment);
093                    }
094                }
095                else
096                {
097                    binary = dataHolder.getValue(pathSegment);
098                }
099            }
100            
101            return binary;
102        }
103    }
104    
105    private String _getCacheDirectory(String metadataPath, String fileName, String contentName, String siteName)
106    {
107        StringBuilder buff = _getContentCacheDirectory(contentName, siteName);
108        buff.append("/metadatas/");
109        buff.append(metadataPath);
110        buff.append("/");
111        buff.append(FilenameUtils.encodeName(fileName));
112        
113        return buff.toString();
114    }
115
116    private StringBuilder _getContentCacheDirectory(String contentName, String siteName)
117    {
118        StringBuilder buff = new StringBuilder();
119        buff.append("/");
120        buff.append(siteName);
121        buff.append("/contents/");
122        buff.append(contentName);
123        return buff;
124    }
125    
126    /**
127     * Remove all cached attribute image for the given content and sitename in the flipbook cache
128     * @param content the content linked to the info to remove
129     * @param siteName the sitename linked to the info to remove
130     */
131    public void doCleanCache(Content content, String siteName)
132    {
133        // target the metadata cache only to avoid removing the attachment cache if its unnecessary
134        cleanCache(_getContentCacheDirectory(content.getName(), siteName).toString() + "/metadatas");
135    }
136}