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.HashMap;
019import java.util.List;
020import java.util.Map;
021import java.util.Optional;
022
023import javax.jcr.Node;
024
025import org.apache.commons.collections4.MapUtils;
026import org.slf4j.Logger;
027import org.slf4j.LoggerFactory;
028import org.xml.sax.ContentHandler;
029import org.xml.sax.SAXException;
030
031import org.ametys.plugins.repository.AmetysObject;
032import org.ametys.plugins.repository.AmetysObjectIterable;
033import org.ametys.plugins.repository.AmetysRepositoryException;
034import org.ametys.plugins.repository.CopiableAmetysObject;
035import org.ametys.plugins.repository.ModifiableTraversableAmetysObject;
036import org.ametys.plugins.repository.RepositoryConstants;
037import org.ametys.plugins.repository.TraversableAmetysObject;
038import org.ametys.plugins.repository.data.holder.ModifiableModelAwareDataHolder;
039import org.ametys.plugins.repository.data.holder.ModifiableModelLessDataHolder;
040import org.ametys.plugins.repository.data.holder.impl.DefaultModifiableModelLessDataHolder;
041import org.ametys.plugins.repository.data.repositorydata.ModifiableRepositoryData;
042import org.ametys.plugins.repository.data.repositorydata.impl.JCRRepositoryData;
043import org.ametys.plugins.repository.jcr.DefaultTraversableAmetysObject;
044import org.ametys.plugins.repository.metadata.ModifiableCompositeMetadata;
045import org.ametys.runtime.model.View;
046import org.ametys.runtime.model.exception.NotUniqueTypeException;
047import org.ametys.runtime.model.exception.UnknownTypeException;
048import org.ametys.runtime.model.type.DataContext;
049import org.ametys.web.parameters.view.ViewParametersManager;
050import org.ametys.web.parameters.view.ViewParametersModel;
051import org.ametys.web.repository.page.ModifiablePage;
052import org.ametys.web.repository.page.ModifiableZone;
053import org.ametys.web.repository.page.ModifiableZoneItem;
054import org.ametys.web.repository.page.SitemapElement;
055import org.ametys.web.repository.page.Zone;
056
057/**
058 * JCR implementation of an {@link Zone}.
059 */
060public class DefaultZone extends DefaultTraversableAmetysObject<DefaultZoneFactory> implements ModifiableZone, CopiableAmetysObject
061{
062    /** Constant for zone items node name */
063    public static final String ZONEITEMS_NODE_NAME = RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ":zoneItems";
064    /** Constant for zone item node name */
065    public static final String ZONEITEM_NODE_NAME = RepositoryConstants.NAMESPACE_PREFIX + ":" + ZONEITEM_DATA_NAME;
066    /** Constant for zone items node type */
067    public static final String ZONEITEM_NODETYPE_NAME = RepositoryConstants.NAMESPACE_PREFIX + ":zoneItem";
068
069    private static final Logger __LOGGER = LoggerFactory.getLogger(DefaultZone.class);
070    
071    /**
072     * Creates a {@link DefaultZone}.
073     * 
074     * @param node the node backing this {@link AmetysObject}.
075     * @param parentPath the parent path in the Ametys hierarchy.
076     * @param factory the {@link DefaultZoneFactory} which creates the AmetysObject.
077     */
078    public DefaultZone(Node node, String parentPath, DefaultZoneFactory factory)
079    {
080        super(node, parentPath, factory);
081    }
082
083    @Override
084    public AmetysObjectIterable<ModifiableZoneItem> getZoneItems() throws AmetysRepositoryException
085    {
086        return ((TraversableAmetysObject) getChild(ZONEITEMS_NODE_NAME)).getChildren(); 
087    }
088    
089    @Override
090    public ModifiableZoneItem addZoneItem() throws AmetysRepositoryException
091    {
092        return ((ModifiableTraversableAmetysObject) getChild(ZONEITEMS_NODE_NAME)).createChild(ZONEITEM_NODE_NAME, ZONEITEM_NODETYPE_NAME); 
093    }
094    
095    @Override
096    public SitemapElement getSitemapElement()
097    {
098        return getParent().getParent();
099    }
100    
101    @Override
102    public ModifiableZone copyTo(ModifiableTraversableAmetysObject parent, String name) throws AmetysRepositoryException
103    {
104        if (parent instanceof ModifiablePage)
105        {
106            ModifiableZone cZone = ((ModifiablePage) parent).createZone(getName());
107            
108            // Copy view parameters
109            getZoneParametersHolder().copyTo(cZone.getZoneParametersHolder());
110            
111            for (ModifiableZoneItem zoneItem : getZoneItems())
112            {
113                if (zoneItem instanceof CopiableAmetysObject)
114                {
115                    ((CopiableAmetysObject) zoneItem).copyTo((ModifiableTraversableAmetysObject) cZone, null);
116                }
117            }
118            return cZone;
119        }
120        else
121        {
122            throw new AmetysRepositoryException("Can not copy zone " + getId() + " of type DefaultZone to something that is not a ModifiablePage " + parent.getId());
123        }
124    }
125    
126    @Override
127    public AmetysObject copyTo(ModifiableTraversableAmetysObject parent, String name, List<String> restrictTo) throws AmetysRepositoryException
128    {
129        return copyTo(parent, name);
130    }
131
132    public ModifiableModelLessDataHolder getDataHolder()
133    {
134        ModifiableRepositoryData repositoryData = new JCRRepositoryData(getNode());
135        return new DefaultModifiableModelLessDataHolder(_getFactory().getPageDataTypeExtensionPoint(), repositoryData);
136    }
137    
138    @Override
139    public ModifiableCompositeMetadata getMetadataHolder()
140    {
141        __LOGGER.warn("The getMetadataHolder method of DefaultZone is deprecated. Use the getDataHolder instead. StackTrace: ", new Exception());
142        return super.getMetadataHolder();
143    }
144    
145    public ModifiableModelAwareDataHolder getZoneParametersHolder() throws AmetysRepositoryException
146    {
147        JCRRepositoryData zoneRepositoryData = new JCRRepositoryData(getNode());
148        
149        // Get the zone Id
150        String zoneId = getName();
151        
152        // Get the template Id
153        SitemapElement sitemapElement = getSitemapElement();
154        String templateId = sitemapElement.getTemplate();
155        
156        // Get the skin Id
157        String skinId = sitemapElement.getSite().getSkinId();
158        
159        ViewParametersManager viewParametersManager = _getFactory().getViewParametersManager();
160        Optional<ViewParametersModel> zoneViewParameters = viewParametersManager.getZoneViewParametersModel(skinId, templateId, zoneId);
161        if (zoneViewParameters.isEmpty())
162        {
163            zoneViewParameters = Optional.of(new ViewParametersModel("zone-no-param", new View(), MapUtils.EMPTY_SORTED_MAP));
164        }
165        return viewParametersManager.getParametersHolder(zoneRepositoryData, zoneViewParameters.get());
166    }
167    
168    public void dataToSAX(ContentHandler contentHandler, DataContext context) throws SAXException, UnknownTypeException, NotUniqueTypeException
169    {
170        for (String dataName : getDataNames())
171        {
172            DataContext newContext = context.cloneContext().addSegmentToDataPath(dataName);
173            dataToSAX(contentHandler, dataName, newContext);
174        }
175    }
176    
177    public void dataToSAX(ContentHandler contentHandler, String dataPath, DataContext context) throws SAXException
178    {
179        // Do not generate SAX events for view parameters
180        if (!ViewParametersManager.VIEW_PARAMETERS_COMPOSITE_NAME.equals(dataPath))
181        {
182            ModifiableZone.super.dataToSAX(contentHandler, dataPath, context);
183        }
184    }
185    
186    public Map<String, Object> dataToJSON(DataContext context) throws UnknownTypeException, NotUniqueTypeException
187    {
188        Map<String, Object> result = new HashMap<>();
189        for (String dataName : getDataNames())
190        {
191            DataContext newContext = context.cloneContext().addSegmentToDataPath(dataName);
192            result.put(dataName, dataToJSON(dataName, newContext));
193        }
194        
195        return result;
196    }
197    
198    public Object dataToJSON(String dataPath, DataContext context)
199    {
200        // Do not convert view parameters
201        return !ViewParametersManager.VIEW_PARAMETERS_COMPOSITE_NAME.equals(dataPath)
202                ? ModifiableZone.super.dataToJSON(dataPath, context)
203                : null;
204    }
205}