001/*
002 *  Copyright 2017 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.odf.workflow.copy;
017
018import java.util.HashMap;
019import java.util.List;
020import java.util.Map;
021import java.util.Set;
022
023import org.ametys.cms.repository.Content;
024import org.ametys.cms.repository.ModifiableContent;
025import org.ametys.cms.workflow.copy.CreateContentByCopyFunction;
026import org.ametys.odf.ProgramItem;
027import org.ametys.odf.course.Course;
028import org.ametys.odf.courselist.CourseList;
029import org.ametys.odf.courselist.CourseListContainer;
030import org.ametys.odf.program.Program;
031import org.ametys.odf.program.ProgramPart;
032import org.ametys.odf.workflow.copy.CopyODFContentClientSideElement.DuplicationMode;
033import org.ametys.plugins.repository.data.holder.values.SynchronizableValue;
034import org.ametys.plugins.repository.data.holder.values.SynchronizableValue.Mode;
035
036import com.opensymphony.workflow.WorkflowException;
037
038/**
039 * OSWorkflow function to create a program item by copy of another
040 */
041public abstract class AbstractCreateProgramItemByCopyFunction extends AbstractCreateODFContentByCopyFunction
042{
043    /** Key for the parent of the target content */
044    public static final String PARENT_KEY = AbstractCreateProgramItemByCopyFunction.class.getName() + "$parentId";
045    
046    @Override
047    protected Map<String, Object> getAdditionalCopyMap(Map transientVars, Content baseContent, String viewName, String fallbackViewName) throws WorkflowException
048    {
049        Map<String, Object> additionalCopyMap = new HashMap<>();
050        additionalCopyMap.put(ProgramItem.CATALOG, null);
051        
052        @SuppressWarnings("unchecked")
053        Map<String, Object> copyMap = (Map<String, Object>) transientVars.get(CreateContentByCopyFunction.COPY_MAP_KEY);
054        
055        DuplicationMode duplicationMode = copyMap.containsKey(CopyODFContentClientSideElement.DUPLICATION_MODE_KEY) ? DuplicationMode.valueOf((String) copyMap.get(CopyODFContentClientSideElement.DUPLICATION_MODE_KEY)) : DuplicationMode.SINGLE;
056        
057        Set<String> childReferenceMetadataNames = _getChildReferenceMetadataName();
058        if (!childReferenceMetadataNames.isEmpty())
059        {
060            boolean isValidDuplicationMode = true;
061            Map<String, Object> childReferenceMap = new HashMap<>();
062            childReferenceMap.put(CopyODFContentClientSideElement.DUPLICATION_MODE_KEY, duplicationMode.toString());
063            switch (duplicationMode)
064            {
065                case SINGLE:
066                    childReferenceMap.put("$mode", "reference");
067                    break;
068                case STRUCTURE_ONLY:
069                    if (baseContent instanceof CourseList)
070                    {
071                        childReferenceMap.put("$mode", "reference");
072                    }
073                    else
074                    {
075                        childReferenceMap.put("$mode", "create");
076                    }
077                    break;
078                case FULL:
079                    childReferenceMap.put("$mode", "create");
080                    break;
081                default:
082                    isValidDuplicationMode = false;
083                    break;
084            }
085            
086            if (isValidDuplicationMode)
087            {
088                for (String childReferenceMetadataName : childReferenceMetadataNames)
089                {
090                    additionalCopyMap.put(childReferenceMetadataName, childReferenceMap);
091                }
092            }
093        }
094        
095        return additionalCopyMap;
096    }
097    
098    @Override
099    protected void processValues(Map transientVars, ModifiableContent targetContent, Map<String, Object> values) throws WorkflowException
100    {
101        super.processValues(transientVars, targetContent, values);
102        
103        String parentId = (String) transientVars.get(PARENT_KEY);
104        
105        if (parentId != null)
106        {
107            Content parent = _resolver.resolveById(parentId);
108            
109            if (!(targetContent instanceof Program))
110            {
111                SynchronizableValue value = new SynchronizableValue(List.of(parentId));
112                value.setMode(Mode.APPEND);
113                
114                if (targetContent instanceof CourseList && parent instanceof CourseListContainer)
115                {
116                    if (parent instanceof Course)
117                    {
118                        values.put(CourseList.PARENT_COURSES, value);
119                    }
120                    else
121                    {
122                        values.put(ProgramPart.PARENT_PROGRAM_PARTS, value);
123                    }
124                }
125                else if (targetContent instanceof ProgramPart && parent instanceof ProgramPart)
126                {
127                    values.put(ProgramPart.PARENT_PROGRAM_PARTS, value);
128                }
129                else if (targetContent instanceof Course && parent instanceof CourseList)
130                {
131                    values.put(Course.PARENT_COURSE_LISTS, value);
132                }
133            }
134        }
135    }
136    
137    @Override
138    protected void _populateAdditionalData(Map transientVars, ModifiableContent content) throws WorkflowException
139    {
140        super._populateAdditionalData(transientVars, content);
141        
142        // Generate new code
143        content.setValue(ProgramItem.CODE, org.ametys.core.util.StringUtils.generateKey().toUpperCase());
144        
145        // copy catalog
146        // FIXME remove as soon as the canWrite returns really true at creation
147        content.setValue(ProgramItem.CATALOG, getBaseContentForCopy(transientVars).getValue(ProgramItem.CATALOG));
148    }
149    
150    /**
151     * Get the metadata name holding the child relation between the content to create and its children
152     * @return the metadata name
153     */
154    protected abstract Set<String> _getChildReferenceMetadataName();
155}