Java tutorial
/* * 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() { } }