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.IOException;
019import java.io.InputStream;
020import java.time.ZonedDateTime;
021
022import javax.jcr.Node;
023import javax.jcr.PathNotFoundException;
024import javax.jcr.RepositoryException;
025
026import org.apache.commons.lang3.StringUtils;
027
028import org.ametys.cms.data.Binary;
029import org.ametys.cms.data.type.ModelItemTypeConstants;
030import org.ametys.plugins.repository.AmetysObject;
031import org.ametys.plugins.repository.AmetysRepositoryException;
032import org.ametys.plugins.repository.CopiableAmetysObject;
033import org.ametys.plugins.repository.RepositoryConstants;
034import org.ametys.plugins.repository.jcr.DefaultTraversableAmetysObject;
035import org.ametys.plugins.repository.jcr.DefaultTraversableAmetysObjectFactory;
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 SurveyElementFactory> 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 Binary getExternalPicture() throws AmetysRepositoryException
069    {
070        return getValue(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            Binary pic = new Binary();
089            
090            pic.setLastModificationDate(ZonedDateTime.now());
091            pic.setInputStream(stream);
092            pic.setMimeType(mimeType);
093            pic.setFilename(filename);
094            
095            setValue(PROPERTY_PICTURE, pic, ModelItemTypeConstants.BINARY_ELEMENT_TYPE_ID);
096        }
097        catch (IOException | RepositoryException e)
098        {
099            throw new AmetysRepositoryException("Error setting the external picture property.", e);
100        }
101    }
102    
103    /**
104     * Get the picture resource ID.
105     * @return the resource ID.
106     * @throws AmetysRepositoryException if an error occurs.
107     */
108    public String getResourcePictureId() throws AmetysRepositoryException
109    {
110        try
111        {
112            return getNode().getProperty(PROPERTY_PICTURE_ID).getString();
113        }
114        catch (PathNotFoundException e)
115        {
116            return null;
117        }
118        catch (RepositoryException e)
119        {
120            throw new AmetysRepositoryException("Error getting the picture ID property.", e);
121        }
122    }
123        
124    /**
125     * Set the picture from an explorer resource.
126     * @param resourceId the resource ID.
127     * @throws AmetysRepositoryException if an error occurs.
128     */
129    public void setResourcePicture(String resourceId) throws AmetysRepositoryException
130    {
131        try
132        {
133            removePictureMetas();
134            
135            setPictureType("resource");
136            
137            getNode().setProperty(PROPERTY_PICTURE_ID, resourceId);
138        }
139        catch (RepositoryException e)
140        {
141            throw new AmetysRepositoryException("Error setting the alternative property.", e);
142        }
143    }
144    
145    /**
146     * Removes any picture currently assigned.
147     * @throws AmetysRepositoryException if an error occurs.
148     */
149    public void setNoPicture() throws AmetysRepositoryException
150    {
151        try
152        {
153            setPictureType("");
154            
155            removePictureMetas();
156        }
157        catch (RepositoryException e)
158        {
159            throw new AmetysRepositoryException("Error setting the alternative property.", e);
160        }
161    }
162
163    /**
164     * Get the picture type.
165     * @return the picture type.
166     * @throws AmetysRepositoryException if an error occurs.
167     */
168    public String getPictureType() throws AmetysRepositoryException
169    {
170        try
171        {
172            return getNode().getProperty(PROPERTY_PICTURE_TYPE).getString();
173        }
174        catch (PathNotFoundException e)
175        {
176            return null;
177        }
178        catch (RepositoryException e)
179        {
180            throw new AmetysRepositoryException("Error getting the type property.", e);
181        }
182    }
183    
184    /**
185     * Set the picture type.
186     * @param type the picture type to set.
187     * @throws AmetysRepositoryException if an error occurs.
188     */
189    public void setPictureType(String type) throws AmetysRepositoryException
190    {
191        try
192        {
193            getNode().setProperty(PROPERTY_PICTURE_TYPE, type);
194        }
195        catch (RepositoryException e)
196        {
197            throw new AmetysRepositoryException("Error setting the type property.", e);
198        }
199    }
200    
201    /**
202     * Get the picture alternative.
203     * @return the picture alternative.
204     * @throws AmetysRepositoryException if an error occurs.
205     */
206    public String getPictureAlternative() throws AmetysRepositoryException
207    {
208        try
209        {
210            return getNode().getProperty(PROPERTY_PICTURE_ALTERNATIVE).getString();
211        }
212        catch (PathNotFoundException e)
213        {
214            return null;
215        }
216        catch (RepositoryException e)
217        {
218            throw new AmetysRepositoryException("Error getting the alternative property.", e);
219        }
220    }
221    
222    /**
223     * Set the picture alternative.
224     * @param alternative the picture alternative to set.
225     * @throws AmetysRepositoryException if an error occurs.
226     */
227    public void setPictureAlternative(String alternative) throws AmetysRepositoryException
228    {
229        try
230        {
231            getNode().setProperty(PROPERTY_PICTURE_ALTERNATIVE, alternative);
232        }
233        catch (RepositoryException e)
234        {
235            throw new AmetysRepositoryException("Error setting the alternative property.", e);
236        }
237    }
238    
239    /**
240     * Remove all picture metas (picture ID and picture binary).
241     * @throws RepositoryException if an error occurs.
242     */
243    protected void removePictureMetas() throws RepositoryException
244    {
245        getNode().setProperty(PROPERTY_PICTURE_ID, StringUtils.EMPTY);
246        removeValue(PROPERTY_PICTURE);
247    }
248    
249    /**
250     * Copy the picture of this {@link AbstractSurveyElement} to the element in arguments
251     * @param elmt The element
252     */
253    protected void copyPictureTo (AbstractSurveyElement elmt)
254    {
255        String pictureType = getPictureType();
256        if (StringUtils.isBlank(pictureType))
257        {
258            elmt.setNoPicture();
259        }
260        else if (pictureType.equals("resource"))
261        {
262            String pictureId = getResourcePictureId();
263            if (StringUtils.isNotBlank(pictureId))
264            {
265                elmt.setResourcePicture(pictureId);
266            }
267            else
268            {
269                elmt.setNoPicture();
270            }
271        }
272        else if (pictureType.equals("external"))
273        {
274            Binary externalPicture = getExternalPicture();
275            elmt.setExternalPicture(externalPicture.getMimeType(), externalPicture.getFilename(), externalPicture.getInputStream());
276        }
277        
278        String pictureAlternative = getPictureAlternative();
279        if (pictureAlternative != null)
280        {
281            elmt.setPictureAlternative(pictureAlternative);
282        }
283    }
284}