001/* 002 * Copyright 2012 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.cms.repository; 017 018import java.util.Date; 019import java.util.GregorianCalendar; 020import java.util.List; 021import java.util.Locale; 022import java.util.Map; 023 024import javax.jcr.Node; 025import javax.jcr.RepositoryException; 026 027import org.apache.avalon.framework.component.Component; 028 029import org.ametys.cms.content.references.OutgoingReferences; 030import org.ametys.cms.data.type.ModelItemTypeConstants; 031import org.ametys.core.user.UserIdentity; 032import org.ametys.plugins.repository.AmetysRepositoryException; 033import org.ametys.plugins.repository.RepositoryConstants; 034import org.ametys.plugins.repository.data.repositorydata.ModifiableRepositoryData; 035import org.ametys.plugins.repository.data.repositorydata.impl.JCRRepositoryData; 036import org.ametys.runtime.model.ElementDefinition; 037import org.ametys.runtime.model.ModelItem; 038 039 040/** 041 * Provides helper methods to use the {@link ModifiableContent} API on {@link DefaultContent}s. 042 */ 043public class ModifiableContentHelper implements Component 044{ 045 /** The Avalon role */ 046 public static final String ROLE = ModifiableContentHelper.class.getName(); 047 048 /** 049 * Set a {@link DefaultContent} title for the given locale. 050 * @param content the {@link DefaultContent} to set. 051 * @param title the title to set. 052 * @param locale The locale. Can be null if the content is not a multilingual content. 053 * @throws AmetysRepositoryException if an error occurs. 054 */ 055 public void setTitle(DefaultContent content, String title, Locale locale) throws AmetysRepositoryException 056 { 057 ModelItem titleDefinition = content.getDefinition(Content.ATTRIBUTE_TITLE); 058 ModifiableRepositoryData repositoryData = new JCRRepositoryData(content.getNode()); 059 if (titleDefinition instanceof ElementDefinition && ModelItemTypeConstants.MULTILINGUAL_STRING_ELEMENT_TYPE_ID.equals(((ElementDefinition) titleDefinition).getType().getId())) 060 { 061 if (locale == null) 062 { 063 throw new IllegalArgumentException("Cannot set a title with null locale on a multilingual title"); 064 } 065 066 ModifiableRepositoryData titleRepositoryData; 067 if (repositoryData.hasValue(Content.ATTRIBUTE_TITLE)) 068 { 069 titleRepositoryData = repositoryData.getRepositoryData(Content.ATTRIBUTE_TITLE); 070 } 071 else 072 { 073 titleRepositoryData = repositoryData.addRepositoryData(Content.ATTRIBUTE_TITLE, RepositoryConstants.MULTILINGUAL_STRING_METADATA_NODETYPE); 074 } 075 titleRepositoryData.setValue(locale.toString(), title); 076 } 077 else 078 { 079 repositoryData.setValue(Content.ATTRIBUTE_TITLE, title); 080 } 081 } 082 083 /** 084 * Set the title of non-multilingual {@link DefaultContent}. 085 * Be careful! Use only if content's title is not a multilingual string. If not sure use {@link #setTitle(DefaultContent, String, Locale)} instead. 086 * @param content the {@link DefaultContent} to set. 087 * @param title the title to set. 088 * @throws AmetysRepositoryException if an error occurs. 089 */ 090 public void setTitle(DefaultContent content, String title) throws AmetysRepositoryException 091 { 092 setTitle(content, title, null); 093 } 094 095 /** 096 * Copy the title of the source content to the target content 097 * @param srcContent The source content 098 * @param targetContent The target content 099 * @throws AmetysRepositoryException if an error occurs. 100 */ 101 public void copyTitle(Content srcContent, ModifiableContent targetContent) throws AmetysRepositoryException 102 { 103 targetContent.setValue(Content.ATTRIBUTE_TITLE, srcContent.getValue(Content.ATTRIBUTE_TITLE)); 104 } 105 106 /** 107 * Set a {@link DefaultContent} user. 108 * @param content the {@link DefaultContent} to set. 109 * @param user the user to set. 110 * @throws AmetysRepositoryException if an error occurs. 111 */ 112 public void setCreator(DefaultContent content, UserIdentity user) throws AmetysRepositoryException 113 { 114 try 115 { 116 // TODO CMS-9336 All the metatadata here should be store using types 117 ModifiableRepositoryData repositoryData = new JCRRepositoryData(content.getNode()); 118 ModifiableRepositoryData creatorRepositoryData; 119 if (repositoryData.hasValue(DefaultContent.METADATA_CREATOR)) 120 { 121 creatorRepositoryData = repositoryData.getRepositoryData(DefaultContent.METADATA_CREATOR); 122 } 123 else 124 { 125 creatorRepositoryData = repositoryData.addRepositoryData(DefaultContent.METADATA_CREATOR, RepositoryConstants.USER_NODETYPE); 126 } 127 creatorRepositoryData.setValue("login", user.getLogin()); 128 creatorRepositoryData.setValue("population", user.getPopulationId()); 129 } 130 catch (AmetysRepositoryException e) 131 { 132 throw new AmetysRepositoryException("Error setting the creator property.", e); 133 } 134 } 135 136 /** 137 * Set a {@link DefaultContent} creation date. 138 * @param content the {@link DefaultContent} to set. 139 * @param creationDate the creation date to set. 140 * @throws AmetysRepositoryException if an error occurs. 141 */ 142 public void setCreationDate(DefaultContent content, Date creationDate) throws AmetysRepositoryException 143 { 144 ModifiableRepositoryData repositoryData = new JCRRepositoryData(content.getNode()); 145 GregorianCalendar calendar = new GregorianCalendar(); 146 calendar.setTime(creationDate); 147 repositoryData.setValue(DefaultContent.METADATA_CREATION, calendar); 148 } 149 150 /** 151 * Set a {@link DefaultContent} contributor. 152 * @param content the {@link DefaultContent} to set. 153 * @param user the contributor to set. 154 * @throws AmetysRepositoryException if an error occurs. 155 */ 156 public void setLastContributor(DefaultContent content, UserIdentity user) throws AmetysRepositoryException 157 { 158 try 159 { 160 ModifiableRepositoryData repositoryData = new JCRRepositoryData(content.getNode()); 161 ModifiableRepositoryData contributorRepositoryData; 162 if (repositoryData.hasValue(DefaultContent.METADATA_CONTRIBUTOR)) 163 { 164 contributorRepositoryData = repositoryData.getRepositoryData(DefaultContent.METADATA_CONTRIBUTOR); 165 } 166 else 167 { 168 contributorRepositoryData = repositoryData.addRepositoryData(DefaultContent.METADATA_CONTRIBUTOR, RepositoryConstants.USER_NODETYPE); 169 } 170 contributorRepositoryData.setValue("login", user.getLogin()); 171 contributorRepositoryData.setValue("population", user.getPopulationId()); 172 } 173 catch (AmetysRepositoryException e) 174 { 175 throw new AmetysRepositoryException("Error setting the last contributor property.", e); 176 } 177 } 178 179 /** 180 * Set a {@link DefaultContent} last modification date. 181 * @param content the {@link DefaultContent} to set. 182 * @param lastModified the last modification date to set. 183 * @throws AmetysRepositoryException if an error occurs. 184 */ 185 public void setLastModified(DefaultContent content, Date lastModified) throws AmetysRepositoryException 186 { 187 ModifiableRepositoryData repositoryData = new JCRRepositoryData(content.getNode()); 188 GregorianCalendar calendar = new GregorianCalendar(); 189 calendar.setTime(lastModified); 190 repositoryData.setValue(DefaultContent.METADATA_MODIFIED, calendar); 191 } 192 193 /** 194 * Set a {@link DefaultContent} first validation date. 195 * @param content the {@link DefaultContent} to set. 196 * @param validationDate the first validation date. 197 * @throws AmetysRepositoryException if an error occurs. 198 */ 199 public void setFirstValidationDate(DefaultContent content, Date validationDate) throws AmetysRepositoryException 200 { 201 ModifiableRepositoryData repositoryData = new JCRRepositoryData(content.getNode()); 202 GregorianCalendar calendar = new GregorianCalendar(); 203 calendar.setTime(validationDate); 204 repositoryData.setValue(DefaultContent.METADATA_FIRST_VALIDATION, calendar); 205 } 206 207 /** 208 * Set a {@link DefaultContent} last validation date. 209 * @param content the {@link DefaultContent} to set. 210 * @param validationDate the last validation date. 211 * @throws AmetysRepositoryException if an error occurs. 212 */ 213 public void setLastValidationDate(DefaultContent content, Date validationDate) throws AmetysRepositoryException 214 { 215 ModifiableRepositoryData repositoryData = new JCRRepositoryData(content.getNode()); 216 GregorianCalendar calendar = new GregorianCalendar(); 217 calendar.setTime(validationDate); 218 repositoryData.setValue(DefaultContent.METADATA_LAST_VALIDATION, calendar); 219 } 220 221 /** 222 * Set a {@link DefaultContent} last major validation date. 223 * @param content the {@link DefaultContent} to set. 224 * @param validationDate the last major validation date. 225 * @throws AmetysRepositoryException if an error occurs. 226 */ 227 public void setLastMajorValidationDate(DefaultContent content, Date validationDate) throws AmetysRepositoryException 228 { 229 ModifiableRepositoryData repositoryData = new JCRRepositoryData(content.getNode()); 230 GregorianCalendar calendar = new GregorianCalendar(); 231 calendar.setTime(validationDate); 232 repositoryData.setValue(DefaultContent.METADATA_LAST_MAJORVALIDATION, calendar); 233 } 234 235 /** 236 * Store the outgoing references on the content. 237 * @param content The content concerned by these outgoing references. 238 * @param references A non null map of outgoing references grouped by metadata (key are metadata path) 239 * @throws AmetysRepositoryException if an error occurs. 240 */ 241 public void setOutgoingReferences(DefaultContent content, Map<String, OutgoingReferences> references) throws AmetysRepositoryException 242 { 243 try 244 { 245 Node contentNode = content.getNode(); 246 if (contentNode.hasNode(RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ':' + DefaultContent.METADATA_ROOT_OUTGOING_REFERENCES)) 247 { 248 contentNode.getNode(RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ':' + DefaultContent.METADATA_ROOT_OUTGOING_REFERENCES).remove(); 249 } 250 251 if (references.size() != 0) 252 { 253 Node rootOutgoingRefsNode = contentNode.addNode(RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ':' + DefaultContent.METADATA_ROOT_OUTGOING_REFERENCES); 254 for (String path : references.keySet()) 255 { 256 // Outgoing references node creation (for the given path) 257 Node outgoingRefsNode = rootOutgoingRefsNode.addNode(RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ':' + DefaultContent.METADATA_OUTGOING_REFERENCES); 258 outgoingRefsNode.setProperty(RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ':' + DefaultContent.METADATA_OUTGOING_REFERENCES_PATH_PROPERTY, path); 259 260 // Reference nodes per type 261 OutgoingReferences outgoingReferences = references.get(path); 262 263 for (String type : outgoingReferences.keySet()) 264 { 265 List<String> referenceValues = outgoingReferences.get(type); 266 if (referenceValues != null && !referenceValues.isEmpty()) 267 { 268 Node outgoingReferenceNode = outgoingRefsNode.addNode(type, RepositoryConstants.NAMESPACE_PREFIX + ':' + DefaultContent.METADATA_OUTGOING_REFERENCE_NODETYPE); 269 outgoingReferenceNode.setProperty(RepositoryConstants.NAMESPACE_PREFIX + ':' + DefaultContent.METADATA_OUTGOING_REFERENCE_PROPERTY, referenceValues.toArray(new String[referenceValues.size()])); 270 } 271 } 272 } 273 } 274 } 275 catch (RepositoryException e) 276 { 277 throw new AmetysRepositoryException(e); 278 } 279 } 280}