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.List;
020import java.util.Map;
021
022import javax.jcr.Node;
023import javax.jcr.RepositoryException;
024
025import org.ametys.cms.content.references.OutgoingReferences;
026import org.ametys.core.user.UserIdentity;
027import org.ametys.plugins.repository.AmetysRepositoryException;
028import org.ametys.plugins.repository.RepositoryConstants;
029
030/**
031 * Provides helper methods to use the {@link ModifiableContent} API on {@link DefaultContent}s.
032 */
033public final class ModifiableContentHelper
034{
035    /** Constants for the root outgoing references node */
036    public static final String METADATA_ROOT_OUTGOING_REFERENCES = "root-outgoing-references";
037    
038    /** Constants for the outgoing references node */
039    public static final String METADATA_OUTGOING_REFERENCES = "outgoing-references";
040    
041    /** Constants for the outgoing references path property */
042    public static final String METADATA_OUTGOING_REFERENCES_PATH_PROPERTY = "path";
043    
044    /** Constants for the outgoing reference property */
045    public static final String METADATA_OUTGOING_REFERENCE_PROPERTY = "reference";
046    
047    /** Constants for the outgoing reference property */
048    public static final String METADATA_OUTGOING_REFERENCE_NODETYPE = "reference";
049    
050    /** Constants for language Metadata* */
051    public static final String METADATA_LANGUAGE = "language";
052    
053    /** Constants for title Metadata* */
054    public static final String METADATA_TITLE = "title";
055    
056    /** Constants for author Metadata* */
057    public static final String METADATA_CREATOR = "creator";
058    
059    /** Constants for lastModified Metadata* */
060    public static final String METADATA_CREATION = "creationDate";
061
062    /** Constants for lastValidationDate Metadata* */
063    public static final String METADATA_LAST_VALIDATION = "lastValidationDate";
064    
065    /** Constants for lastMajorValidationDate Metadata* */
066    public static final String METADATA_LAST_MAJORVALIDATION = "lastMajorValidationDate";
067    
068    /** Constants for last contributor Metadata* */
069    public static final String METADATA_CONTRIBUTOR = "contributor";
070    
071    /** Constants for lastModified Metadata* */
072    public static final String METADATA_MODIFIED = "lastModified";
073    
074    private ModifiableContentHelper()
075    {
076        // Hides default constructor.
077    }
078    
079    /**
080     * Set a {@link DefaultContent} type.
081     * @param content the {@link DefaultContent} to set.
082     * @param type the type.
083     * @throws AmetysRepositoryException if an error occurs.
084     */
085    public static void setType(DefaultContent content, String type) throws AmetysRepositoryException
086    {
087        setTypes(content, new String[] {type});
088    }
089    
090    /**
091     * Set {@link DefaultContent} types.
092     * @param content the {@link DefaultContent} to set.
093     * @param types the types.
094     * @throws AmetysRepositoryException if an error occurs.
095     */
096    public static void setTypes(DefaultContent content, String[] types) throws AmetysRepositoryException
097    {
098        Node node = content.getNode();
099        
100        try
101        {
102            content._checkLock();
103            node.setProperty(RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ':' + DefaultContent.METADATA_CONTENTTYPE, types);
104        }
105        catch (RepositoryException e)
106        {
107            throw new AmetysRepositoryException("Unable to set contentType property", e);
108        }
109    }
110    
111    /**
112     * Set {@link DefaultContent} mixins.
113     * @param content the {@link DefaultContent} to set.
114     * @param mixins the mixins.
115     * @throws AmetysRepositoryException if an error occurs.
116     */
117    public static void setMixinTypes(DefaultContent content, String[] mixins) throws AmetysRepositoryException
118    {
119        Node node = content.getNode();
120        
121        try
122        {
123            content._checkLock();
124            node.setProperty(RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ':' + DefaultContent.METADATA_MIXINCONTENTTYPES, mixins);
125        }
126        catch (RepositoryException e)
127        {
128            throw new AmetysRepositoryException("Unable to set mixins property", e);
129        }
130    }
131    
132    /**
133     * Set a {@link DefaultContent} language.
134     * @param content the {@link DefaultContent} to modify.
135     * @param language the language to set.
136     * @throws AmetysRepositoryException if an error occurs.
137     */
138    public static void setLanguage(DefaultContent content, String language) throws AmetysRepositoryException
139    {
140        Node node = content.getNode();
141        
142        try
143        {
144            content._checkLock();
145            node.setProperty(RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ':' + METADATA_LANGUAGE, language);
146        }
147        catch (RepositoryException e)
148        {
149            throw new AmetysRepositoryException("Unable to set language property", e);
150        }
151    }
152    
153    /**
154     * Set a {@link DefaultContent} title.
155     * @param content the {@link DefaultContent} to set.
156     * @param title the title to set.
157     * @throws AmetysRepositoryException if an error occurs.
158     */
159    public static void setTitle(DefaultContent content, String title) throws AmetysRepositoryException
160    {
161        content.getMetadataHolder().setMetadata(METADATA_TITLE, title);
162    }
163    
164    /**
165     * Set a {@link DefaultContent} user.
166     * @param content the {@link DefaultContent} to set.
167     * @param user the user to set.
168     * @throws AmetysRepositoryException if an error occurs.
169     */
170    public static void setCreator(DefaultContent content, UserIdentity user) throws AmetysRepositoryException
171    {
172        try
173        {
174            Node creatorNode = null;
175            if (content.getNode().hasNode(RepositoryConstants.NAMESPACE_PREFIX + ':' + METADATA_CREATOR))
176            {
177                creatorNode = content.getNode().getNode(RepositoryConstants.NAMESPACE_PREFIX + ':' + METADATA_CREATOR);
178            }
179            else
180            {
181                creatorNode = content.getNode().addNode(RepositoryConstants.NAMESPACE_PREFIX + ':' + METADATA_CREATOR, RepositoryConstants.USER_NODETYPE);
182            }
183            creatorNode.setProperty(RepositoryConstants.NAMESPACE_PREFIX + ":login", user.getLogin());
184            creatorNode.setProperty(RepositoryConstants.NAMESPACE_PREFIX + ":population", user.getPopulationId());
185        }
186        catch (RepositoryException e)
187        {
188            throw new AmetysRepositoryException("Error setting the creator property.", e);
189        }
190    }
191    
192    /**
193     * Set a {@link DefaultContent} creation date.
194     * @param content the {@link DefaultContent} to set.
195     * @param creationDate the creation date to set.
196     * @throws AmetysRepositoryException if an error occurs.
197     */
198    public static void setCreationDate(DefaultContent content, Date creationDate) throws AmetysRepositoryException
199    {
200        content.getMetadataHolder().setMetadata(METADATA_CREATION, creationDate);
201    }
202    
203    /**
204     * Set a {@link DefaultContent} contributor.
205     * @param content the {@link DefaultContent} to set.
206     * @param user the contributor to set.
207     * @throws AmetysRepositoryException if an error occurs.
208     */
209    public static void setLastContributor(DefaultContent content, UserIdentity user) throws AmetysRepositoryException
210    {
211        try
212        {
213            Node creatorNode = null;
214            if (content.getNode().hasNode(RepositoryConstants.NAMESPACE_PREFIX + ':' + METADATA_CONTRIBUTOR))
215            {
216                creatorNode = content.getNode().getNode(RepositoryConstants.NAMESPACE_PREFIX + ':' + METADATA_CONTRIBUTOR);
217            }
218            else
219            {
220                creatorNode = content.getNode().addNode(RepositoryConstants.NAMESPACE_PREFIX + ':' + METADATA_CONTRIBUTOR, RepositoryConstants.USER_NODETYPE);
221            }
222            creatorNode.setProperty(RepositoryConstants.NAMESPACE_PREFIX + ":login", user.getLogin());
223            creatorNode.setProperty(RepositoryConstants.NAMESPACE_PREFIX + ":population", user.getPopulationId());
224        }
225        catch (RepositoryException e)
226        {
227            throw new AmetysRepositoryException("Error setting the last contributor property.", e);
228        }
229    }
230    
231    /**
232     * Set a {@link DefaultContent} last modification date.
233     * @param content the {@link DefaultContent} to set.
234     * @param lastModified the last modification date to set.
235     * @throws AmetysRepositoryException if an error occurs.
236     */
237    public static void setLastModified(DefaultContent content, Date lastModified) throws AmetysRepositoryException
238    {
239        content.getMetadataHolder().setMetadata(METADATA_MODIFIED, lastModified);
240    }
241    
242    /**
243     * Set a {@link DefaultContent} last validation date.
244     * @param content the {@link DefaultContent} to set.
245     * @param validationDate the last validation date.
246     * @throws AmetysRepositoryException if an error occurs.
247     */
248    public static void setLastValidationDate(DefaultContent content, Date validationDate) throws AmetysRepositoryException
249    {
250        content.getMetadataHolder().setMetadata(METADATA_LAST_VALIDATION, validationDate);
251    }
252    
253    /**
254     * Set a {@link DefaultContent} last major validation date.
255     * @param content the {@link DefaultContent} to set.
256     * @param validationDate the last major validation date.
257     * @throws AmetysRepositoryException if an error occurs.
258     */
259    public static void setLastMajorValidationDate(DefaultContent content, Date validationDate) throws AmetysRepositoryException
260    {
261        content.getMetadataHolder().setMetadata(METADATA_LAST_MAJORVALIDATION, validationDate);
262    }
263    
264    /**
265     * Store the outgoing references on the content.
266     * @param content The content concerned by these outgoing references.
267     * @param references A non null map of outgoing references grouped by metadata (key are metadata path)
268     * @throws AmetysRepositoryException if an error occurs.
269     */
270    public static void setOutgoingReferences(DefaultContent content, Map<String, OutgoingReferences> references) throws AmetysRepositoryException
271    {
272        try
273        {
274            Node contentNode = content.getNode();
275            if (contentNode.hasNode(RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ':' + METADATA_ROOT_OUTGOING_REFERENCES))
276            {
277                contentNode.getNode(RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ':' + METADATA_ROOT_OUTGOING_REFERENCES).remove();
278            }
279            
280            if (references.size() != 0)
281            {
282                Node rootOutgoingRefsNode = contentNode.addNode(RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ':' + METADATA_ROOT_OUTGOING_REFERENCES);
283                for (String path : references.keySet())
284                {
285                    // Outgoing references node creation (for the given path)
286                    Node outgoingRefsNode = rootOutgoingRefsNode.addNode(RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ':' + METADATA_OUTGOING_REFERENCES);
287                    outgoingRefsNode.setProperty(RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ':' + METADATA_OUTGOING_REFERENCES_PATH_PROPERTY, path);
288                    
289                    // Reference nodes per type
290                    OutgoingReferences outgoingReferences = references.get(path);
291                    
292                    for (String type : outgoingReferences.keySet())
293                    {
294                        List<String> referenceValues = outgoingReferences.get(type);
295                        if (referenceValues != null && !referenceValues.isEmpty())
296                        {
297                            Node outgoingReferenceNode = outgoingRefsNode.addNode(type, RepositoryConstants.NAMESPACE_PREFIX + ':' + METADATA_OUTGOING_REFERENCE_NODETYPE);
298                            outgoingReferenceNode.setProperty(RepositoryConstants.NAMESPACE_PREFIX + ':' + METADATA_OUTGOING_REFERENCE_PROPERTY, referenceValues.toArray(new String[referenceValues.size()]));
299                        }
300                    }
301                }
302            }
303        }
304        catch (RepositoryException e)
305        {
306            throw new AmetysRepositoryException(e);
307        }
308    }
309}