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.workflow;
017
018import java.util.HashMap;
019import java.util.List;
020import java.util.Map;
021import java.util.concurrent.Future;
022
023import org.apache.avalon.framework.service.ServiceException;
024import org.apache.avalon.framework.service.ServiceManager;
025
026import org.ametys.cms.FilterNameHelper;
027import org.ametys.cms.repository.Content;
028import org.ametys.cms.repository.ModifiableContent;
029import org.ametys.cms.repository.ModifiableWorkflowAwareContent;
030import org.ametys.core.observation.Event;
031import org.ametys.core.user.CurrentUserProvider;
032import org.ametys.plugins.repository.ModifiableTraversableAmetysObject;
033import org.ametys.plugins.repository.RepositoryConstants;
034import org.ametys.plugins.repository.RepositoryIntegrityViolationException;
035import org.ametys.plugins.repository.UnknownAmetysObjectException;
036import org.ametys.plugins.repository.collection.AmetysObjectCollection;
037import org.ametys.web.ObservationConstants;
038import org.ametys.web.repository.ModifiableSiteAwareAmetysObject;
039import org.ametys.web.repository.page.ModifiablePage;
040import org.ametys.web.repository.page.ModifiableZone;
041import org.ametys.web.repository.page.ModifiableZoneItem;
042import org.ametys.web.repository.page.Page;
043import org.ametys.web.repository.page.Page.PageType;
044import org.ametys.web.repository.page.ZoneItem;
045import org.ametys.web.repository.page.ZoneItem.ZoneType;
046import org.ametys.web.repository.site.Site;
047import org.ametys.web.repository.site.SiteManager;
048
049import com.opensymphony.workflow.WorkflowException;
050
051/**
052 * OSWorkflow function for creating a content.
053 */
054public class CreateContentFunction extends org.ametys.cms.workflow.CreateContentFunction
055{
056    /** Constant for storing the site to use into the transient variables map. */
057    public static final String SITE_KEY = Site.class.getName();
058    /** Constant for knowing on which page the content will be affected. */
059    public static final String PAGE_KEY = CreateContentFunction.class.getName() + "$pageId";
060    /** Constant for knowing on which zone of the page to affect the content. */
061    public static final String PAGE_ZONE_KEY = CreateContentFunction.class.getName() + "$zoneName";
062    
063    /** The sites manager */
064    protected SiteManager _siteManager;
065    /** Current user provider */
066    protected CurrentUserProvider _currentUserProvider;
067    
068    @Override
069    public void service(ServiceManager manager) throws ServiceException
070    {
071        super.service(manager);
072        _siteManager = (SiteManager) manager.lookup(SiteManager.ROLE);
073        _currentUserProvider = (CurrentUserProvider) manager.lookup(CurrentUserProvider.ROLE);
074    }
075    
076    @Override
077    protected List<Future> _notifyContentAdded(Content content, Map transientVars) throws WorkflowException
078    {
079        List<Future> futures = super._notifyContentAdded(content, transientVars);
080        
081        String pageId = (String) transientVars.get(PAGE_KEY);
082        if (pageId != null)
083        {
084            Page page = _resolver.resolveById(pageId);
085    
086            Map<String, Object> eventParams = new HashMap<>();
087            eventParams.put(ObservationConstants.ARGS_PAGE, page);
088            eventParams.put(ObservationConstants.ARGS_ZONE_ITEM_ID, getResultsMap(transientVars).get("zoneitem-id"));
089            eventParams.put(ObservationConstants.ARGS_ZONE_TYPE, ZoneType.CONTENT);
090            eventParams.put(ObservationConstants.ARGS_ZONE_ITEM_CONTENT, content);
091            _observationManager.notify(new Event(ObservationConstants.EVENT_ZONEITEM_ADDED, _currentUserProvider.getUser(), eventParams));
092        }
093        
094        return futures;
095    }
096    
097    @Override
098    protected ModifiableWorkflowAwareContent _createContent(Map transientVars, String desiredContentName, ModifiableTraversableAmetysObject contentsNode)
099    {
100        ModifiableWorkflowAwareContent content = null;
101        
102        String contentName = FilterNameHelper.filterName(desiredContentName);
103        int errorCount = 0;
104        do
105        {
106            if (errorCount != 0)
107            {
108                contentName = FilterNameHelper.filterName(desiredContentName + " " + (errorCount + 1));
109            }
110            try
111            {
112                content = contentsNode.createChild(contentName, RepositoryConstants.NAMESPACE_PREFIX + ":defaultWebContent");
113            }
114            catch (RepositoryIntegrityViolationException e)
115            {
116                // Content name is already used
117                errorCount++;
118            }
119        }
120        while (content == null);
121        
122        return content;
123    }
124        
125    @Override
126    protected AmetysObjectCollection< ? , ModifiableWorkflowAwareContent> _getContentRoot(Map transientVars) throws WorkflowException
127    {
128        String siteName = _getNonNullVar(transientVars, SITE_KEY, "Missing sitename");
129
130        Site site = null;
131        try
132        {
133            site = _siteManager.getSite(siteName);
134        }
135        catch (UnknownAmetysObjectException e)
136        {
137            throw new WorkflowException("Site does not exist", e);
138        }
139        
140        // FIXME use constant or site getter
141        return site.getChild(RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ":contents");
142    }
143    
144    @Override
145    protected void _populateContent(Map transientVars, ModifiableContent content) throws WorkflowException
146    {
147        super._populateContent(transientVars, content);
148        
149        String siteName = _getNonNullVar(transientVars, SITE_KEY, "Missing sitename");
150        
151        // FIXME API what if not modifiable
152        ((ModifiableSiteAwareAmetysObject) content).setSiteName(siteName);
153    }
154    
155    @Override
156    protected void _populateAdditionalData(Map transientVars, ModifiableContent content) throws WorkflowException
157    {
158        super._populateAdditionalData(transientVars, content);
159        
160        // FIXME API test if not modifiable
161        ModifiablePage page = null;
162        ModifiableZone zone = null;
163        try
164        {
165            String zoneName = (String) transientVars.get(PAGE_ZONE_KEY);
166            if (zoneName != null)
167            {
168                String pageId = (String) transientVars.get(PAGE_KEY);
169                if (pageId != null)
170                {
171                    page = _resolver.resolveById(pageId);
172                    
173                    if (page.getType() != PageType.CONTAINER)
174                    {
175                        throw new WorkflowException("Page is not of type Container");
176                    }
177                    
178                    if (page.hasZone(zoneName))
179                    {
180                        zone = page.getZone(zoneName);
181                    }
182                    else
183                    {
184                        zone = page.createZone(zoneName);
185                    }
186                    
187                    ModifiableZoneItem zoneItem = zone.addZoneItem();
188                    zoneItem.setType(ZoneItem.ZoneType.CONTENT);
189                    zoneItem.setContent(content);
190                    zoneItem.setMetadataSetName("main");
191                    page.saveChanges();
192
193                    getResultsMap(transientVars).put("zoneitem-id", zoneItem.getId());
194                }
195            }
196        }
197        catch (UnknownAmetysObjectException e)
198        {
199            throw new WorkflowException("Page does not exist", e);
200        }
201    }
202}