com.formkiq.core.form.bean.ObjectBuilder.java Source code

Java tutorial

Introduction

Here is the source code for com.formkiq.core.form.bean.ObjectBuilder.java

Source

/*
 * Copyright (C) 2017 FormKiQ Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.formkiq.core.form.bean;

import static com.formkiq.core.form.FormFinder.findValueByKey;
import static org.springframework.util.CollectionUtils.isEmpty;
import static org.springframework.util.StringUtils.hasText;
import static org.springframework.util.StringUtils.isEmpty;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;

import org.apache.commons.beanutils.BeanUtilsBean;
import org.apache.commons.beanutils.PropertyUtilsBean;

import com.formkiq.core.form.dto.ArchiveDTO;
import com.formkiq.core.form.dto.FormJSON;
import com.formkiq.core.form.dto.FormJSONField;
import com.formkiq.core.form.dto.FormJSONFieldType;
import com.formkiq.core.form.dto.FormJSONSection;
import com.formkiq.core.form.dto.Workflow;
import com.formkiq.core.form.dto.WorkflowOutputFormField;
import com.formkiq.core.util.BeanUtilsUUIDResolver;
import com.formkiq.core.util.GenericBuilder;

/**
 * Builder for different types of objects.
 *
 */
public final class ObjectBuilder {

    /** Default Static Text. */
    public static final String STATIC_TEXT_DEFAULT = "Lorem ipsum dolor sit " + "amet, his ex stet idque "
            + "invidunt, id eos modus essent. Wisi feugiat et eam,"
            + " pri id alia nemore ponderum, vim ne novum epicuri."
            + " Eirmod commune forensibus no vel, putant legimus " + "mel ei, etiam philosophia in quo.";

    /**
     * Build {@link ArchiveDTO}.
     * @param workflowname {@link String}
     * @param forms {@link FormJSON}
     * @return {@link ArchiveDTO}
     */
    public static ArchiveDTO buildArchiveDTO(final String workflowname, final FormJSON... forms) {
        ArchiveDTO dto = GenericBuilder.of(ArchiveDTO::new)
                .with(ArchiveDTO::setWorkflow, buildWorkflow(workflowname, forms)).build();

        for (FormJSON form : forms) {
            dto.addForm(form);
        }

        return dto;
    }

    /**
     * Build {@link FormJSON} from a {@link List} of objects.
     * @param <T> T
     * @param list {@link List}
     * @param fieldNames {@link Collection} of {@link String} - fields to return
     * @return {@link FormJSON}
     */
    public static <T> FormJSON buildForm(final List<T> list, final Collection<String> fieldNames) {

        BeanUtilsBean bean = getBeanUtils();
        FormJSON form = buildFormJSON(null);

        List<FormJSONSection> sections = new ArrayList<>();
        form.setSections(sections);

        if (!isEmpty(list)) {
            for (T t : list) {

                try {

                    Map<String, String> m = getFieldValueMap(bean, t, fieldNames);

                    List<FormJSONField> fields = new ArrayList<>();
                    sections.add(buildFormJSONSection("", fields));

                    for (Map.Entry<String, String> e : m.entrySet()) {

                        FormJSONField f = buildFormJSONField(form, FormJSONFieldType.TEXTBOX, e.getKey());
                        f.setValuekey(e.getKey());
                        f.setValue(e.getValue());
                        fields.add(f);
                    }

                } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
                    throw new RuntimeException(e);
                }
            }
        } else {

            form = new FormJSON();
        }

        return form;
    }

    /**
     * Build {@link FormJSON}.
     * @param name {@link String}
     * @return {@link FormJSON}
     */
    public static FormJSON buildFormJSON(final String name) {
        return GenericBuilder.of(FormJSON::new).with(FormJSON::setUUID, UUID.randomUUID().toString())
                .with(FormJSON::setName, name).build();
    }

    /**
     * Build {@link FormJSONField}.
     * @param form {@link FormJSON}
     * @param type {@link FormJSONFieldType}
     * @param label {@link String}
     * @return {@link FormJSONField}
     */
    @SuppressWarnings("boxing")
    public static FormJSONField buildFormJSONField(final FormJSON form, final FormJSONFieldType type,
            final String label) {
        FormJSONField field = GenericBuilder.of(FormJSONField::new)
                .with(FormJSONField::setId, getNextFormJSONFieldId(form)).with(FormJSONField::setLabel, label)
                .with(FormJSONField::setType, type).build();

        if (FormJSONFieldType.STATIC_TEXT.equals(type)) {
            field.setLabel(null);
            field.setValue(STATIC_TEXT_DEFAULT);
        }

        return field;
    }

    /**
     * Build {@link FormJSONSection}.
     * @param title {@link String}
     * @param fields {@link List} of {@link FormJSONField}
     * @return {@link FormJSONSection}
     */
    public static FormJSONSection buildFormJSONSection(final String title, final List<FormJSONField> fields) {
        return GenericBuilder.of(FormJSONSection::new).with(FormJSONSection::setTitle, title)
                .with(FormJSONSection::setUUID, UUID.randomUUID().toString())
                .with(FormJSONSection::setFields, fields != null ? fields : new ArrayList<>()).build();
    }

    /**
     * Transfers a {@link FormJSON} to an object.
     * @param <T> Type of object
     * @param form {@link FormJSON}
     * @param t T
     * @return T
     */
    public static <T> T buildObject(final FormJSON form, final T t) {
        return buildObject(form, t, null);
    }

    /**
     * Transfers a {@link FormJSON} to an object.
     * @param <T> Type of object
     * @param form {@link FormJSON}
     * @param additional {@link Map} additional key/values
     * @param t T
     * @return T
     */
    public static <T> T buildObject(final FormJSON form, final T t, final Map<String, String> additional) {

        Map<String, String> valueMap = getValueKeyMap(form);

        try {
            BeanUtilsBean bean = getBeanUtils();
            bean.populate(t, valueMap);

            if (additional != null) {
                bean.populate(t, additional);
            }

        } catch (IllegalAccessException | InvocationTargetException e) {
            throw new RuntimeException(e);
        }

        return t;
    }

    /**
     * Build {@link Workflow}.
     * @param workflowname {@link String}
     * @param forms {@link FormJSON}
     * @return {@link Workflow}
     */
    public static Workflow buildWorkflow(final String workflowname, final FormJSON... forms) {

        Workflow workflow = GenericBuilder.of(Workflow::new).with(Workflow::setUUID, UUID.randomUUID().toString())
                .with(Workflow::setName, workflowname).build();

        List<String> steps = new ArrayList<>();
        for (FormJSON form : forms) {
            steps.add(form.getUUID());
        }

        workflow.setSteps(steps);

        return workflow;
    }

    /**
     * Builder for {@link WorkflowOutputFormField}.
     *
     * @param form {@link FormJSON}
     * @param field {@link FormJSONField}
     * @param documentField {@link String}
     * @return {@link WorkflowOutputFormField}
     */
    public static WorkflowOutputFormField buildWorkflowOuputFormField(final FormJSON form,
            final FormJSONField field, final String documentField) {

        WorkflowOutputFormField wo = new WorkflowOutputFormField();
        wo.setForm(form.getName() + "[" + form.getUUID() + "]");
        wo.setField(field.getLabel() + "[" + field.getId() + "]");
        wo.setDocumentfieldname(documentField);
        return wo;
    }

    /**
     * @return {@link BeanUtilsBean}
     */
    public static BeanUtilsBean getBeanUtils() {
        PropertyUtilsBean pbean = new PropertyUtilsBean();
        pbean.setResolver(new BeanUtilsUUIDResolver());

        CustomConvertUtilsBean cbean = new CustomConvertUtilsBean();
        cbean.register(new UUIDConverter(), UUID.class);
        cbean.register(new DateConverter(), Date.class);
        cbean.register(new StringConverter(), String.class);

        BeanUtilsBean bean = new BeanUtilsBean(cbean, pbean);
        return bean;
    }

    /**
     * Get Field Value Map from Object.
     * @param bean {@link BeanUtilsBean}
     * @param obj {@link Object}
     * @param fieldNames {@link Collection} of {@link String}
     * @return {@link Map}
     * @throws IllegalAccessException IllegalAccessException
     * @throws InvocationTargetException InvocationTargetException
     * @throws NoSuchMethodException NoSuchMethodException
     */
    private static Map<String, String> getFieldValueMap(final BeanUtilsBean bean, final Object obj,
            final Collection<String> fieldNames)
            throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {

        Map<String, String> m = bean.describe(obj);

        if (!isEmpty(fieldNames)) {

            Map<String, String> r = new HashMap<>(fieldNames.size());

            for (String fieldname : fieldNames) {
                r.put(fieldname, m.getOrDefault(fieldname, ""));
            }

            m = r;

        } else {
            m.remove("class");
        }

        return m;
    }

    /**
     * Calculates the field id.
     * @param form {@link FormJSON}
     * @return int
     */
    public static int getNextFormJSONFieldId(final FormJSON form) {
        int fieldId = 1;
        int fieldCount = 0;
        for (FormJSONSection section : form.getSections()) {
            for (FormJSONField field : section.getFields()) {
                fieldCount++;
                fieldId = Math.max(fieldId, field.getId());
            }
        }

        return fieldCount > 0 ? fieldId + 1 : fieldId;
    }

    /**
     * Transfers {@link FormJSON} to a {@link Map}.
     * @param form {@link FormJSON}
     * @return {@link Map}
     */
    public static Map<String, String> getValueKeyMap(final FormJSON form) {

        Map<String, String> map = new HashMap<>();

        for (FormJSONSection section : form.getSections()) {
            for (FormJSONField field : section.getFields()) {
                if (!field.isHide() && hasText(field.getValuekey())) {
                    map.put(field.getValuekey(), field.getValue());
                }
            }
        }

        return map;
    }

    /**
     * Populate {@link FormJSON} from {@link Map}.
     * @param form {@link FormJSON}
     * @param values {@link Map}
     */
    public static void populate(final FormJSON form, final Map<String, String> values) {

        if (values != null) {
            for (Map.Entry<String, String> e : values.entrySet()) {

                Optional<FormJSONField> op = findValueByKey(form, e.getKey());
                if (op.isPresent()) {
                    if (e.getValue() != null) {
                        op.get().setValue(e.getValue());
                    } else {
                        op.get().setValue("");
                    }
                }
            }
        }
    }

    /**
     * Populate {@link FormJSON} from a {@link Object}.
     * @param form {@link FormJSON}
     * @param object {@link Object}
     * @throws NoSuchMethodException {@link NoSuchMethodException}
     * @throws InvocationTargetException {@link InvocationTargetException}
     * @throws IllegalAccessException {@link IllegalAccessException}
     */
    public static void populateFromObject(final FormJSON form, final Object object)
            throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {

        BeanUtilsBean bean = getBeanUtils();
        Map<String, String> strs = bean.describe(object);
        populate(form, strs);
    }

    /**
     * Transforms a {@link FormJSON} to a {@link List}.
     * @param <T> Type of object
     * @param form {@link FormJSON}
     * @param clazz {@link Class}
     * @return {@link List}
     */
    public static <T> List<T> toObject(final FormJSON form, final Class<T> clazz) {

        try {

            List<T> list = new ArrayList<>();
            BeanUtilsBean bbean = getBeanUtils();

            for (FormJSONSection section : form.getSections()) {

                T bean = clazz.newInstance();
                list.add(bean);

                for (FormJSONField f : section.getFields()) {
                    if (!isEmpty(f.getValuekey())) {
                        bbean.setProperty(bean, f.getValuekey(), f.getValue());
                    }
                }

                updateFieldIfNullAndExists(bbean, bean, "insertedDate", new Date());
                updateFieldIfNullAndExists(bbean, bean, "updatedDate", new Date());
            }

            return list;

        } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * Updates InsertedDate / UpdatedDate if they exist on object.
     * @param bean {@link BeanUtilsBean}
     * @param obj {@link Object}
     * @param field {@link String}
     * @param value {@link Object}
     */
    @Deprecated
    private static void updateFieldIfNullAndExists(final BeanUtilsBean bean, final Object obj, final String field,
            final Object value) {

        try {
            String val = bean.getProperty(obj, field);

            if (isEmpty(val)) {
                bean.setProperty(obj, field, value);
            }

        } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
            // ignore error
        }

    }

    /**
     * private contructor.
     */
    private ObjectBuilder() {
    }
}