All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.adobe.aemds.guide.utils.DefaultProgressiveOrderingGenerator Maven / Gradle / Ivy

package com.adobe.aemds.guide.utils;

import com.adobe.aemds.guide.common.FormsGuideException;
import com.adobe.aemds.guide.progressive.GuideProgressiveCompletionInfo;
import com.day.cq.commons.jcr.JcrConstants;
import org.apache.commons.lang.StringUtils;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.commons.json.JSONException;
import org.apache.sling.commons.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;



/**
 * Generates the progressive order for an adaptive forms as per following rules:
 * 1. In adaptive forms node structure, for each panel having fields there would be one section. The direct fields of that panel (fields in nested panel not included) would appear as section fields
 * 2. Title of section is taken from panel title or panel name if title is missing
 * 3. For repeatable panel, the generated repeating section would have additional property called repeatablePanelPath. For repeating section would hold the fields for entire
 *      repeatable panel hierarchy including fields in nested panel. Additionally, we do not support repeatable panel, inside another repeatable panel.
 * 4. The sections are in flat hierarchy. The panel hierarchy is traversed in DFS order for generating flat sections hierarchy except for repeatable panels where no section is generated for
 *      child panels of repeatable panel.
 * 5. Progressive Ordering additionally contains information for completion section which is final section in node hierarchy
 * @pad.exclude Exclude from Published API.
 */
public class DefaultProgressiveOrderingGenerator {
    private static Logger logger = LoggerFactory.getLogger(DefaultProgressiveOrderingGenerator.class);
    private ResourceResolver resourceResolver;

    public DefaultProgressiveOrderingGenerator(ResourceResolver resResolver) {
        this.resourceResolver = resResolver;
    }

    /**
     * Mapping between field and its fragment prefix id of adaptive forms
     */
    public class FieldFragRefMapping {
        private String path;
        private String fragPrefix;

        public FieldFragRefMapping(String field, String fragRef){
            this.path = field;
            this.fragPrefix = fragRef;
        }

        public String getPath(){
            return this.path;
        }
        public String getFragPrefix(){
            return this.fragPrefix;
        }
    }

    private CustomJSONWriter jsonWriter = null;
    int sectionId = 0;
    int fieldCounter = 0;
    public String generateProgressiveOrdering(JSONObject guideContainerJson) throws FormsGuideException{
        try {
            JSONObject rootPanel = guideContainerJson.getJSONObject("rootPanel");
            StringWriter stringWriter = new StringWriter();
            jsonWriter = new CustomJSONWriter(stringWriter);
            jsonWriter.object();
            String fragPrefixString = null;
            String fragRef = getJsonValue((JSONObject) rootPanel, GuideConstants.FRAG_REF);
            if (fragRef != null) {
                String path = getJsonValue((JSONObject) rootPanel, GuideConstants.JCR_PATH);
                Resource panel = resourceResolver.getResource(path);
                fragPrefixString = NodeStructureUtils.getFragPrefixString(panel, null);
            }
            generateSectionForPanel(rootPanel, fragPrefixString);
            // Creating this as a node instead of property in pdc order
            jsonWriter.key(GuideProgressiveCompletionInfo.id).object();
            jsonWriter.key(GuideConstants.GUIDE_PROGRESSIVE_COMPLETION_TITLE).value("Submit the form");
            jsonWriter.key(GuideConstants.GUIDE_PROGRESSIVE_COMPLETION_AFTER_MESSAGE).value("Thank you for submitting the form.");
            jsonWriter.key(GuideConstants.GUIDE_PROGRESSIVE_COMPLETION_BEFORE_MESSAGE).value("Do you want to submit the form?");
            jsonWriter.key(GuideConstants.GUIDE_PROGRESSIVE_COMPLETION_BUTTON_TEXT).value("Submit");
            jsonWriter.key(GuideConstants.GUIDE_NODE_CLASS).value(GuideConstants.GUIDE_PROGRESSIVE_COMPLETION_SECTION_NODE_CLASS);
            jsonWriter.key(GuideConstants.GUIDE_PROGRESSIVE_COMPLETION_SCRIPT).value("window.guideBridge.submit(options)");
            jsonWriter.key(GuideConstants.GUIDE_PROGRESSIVE_COMPLETION_SUCCESS_SCRIPT).value("");
            jsonWriter.key(GuideConstants.GUIDE_PROGRESSIVE_COMPLETION_FAILURE_SCRIPT).value("");
            // End completion info section object
            jsonWriter.endObject();
            jsonWriter.endObject();
            return stringWriter.toString();
        } catch(Exception e){
            logger.error(e.getMessage(), e);
            throw new FormsGuideException(e);
        }
    }

    private void generateSectionForPanel(JSONObject panel,String fragPrefixString) throws JSONException{
        //Create a new section for panel.
        int maxOccur = Integer.valueOf(this.getOrElse(panel, GuideConstants.MAX_OCCUR, "1"));
        //Check 1: If repeatable panel. create a repeatable section for this and add all nested fields as part of repeatable section.
        if( maxOccur < 0 || maxOccur > 1 ){
            writeProgressiveSectionJson(panel, true, this.getFields(panel, false, fragPrefixString),fragPrefixString);
            return;
        }
        //Check 2: If non-repeatable panel has direct fields, create a section out of it which contains only direct fields.
        List directFields = this.getFields(panel, true, fragPrefixString);
        if( directFields.size() >0 ){
            writeProgressiveSectionJson(panel, false, directFields,fragPrefixString);
        }

        //Check 3: create separate sections for nested panel of non-repeatable child panel.
        JSONObject panelItems = null;
        if(panel.has("items") && panel.get("items") instanceof JSONObject){
            panelItems = panel.getJSONObject("items");
            for(Iterator itemIterator = panelItems.keys(); itemIterator.hasNext(); ){
                String itemKey = itemIterator.next();
                Object itemValue = panelItems.get(itemKey);
                if(itemValue instanceof JSONObject){
                    String guideNodeClass = getJsonValue((JSONObject)itemValue, GuideConstants.GUIDE_NODE_CLASS);
                    if(GuideConstants.GUIDE_PANEL.equals(guideNodeClass)){
                        String fragRef = getJsonValue((JSONObject) itemValue, GuideConstants.FRAG_REF);
                        String fragPrefixStringForChildPanel = null;
                        if (fragRef != null) {
                            String path = getJsonValue((JSONObject) itemValue, GuideConstants.JCR_PATH);
                            Resource res = resourceResolver.getResource(path);
                            fragPrefixStringForChildPanel = NodeStructureUtils.getFragPrefixString(res, fragPrefixString);
                        }
                        if (fragPrefixStringForChildPanel == null) {
                            fragPrefixStringForChildPanel = fragPrefixString;
                        }
                        generateSectionForPanel((JSONObject) itemValue, fragPrefixStringForChildPanel);
                    }
                }
            }
        }
    }

    private void writeProgressiveSectionJson(JSONObject panel, boolean isRepeatable, List pdcFields, String fragPrefixString ) throws JSONException {
        String id = "section_" + sectionId++;
        jsonWriter.key(id).object();
        jsonWriter.key(GuideConstants.GUIDE_NODE_CLASS).value(GuideConstants.GUIDE_PROGRESSIVE_SECTION_NODE_CLASS);
        jsonWriter.key(JcrConstants.JCR_TITLE).value(this.getSectionTitle(panel));
        jsonWriter.key("name").value(this.getSectionName(panel, id));
        if(isRepeatable) {
            String panelPath = getJsonValue(panel, JcrConstants.JCR_PATH);
            Resource pdcPanelResource = resourceResolver.getResource(panelPath);
            String repeatablePanelId = NodeStructureUtils.getGuideNodeHtmlId(pdcPanelResource);
            jsonWriter.key(GuideConstants.GUIDE_PROGRESSIVE_REPEATABLE_PANEL_PATH).value(panelPath);
            jsonWriter.key(GuideConstants.GUIDE_PROGRESSIVE_REPEATABLE_PANEL_ID).value(repeatablePanelId);
        }
        jsonWriter.key(GuideConstants.ITEMS_NODENAME).object();
        for (FieldFragRefMapping pdcField : pdcFields) {
            int index = pdcField.getPath().lastIndexOf('/');
            // to make the nodename of each pdc field unique, we take substring at index + 1 and add a field counter.
            String name = pdcField.getPath().substring(index + 1) + "_" + fieldCounter;
            fieldCounter++;
            jsonWriter.key(name).object();
            jsonWriter.key(GuideConstants.JCR_PRIMARY_TYPE).value(GuideConstants.NT_UNSTRUCTURED);
            Resource pdcFieldResource = resourceResolver.getResource(pdcField.getPath());
            String pdcFieldId = NodeStructureUtils.getGuideNodeHtmlId(pdcFieldResource, pdcField.getFragPrefix());
            jsonWriter.key("id").value(pdcFieldId);
            jsonWriter.key(GuideConstants.PATH).value(pdcField.getPath());
            if (pdcField.getFragPrefix() != null) {
                jsonWriter.key("prefixId").value(pdcField.getFragPrefix());
            }
            jsonWriter.endObject();
        }
        jsonWriter.endObject();
        jsonWriter.endObject();
    }

    private String getSectionTitle(JSONObject panel) throws JSONException {
        //Set Section Title from panel title. If panel title is null then use panel name.
        String title = this.getJsonValue(panel, GuideConstants.JCR_TITLE);
        if(StringUtils.isEmpty(title)){
            title = this.getJsonValue(panel, GuideConstants.NAME);
        }
        return  title;
    }

    private String getSectionName(JSONObject panel, String id) throws JSONException {
        //Set Section Title from panel title. If panel title is null then use panel name.
        String name = this.getJsonValue(panel, GuideConstants.NAME);
        if(StringUtils.isEmpty(name)){
            // fallback is id for name
            name = id;
        }
        return  name;
    }

    private List getFields(JSONObject panel, boolean onlyDirectFields, String fragPrefixString) throws JSONException {
        List fields = new ArrayList();
        JSONObject panelItems = null;
        if(panel.has("items") && panel.get("items") instanceof JSONObject){
            panelItems = panel.getJSONObject("items");
            for(Iterator itemIterator = panelItems.keys(); itemIterator.hasNext(); ){
                String itemKey = itemIterator.next();
                Object itemValue = panelItems.get(itemKey);
                if(itemValue instanceof JSONObject){
                    String guideNodeClass = getJsonValue((JSONObject)itemValue, GuideConstants.GUIDE_NODE_CLASS);
                    if(GuideProgressiveUtils.isGuideProgressiveFieldModel(guideNodeClass)){
                        fields.add(new FieldFragRefMapping(getJsonValue((JSONObject)itemValue, JcrConstants.JCR_PATH), fragPrefixString));
                    }
                    else if(GuideConstants.GUIDE_PANEL.equals(guideNodeClass) && !onlyDirectFields){
                        String fragref = getJsonValue((JSONObject) itemValue, GuideConstants.FRAG_REF);
                        String fragPrefixStringForChildPanel = null;
                        if (fragref != null) {
                            // Use the existing fragPrefix String to generate new fragPrefixString
                            String path = getJsonValue((JSONObject) itemValue, GuideConstants.JCR_PATH);
                            Resource res = resourceResolver.getResource(path);
                            //if(fragPrefixString != null){
                                // written for fragment inside fragment
                            //    fragPrefixStringForChildPanel = NodeStructureUtils.getGuideNodeHtmlId(res, fragPrefixString);
                           // } else {
                                fragPrefixStringForChildPanel = NodeStructureUtils.getFragPrefixString(res, fragPrefixString);
                            //}
                        } else {
                            fragPrefixStringForChildPanel = fragPrefixString;
                        }
                        fields.addAll(this.getFields((JSONObject) itemValue, onlyDirectFields, fragPrefixStringForChildPanel));
                    }
                }
            }
        }
        return fields;
    }

    private String getJsonValue(JSONObject jsonObject, String keyName) throws JSONException {
        if(jsonObject.has(keyName)){
            return jsonObject.getString(keyName);
        }
        return null;
    }

    private String getOrElse(JSONObject jsonObject, String keyName, String fallbackValue) throws JSONException {
        String value = getJsonValue(jsonObject, keyName);
        return value!= null? value : fallbackValue;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy