001/*
002 *  Copyright 2010 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.web.repository.page.jcr;
017
018import java.util.List;
019
020import javax.jcr.Node;
021import javax.jcr.RepositoryException;
022
023import org.ametys.cms.repository.Content;
024import org.ametys.cms.repository.DefaultContent;
025import org.ametys.plugins.repository.AmetysObject;
026import org.ametys.plugins.repository.AmetysRepositoryException;
027import org.ametys.plugins.repository.CopiableAmetysObject;
028import org.ametys.plugins.repository.ModifiableTraversableAmetysObject;
029import org.ametys.plugins.repository.RepositoryConstants;
030import org.ametys.plugins.repository.RepositoryIntegrityViolationException;
031import org.ametys.plugins.repository.jcr.JCRAmetysObject;
032import org.ametys.plugins.repository.jcr.SimpleAmetysObject;
033import org.ametys.plugins.repository.metadata.ModifiableCompositeMetadata;
034import org.ametys.web.repository.content.WebContent;
035import org.ametys.web.repository.page.ModifiableZone;
036import org.ametys.web.repository.page.ModifiableZoneItem;
037import org.ametys.web.repository.page.Zone;
038import org.ametys.web.repository.page.ZoneItem;
039
040/**
041 *  implementation of an {@link ZoneItem}.
042 */
043public class DefaultZoneItem extends SimpleAmetysObject<DefaultZoneItemFactory> implements ModifiableZoneItem, CopiableAmetysObject
044{
045    /** Constant for title metadata. */
046    public static final String METADATA_TYPE = RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ":type";
047    /** Constant for service metadata. */
048    public static final String METADATA_SERVICE = RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ":service";
049    /** Constant for service metadata. */
050    public static final String METADATA_SERVICE_PARAM = "service_parameters";
051    /** Constant for content metadata. */
052    public static final String METADATA_CONTENT = RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ":content";
053    /** Constant for "metadata set name" metadata. */
054    public static final String METADATA_METADATASET_NAME = RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ":metadataSetName";
055
056    /**
057     * Creates a {@link DefaultZoneItem}.
058     * 
059     * @param node the node backing this {@link AmetysObject}.
060     * @param parentPath the parent path in the Ametys hierarchy.
061     * @param factory the {@link DefaultZoneItemFactory} which creates the AmetysObject.
062     */
063    public DefaultZoneItem(Node node, String parentPath, DefaultZoneItemFactory factory)
064    {
065        super(node, parentPath, factory);
066    }
067    
068    @Override
069    public ZoneType getType() throws AmetysRepositoryException
070    {
071        try
072        {
073            return ZoneType.valueOf(getNode().getProperty(METADATA_TYPE).getString());
074        }
075        catch (RepositoryException e)
076        {
077            throw new AmetysRepositoryException("Unable to get type property", e);
078        }
079    }
080
081    @Override
082    public void setType(ZoneType type) throws AmetysRepositoryException
083    {
084        try
085        {
086            getNode().setProperty(METADATA_TYPE, type.name());
087        }
088        catch (RepositoryException e)
089        {
090            throw new AmetysRepositoryException("Unable to set type property", e);
091        }
092    }
093
094    @Override
095    public <C extends Content> C getContent() throws AmetysRepositoryException
096    {
097        try
098        {
099            return _getFactory().<C>resolveAmetysObject(getNode().getProperty(METADATA_CONTENT).getNode());
100        }
101        catch (RepositoryException e)
102        {
103            throw new AmetysRepositoryException("Unable to get content property", e);
104        }
105    }
106
107    @Override
108    public <C extends Content> void setContent(C content) throws AmetysRepositoryException
109    {
110        try
111        {
112            // FIXME stop using getNode that is JCR but use AmetysObject API... if it seems cool to you
113            getNode().setProperty(METADATA_CONTENT, ((JCRAmetysObject) content).getNode());
114        }
115        catch (RepositoryException e)
116        {
117            throw new AmetysRepositoryException("Unable to set content property", e);
118        }    
119    }
120    
121    @Override
122    public String getMetadataSetName() throws AmetysRepositoryException
123    {
124        try
125        {
126            if (getNode().hasProperty(METADATA_METADATASET_NAME))
127            {
128                return getNode().getProperty(METADATA_METADATASET_NAME).getString();
129            }
130            return null;
131        }
132        catch (RepositoryException e)
133        {
134            throw new AmetysRepositoryException("Unable to get metadata set name property.", e);
135        }
136    }
137    
138    @Override
139    public void setMetadataSetName(String metadataSetName) throws AmetysRepositoryException
140    {
141        try
142        {
143            getNode().setProperty(METADATA_METADATASET_NAME, metadataSetName);
144        }
145        catch (RepositoryException e)
146        {
147            throw new AmetysRepositoryException("Unable to set metadata set name property.", e);
148        }
149    }
150    
151    @Override
152    public String getServiceId() throws AmetysRepositoryException
153    {
154        try
155        {
156            return getNode().getProperty(METADATA_SERVICE).getString();
157        }
158        catch (RepositoryException e)
159        {
160            throw new AmetysRepositoryException("Unable to get service property", e);
161        }
162    }
163    
164    @Override
165    public ModifiableCompositeMetadata getServiceParameters() throws AmetysRepositoryException
166    {
167        return getMetadataHolder().getCompositeMetadata(METADATA_SERVICE_PARAM, true);
168    }
169
170    @Override
171    public void setServiceId(String serviceId) throws AmetysRepositoryException
172    {
173        try
174        {
175            getNode().setProperty(METADATA_SERVICE, serviceId);
176        }
177        catch (RepositoryException e)
178        {
179            throw new AmetysRepositoryException("Unable to set service property", e);
180        }
181    }
182    
183    @Override
184    public ModifiableZoneItem copyTo(ModifiableTraversableAmetysObject parent, String name, List<String> restrictTo) throws AmetysRepositoryException
185    {
186        return copyTo (parent, name);
187    }
188    
189    @Override
190    public ModifiableZoneItem copyTo(ModifiableTraversableAmetysObject parent, String name) throws AmetysRepositoryException
191    {
192        if (parent instanceof DefaultZone)
193        {
194            ModifiableZone parentZone = (ModifiableZone) parent;
195            ModifiableZoneItem cZoneItem = parentZone.addZoneItem();
196            
197            ZoneType type = getType();
198            cZoneItem.setType(type);
199            
200            if (ZoneType.SERVICE.equals(type))
201            {
202                cZoneItem.setServiceId(getServiceId());
203                // Copy services parameters
204                getMetadataHolder().copyTo(cZoneItem.getMetadataHolder());
205            }
206            else
207            {
208                Content content = getContent();
209                if (content instanceof WebContent)
210                {
211                    WebContent webContent = (WebContent) content;
212                    if (getZone().getPage().getSiteName().equals(webContent.getSiteName()))
213                    {
214                        if (webContent instanceof DefaultContent)
215                        {
216                            Content cContent = ((DefaultContent) webContent).copyTo(webContent.getSite().getRootContents(), null);
217                            cZoneItem.setContent(cContent);
218                            
219                            // Update references to AmetysObject in RichText
220                            _getFactory().getCopySiteComponent().updateLinksInRichText(getZone().getPage(), cZoneItem.getZone().getPage(), content, cContent);
221                        }
222                    }
223                    else
224                    {
225                        // Copy reference  
226                        cZoneItem.setContent(getContent());
227                    }
228                }
229                else
230                {
231                    // Copy reference
232                    cZoneItem.setContent(getContent());
233                }
234                
235                String metadataSetName = getMetadataSetName();
236                if (metadataSetName != null)
237                {
238                    cZoneItem.setMetadataSetName(metadataSetName);
239                }
240            }
241            
242            return cZoneItem;
243        }
244        else
245        {
246            throw new AmetysRepositoryException("Can not copy a zone item " + getId() + " of type DefaultZoneItem to something that is not a DefaultZone " + parent.getId());
247        }
248    }
249    
250    @Override
251    public boolean canMoveTo(AmetysObject newParent) throws AmetysRepositoryException
252    {
253        return newParent instanceof DefaultZone;
254    }
255    
256    @Override
257    public void moveTo(AmetysObject newParent, boolean renameIfExist) throws AmetysRepositoryException, RepositoryIntegrityViolationException
258    {
259        if (!canMoveTo(newParent))
260        {
261            throw new AmetysRepositoryException("Can not move a zone item " + getId() + " of type DefaultZoneItem to something that is not a DefaultZone " + newParent.getId());
262        }
263        
264        Node node = getNode();
265
266        try
267        {
268            DefaultZone newParentZone = (DefaultZone) newParent;
269                
270            // Move node
271            node.getSession().move(node.getPath(), newParentZone.getNode().getPath() + "/" + DefaultZone.ZONEITEMS_NODE_NAME + "/" + node.getName());
272        }
273        catch (RepositoryException e)
274        {
275            throw new AmetysRepositoryException("Can not move DefaultZoneItem " + getId() + " to DefaultZone " + newParent.getId(), e);
276        }
277    }
278    
279    @Override
280    public void orderBefore(AmetysObject siblingObject) throws AmetysRepositoryException
281    {
282        if (siblingObject != null && !(siblingObject instanceof JCRAmetysObject))
283        {
284            throw new AmetysRepositoryException(String.format("Unable to order zone item '%s' before sibling '%s' (sibling is not a JCRAmetysObject)", this.getId(), siblingObject.getId()));
285        }
286        
287        Node node = getNode();
288        Node siblingNode = siblingObject != null ? ((JCRAmetysObject) siblingObject).getNode() : null;
289        
290        try
291        {
292            node.getParent().orderBefore(node.getName() + "[" + node.getIndex() + "]", siblingNode != null ? siblingNode.getName() + "[" + siblingNode.getIndex() + "]" : null);
293        }
294        catch (RepositoryException e)
295        {
296            throw new AmetysRepositoryException(String.format("Unable to order zone item '%s' before sibling '%s'", this.getId(), siblingObject != null ? siblingObject.getId() : ""), e);
297        }
298    }
299    
300    @Override
301    public Zone getZone()
302    {
303        return getParent().getParent();
304    }
305}