/**
* Axelor Business Solutions
*
* Copyright (C) 2016 Axelor (<http://axelor.com>).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.axelor.apps.base.test;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import com.axelor.apps.tool.file.CsvTool;
public class ExportObject {
public static List<String> fieldAttrs = Arrays.asList("object","module", "name","type","title","help");
private static final Logger log = LoggerFactory.getLogger(ExportObject.class);
private SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
private List<Map<String,Object>> menuList = new ArrayList<Map<String,Object>>();
private Map<String,Object> objectMap = new HashMap<String,Object>();
private List<String[]> fieldDataList = new ArrayList<String[]>();
private List<String> objectList = new ArrayList<String>();
private String modulesPath = "/home/axelor/axelor-erp/gradle/axelor-erp/modules";
private String csvPath = "/home/axelor/Desktop/";
@Test
public void exportObject() {
File moduleDir = new File(modulesPath);
if(moduleDir.exists()){
prepareObject(Arrays.asList(moduleDir.listFiles()));
}
else{
log.debug("Module source directory not exist");
}
}
private void prepareObject(List<File> modules) {
try {
XmlHandler xmlHandler = new XmlHandler();
SAXParser parser = saxParserFactory.newSAXParser();
for(File module : modules){
String modulePath = module.getAbsolutePath();
File menuFile = new File(modulePath+"/src/main/resources/views/menu.xml");
if(menuFile.exists()){
log.debug("Parsing menu: {}",menuFile.getAbsolutePath());
parser.parse(new InputSource(new FileInputStream(menuFile)), xmlHandler);
}
}
updateMenuGraph(xmlHandler,null);
Collections.sort(menuList,new MenuComparator());
updateObjectMap(modules,parser,xmlHandler);
writeCsv();
} catch (SAXException | IOException | ParserConfigurationException e) {
e.printStackTrace();
}
}
private Object updateMenuGraph(XmlHandler xmlHandler, String parentName) {
List<String> keyList = new ArrayList<String>(xmlHandler.menuMap.keySet());
List<Map<String,Object>> children = new ArrayList<Map<String,Object>>();
for(String menuName : keyList) {
Map<String,String> menuMap = xmlHandler.menuMap.get(menuName);
if(menuMap == null) {continue;}
Map<String,Object> menuGraph = new HashMap<String,Object>();
menuGraph.put("priority", menuMap.get("priority"));
menuGraph.put("object",menuMap.get("object"));
menuGraph.put("name", menuName);
String parent = menuMap.get("parent");
if(parent == null){
xmlHandler.menuMap.remove(menuName);
menuGraph.put("children",updateMenuGraph(xmlHandler,menuName));
menuList.add(menuGraph);
continue;
}
if(parent != null && parent.equals(parentName)){
xmlHandler.menuMap.remove(menuName);
menuGraph.put("children",updateMenuGraph(xmlHandler,menuName));
children.add(menuGraph);
}
}
Collections.sort(children,new MenuComparator());
return children;
}
@SuppressWarnings("unchecked")
private void updateObjectMap(List<File> modules, SAXParser parser, XmlHandler xmlHandler) throws SAXException, IOException {
for(File module : modules){
String modulePath = module.getAbsolutePath();
File modelDir = new File(modulePath+"/src/main/resources/domains/");
if(!modelDir.exists()){ continue;}
log.debug("Module : {}",modelDir.getAbsolutePath());
for(File objectFile : modelDir.listFiles()){
log.debug("Parsing domain : {}",objectFile.getName());
String objectName = objectFile.getName().split("\\.")[0];
if(xmlHandler.objectList.contains(objectName)){
parser.parse(new InputSource(new FileInputStream(objectFile)), xmlHandler);
Map<String,Object> moduleMap = (Map<String, Object>) objectMap.get(objectName);
if(moduleMap == null) { moduleMap = new HashMap<String,Object>();}
moduleMap.put(module.getName(),xmlHandler.fieldList);
objectMap.put(objectName,moduleMap);
}
}
}
}
private void writeCsv() {
try {
updateObjectList(menuList);
updateFieldList();
String[] headers = fieldAttrs.toArray(new String[fieldAttrs.size()]);
CsvTool.csvWriter(csvPath, "ExportObj.csv", ';', headers, fieldDataList);
} catch (IOException e) {
e.printStackTrace();
}
}
@SuppressWarnings("unchecked")
private void updateObjectList(List<Map<String, Object>> orderedMenuList){
Iterator<Map<String, Object>> menuIterator = orderedMenuList.iterator();
while(menuIterator.hasNext()){
Map<String,Object> menu = menuIterator.next();
String objectName = (String) menu.get("object");
if(objectName != null && !objectList.contains(objectName)){
objectList.add(objectName);
}
List<Map<String, Object>> childrenMenuList = (List<Map<String, Object>>)menu.get("children");
if(!childrenMenuList.isEmpty())
updateObjectList(childrenMenuList);
}
}
@SuppressWarnings("unchecked")
private void updateFieldList() {
for(String objName : objectList) {
String[] objectName = objName.split("\\.");
Map<String,Object> moduleMap = (Map<String, Object>)objectMap.get(objectName[objectName.length-1]);
log.debug("Adding object: {}",objectName[objectName.length-1]);
if(moduleMap == null) {
log.debug("No domain file found for: {}",objName);
continue;
}
for (Entry<String, Object> module : moduleMap.entrySet()) {
String moduleName = module.getKey();
for(Map<String,String> field : (List<Map<String,String>>)module.getValue()){
Iterator<String> fieldAtt = fieldAttrs.iterator();
List<String> fieldData = new ArrayList<String>();
field.put("object",objName);
field.put("module", moduleName);
while(fieldAtt.hasNext()){
fieldData.add(field.get(fieldAtt.next()));
}
fieldDataList.add(fieldData.toArray(new String[fieldData.size()]));
}
}
}
}
}
class XmlHandler extends DefaultHandler {
public List<String> objectList = new ArrayList<String>();
public Map<String,Map<String,String>> menuMap = new HashMap<String,Map<String,String>>();
private Map<String,String> actionMenuMap = new HashMap<String,String>();
public List<Map<String,String>> fieldList;
private boolean isObject = false;
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes)
throws SAXException {
switch(qName){
case "menuitem": {
if(attributes.getValue("top") == null){ handleMenu(attributes); }
break;
}
case "action-view": {
handleAction(attributes);
break;
}
case "entity": {
isObject = true;
fieldList = new ArrayList<Map<String,String>>();
break;
}
default: {
if(isObject){
Map<String,String> fieldMap = new HashMap<String,String>();
fieldMap.put("type", qName);
for(String fieldAttr : ExportObject.fieldAttrs){
if(attributes.getValue(fieldAttr) != null){
fieldMap.put(fieldAttr, attributes.getValue(fieldAttr));
}
}
fieldList.add(fieldMap);
}
}
}
super.startElement(uri, localName, qName, attributes);
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
if(qName.equals("entity")){
isObject = false;
}
super.endElement(uri, localName, qName);
}
public void handleMenu(Attributes attributes) {
Map<String,String> menuAttr = new HashMap<String,String>();
String name = attributes.getValue("name");
menuAttr.put("parent",attributes.getValue("parent"));
menuAttr.put("priority", attributes.getValue("priority"));
if(attributes.getValue("action") != null){ actionMenuMap.put(attributes.getValue("action"),name);}
menuMap.put(name,menuAttr);
}
public void handleAction(Attributes attributes) {
String name = attributes.getValue("name");
String model = attributes.getValue("model");
if(actionMenuMap.containsKey(name) && model != null) {
Map<String, String> menu = menuMap.get(actionMenuMap.get(name));
menu.put("object", model);
menuMap.put(actionMenuMap.get(name), menu);
String objectName[] = model.split("\\.");
if(!objectList.contains(objectName[objectName.length-1]))
objectList.add(objectName[objectName.length-1]);
}
}
}
class MenuComparator implements Comparator<Map<String,Object>>{
@Override
public int compare(Map<String, Object> o1, Map<String, Object> o2) {
Integer priority1 = o1.get("priority") != null ? Integer.parseInt(o1.get("priority").toString()) : 0;
Integer priority2 = o2.get("priority") != null ? Integer.parseInt(o2.get("priority").toString()) : 0;
if(priority1 < priority2){ return 1; }
return -1;
}
}