/*
* Copyright 2002-2007 the original author or authors.
*
* 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 org.suren.autotest.web.framework.code;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.VisitorSupport;
import org.dom4j.io.SAXReader;
import org.dom4j.xpath.DefaultXPath;
import org.jaxen.SimpleNamespaceContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.suren.autotest.web.framework.core.Callback;
import org.suren.autotest.web.framework.util.StringUtils;
import freemarker.cache.ClassTemplateLoader;
import freemarker.cache.TemplateLoader;
import freemarker.core.InvalidReferenceException;
import freemarker.template.Configuration;
import freemarker.template.DefaultObjectWrapper;
import freemarker.template.Template;
import freemarker.template.TemplateException;
/**
* 根据xml来生成Java源码
* @author suren
* @date 2016年12月3日 下午8:43:19
*/
@Component("xml_to_java")
public class DefaultXmlCodeGenerator implements Generator
{
private static final Logger logger = LoggerFactory.getLogger(DefaultXmlCodeGenerator.class);
private Map<String, List<AutoField>> pageFieldMap = new HashMap<String, List<AutoField>>();
private Map<String, String> pageCommentMap = new HashMap<String, String>();
private Map<String, String> fieldTypeMap = new HashMap<String, String>();
private ClassLoader classLoader;
private String outputDir;
/**
* 默认构造函数
*/
public DefaultXmlCodeGenerator()
{
fieldTypeMap.put("button", "Button");
fieldTypeMap.put("input", "Text");
fieldTypeMap.put("select", "Selector");
fieldTypeMap.put("file_upload", "FileUpload");
fieldTypeMap.put("check_box_group", "CheckBoxGroup");
}
@Override
public void generate(String srcCoding, String outputDir)
{
this.outputDir = outputDir;
classLoader = this.getClass().getClassLoader();
if(new File(srcCoding).isFile())
{
try(InputStream inputStream = new FileInputStream(new File(srcCoding)))
{
SAXReader saxReader = new SAXReader();
saxReader.setEncoding("utf-8");
Document document = saxReader.read(inputStream);
read(document);
}
catch (DocumentException | IOException e)
{
e.printStackTrace();
}
}
else
{
try(InputStream inputStream = classLoader.getResourceAsStream(srcCoding))
{
Document document = new SAXReader().read(inputStream);
read(document);
}
catch (DocumentException | IOException e)
{
e.printStackTrace();
}
}
Iterator<String> pageIt = pageFieldMap.keySet().iterator();
while(pageIt.hasNext())
{
String pageCls = pageIt.next();
AutoPage autoPage = new AutoPage();
int index = pageCls.lastIndexOf(".");
if(index > 0)
{
autoPage.setPackageName(pageCls.substring(0, index));
}
autoPage.setName(pageCls.substring(index + 1));
autoPage.setComment("");
if(pageCommentMap.containsKey(pageCls))
{
autoPage.setComment(pageCommentMap.get(pageCls));
}
List<AutoField> fieldList = pageFieldMap.get(pageCls);
for(AutoField autoField : fieldList)
{
if(StringUtils.isBlank(autoField.getType()))
{
continue;
}
if(fieldTypeMap.get(autoField.getType()) != null)
{
autoField.setType(fieldTypeMap.get(autoField.getType()));
}
String fieldName = autoField.getName();
String methodField = fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
autoField.setGetterMethod("get" + methodField);
autoField.setSetterMethod("set" + methodField);
}
autoPage.setFields(fieldList);
create(autoPage);
}
done();
}
@Override
public void generate(InputStream input, String outputDir, Callback callback)
{
// TODO Auto-generated method stub
}
/**
* 代码生成完毕
*/
protected void done()
{
}
/**
* 根据Page对象来创建Java源文件
* @param autoPage
*/
protected void create(AutoPage autoPage)
{
try
{
TemplateLoader templateLoader = new ClassTemplateLoader(this.getClass(), "/template");
Configuration configuration = new Configuration();
// configuration.setDirectoryForTemplateLoading(new File("d:/ftp"));
configuration.setTemplateLoader(templateLoader);
configuration.setObjectWrapper(new DefaultObjectWrapper());
configuration.setDefaultEncoding("UTF-8");
Map<String, AutoPage> paramMap = new HashMap<String, AutoPage>();
paramMap.put("page", autoPage);
Template template = configuration.getTemplate("page.ftl");
StringBuffer pathBuf = new StringBuffer(outputDir);
pathBuf.append("/");
String packageName = autoPage.getPackageName();
String[] packageArray = packageName.split("\\.");
if(packageArray != null && packageArray.length > 0)
{
for(String pkName : packageArray)
{
if(!pkName.equals(""))
{
pathBuf.append(pkName).append("/");
}
}
}
String parentDir = pathBuf.toString();
new File(parentDir).mkdirs();
Writer writer = new OutputStreamWriter(
new FileOutputStream(parentDir + autoPage.getName() + ".java"),"UTF-8");
template.process(paramMap, writer);
}
catch (IOException e)
{
e.printStackTrace();
}
catch(InvalidReferenceException e)
{
System.out.println(autoPage);
e.printStackTrace();
}
catch (TemplateException e)
{
e.printStackTrace();
}
}
/**
* @param document
*/
private void read(Document doc)
{
SimpleNamespaceContext simpleNamespaceContext = new SimpleNamespaceContext();
simpleNamespaceContext.addNamespace("ns", "http://surenpi.com");
DefaultXPath xpath = new DefaultXPath("/ns:autotest/ns:pages");
xpath.setNamespaceContext(simpleNamespaceContext);
Element pagesEle = (Element) xpath.selectSingleNode(doc);
String pagePackage = pagesEle.attributeValue("pagePackage", "");
if(StringUtils.isNotBlank(pagePackage))
{
pagePackage = (pagePackage.trim() + ".");
}
// pages parse progress
xpath = new DefaultXPath("/ns:autotest/ns:pages/ns:page");
xpath.setNamespaceContext(simpleNamespaceContext);
@SuppressWarnings("unchecked")
List<Element> pageNodes = xpath.selectNodes(doc);
if (pageNodes != null)
{
for (Element ele : pageNodes)
{
String pageClsStr = ele.attributeValue("class");
if (pageClsStr == null)
{
logger.warn("can not found class attribute.");
continue;
}
pageClsStr = (pagePackage + pageClsStr);
Object commentObj = ele.getData();
if(commentObj != null)
{
pageCommentMap.put(pageClsStr, commentObj.toString().trim());
}
try
{
List<AutoField> fieldList = new ArrayList<AutoField>();
pageFieldMap.put(pageClsStr, fieldList);
parsePage(pageClsStr, ele, fieldList);
}
catch (Exception e)
{
logger.error("page element parse error.", e);
}
}
}
}
/**
* 解析页面Page对象
*
* @param pageClsStr
* @param dataSrcClsStr
* @param ele
* @param fieldList
*/
private void parsePage(final String pageClsStr, Element ele, final List<AutoField> fieldList) throws Exception
{
ele.accept(new VisitorSupport()
{
@Override
public void visit(Element node)
{
if (!"field".equals(node.getName()))
{
return;
}
String fieldName = node.attributeValue("name");
String type = node.attributeValue("type");
if (fieldName == null || "".equals(fieldName)
|| type == null || "".equals(type))
{
return;
}
AutoField autoField = new AutoField(fieldName, type);
Object commentObj = node.getData();
if(commentObj != null)
{
autoField.setComment(commentObj.toString().trim());
}
fieldList.add(autoField);
}
});
}
/**
* @return 解析配置文件所使用的类加载器
*/
public ClassLoader getClassLoader()
{
return classLoader;
}
}