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