001/*
002 *  Copyright 2021 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 */
016
017package org.ametys.plugins.forms.repository;
018
019import java.util.List;
020import java.util.stream.Collectors;
021
022import javax.jcr.Node;
023import javax.jcr.PathNotFoundException;
024import javax.jcr.RepositoryException;
025
026import org.ametys.plugins.forms.repository.FormPageRule.PageRuleType;
027import org.ametys.plugins.repository.AmetysObject;
028import org.ametys.plugins.repository.AmetysRepositoryException;
029import org.ametys.plugins.repository.CopiableAmetysObject;
030import org.ametys.plugins.repository.ModifiableTraversableAmetysObject;
031import org.ametys.plugins.repository.RepositoryConstants;
032import org.ametys.plugins.repository.jcr.DefaultTraversableAmetysObject;
033
034/**
035 * {@link AmetysObject} for storing form
036 */
037public class FormPage extends DefaultTraversableAmetysObject<FormPageFactory> implements CopiableAmetysObject
038{
039    /** Constants for title property. */
040    private static final String __PROPERTY_TITLE = RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ":title";
041    
042    /** Constant for node's name */
043    private static final String __PROPERTY_RULE = "ametys-internal:rule";
044    
045    /**
046     * Creates a {@link FormPage}.
047     * @param node the node backing this {@link AmetysObject}.
048     * @param parentPath the parent path in the Ametys hierarchy.
049     * @param factory the {@link FormFactory} which creates the AmetysObject.
050     */
051    public FormPage(Node node, String parentPath, FormPageFactory factory)
052    {
053        super(node, parentPath, factory);
054    }
055
056    /**
057     * Retrieves the title.
058     * @return the title.
059     * @throws AmetysRepositoryException if an error occurs.
060     */
061    public String getTitle() throws AmetysRepositoryException
062    {
063        try
064        {
065            return getNode().getProperty(__PROPERTY_TITLE).getString();
066        }
067        catch (PathNotFoundException e)
068        {
069            return null;
070        }
071        catch (RepositoryException e)
072        {
073            throw new AmetysRepositoryException("Unable to get title property", e);
074        }
075    }
076    
077    /**
078     * Get the Form to which this page belongs.
079     * @return the Form to which this page belongs.
080     * @throws AmetysRepositoryException if an error occurs when retrieving the form of a page
081     */
082    public Form getForm() throws AmetysRepositoryException
083    {
084        return getParent();
085    }
086    
087    /**
088     * Set the title.
089     * @param title the title.
090     * @throws AmetysRepositoryException if an error occurs.
091     */
092    public void setTitle(String title) throws AmetysRepositoryException
093    {
094        try
095        {
096            getNode().setProperty(__PROPERTY_TITLE, title);
097        }
098        catch (RepositoryException e)
099        {
100            throw new AmetysRepositoryException("Unable to set title property", e);
101        }
102    }
103    
104    /**
105     * Get the page's questions.
106     * @return the page's questions.
107     * @throws AmetysRepositoryException if an error occurs when retrieving all the questions of a form
108     */
109    public List<FormQuestion> getQuestions() throws AmetysRepositoryException
110    {
111        return getChildren().stream()
112                .filter(FormQuestion.class::isInstance)
113                .map(FormQuestion.class::cast)
114                .collect(Collectors.toList());
115    }
116    
117    /**
118     * Determines if the page has a rule
119     * @return true if the page has a rule
120     */
121    public boolean hasRule () 
122    {
123        return hasChild(__PROPERTY_RULE);
124    }
125    
126    /**
127     * Get the rule
128     * @return the rule
129     * @throws AmetysRepositoryException if an error occurs.
130     */
131    public FormPageRule getRule () throws AmetysRepositoryException
132    {
133        return hasRule() ? getChild(__PROPERTY_RULE) : null;
134    }
135    
136    /**
137     * Set the rule for branching
138     * @param ruleType the rule type
139     * @param page the page to jump or skip. Can be null.
140     * @throws AmetysRepositoryException if an error occurs.
141     */
142    public void setRule (PageRuleType ruleType, String page) throws AmetysRepositoryException
143    {
144        if (!hasChild(__PROPERTY_RULE))
145        {
146            createChild(__PROPERTY_RULE, "ametys:form-page-rule");
147        }
148        
149        FormPageRule rule = getRule();
150        
151        rule.setType(ruleType);
152        if (ruleType == PageRuleType.JUMP || ruleType == PageRuleType.SKIP)
153        {
154            rule.setPageId(page);
155        }
156    }
157    
158    /**
159     * Delete the rule
160     */
161    public void deleteRule ()
162    {
163        if (hasChild(__PROPERTY_RULE))
164        {
165            ((FormPageRule) getChild(__PROPERTY_RULE)).remove();
166        }
167    }
168    
169    @Override
170    public FormPage copyTo(ModifiableTraversableAmetysObject parent, String name) throws AmetysRepositoryException
171    {
172        FormPage page = parent.createChild(name, "ametys:form-page");
173        page.setTitle(getTitle());
174        
175        Form parentForm = page.getForm();
176        for (FormQuestion question : getQuestions())
177        {
178            String questionName = parentForm.findUniqueQuestionName(question.getNameForForm());
179            FormQuestion questionCopy = page.createChild(questionName, "ametys:form-question");
180            question.copyTo(questionCopy);
181            questionCopy.setTypeId(question.getType().getId());
182            questionCopy.setNameForForm(questionName);
183        }
184        
185        return page;
186    }
187
188    @Override
189    public AmetysObject copyTo(ModifiableTraversableAmetysObject parent, String name, List<String> restrictTo) throws AmetysRepositoryException
190    {
191        return copyTo(parent, name);
192    }
193}