package com.sagacloud.endpoints.tagset;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.sagacloud.dto.DicEnumConf;
import com.sagacloud.dto.ObjectTagConf;
import com.sagacloud.endpoints.Consumable;
import com.sagacloud.utils.CommonUtil;
import com.sagacloud.utils.DpUtils;
import com.sagacloud.utils.OssUtils;
import com.sagacloud.utils.ZillionAgentProvider;
import com.sagacloud.utils.tables.HBaseTable;

@Path("objtag")
public class ObjectTag {
	private static final Logger log = LoggerFactory.getLogger(ObjectTag.class);
	private static boolean cacheInitSuccess = false;
	private final String tableName_enum = "dic_enum_map";
	private static final String tableName_relation = "obj_tag_set";
	private final String dic_type = ObjectTagConf.business;
	private final String enum_type = DicEnumConf.business_property;
	private final String items = "items";
	private final String success = "success";
	private final String allowObj = "Pj,Bd,Fl,Sp,Eq,Ec,St,Sc,Si,Sh";
	// 业务标签
	private static final Map<String, String> tagMap = new HashMap<>();
	static {
		tagMap.put("EMS", "能源系统");
		tagMap.put("TENANT", "租户系统");
		tagMap.put("FM", "设备设施系统");
		tagMap.put("DISTRIBUTION", "配电监控系统");
		tagMap.put("COLDSTATION", "冷站群控系统");
		tagMap.put("BIM", "BIM系统");
		tagMap.put("SAFETY", "安全风险管理系统 ");
		tagMap.put("ENVIRONMENT", "环境健康管理系统");
		tagMap.put("ENERGYBUDGET", "定额能效管理系统");
		tagMap.put("UNICHARGE", "统一收费管理系统");
	}

	@Path("/setTags")
	@POST
	@Produces(MediaType.APPLICATION_JSON)
	public String setTags(String jsonStr) {
		if(!cacheInitSuccess) {
			return DpUtils.errorJsonMsg("对象业务标签缓存初始化失败！");
		}
		
		try {
			JSONObject paramJson = JSONObject.parseObject(jsonStr);
			if(paramJson == null || !paramJson.containsKey("optType") || !paramJson.containsKey("relation")) {
				return DpUtils.errorJsonMsg("参数有误："+jsonStr);
			}
			
			// 是否为增量式添加
			boolean ifUpdate = "update".equals(paramJson.getString("optType"));
			
			JSONArray relationAray = paramJson.getJSONArray("relation");
			for(Object obj : relationAray) {
				JSONObject jsonObj = (JSONObject) obj;
				String tag = jsonObj.getString("tag");
				
				JSONObject param = new JSONObject();
				param.put("objList", jsonObj.getJSONArray("objList"));
				JSONArray codeList = new JSONArray();
				codeList.add(tag);
				param.put("codeList", codeList);
				
				if(ifUpdate) {
					String resultString = batchSetTags(param.toJSONString());
					if(null == resultString || resultString.contains("failure")) {
						return resultString;
					}
				}else {
					String resultString = delTagsOfObj(param.toJSONString());
					if(null == resultString || resultString.contains("failure")) {
						return resultString;
					}
				}
			}
		} catch (Exception ex) {
			ex.printStackTrace();
			return DpUtils.errorJsonMsg(ex.getMessage());
		}
		
		JSONObject resultJson = new JSONObject();
		resultJson.put("Result", "success");

		return resultJson.toJSONString();
	}
	
	@Path("/batchSetTags")
	@POST
	@Produces(MediaType.APPLICATION_JSON)
	public String batchSetTags(String jsonStr) {
		if(!cacheInitSuccess) {
			return DpUtils.errorJsonMsg("对象业务标签缓存初始化失败！");
		}
		
		try {
			JSONObject paramJson = JSONObject.parseObject(jsonStr);

			if(!JSON.isValidArray(paramJson.getString("objList")) || !JSON.isValidArray(paramJson.getString("codeList"))) {
				throw new Exception("参数格式有误！");
			}
			
			// 对象id集合
			List<String> objList = (List<String>) paramJson.get("objList");
			// 标签编码集合
			List<String> codeList = (List<String>) paramJson.get("codeList");
			
			if(objList.size() == 0 || codeList.size() == 0) {
				throw new Exception("参数格式有误！");
			}
			
			// 新增记录 {对象id:[标签编码]}
			Map<String, Set<String>> addObjs = new HashMap<>();
			// 更新记录 {对象id:[标签编码]}
			Map<String, Set<String>> updateObjs = new HashMap<>();
			
			for(String objId : objList) {
				if(allowObj.contains(objId.substring(0, 2))) {
					Set<String> tagsSet = new HashSet<>(codeList);
					
					if(ObjectTagCache.getObjsThatHasTag().contains(objId)) {
						// 对象记录已存在
						
						if(ObjectTagCache.getTagsByObjId(objId).containsAll(tagsSet)) {
							// 已配置了所需设置的标签编码，则不必更新
							continue;
						}
						
						tagsSet.addAll(ObjectTagCache.getTagsByObjId(objId));
						updateObjs.put(objId, tagsSet);
					}else {
						addObjs.put(objId, tagsSet);
					}
				}else {
					throw new Exception("id："+objId+"不合法！");
				}
			}
			
			JSONObject zillionResult = new JSONObject();
			JSONObject zillionJson = getZillionParam("batch_insert", tableName_relation);
			String timeNow = CommonUtil.getTime();
			
			if(!addObjs.isEmpty()) {
				// 新增记录
				
				JSONArray paramInsertObjects = new JSONArray();
				zillionJson.put("InsertObjects", paramInsertObjects);
				for(String objId : addObjs.keySet()) {
					JSONObject addItem = new JSONObject();
					addItem.put("obj_id", objId);
					addItem.put("business_tag", cllectionToStr(addObjs.get(objId)));
					addItem.put("create_time", timeNow);
					addItem.put("update_time", timeNow);
					paramInsertObjects.add(addItem);
				}
				zillionResult = ZillionAgentProvider.GetAgent().Query(zillionJson);
				if (!zillionResult.toString().contains(success)) {
					throw new Exception("zillion新增数据失败！");
				}
				// 向缓存添加数据
				ObjectTagCache.addObjAndTags(addObjs);
			}
			
			if(!updateObjs.isEmpty()) {
				// 更新记录
				
				zillionJson = getZillionParam("batch_update", tableName_relation);
				
				JSONArray paramCriterias = new JSONArray();
				zillionJson.put("Criterias", paramCriterias);
				
				JSONArray paramSets = new JSONArray();
				zillionJson.put("Sets", paramSets);
				
				for(String objId : updateObjs.keySet()) {
					JSONObject criteriaItem = new JSONObject();
					criteriaItem.put("obj_id", objId);
					paramCriterias.add(criteriaItem);
					
					JSONObject setItem = new JSONObject();
					setItem.put("business_tag", cllectionToStr(updateObjs.get(objId)));
					setItem.put("update_time", timeNow);
					paramSets.add(setItem);
				}
				
				zillionResult = ZillionAgentProvider.GetAgent().Query(zillionJson);
				if (!zillionResult.toString().contains(success)) {
					throw new Exception("zillion更新数据失败！");
				}
				// 向缓存添加数据
				ObjectTagCache.addObjAndTags(updateObjs);
			}
			
			JSONObject resultJson = new JSONObject();
			resultJson.put("Result", "success");

			return resultJson.toJSONString();
		} catch (Exception ex) {
			ex.printStackTrace();
			return DpUtils.errorJsonMsg(ex.getMessage());
		}
	}
	
	@Path("/batchDeleteTags")
	@POST
	@Produces(MediaType.APPLICATION_JSON)
	public String delTagsOfObj(String jsonStr) {
		if(!cacheInitSuccess) {
			return DpUtils.errorJsonMsg("对象业务标签缓存初始化失败！");
		}
		
		try {
			JSONObject paramJson = JSONObject.parseObject(jsonStr);

			if(!JSON.isValidArray(paramJson.getString("objList")) || !JSON.isValidArray(paramJson.getString("codeList"))) {
				throw new Exception("参数格式有误！");
			}
			
			// 对象id集合
			List<String> objList = (List<String>) paramJson.get("objList");
			// 标签编码集合
			List<String> codeList = (List<String>) paramJson.get("codeList");
			
			if(objList.size() == 0 || codeList.size() == 0) {
				throw new Exception("参数格式有误！");
			}
			
			// 更新记录 {对象id:[标签编码]}
			Map<String, Set<String>> updateObjs = new HashMap<>();
			
			int tagSize = 0;
			for(String objId : objList) {
				if(allowObj.contains(objId.substring(0, 2))) {
					
					if(ObjectTagCache.getObjsThatHasTag().contains(objId)) {
						// 对象记录已存在
						
						Set<String> tagsSet = new HashSet<>(ObjectTagCache.getTagsByObjId(objId));
						tagSize = tagsSet.size();
						tagsSet.removeAll(codeList);
						
						if(tagSize == tagsSet.size()) {
							// 对象标签中不含有所需删除的标签编码，则不更新
							continue;
						}
						
						updateObjs.put(objId, tagsSet);
					}
				}else {
					throw new Exception("id："+objId+"不合法！");
				}
			}
			
			if(!updateObjs.isEmpty()) {
				// 更新记录
				JSONObject zillionResult = new JSONObject();
				JSONObject zillionJson = getZillionParam("batch_update", tableName_relation);
				
				JSONArray paramCriterias = new JSONArray();
				zillionJson.put("Criterias", paramCriterias);
				
				JSONArray paramSets = new JSONArray();
				zillionJson.put("Sets", paramSets);
				
				String timeNow = CommonUtil.getTime();
				
				for(String objId : updateObjs.keySet()) {
					JSONObject criteriaItem = new JSONObject();
					criteriaItem.put("obj_id", objId);
					paramCriterias.add(criteriaItem);
					
					JSONObject setItem = new JSONObject();
					setItem.put("business_tag", cllectionToStr(updateObjs.get(objId)));
					setItem.put("update_time", timeNow);
					paramSets.add(setItem);
				}
				
				zillionResult = ZillionAgentProvider.GetAgent().Query(zillionJson);
				if (!zillionResult.toString().contains(success)) {
					throw new Exception("zillion更新数据失败！");
				}
				// 刷新缓存数据
				ObjectTagCache.delObjInTag(new HashSet<>(codeList), new HashSet<>(objList));
			}
			
			JSONObject resultJson = new JSONObject();
			resultJson.put("Result", "success");

			return resultJson.toJSONString();
		} catch (Exception ex) {
			ex.printStackTrace();
			return DpUtils.errorJsonMsg(ex.getMessage());
		}
	}
	
	@Path("/queryTagSet")
	@POST
	@Produces(MediaType.APPLICATION_JSON)
	public String queryTagSet(String jsonStr) {
		if(!cacheInitSuccess) {
			return DpUtils.errorJsonMsg("对象业务标签缓存初始化失败！");
		}
		
		try {
			JSONObject paramJson = JSONObject.parseObject(jsonStr);

			if(!JSON.isValidArray(paramJson.getString("objList"))) {
				throw new Exception("参数格式有误！");
			}
			
			// 对象id集合
			List<String> objList = (List<String>) paramJson.get("objList");
			
			JSONArray contentAray = new JSONArray();
			if(!objList.isEmpty()) {
				for(String objId : objList) {
					JSONObject contentItem = new JSONObject();
					contentItem.put("objId", objId);
					contentItem.put("codeList", ObjectTagCache.getTagsByObjId(objId));
					contentAray.add(contentItem);
				}
			}
			
			JSONObject resultJson = new JSONObject();
			resultJson.put("Result", "success");
			resultJson.put("Content", contentAray);

			return resultJson.toJSONString();
		} catch (Exception ex) {
			ex.printStackTrace();
			return DpUtils.errorJsonMsg(ex.getMessage());
		}
	}
	
	private static String cllectionToStr(Collection<String> c) {
		String result = ""+c;
		result = result.startsWith("[")?result.substring(1):result;
		result = result.endsWith("]")?result.substring(0,result.length()-1):result;
		result = result.replaceAll(" ", "");
		return result;
	}
	
	@Path("/tag/createUpdate")
	@POST
	@Produces(MediaType.APPLICATION_JSON)
	public String tagCreateUpdate(String jsonStr) {
		try {
			JSONObject paramJson = JSONObject.parseObject(jsonStr);
			if (!paramJson.containsKey(items) || !JSON.isValidArray(paramJson.getString(items))) {
				throw new Exception(items + "参数错误");
			}

			JSONArray itemAray = paramJson.getJSONArray(items);

			JSONObject zillionJson = getZillionParam("update");
			JSONObject paramCriteria = new JSONObject();
			JSONObject zillionResult = new JSONObject();
			String timeNow = CommonUtil.getTime();

			if (!itemAray.isEmpty()) {
				// 更新式新增数据

				// 1. 查询出所有有效数据
				zillionJson = getZillionParam("select");
				zillionJson.put("Criteria", paramCriteria);
				paramCriteria.put("dic_type", dic_type);
				paramCriteria.put("enum_type", enum_type);
				paramCriteria.put("valid", true);
				zillionResult = ZillionAgentProvider.GetAgent().Query(zillionJson);
				if (!zillionResult.toString().contains(success)) {
					throw new Exception("zillion查询数据失败！");
				}

				Set<String> existCodeSet = new HashSet<>();
				if (JSON.isValidArray(zillionResult.getString("Content"))) {
					for (Object obj : zillionResult.getJSONArray("Content")) {
						JSONObject item = (JSONObject) obj;
						existCodeSet.add(item.getString("code"));
					}
				}

				// 2. 组织出批量新增和更新的数据分别进行新增和更新

				// 新增数据集合
				JSONArray paramInsertObjects = new JSONArray();
				// 更新数据集合
				JSONArray paramUpdateCriterias = new JSONArray();
				JSONArray paramUpdateSets = new JSONArray();
				for (Object obj : itemAray) {
					JSONObject item = (JSONObject) obj;
					String code = item.getString("code");
					if (existCodeSet.contains(code)) {
						// 放入待更新集合
						paramUpdateCriterias.add(getUpdateParam(item.getString("code")));
						paramUpdateSets.add(getUpdateSet(item.getString("value"), timeNow));
					} else {
						// 放入新增集合
						paramInsertObjects.add(getInsertItem(item.getString("code"), item.getString("value"),
								item.getString("pcode"), timeNow));
					}
				}

				if (!paramUpdateCriterias.isEmpty()) {
					zillionJson = getZillionParam("batch_update");
					zillionJson.put("Criterias", paramUpdateCriterias);
					zillionJson.put("Sets", paramUpdateSets);
					zillionResult = ZillionAgentProvider.GetAgent().Query(zillionJson);
					if (!zillionResult.toString().contains(success)) {
						throw new Exception("zillion更新数据失败！");
					}
				}

				if (!paramInsertObjects.isEmpty()) {
					// 2. 批量新增数据
					zillionJson = getZillionParam("batch_insert");
					zillionJson.put("InsertObjects", paramInsertObjects);

					zillionResult = ZillionAgentProvider.GetAgent().Query(zillionJson);
					if (!zillionResult.toString().contains(success)) {
						throw new Exception("zillion新增数据失败！");
					}
				}
			}

			return DpUtils.successJsonMsg("");
		} catch (Exception ex) {
			ex.printStackTrace();
			return DpUtils.errorJsonMsg("失败" + ex.getMessage());
		}
	}

	@Path("/tag/batchDelete")
	@POST
	@Produces(MediaType.APPLICATION_JSON)
	public String tagBatchDelete(String jsonStr) {
		try {
			JSONObject insertJson = JSONObject.parseObject(jsonStr);

			if (JSON.isValidArray(insertJson.getString("codeList"))) {
				JSONArray codeList = insertJson.getJSONArray("codeList");
				
				JSONObject resultJson = new JSONObject();
				resultJson.put("Count", 0);
				
				if (!codeList.isEmpty()) {
					JSONObject zillionJson = getZillionParam("batch_update");
					JSONArray paramCriterias = new JSONArray();
					JSONObject paramSet = new JSONObject();
					zillionJson.put("Criterias", paramCriterias);
					zillionJson.put("Set", paramSet);

					for (Object codeObj : codeList) {
						JSONObject itemCriteria = new JSONObject();
						itemCriteria.put("dic_type", dic_type);
						itemCriteria.put("enum_type", enum_type);
						itemCriteria.put("code", "" + codeObj);
						itemCriteria.put("valid", true);
						paramCriterias.add(itemCriteria);
					}
					paramSet.put("valid", false);
					paramSet.put("update_time", CommonUtil.getTime());

					JSONObject zillionResult = ZillionAgentProvider.GetAgent().Query(zillionJson);
					if (!zillionResult.toString().contains(success)) {
						throw new Exception("zillion执行更新操作失败！");
					}else {
						JSONArray cAray = zillionResult.getJSONArray("Content");
						int updateRecordNum = 0;
						if(!cAray.isEmpty()) {
							for(Object obj : cAray) {
								updateRecordNum += ((JSONObject) obj).getIntValue("Count");
							}
						}
						resultJson.put("Count", updateRecordNum);
					}
				}

				resultJson.put("Result", "success");
				return resultJson.toJSONString();
			} else {
				throw new Exception("参数codeList不合法！");
			}
		} catch (Exception ex) {
			ex.printStackTrace();
			return DpUtils.errorJsonMsg(ex.getMessage());
		}
	}

	@Path("/tag/query")
	@POST
	@Produces(MediaType.APPLICATION_JSON)
	public String tagQuery(String jsonStr) {
		if(null != jsonStr) {
			
			JSONObject resultJson = new JSONObject();
			JSONArray contentList = new JSONArray();
			for(String tagCode : tagMap.keySet()) {
				JSONObject item = new JSONObject();
				item.put("code", tagCode);
				item.put("name", tagMap.get(tagCode));
				contentList.add(item);
			}
			resultJson.put("Result", "success");
			resultJson.put("Count", tagMap.size());
			resultJson.put("Content", contentList);

			return resultJson.toJSONString();
		}
		
		try {
			JSONObject insertJson = JSONObject.parseObject(jsonStr);

			String code = insertJson.getString("code");
			String pcode = insertJson.getString("pcode");

			List<ResultDTO> contentList = new ArrayList<>();

			JSONObject zillionJson = getZillionParam("select");
			JSONObject paramCriteria = new JSONObject();
			zillionJson.put("Criteria", paramCriteria);
			paramCriteria.put("dic_type", dic_type);
			paramCriteria.put("enum_type", enum_type);
			paramCriteria.put("valid", true);
			if (code != null) {
				paramCriteria.put("code", code);
			}
			if (pcode != null) {
				paramCriteria.put("pcode", pcode);
			}

			JSONObject zillionResult = ZillionAgentProvider.GetAgent().Query(zillionJson);
			if (!zillionResult.toString().contains(success)) {
				throw new Exception("zillion查询数据失败！");
			}

			if (JSON.isValidArray(zillionResult.getString("Content"))) {
				JSONArray objAray = zillionResult.getJSONArray("Content");
				for (Object obj : objAray) {
					JSONObject item = (JSONObject) obj;
					// 查询结果数据放入contentList
					contentList.add(new ResultDTO(item.getString("code"), item.getString("pcode"),
							item.getString("value"), item.getString("create_time"), item.getString("update_time")));
				}
			}

			JSONObject resultJson = new JSONObject();
			resultJson.put("Result", "success");
			resultJson.put("Count", contentList.size());
			resultJson.put("Content", contentList);

			return resultJson.toJSONString();
		} catch (Exception ex) {
			ex.printStackTrace();
			return DpUtils.errorJsonMsg(ex.getMessage());
		}
	}
	
	@Path("/refreshCache")
	@POST
	@Produces(MediaType.APPLICATION_JSON)
	public String refreshCache(String jsonStr) {
		log.info("----refreshCache-ObjectTag...");
		return objectTagCacheInit();
	}

	/**
	 * 得到新增对象信息jsonObj,若code和value为空则抛异常
	 * 
	 * @param code
	 * @param value
	 * @param pcode
	 * @param time
	 * @return
	 * @throws Exception
	 */
	private JSONObject getInsertItem(String code, String value, String pcode, String time) throws Exception {
		JSONObject item = new JSONObject();
		if (code == null || code.trim().length() == 0) {
			throw new Exception("code=" + code + "不合法");
		}
		if (value == null || code.trim().length() == 0) {
			throw new Exception("value=" + value + "不合法");
		}
		item.put("dic_type", dic_type);
		item.put("enum_type", enum_type);
		item.put("code", code);
		item.put("value", value);
		if (null != pcode) {
			item.put("pcode", pcode);
		}
		item.put("create_time", time);
		item.put("update_time", time);
		item.put("valid", true);
		return item;
	}

	/**
	 * 获取更新对象条件jsonObj,若code为空则抛异常
	 * 
	 * @param code
	 * @param updateTime
	 * @return
	 * @throws Exception
	 */
	private JSONObject getUpdateParam(String code) throws Exception {
		JSONObject item = new JSONObject();
		if (code == null || code.trim().length() == 0) {
			throw new Exception("code=" + code + "不合法");
		}

		item.put("dic_type", dic_type);
		item.put("enum_type", enum_type);
		item.put("code", code);
		item.put("valid", true);
		return item;
	}

	/**
	 * 获取更新对象设定值jsonObj,若value为空则抛异常
	 * 
	 * @param value
	 * @param updateTime
	 * @return
	 * @throws Exception
	 */
	private JSONObject getUpdateSet(String value, String updateTime) throws Exception {
		JSONObject item = new JSONObject();
		if (value == null || value.trim().length() == 0) {
			throw new Exception("value=" + value + "不合法");
		}

		item.put("value", value);
		item.put("update_time", updateTime);
		return item;
	}

	/**
	 * 生成执行zillion语句的json对象，默认Database为配置文件中设置的数据字典数据库
	 * 
	 * @param queryType
	 *            执行操作类型
	 * @return
	 */
	private JSONObject getZillionParam(String queryType) {
		JSONObject zillionJson = new JSONObject();
		zillionJson.put("Database", OssUtils.getProperty("database.name"));
		zillionJson.put("QueryType", queryType);
		zillionJson.put("Datatable", tableName_enum);

		return zillionJson;
	}
	
	private static JSONObject getZillionParam(String queryType, String tableName) {
		JSONObject zillionJson = new JSONObject();
		zillionJson.put("Database", OssUtils.getProperty("database.name"));
		zillionJson.put("QueryType", queryType);
		zillionJson.put("Datatable", tableName);

		return zillionJson;
	}
	
	private static void analysisCategoryTree(String pcode, JSONArray dataList, JSONArray sonList) {
		if(null != sonList && !sonList.isEmpty()) {
			for(int i=0; i<sonList.size(); i++) {
				JSONObject item = sonList.getJSONObject(i);
				
				JSONObject addItem = new JSONObject();
				dataList.add(addItem);
				addItem.put("code", item.getString("code"));
				addItem.put("name", item.getString("name"));
				addItem.put("parent", pcode);
				
				JSONArray subsonList = item.getJSONArray("content");
				analysisCategoryTree(item.getString("code"), dataList, subsonList);
			}
		}
	}
	
	public static void comsumableCategoryUpdate(JSONArray dataList) throws Exception {
		JSONObject criteria = new JSONObject();
		criteria.put("obj_id", Consumable.defaultId);
		
		JSONObject setdata = new JSONObject();
		setdata.put("other_tag", dataList.toString());
		setdata.put("update_time", CommonUtil.getTime());
		
		CommonUtil.update(false, HBaseTable.obj_tag_set, criteria, setdata);
	}
	
	public static JSONArray comsumableCategoryQuery() throws Exception {
		JSONObject criteria = new JSONObject();
		criteria.put("obj_id", Consumable.defaultId);
		
		JSONArray dataList = new JSONArray();
		JSONObject result = CommonUtil.query(false, HBaseTable.obj_tag_set, criteria);
		if(null != result && result.toString().contains("success")) {
			JSONArray content = result.getJSONArray("Content");
			if(content != null && content.size() > 0) {
				JSONObject item = content.getJSONObject(0);
				String jsonStr = item.getString("other_tag");
				dataList = JSONArray.parseArray(jsonStr);
			}
		}
		return dataList;
	}
	
	private static JSONArray treeDataToPlainData(JSONArray source, JSONArray result, String parent) {
		if(result == null) {
			result = new JSONArray();
		}
		
		if(source != null && !source.isEmpty()) {
			for(int i=0; i<source.size(); i++) {
				JSONObject item = source.getJSONObject(i);
				item.put("parent", parent);
				result.add(item);
				JSONArray content = item.getJSONArray("content");
				if(null != content && !content.isEmpty()) {
					treeDataToPlainData(content, result, item.getString("code"));
				}
			}
		}
		
		return result;
	}
	
	public static JSONArray comsumableCategoryTreeQuery() throws Exception {
		JSONArray records = comsumableCategoryQuery();
		if(null != records && !records.isEmpty()) {
			Map<String, Set<String>> parent_sons = new HashMap<>();
			Map<String, JSONObject> itemMap = new HashMap<>();

			String code = null, parent = null;
			Set<String> rootCode = new HashSet<>();
			for(int i=0; i<records.size(); i++) {
				JSONObject cobj = records.getJSONObject(i);
				cobj.put("content", new JSONArray());
				code = cobj.getString("code");
				parent = cobj.getString("parent");
				cobj.remove("parent");
				
				if(null != parent) {
					if(parent_sons.containsKey(parent)) {
						parent_sons.get(parent).add(code);
					}else {
						parent_sons.put(parent, new HashSet<>(Arrays.asList(code)));
					}
				}else {
					rootCode.add(code);
				}
				itemMap.put(code, cobj);
			}
			
			JSONArray resultArray = new JSONArray();
			for(String sonCode : itemMap.keySet()) {
				Set<String> subItemCodes = parent_sons.get(sonCode);
				if(null != subItemCodes) {
					JSONArray subItems = new JSONArray();
					for(String ccode : subItemCodes) {
						subItems.add(itemMap.get(ccode));
					}
					itemMap.get(sonCode).put("content", subItems);
				}
				if(rootCode.contains(sonCode)) {
					resultArray.add(itemMap.get(sonCode));
				}
			}
			
			return resultArray;
		}
		
		return new JSONArray();
	}
	
	public static void comsumableCategoryConfigToDB() throws Exception {
		JSONObject zillionResult = new JSONObject();
		JSONObject zillionJson = getZillionParam("batch_insert", tableName_relation);
		String timeNow = CommonUtil.getTime();
		
        String configJson =  OssUtils.getFileAsString("property/Dictionary/consumableRel.json");
		JSONObject configObj = JSONObject.parseObject(configJson);
        
		if(!configObj.isEmpty()) {
			JSONArray allObj = configObj.getJSONArray("all");
			JSONArray dataList = new JSONArray();
			analysisCategoryTree(null, dataList, allObj);
			
			
			JSONArray paramInsertObjects = new JSONArray();
			zillionJson.put("InsertObjects", paramInsertObjects);
			JSONObject addItem = new JSONObject();
			addItem.put("obj_id", Consumable.defaultId);
			addItem.put("other_tag", dataList.toString());
			addItem.put("create_time", timeNow);
			addItem.put("update_time", timeNow);
			paramInsertObjects.add(addItem);
			
			
			zillionResult = ZillionAgentProvider.GetAgent().Query(zillionJson);
			if (!zillionResult.toString().contains("success")) {
				throw new Exception("zillion新增耗材类型数据失败！zillionSQL:" + zillionJson.toJSONString());
			}else {
				log.info("zillion新增耗材类型数据success! recordNum="+dataList.size());
			}
		}
	}
	
	public static String objectTagCacheInit() {
		log.info("初始化对象业务标签信息缓存--start-thread");
		
		String jsonStr = "{\"QueryType\":\"select\",\"Datatable\":\"obj_tag_set\"}";
		JSONObject paramJson = JSONObject.parseObject(jsonStr);
		paramJson.put("Database", OssUtils.getProperty("database.name"));
		paramJson.put("Criteria", new JSONObject());
		try {
			JSONObject result = ZillionAgentProvider.GetAgent().Query(paramJson);
			if("success".equals(result.getString("Result"))) {
				JSONArray recordContent = result.getJSONArray("Content");
				boolean ifInitComsumableCategory = true;
				
				int bussinessTagNum = 0;
				
				if(null != recordContent && !recordContent.isEmpty()) {
					JSONObject item = null;
					String objId = null, businessTag = null;
					Map<String, Set<String>> obj_tags = new HashMap<String, Set<String>>();
					for(Object obj : recordContent) {
						item = (JSONObject) obj;
						objId = item.getString("obj_id");
						if(Consumable.defaultId.equals(objId)) {
							ifInitComsumableCategory = false;
							String otherTag = item.getString("other_tag");
							if(null != otherTag) {
								JSONArray ccategory = JSONArray.parseArray(otherTag);
								if(!ccategory.isEmpty()) {
									log.info("初始化耗材类型数据--success--num:" + ccategory.size());
								}
							}
						}else {
							bussinessTagNum ++;
							businessTag = item.getString("business_tag");
							if(businessTag != null) {
								obj_tags.put(objId, new HashSet<>(Arrays.asList(businessTag.split(","))));
							}
						}
					}
					ObjectTagCache.cleanCache();
					ObjectTagCache.addObjAndTags(obj_tags);
				}
				
				if(ifInitComsumableCategory) {
					try {
						comsumableCategoryConfigToDB();
						log.info("初始化耗材类型数据--success");
					}catch (Exception e) {
						log.error("初始化耗材类型数据失败！" + e.getMessage());
						e.printStackTrace();
					}
				}
				
				log.info("初始化对象业务标签信息缓存--end-success-add:" + bussinessTagNum);
				cacheInitSuccess = true;
				return DpUtils.successJsonMsg("");
			}else {
				return DpUtils.errorJsonMsg("查询对象标签信息失败！");
			}
		}catch (Exception e) {
			e.printStackTrace();
			log.error("初始化对象业务标签信息缓存--end-failure");
			return DpUtils.errorJsonMsg(e.getMessage());
		}
	}

	class ResultDTO {
		private String code;
		private String pcode;
		private String name;
		private String createTime;
		private String updateTime;

		public ResultDTO(String code, String pcode, String name, String createTime, String updateTime) {
			super();
			this.code = code;
			this.pcode = pcode;
			this.name = name;
			this.createTime = createTime;
			this.updateTime = updateTime;
		}

		public String getCode() {
			return code;
		}

		public void setCode(String code) {
			this.code = code;
		}

		public String getPcode() {
			return pcode;
		}

		public void setPcode(String pcode) {
			this.pcode = pcode;
		}

		public String getName() {
			return name;
		}

		public void setName(String name) {
			this.name = name;
		}

		public String getCreateTime() {
			return createTime;
		}

		public void setCreateTime(String createTime) {
			this.createTime = createTime;
		}

		public String getUpdateTime() {
			return updateTime;
		}

		public void setUpdateTime(String updateTime) {
			this.updateTime = updateTime;
		}
	}
}
