Java tutorial
/** * This file is part of SIMPL4(http://simpl4.org). * * Copyright [2014] [Manfred Sattler] <manfred@ms123.org> * * SIMPL4 is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * SIMPL4 is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with SIMPL4. If not, see <http://www.gnu.org/licenses/>. */ package org.ms123.common.form; import flexjson.*; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.Calendar; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.io.FileOutputStream; import java.io.OutputStream; import java.io.File; import java.io.InputStream; import java.io.InputStreamReader; import java.io.FileInputStream; import java.io.Reader; import java.lang.reflect.*; import org.osgi.framework.wiring.*; import javax.jdo.annotations.Element; import javax.jdo.annotations.Persistent; import java.lang.annotation.Annotation; import org.ms123.common.git.GitService; import org.ms123.common.stencil.api.StencilService; import org.ms123.common.data.api.DataLayer; import org.ms123.common.data.api.SessionContext; import org.ms123.common.store.StoreDesc; import javax.validation.ValidatorFactory; import javax.validation.Validator; import javax.validation.ConstraintViolation; import javax.validation.Validation; import javax.validation.Validator; import javax.validation.ValidatorFactory; import org.apache.commons.beanutils.PropertyUtils; import org.osgi.framework.BundleContext; import org.apache.commons.beanutils.BeanMap; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.text.SimpleDateFormat; import java.text.ParsePosition; import org.apache.commons.beanutils.ConvertUtils; /** * */ @SuppressWarnings("unchecked") class BaseFormServiceImpl { protected BundleContext m_bc; protected DataLayer m_dataLayer; protected GitService m_gitService; protected StencilService m_stencilService; protected JSONDeserializer m_ds = new JSONDeserializer(); protected JSONSerializer m_js = new JSONSerializer(); private ValidatorFactory m_factory = Validation.buildDefaultValidatorFactory(); private Validator m_validator = null; protected Map _validateForm(String namespace, String name, Map data, boolean cleanData) throws Exception { String json = m_gitService.searchContent(namespace, name, "sw.form"); Map rootShape = (Map) m_ds.deserialize(json); Map<String, List> constraintsMeta = getConstraintsFromStencil(namespace); List<Map> inputShapes = new ArrayList(); List<String> idList = new ArrayList(); idList.add("input"); idList.add("textarea"); traverseElement(inputShapes, rootShape, idList); long time = new java.util.Date().getTime(); BundleDelegatingClassLoader bdc = new BundleDelegatingClassLoader(m_bc.getBundle()); ClassBuilder cb = new ClassBuilder(bdc, inputShapes, constraintsMeta); Class clazz = cb.getClazz(); findAnnotatedFields(clazz); Object obj = clazz.newInstance(); BeanMap bm = new BeanMap(obj); try { bm.putAll(cleanData(data, inputShapes, true)); } catch (Exception e) { for (Object key : bm.keySet()) { System.out.println("\tkey:" + key + "=" + bm.getType((String) key)); } e.printStackTrace(); throw new RuntimeException("FormService._validateForm:", e); } Set cv = validate(obj); List<Map> errors = new ArrayList(); if (cv.size() > 0) { errors = constructConstraitViolationList(cv, inputShapes, constraintsMeta); System.out.println("cv:" + errors); } else { StoreDesc sdesc = StoreDesc.getNamespaceData(namespace); SessionContext sc = m_dataLayer.getSessionContext(sdesc); for (Map shape : inputShapes) { Map filterCheck = getFilterCheck(shape); if (filterCheck == null) { continue; } String fieldName = getName(shape); Object value = data.get(fieldName); boolean ok = executeFilter(sc, filterCheck, fieldName, value); if (!ok) { Map error = new HashMap(); errors.add(error); error.put("path", fieldName); String msg = (String) filterCheck.get("message"); error.put("message", msg != null ? msg : "%field_not_in_database"); } } } Map ret = new HashMap(); ret.put("errors", errors); if (cleanData) { inputShapes = new ArrayList(); idList = new ArrayList(); idList.add("input"); idList.add("textarea"); idList.add("gridinput"); idList.add("tableselect"); idList.add("enumselect"); idList.add("alert"); idList.add("actionbutton"); traverseElement(inputShapes, rootShape, idList); ret.put("cleanData", cleanData(data, inputShapes, false)); } ret.put("postProcess", getPostProcessScript(rootShape)); return ret; } public String getFormName(String namespace, String formKey) throws Exception { String json = m_gitService.searchContent(namespace, formKey, "sw.form"); Map rootShape = (Map) m_ds.deserialize(json); Map properties = (Map) rootShape.get("properties"); String name = ((String) properties.get("xf_name")); if (name == null || name.length() == 0) { if (formKey != null && formKey.endsWith(".form")) { return formKey.substring(0, formKey.length() - 5); } return formKey; } return name; } public Set<String> getFormInputVariables(String namespace, String formKey) throws Exception { Set<String> result = new HashSet<String>(); String json = m_gitService.searchContent(namespace, formKey, "sw.form"); Map rootShape = (Map) m_ds.deserialize(json); List<Map> inputShapes = new ArrayList<Map>(); traverseElement(inputShapes, rootShape, (shape) -> { Map<String, String> properties = (Map) shape.get("properties"); String il = properties.get("xf_inputlistname"); return !isEmpty(il); }); for (Map shape : inputShapes) { Map<String, String> properties = (Map) shape.get("properties"); result.add(properties.get("xf_inputlistname")); } System.out.println("getFormInputVariables:" + result); return result; } private boolean executeFilter(SessionContext sc, Map filterCheck, String fieldName, Object value) throws Exception { Map fdesc = filterCheck; String filterName = (String) fdesc.get("name"); List<Map> items = (List) fdesc.get("items"); Map params = new HashMap(); for (Map<String, String> item : items) { String param = item.get("param"); params.put(param, value); break; } System.out.println("FormService.executeFilter.params:" + params); Map result = sc.executeNamedFilter(filterName, params); List rows = (List) result.get("rows"); System.out.println("FormService.executeFilter.rows:" + rows); return rows.size() > 0; } private Set validate(Object obj) { if (m_validator == null) { m_validator = m_factory.getValidator(); } ClassLoader clParent = Thread.currentThread().getContextClassLoader(); try { BundleDelegatingClassLoader bdc = new BundleDelegatingClassLoader(m_bc.getBundle(), clParent); Thread.currentThread().setContextClassLoader(bdc); return m_validator.validate(obj); } finally { Thread.currentThread().setContextClassLoader(clParent); } } public void findAnnotatedFields(Class clazz) throws Exception { Field[] declaredFields = clazz.getDeclaredFields(); List<Field> annotatedFields = new ArrayList<Field>(declaredFields.length); for (Field field : declaredFields) { //System.out.println("Field:" + field); Annotation[] ann = findFieldAnnotations(field); for (Annotation a : ann) { //System.out.println("\tAnno:" + a); } } } public Annotation[] findFieldAnnotations(Field field) throws Exception { return field.getAnnotations(); } protected Map cleanData(Map data, List<Map> shapes, boolean convert) { Map newMap = new HashMap(); System.out.println("FormService.cleanData.start(" + convert + "):" + data); for (Map shape : shapes) { String name = getName(shape); Class type = ConstraintsUtils.getType(shape); Object value = data.get(name); System.out.println("\tname:" + name + "/" + type + "=" + value); if (name == null || "".equals(name.trim())) continue; if (value != null && convert) { if (type == Double.class || type == Integer.class) { if (value instanceof String && "".equals(value)) { value = null; } } if (type == Date.class) { try { if (value instanceof String) { value = new SimpleDateFormat( (((String) value).indexOf("T") > 0) ? "yyyy-MM-dd'T'HH:mm" : "yyyy-MM-dd") .parse((String) value, new ParsePosition(0)); } else { Calendar cal = Calendar.getInstance(); cal.setTimeInMillis(((Long) value)); value = cal.getTime(); } } catch (Exception e) { System.out.println("DateException:" + name + "=" + value + ":" + e.getMessage()); value = null; } } } if (value != null && !convert) {//@@@MS Hack Iso-Date -> long if (type == Date.class) { try { if (value instanceof String) { Date d = new SimpleDateFormat( (((String) value).indexOf("T") > 0) ? "yyyy-MM-dd'T'HH:mm" : "yyyy-MM-dd") .parse((String) value, new ParsePosition(0)); value = d.getTime(); } } catch (Exception e) { System.out.println("DateException,iso:" + name + "=" + value + ":" + e.getMessage()); value = null; } } } newMap.put(name, value); } System.out.println("FormService.cleanData.end:" + newMap); return newMap; } private boolean isEmpty(String s) { return s == null || s.length() == 0; } protected String getName(Map element) { Map properties = (Map) element.get("properties"); return ((String) properties.get("xf_id")); } protected String getPostProcessScript(Map element) { Map properties = (Map) element.get("properties"); return ((String) properties.get("xf_postprocess")); } protected Map getFilterCheck(Map element) { Map properties = (Map) element.get("properties"); if (properties.get("xf_filtercheck") instanceof Map) { return ((Map) properties.get("xf_filtercheck")); } return null; } private List<Map> constructConstraitViolationList(Set<ConstraintViolation> constraintViolations, List<Map> shapes, Map<String, List> constraintsMeta) { List<Map> cvList = new ArrayList(); for (ConstraintViolation cv : constraintViolations) { Map<String, Object> mapCV = new HashMap(); String path = cv.getPropertyPath() + ""; String message = cv.getMessage() + ""; String annoName = cv.getConstraintDescriptor().getAnnotation().annotationType().getSimpleName(); if (annoName.equals("DateMax") || annoName.equals("DateMin")) { Map shape = getShape(path, shapes); Map cd = ConstraintsUtils.getConstraintsData(shape); List vals = (List) cd.get(annoName); //Map cm = ConstraintsUtils.getConstraintsMeta(annoClass, shape, constraintsMeta); mapCV.put("time", vals.get(1)); } mapCV.put("message", message); mapCV.put("path", path); cvList.add(mapCV); } return cvList; } private Map getShape(String name, List<Map> shapes) { for (Map shape : shapes) { if (getName(shape).equals(name)) { return shape; } } return null; } private String getCleanMessage(String msg) { String pattern = ".*RuntimeClassFile\\$\\d+\\.(.*)"; String ret = msg.replaceAll(pattern, "$1"); return ret; } private Map<String, List> getConstraintsFromStencil(String namespace) throws Exception { Map<String, List> retMap = new HashMap(); JSONDeserializer ds = new JSONDeserializer(); Map<String, List> ssMap = (Map) ds.deserialize(m_stencilService.getStencilSet(namespace, "form")); List<Map> stencilList = ssMap.get("stencils"); List<String> retList = new ArrayList(); for (Map stencil : stencilList) { if ("input".equals(((String) stencil.get("id")).toLowerCase())) { List<Map> properties = (List) stencil.get("properties"); for (Map prop : properties) { String pid = ((String) prop.get("id")).toLowerCase(); if (pid.startsWith("xf_constraint")) { retMap.put(pid.substring("xf_constraint_".length()), (List) prop.get("config")); } } } } System.out.println("retMap:" + retMap); return retMap; } interface ShapeCompare { boolean compare(Map shape); } private void traverseElement(List<Map> result, Map shape, ShapeCompare sc) throws Exception { String id = getStencilId(shape); if (sc.compare(shape)) { result.add(shape); } List<Map> childShapes = (List) shape.get("childShapes"); for (Map child : childShapes) { traverseElement(result, child, sc); } } private void traverseElement(List<Map> fields, Map shape, List<String> idList) throws Exception { String id = getStencilId(shape); if (idList.contains(id)) { //System.out.println("Form.traverseElement:id_used:"+id); fields.add(shape); } else { //System.out.println("Form.traverseElement:id_not_used:"+id); } List<Map> childShapes = (List) shape.get("childShapes"); for (Map child : childShapes) { traverseElement(fields, child, idList); } } private String getStencilId(Map element) { Map stencil = (Map) element.get("stencil"); String id = ((String) stencil.get("id")).toLowerCase(); return id; } }