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;
019import java.util.Optional;
020
021import javax.jcr.Node;
022
023import org.apache.commons.collections4.MapUtils;
024import org.slf4j.Logger;
025import org.slf4j.LoggerFactory;
026import org.xml.sax.ContentHandler;
027import org.xml.sax.SAXException;
028
029import org.ametys.plugins.repository.AmetysObject;
030import org.ametys.plugins.repository.AmetysObjectIterable;
031import org.ametys.plugins.repository.AmetysRepositoryException;
032import org.ametys.plugins.repository.CopiableAmetysObject;
033import org.ametys.plugins.repository.ModifiableTraversableAmetysObject;
034import org.ametys.plugins.repository.RepositoryConstants;
035import org.ametys.plugins.repository.TraversableAmetysObject;
036import org.ametys.plugins.repository.data.holder.ModifiableModelAwareDataHolder;
037import org.ametys.plugins.repository.data.holder.ModifiableModelLessDataHolder;
038import org.ametys.plugins.repository.data.holder.impl.DefaultModifiableModelLessDataHolder;
039import org.ametys.plugins.repository.data.repositorydata.ModifiableRepositoryData;
040import org.ametys.plugins.repository.data.repositorydata.impl.JCRRepositoryData;
041import org.ametys.plugins.repository.jcr.DefaultTraversableAmetysObject;
042import org.ametys.plugins.repository.metadata.ModifiableCompositeMetadata;
043import org.ametys.runtime.model.View;
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.Page;
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 Page getPage()
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)
112                {
113                    ((CopiableAmetysObject) zoneItem).copyTo((ModifiableTraversableAmetysObject) cZone, 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    public ModifiableModelLessDataHolder getDataHolder()
131    {
132        ModifiableRepositoryData repositoryData = new JCRRepositoryData(getNode());
133        return new DefaultModifiableModelLessDataHolder(_getFactory().getPageDataTypeExtensionPoint(), repositoryData);
134    }
135    
136    @Override
137    public ModifiableCompositeMetadata getMetadataHolder()
138    {
139        __LOGGER.warn("The getMetadataHolder method of DefaultZone is deprecated. Use the getDataHolder instead. StackTrace: ", new Exception());
140        return super.getMetadataHolder();
141    }
142    
143    public ModifiableModelAwareDataHolder getZoneParametersHolder() throws AmetysRepositoryException
144    {
145        JCRRepositoryData zoneRepositoryData = new JCRRepositoryData(getNode());
146        
147        // Get the zone Id
148        String zoneId = getName();
149        
150        // Get the template Id
151        Page page = getPage();
152        String templateId = page.getTemplate();
153        
154        // Get the skin Id
155        String skinId = page.getSite().getSkinId();
156        
157        ViewParametersManager viewParametersManager = _getFactory().getViewParametersManager();
158        Optional<ViewParametersModel> zoneViewParameters = viewParametersManager.getZoneViewParametersModel(skinId, templateId, zoneId);
159        if (zoneViewParameters.isEmpty())
160        {
161            zoneViewParameters = Optional.of(new ViewParametersModel("zone-no-param", new View(), MapUtils.EMPTY_SORTED_MAP));
162        }
163        return viewParametersManager.getParametersHolder(zoneRepositoryData, zoneViewParameters.get());
164    }
165    
166    /*
167     * The default implementation is overridden here to not use the getDataHolder()#dataToSAX implementation
168     * Each #dataToSAX method calls the next one and the implementation that has to change is the last one.
169     * If the getDataHolder() is used for one, the next ones will be called with the default implementation
170     */
171    public void dataToSAX(ContentHandler contentHandler, DataContext context) throws SAXException, UnknownTypeException, NotUniqueTypeException
172    {
173        for (String name : getDataNames())
174        {
175            dataToSAX(contentHandler, name, context);
176        }
177    }
178    
179    public void dataToSAX(ContentHandler contentHandler, String dataPath, DataContext context) throws SAXException
180    {
181        if (!ViewParametersManager.VIEW_PARAMETERS_COMPOSITE_NAME.equals(dataPath))
182        {
183            ModifiableZone.super.dataToSAX(contentHandler, dataPath, context);
184        }
185    }
186}