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.io.IOException;
019import java.util.List;
020import java.util.Locale;
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.web.parameters.view.ViewParametersModel;
049import org.ametys.web.parameters.view.ViewParametersManager;
050import org.ametys.web.repository.page.ModifiablePage;
051import org.ametys.web.repository.page.ModifiableZone;
052import org.ametys.web.repository.page.ModifiableZoneItem;
053import org.ametys.web.repository.page.Page;
054import org.ametys.web.repository.page.Zone;
055
056/**
057 * JCR implementation of an {@link Zone}.
058 */
059public class DefaultZone extends DefaultTraversableAmetysObject<DefaultZoneFactory> implements ModifiableZone, CopiableAmetysObject
060{
061    /** Constant for zone items node name */
062    public static final String ZONEITEMS_NODE_NAME = RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ":zoneItems";
063    /** Constant for zone item node name */
064    public static final String ZONEITEM_NODE_NAME = RepositoryConstants.NAMESPACE_PREFIX + ":" + ZONEITEM_DATA_NAME;
065    /** Constant for zone items node type */
066    public static final String ZONEITEM_NODETYPE_NAME = RepositoryConstants.NAMESPACE_PREFIX + ":zoneItem";
067
068    private static final Logger __LOGGER = LoggerFactory.getLogger(DefaultZone.class);
069    
070    /**
071     * Creates a {@link DefaultZone}.
072     * 
073     * @param node the node backing this {@link AmetysObject}.
074     * @param parentPath the parent path in the Ametys hierarchy.
075     * @param factory the {@link DefaultZoneFactory} which creates the AmetysObject.
076     */
077    public DefaultZone(Node node, String parentPath, DefaultZoneFactory factory)
078    {
079        super(node, parentPath, factory);
080    }
081
082    @Override
083    public AmetysObjectIterable<ModifiableZoneItem> getZoneItems() throws AmetysRepositoryException
084    {
085        return ((TraversableAmetysObject) getChild(ZONEITEMS_NODE_NAME)).getChildren(); 
086    }
087    
088    @Override
089    public ModifiableZoneItem addZoneItem() throws AmetysRepositoryException
090    {
091        return ((ModifiableTraversableAmetysObject) getChild(ZONEITEMS_NODE_NAME)).createChild(ZONEITEM_NODE_NAME, ZONEITEM_NODETYPE_NAME); 
092    }
093    
094    @Override
095    public Page getPage()
096    {
097        return getParent().getParent();
098    }
099    
100    @Override
101    public ModifiableZone copyTo(ModifiableTraversableAmetysObject parent, String name) throws AmetysRepositoryException
102    {
103        if (parent instanceof ModifiablePage)
104        {
105            ModifiableZone cZone = ((ModifiablePage) parent).createZone(getName());
106            
107            // Copy view parameters
108            getZoneParametersHolder().copyTo(cZone.getZoneParametersHolder());
109            
110            for (ModifiableZoneItem zoneItem : getZoneItems())
111            {
112                if (zoneItem instanceof CopiableAmetysObject)
113                {
114                    ((CopiableAmetysObject) zoneItem).copyTo((ModifiableTraversableAmetysObject) cZone, null);
115                }
116            }
117            return cZone;
118        }
119        else
120        {
121            throw new AmetysRepositoryException("Can not copy zone " + getId() + " of type DefaultZone to something that is not a ModifiablePage " + parent.getId());
122        }
123    }
124    
125    @Override
126    public AmetysObject copyTo(ModifiableTraversableAmetysObject parent, String name, List<String> restrictTo) throws AmetysRepositoryException
127    {
128        return copyTo(parent, name);
129    }
130
131    public ModifiableModelLessDataHolder getDataHolder()
132    {
133        ModifiableRepositoryData repositoryData = new JCRRepositoryData(getNode());
134        return new DefaultModifiableModelLessDataHolder(_getFactory().getPageDataTypeExtensionPoint(), repositoryData);
135    }
136    
137    @Override
138    public ModifiableCompositeMetadata getMetadataHolder()
139    {
140        __LOGGER.warn("The getMetadataHolder method of DefaultZone is deprecated. Use the getDataHolder instead. StackTrace: ", new Exception());
141        return super.getMetadataHolder();
142    }
143    
144    public ModifiableModelAwareDataHolder getZoneParametersHolder() throws AmetysRepositoryException
145    {
146        JCRRepositoryData zoneItemRepositoryData = new JCRRepositoryData(getNode());
147        
148        // Get the zone Id
149        String zoneId = getName();
150        
151        // Get the template Id
152        Page page = getPage();
153        String templateId = page.getTemplate();
154        
155        // Get the skin Id
156        String skinId = page.getSite().getSkinId();
157        
158        ViewParametersManager viewParametersManager = _getFactory().getViewParametersManager();
159        Optional<ViewParametersModel> zoneViewParameters = viewParametersManager.getZoneViewParametersModel(skinId, templateId, zoneId);
160        if (zoneViewParameters.isEmpty())
161        {
162            zoneViewParameters = Optional.of(new ViewParametersModel("zone-no-param", new View(), MapUtils.EMPTY_SORTED_MAP));
163        }
164        return viewParametersManager.getParametersHolder(zoneItemRepositoryData, zoneViewParameters.get());
165    }
166    
167    /*
168     * The default implementation is overridden here to not use the getDataHolder()#dataToSAX implementation
169     * Each #dataToSAX method calls the next one and the implementation that has to change is the last one.
170     * If the getDataHolder() is used for one, the next ones will be called with the default implementation
171     */
172    public void dataToSAX(ContentHandler contentHandler, Locale locale) throws SAXException, IOException, UnknownTypeException, NotUniqueTypeException
173    {
174        for (String name : getDataNames())
175        {
176            dataToSAX(contentHandler, name, locale);
177        }
178    }
179    
180    public void dataToSAX(ContentHandler contentHandler, String dataPath, Locale locale) throws SAXException, IOException
181    {
182        if (!ViewParametersManager.VIEW_PARAMETERS_COMPOSITE_NAME.equals(dataPath))
183        {
184            ModifiableZone.super.dataToSAX(contentHandler, dataPath, locale);
185        }
186    }
187}