001/*
002 *  Copyright 2015 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.survey.repository;
017
018import java.io.InputStream;
019import java.util.Date;
020
021import javax.jcr.Node;
022import javax.jcr.PathNotFoundException;
023import javax.jcr.RepositoryException;
024
025import org.apache.commons.lang.StringUtils;
026
027import org.ametys.plugins.repository.AmetysObject;
028import org.ametys.plugins.repository.AmetysRepositoryException;
029import org.ametys.plugins.repository.CopiableAmetysObject;
030import org.ametys.plugins.repository.RepositoryConstants;
031import org.ametys.plugins.repository.jcr.DefaultTraversableAmetysObject;
032import org.ametys.plugins.repository.jcr.DefaultTraversableAmetysObjectFactory;
033import org.ametys.plugins.repository.metadata.BinaryMetadata;
034import org.ametys.plugins.repository.metadata.ModifiableBinaryMetadata;
035import org.ametys.plugins.repository.metadata.ModifiableCompositeMetadata;
036
037/**
038 * Abstract {@link AmetysObject} for storing elements of a survey
039 * @param <F> the actual type of factory.
040 */
041public abstract class AbstractSurveyElement<F extends DefaultTraversableAmetysObjectFactory> extends DefaultTraversableAmetysObject<F> implements CopiableAmetysObject
042{
043    /** Constant for picture data property. */
044    public static final String PROPERTY_PICTURE = "picture";
045    /** Constant for picture type property. */
046    public static final String PROPERTY_PICTURE_TYPE = RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ":picture-type";
047    /** Constant for picture id property. */
048    public static final String PROPERTY_PICTURE_ID = RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ":picture-id";
049    /** Constant for picture alternative property. */
050    public static final String PROPERTY_PICTURE_ALTERNATIVE = RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ":picture-alternative";
051    
052    /**
053     * Constructor
054     * @param node the node backing this {@link AmetysObject}.
055     * @param parentPath the parent path in the Ametys hierarchy.
056     * @param factory the {@link DefaultTraversableAmetysObjectFactory} which creates the AmetysObject.
057     */
058    public AbstractSurveyElement(Node node, String parentPath, F factory)
059    {
060        super(node, parentPath, factory);
061    }
062
063    /**
064     * Get the picture as a binary metadata.
065     * @return the picture as a binary metadata.
066     * @throws AmetysRepositoryException if an error occurs.
067     */
068    public BinaryMetadata getExternalPicture() throws AmetysRepositoryException
069    {
070        return getMetadataHolder().getBinaryMetadata(PROPERTY_PICTURE);
071    }
072    
073    /**
074     * Set the picture from an external file.
075     * @param mimeType the file MIME type.
076     * @param filename the file name.
077     * @param stream an input stream on the file bytes.
078     * @throws AmetysRepositoryException if an error occurs.
079     */
080    public void setExternalPicture(String mimeType, String filename, InputStream stream) throws AmetysRepositoryException
081    {
082        try
083        {
084            removePictureMetas();
085            
086            setPictureType("external");
087            
088            ModifiableCompositeMetadata meta = getMetadataHolder();
089            ModifiableBinaryMetadata pic = meta.getBinaryMetadata(PROPERTY_PICTURE, true);
090            
091            pic.setLastModified(new Date());
092            pic.setInputStream(stream);
093            pic.setMimeType(mimeType);
094            pic.setFilename(filename);
095        }
096        catch (RepositoryException e)
097        {
098            throw new AmetysRepositoryException("Error setting the external picture property.", e);
099        }
100    }
101    
102    /**
103     * Get the picture resource ID.
104     * @return the resource ID.
105     * @throws AmetysRepositoryException if an error occurs.
106     */
107    public String getResourcePictureId() throws AmetysRepositoryException
108    {
109        try
110        {
111            return getNode().getProperty(PROPERTY_PICTURE_ID).getString();
112        }
113        catch (PathNotFoundException e)
114        {
115            return null;
116        }
117        catch (RepositoryException e)
118        {
119            throw new AmetysRepositoryException("Error getting the picture ID property.", e);
120        }
121    }
122        
123    /**
124     * Set the picture from an explorer resource.
125     * @param resourceId the resource ID.
126     * @throws AmetysRepositoryException if an error occurs.
127     */
128    public void setResourcePicture(String resourceId) throws AmetysRepositoryException
129    {
130        try
131        {
132            removePictureMetas();
133            
134            setPictureType("resource");
135            
136            getNode().setProperty(PROPERTY_PICTURE_ID, resourceId);
137        }
138        catch (RepositoryException e)
139        {
140            throw new AmetysRepositoryException("Error setting the alternative property.", e);
141        }
142    }
143    
144    /**
145     * Removes any picture currently assigned.
146     * @throws AmetysRepositoryException if an error occurs.
147     */
148    public void setNoPicture() throws AmetysRepositoryException
149    {
150        try
151        {
152            setPictureType("");
153            
154            removePictureMetas();
155        }
156        catch (RepositoryException e)
157        {
158            throw new AmetysRepositoryException("Error setting the alternative property.", e);
159        }
160    }
161
162    /**
163     * Get the picture type.
164     * @return the picture type.
165     * @throws AmetysRepositoryException if an error occurs.
166     */
167    public String getPictureType() throws AmetysRepositoryException
168    {
169        try
170        {
171            return getNode().getProperty(PROPERTY_PICTURE_TYPE).getString();
172        }
173        catch (PathNotFoundException e)
174        {
175            return null;
176        }
177        catch (RepositoryException e)
178        {
179            throw new AmetysRepositoryException("Error getting the type property.", e);
180        }
181    }
182    
183    /**
184     * Set the picture type.
185     * @param type the picture type to set.
186     * @throws AmetysRepositoryException if an error occurs.
187     */
188    public void setPictureType(String type) throws AmetysRepositoryException
189    {
190        try
191        {
192            getNode().setProperty(PROPERTY_PICTURE_TYPE, type);
193        }
194        catch (RepositoryException e)
195        {
196            throw new AmetysRepositoryException("Error setting the type property.", e);
197        }
198    }
199    
200    /**
201     * Get the picture alternative.
202     * @return the picture alternative.
203     * @throws AmetysRepositoryException if an error occurs.
204     */
205    public String getPictureAlternative() throws AmetysRepositoryException
206    {
207        try
208        {
209            return getNode().getProperty(PROPERTY_PICTURE_ALTERNATIVE).getString();
210        }
211        catch (PathNotFoundException e)
212        {
213            return null;
214        }
215        catch (RepositoryException e)
216        {
217            throw new AmetysRepositoryException("Error getting the alternative property.", e);
218        }
219    }
220    
221    /**
222     * Set the picture alternative.
223     * @param alternative the picture alternative to set.
224     * @throws AmetysRepositoryException if an error occurs.
225     */
226    public void setPictureAlternative(String alternative) throws AmetysRepositoryException
227    {
228        try
229        {
230            getNode().setProperty(PROPERTY_PICTURE_ALTERNATIVE, alternative);
231        }
232        catch (RepositoryException e)
233        {
234            throw new AmetysRepositoryException("Error setting the alternative property.", e);
235        }
236    }
237    
238    /**
239     * Remove all picture metas (picture ID and picture binary).
240     * @throws RepositoryException if an error occurs.
241     */
242    protected void removePictureMetas() throws RepositoryException
243    {
244        getNode().setProperty(PROPERTY_PICTURE_ID, "");
245        
246        ModifiableCompositeMetadata meta = getMetadataHolder();
247        if (meta.hasMetadata(PROPERTY_PICTURE))
248        {
249            meta.removeMetadata(PROPERTY_PICTURE);
250        }
251    }
252    
253    /**
254     * Copy the picture of this {@link AbstractSurveyElement} to the element in arguments
255     * @param elmt The element
256     */
257    protected void copyPictureTo (AbstractSurveyElement elmt)
258    {
259        String pictureType = getPictureType();
260        if (StringUtils.isBlank(pictureType))
261        {
262            elmt.setNoPicture();
263        }
264        else if (pictureType.equals("resource"))
265        {
266            String pictureId = getResourcePictureId();
267            if (StringUtils.isNotBlank(pictureId))
268            {
269                elmt.setResourcePicture(pictureId);
270            }
271            else
272            {
273                elmt.setNoPicture();
274            }
275        }
276        else if (pictureType.equals("external"))
277        {
278            BinaryMetadata externalPicture = getExternalPicture();
279            elmt.setExternalPicture(externalPicture.getMimeType(), externalPicture.getFilename(), externalPicture.getInputStream());
280        }
281        
282        String pictureAlternative = getPictureAlternative();
283        if (pictureAlternative != null)
284        {
285            elmt.setPictureAlternative(pictureAlternative);
286        }
287    }
288}