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