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

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

/*************************************************************************
 *
 * ADOBE CONFIDENTIAL
 * __________________
 *
 *  Copyright 2014 Adobe Systems Incorporated
 *  All Rights Reserved.
 *
 * NOTICE:  All information contained herein is, and remains
 * the property of Adobe Systems Incorporated and its suppliers,
 * if any.  The intellectual and technical concepts contained
 * herein are proprietary to Adobe Systems Incorporated and its
 * suppliers and may be covered by U.S. and Foreign Patents,
 * patents in process, and are protected by trade secret or copyright law.
 * Dissemination of this information or reproduction of this material
 * is strictly forbidden unless prior written permission is obtained
 * from Adobe Systems Incorporated.
 **************************************************************************/

package com.adobe.aemds.guide.utils;

import com.adobe.aemds.guide.service.GuideException;
import com.adobe.aemds.guide.service.GuideModuleImporter;
import com.day.cq.commons.jcr.JcrConstants;
import org.apache.commons.lang.StringUtils;
import org.apache.sling.commons.json.JSONArray;
import org.apache.sling.commons.json.JSONException;
import org.apache.sling.commons.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.xml.transform.TransformerException;
import javax.xml.xpath.XPathExpressionException;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @pad.exclude Exclude from Published API.
 */
public class KeyValueDataMerger {

    protected static Set blackListGuideStateKeys = new HashSet(
            Arrays.asList(GuideConstants.FD_RULES, GuideConstants.LAYOUT_NODENAME, GuideConstants.FD_SCRIPTS)
    );
    protected Logger logger = LoggerFactory.getLogger(KeyValueDataMerger.class);

    protected JSONObject guideJSON;

    protected CustomJSONWriter jsonWriter;
    protected StringWriter stringWriter;
    protected String bindProperty;

    protected GuideModuleImporter guideModuleImporter;
    protected Map moduleParameter;
    // uid counter should be deterministic
    private long uidCounter = 1;

    public KeyValueDataMerger(JSONObject guideJson, Map params) {
        this.guideJSON = guideJson;
        this.stringWriter = new StringWriter();
        this.jsonWriter = new CustomJSONWriter(this.stringWriter);
        this.moduleParameter = params;
        if (params != null) {
            this.guideModuleImporter = (GuideModuleImporter) params.get(GuideModuleImporter.class.getName());
        }
    }

    public JSONObject merge() throws GuideException {
        try {
            jsonWriter.object();
            mergeJSONObject("root", this.guideJSON);
            jsonWriter.endObject();
            return new JSONObject(this.stringWriter.toString());
        } catch(XPathExpressionException e){
            if(e.getCause() instanceof TransformerException){
                if("Empty expression!".equals(e.getCause().getMessage())){
                    throw new GuideException("It might be that Unbound repeatable panels are present in AF.This is not supported for adaptive forms using the XFA form template or XSD.", e);
                }
            }
            // In case of invalid xpath
            throw new GuideException("Invalid X Path", e);
        } catch (Exception e) {
            throw new GuideException(e);
        }
    }

    public void updateMergedJson(JSONObject jsonObject, String guideNodeClass) throws Exception {

    }

    protected void updateJsonValue(JSONObject jsonObject, String value) throws Exception{
        //put default value, if there, in case value is null (honour empty value coming from data) from prefill xml
        if (value == null) {
            if(jsonObject.has(GuideConstants._VALUE)) {
                value = jsonObject.getString(GuideConstants._VALUE);
            } else if(jsonObject.optBoolean(GuideConstants.DEFAULT_CURRENT_DATE)) {
                //Adding default value when defaultToCurrentDate is true for Date Picker.
               value =  new SimpleDateFormat("yyyy-MM-dd").format(new Date());
            }
        }
        if (StringUtils.isNotEmpty(value)) {
            jsonWriter.key(GuideConstants._VALUE).value(value);
        }
    }

    /**
     * Writes '_value' for AD Module and AD Module Group.
     * @param jsonObject
     * @param guideNodeClass
     * @throws Exception
     */
    protected void moduleMergeJson(JSONObject jsonObject, String guideNodeClass) throws Exception {
        // no default implementation
    }

    protected void mergeJSONObject(String objectKey, JSONObject jsonObject) throws Exception {
        String guideNodeClass = null;

        guideNodeClass = addGuideNodeClass(jsonObject);
        addValue(jsonObject, guideNodeClass);
        Iterator keys = jsonObject.keys();
        while (keys.hasNext()) {
            String key = keys.next();
            if(!blackListGuideStateKeys.contains(key)) {
                Object value = jsonObject.get(key);
                // we don't support AD Module group in any type of data model except json
                if (value instanceof JSONObject) {
                    jsonWriter.key(key).object();
                    this.mergeJSONObject(key, (JSONObject) value);
                    jsonWriter.endObject();
                } else if (value instanceof JSONArray) {
                    logger.trace("Found an json array in guide node structure. Ignoring this key: " + key);
                }
            }
        }
        moduleMergeJson(jsonObject, guideNodeClass);
    }

    protected String addGuideNodeClass(JSONObject jsonObject) throws Exception {
        String guideNodeClass = null;
        if (jsonObject.has(GuideConstants.GUIDE_NODE_CLASS)) {
            guideNodeClass = jsonObject.getString(GuideConstants.GUIDE_NODE_CLASS);
            jsonWriter.key(GuideConstants.GUIDE_NODE_CLASS).value(guideNodeClass);
        }
        return guideNodeClass;
    }

    /**
     * This is used only for bounded guide composite fields.
     * It will pass the bindref in jsonObject of the composite field to it's items for relevant mergeJSON.
     * @param jsonObject
     * @param bindPath
     * @throws org.apache.sling.commons.json.JSONException
     * @throws Exception
     */
    protected void setCompositeFieldBindRef (JSONObject jsonObject, String bindPath) throws JSONException,Exception {
        JSONObject itemsObj = jsonObject.getJSONObject(GuideConstants.ITEMS_NODENAME);
        JSONArray itemsArr = itemsObj.toJSONArray(itemsObj.names());
        for (int i = 0; i < itemsArr.length(); ++i) {
            JSONObject item = itemsArr.optJSONObject(i);
            if (item != null && !JSONObject.NULL.equals(item)) {
                String name = item.optString(GuideConstants.NAME, "");
                if (StringUtils.isNotBlank(name)) {
                    String bindRef = "";
                    if(StringUtils.startsWith(bindPath, "/")) {
                        bindRef = bindPath + "/" + name;
                    } else {
                        bindRef = "/" + bindPath + "/" + name;
                    }
                    //Adding / to validate bind ref.
                    item.put(this.bindProperty, bindRef);
                }
            }
        }
    }


    protected void addValue(JSONObject jsonObject, String guideNodeClass) throws Exception {
        String name = "";
        if (jsonObject.has(GuideConstants.NAME)) {
            name = jsonObject.getString(GuideConstants.NAME);
            jsonWriter.key(GuideConstants.NAME).value(name);
            if (GuideUtils.isGuideFieldModel(guideNodeClass) ||
                    GuideConstants.GUIDE_COMPOSITE_FIELD_ITEM.equals(guideNodeClass)) {
                updateMergedJson(jsonObject, guideNodeClass);
            } else if(StringUtils.equals(guideNodeClass, GuideConstants.GUIDE_FIELD_TEXTDRAW)) {
                // get the document fragment variables from this object is present
                if(jsonObject.opt(GuideConstants.DOCUMENT_FRAGMENT_VARIABLES) instanceof JSONArray) {
                    JSONArray textVariables = jsonObject.optJSONArray(GuideConstants.DOCUMENT_FRAGMENT_VARIABLES);
                    // walk through the array
                    jsonWriter.key(GuideConstants.DOCUMENT_FRAGMENT_VARIABLES).array();
                    for(int i=0; i




© 2015 - 2025 Weber Informatics LLC | Privacy Policy